Commit Graph
1 Commits
Author SHA1 Message Date
Ge-org Brohammer 26d38779e4 realtek: Fix use-after-free of the SSM error in completion handlers
fp_verify_ssm_done(), fp_enroll_ssm_done(), fp_init_ssm_done() and
fp_delete_ssm_done() each overwrite the GError they are given:

  if (fpi_ssm_get_error (ssm))
    error = fpi_ssm_get_error (ssm);

An SSM completion callback is handed an owned copy of the error --
fpi-ssm.c takes a g_error_copy() before invoking the callback -- whereas
fpi_ssm_get_error() is documented as (transfer none), and the machine's
own error is freed by the fpi_ssm_free() that immediately follows the
callback.

Since every fpi_device_*_complete() takes the error as (transfer full),
these handlers leak the copy they own and hand the consumer a pointer
that is freed moments later. The consumer is then left reading a
dangling GError. For fprintd that is fatal: it logs error->message and
dies with a general protection fault inside strlen(), taking the
session's authentication daemon with it.

  kernel: traps: fprintd[67901] general protection fault
                 ip:7fcef3b6429c sp:7ffd5f4128a8 error:0 in libc.so.6

  #0  __strlen_evex ()
  #3  g_vasprintf () at ../glib/gprintf.c:342
  #5  g_strdup_vprintf () at ../glib/gstrfuncs.c:515
  #9  delete_enrolled_fingers (user=... "ge-org",
                               finger=FP_FINGER_RIGHT_INDEX)
        at ../src/device.c:2420
        local_error = 0x563c2628bcb0

The assignment is redundant even where it is not harmful, because the
error passed to the callback is already a copy of the machine's error;
using it directly is both correct and sufficient. fpi_ssm_dup_error()
is available for callers that do need an owned copy. No other driver in
the tree assigns the borrowed SSM error this way.

Reproduced on a Realtek 2541:fa03 (Minisforum AI X1 Pro 470) by
enrolling a finger while a template was already present in on-chip
storage, which takes the delete path shown above. The same driver bug
reaches fprintd a second way, via fp_enroll_ssm_done() ->
fpi_device_enroll_complete() -> fprintd's enroll_cb().
2026-08-28 13:30:33 +02:00