Commit Graph
2 Commits
Author SHA1 Message Date
Ge-org Brohammer 3a41fa7ccc tests/realtek: Cover the storage error path that returned a freed GError
Deleting a print whose template is not in the sensor's storage makes the
driver fail its task SSM, which is the path that handed an already-freed
GError to fpi_device_delete_complete(). Reading the reported error is
therefore what the test is for.

No enrollment is involved: the test deserializes a stored realtek print
whose template is deliberately not on the device, so the recording needs
no finger presses and the capture stays at 90 packets.

Without the previous commit the test dies rather than fails:

  umockdev-run ... died with <Signals.SIGSEGV: 11>
  1/1 drivers+custom - libfprint:realtek-storage-errors FAIL

The duplicate-enrollment path reaches the same bug through
fp_enroll_ssm_done(), but capturing it needs two full enrollments and
some 1.07M packets of polling traffic, so it is left out here.
2026-08-28 15:19:30 +02:00
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