mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2026-09-09 04:40:06 +00:00
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().
This commit is contained in:
@@ -909,9 +909,6 @@ fp_verify_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
|
||||
fp_info ("Verify complete!");
|
||||
|
||||
if (fpi_ssm_get_error (ssm))
|
||||
error = fpi_ssm_get_error (ssm);
|
||||
|
||||
if (error && error->domain == FP_DEVICE_RETRY)
|
||||
{
|
||||
if (fpi_device_get_current_action (dev) == FPI_DEVICE_ACTION_VERIFY)
|
||||
@@ -936,9 +933,6 @@ fp_enroll_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
|
||||
fp_info ("Enrollment complete!");
|
||||
|
||||
if (fpi_ssm_get_error (ssm))
|
||||
error = fpi_ssm_get_error (ssm);
|
||||
|
||||
if (error)
|
||||
{
|
||||
fpi_device_enroll_complete (dev, NULL, error);
|
||||
@@ -958,9 +952,6 @@ fp_init_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
|
||||
fp_info ("Init complete!");
|
||||
|
||||
if (fpi_ssm_get_error (ssm))
|
||||
error = fpi_ssm_get_error (ssm);
|
||||
|
||||
fpi_device_open_complete (dev, error);
|
||||
self->task_ssm = NULL;
|
||||
}
|
||||
@@ -972,9 +963,6 @@ fp_delete_ssm_done (FpiSsm *ssm, FpDevice *dev, GError *error)
|
||||
|
||||
fp_info ("Delete print complete!");
|
||||
|
||||
if (fpi_ssm_get_error (ssm))
|
||||
error = fpi_ssm_get_error (ssm);
|
||||
|
||||
fpi_device_delete_complete (dev, error);
|
||||
self->task_ssm = NULL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user