From 3933e5d468210516fe1bba5d43b3295dc93b682f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Fri, 19 Jun 2026 11:17:11 +0200 Subject: [PATCH] fpi-device: Only use emulation mode by pre-loading a library Rather than just do it in production if set, make it more difficult to potentially inject the test mode. So rely on a weak definition of fpi_device_emulation_mode_enabled() that can be only set externally --- libfprint/fpi-device.c | 21 ++++----------------- libfprint/libfprint.ver | 1 + tests/meson.build | 24 ++++++++++++++++++++++-- tests/test-emulation.c | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 19 deletions(-) create mode 100644 tests/test-emulation.c diff --git a/libfprint/fpi-device.c b/libfprint/fpi-device.c index 5f73077a..4063f91a 100644 --- a/libfprint/fpi-device.c +++ b/libfprint/fpi-device.c @@ -55,28 +55,15 @@ fp_device_get_instance_private (FpDevice *self) * @device: The #FpDevice to check * * Checks if the device is running in emulation mode, which is enabled by - * setting the FP_DEVICE_EMULATION environment variable to a '1' value. + * setting the FP_DEVICE_EMULATION environment variable to a '1' value but + * only when the test emulation library is pre-loaded. * This is used by some drivers to enable special behavior for testing * and development purposes. */ -gboolean +__attribute__((weak)) gboolean (fpi_device_emulation_mode_enabled) (FpDevice *device) { - static gsize emulation_mode = 0; - - /* FIXME: Add some build constraints to make sure this cannot ever be enabled - * in production, outside in the installed tests case. - */ - - /* This is a global value for now, but ideally we may support a different - * value per device. - */ - if (g_once_init_enter (&emulation_mode)) - g_once_init_leave (&emulation_mode, - g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0 ? - TRUE : G_MAXSIZE); - - return emulation_mode == TRUE; + return FALSE; } /** diff --git a/libfprint/libfprint.ver b/libfprint/libfprint.ver index d99a456a..f754a6d4 100644 --- a/libfprint/libfprint.ver +++ b/libfprint/libfprint.ver @@ -1,6 +1,7 @@ LIBFPRINT_2.0.0 { global: fp_*; + fpi_device_emulation_mode_enabled; local: *; }; diff --git a/tests/meson.build b/tests/meson.build index b3ff0b07..2c1945a9 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -74,6 +74,18 @@ if get_option('introspection') output: 'create-driver-test.py') endif +test_emulation_lib = shared_library('fprint-test-emulation', + 'test-emulation.c', + dependencies: libfprint_private_dep, + install: installed_tests, + install_dir: installed_tests_execdir, +) +test_emulation_lib_name = fs.name(test_emulation_lib.full_path()) + +# Preload the test-emulation library so that the weak NULL implementation +# in libfprint is overridden with one that honours FP_DEVICE_EMULATION. +envs.prepend('LD_PRELOAD', test_emulation_lib.full_path()) + env_parser_cmd = ''' import os; print(" ".join([f"{k}={v}" for k, v in os.environ.items() @@ -86,6 +98,7 @@ envs_str = run_command(python3, '-c', env_parser_cmd, envs_str = ' '.join([ envs_str, + 'LD_PRELOAD=' + (installed_tests_execdir / test_emulation_lib_name), 'G_TEST_SRCDIR=' + installed_tests_testdir, 'G_TEST_BUILDDIR=' + installed_tests_execdir, ]) @@ -133,7 +146,10 @@ if get_option('introspection') python3, args: ut_args, suite: ut_suite, - depends: libfprint_typelib, + depends: [ + libfprint_typelib, + test_emulation_lib, + ], env: envs, ) endforeach @@ -187,7 +203,10 @@ if get_option('introspection') env: driver_envs, suite: ['drivers'], timeout: args.get('timeout', 15), - depends: libfprint_typelib, + depends: [ + libfprint_typelib, + test_emulation_lib, + ], ) if installed_tests @@ -206,6 +225,7 @@ if get_option('introspection') 'driver_test': driver_test, 'driver_env': ' '.join([ driver_envs_str, + 'LD_PRELOAD=' + (installed_tests_execdir / test_emulation_lib_name), 'LD_LIBRARY_PATH=' + installed_tests_libdir, # FIXME: Adding this requires gnome-desktop-testing!12 # 'GI_TYPELIB_PATH=' + installed_tests_libdir / 'girepository-1.0', diff --git a/tests/test-emulation.c b/tests/test-emulation.c new file mode 100644 index 00000000..a204cc4a --- /dev/null +++ b/tests/test-emulation.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2026 Canonical, Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "fpi-device.h" + +gboolean + (fpi_device_emulation_mode_enabled) (FpDevice *device) +{ + static gsize emulation_mode = 0; + + if (g_once_init_enter (&emulation_mode)) + g_once_init_leave (&emulation_mode, + g_strcmp0 (g_getenv ("FP_DEVICE_EMULATION"), "1") == 0 ? + TRUE : G_MAXSIZE); + + return emulation_mode == TRUE; +}