Move amdgpu safety check into the plugin

There are now multiple plugins using drm_dp_aux_dev interface which
may potentially be combined with an amdgpu. Prevent exercising this
interface with any plugin using DP aux unless a new enough kernel is
installed.
This commit is contained in:
Richard Hughes 2021-07-03 21:39:22 +01:00
parent 825cf474ef
commit dfaae2e837
32 changed files with 102 additions and 86 deletions

View File

@ -319,7 +319,6 @@ done
%config(noreplace)%{_sysconfdir}/fwupd/uefi_capsule.conf
%endif
%config(noreplace)%{_sysconfdir}/fwupd/redfish.conf
%config(noreplace)%{_sysconfdir}/fwupd/synaptics_mst.conf
%config(noreplace)%{_sysconfdir}/fwupd/thunderbolt.conf
%dir %{_libexecdir}/fwupd
%{_libexecdir}/fwupd/fwupd

View File

@ -337,6 +337,8 @@ fwupd_plugin_flag_to_string (FwupdPluginFlags plugin_flag)
return "failed-open";
if (plugin_flag == FWUPD_PLUGIN_FLAG_REQUIRE_HWID)
return "require-hwid";
if (plugin_flag == FWUPD_PLUGIN_FLAG_KERNEL_TOO_OLD)
return "kernel-too-old";
if (plugin_flag == FWUPD_DEVICE_FLAG_UNKNOWN)
return "unknown";
return NULL;
@ -379,6 +381,8 @@ fwupd_plugin_flag_from_string (const gchar *plugin_flag)
return FWUPD_PLUGIN_FLAG_FAILED_OPEN;
if (g_strcmp0 (plugin_flag, "require-hwid") == 0)
return FWUPD_PLUGIN_FLAG_REQUIRE_HWID;
if (g_strcmp0 (plugin_flag, "kernel-too-old") == 0)
return FWUPD_PLUGIN_FLAG_KERNEL_TOO_OLD;
return FWUPD_DEVICE_FLAG_UNKNOWN;
}

View File

@ -667,6 +667,14 @@ typedef enum {
* Since: 1.5.8
*/
#define FWUPD_PLUGIN_FLAG_REQUIRE_HWID (1u << 10)
/**
* FWUPD_PLUGIN_FLAG_KERNEL_TOO_OLD:
*
* The feature is not supported as the kernel is too old.
*
* Since: 1.6.2
*/
#define FWUPD_PLUGIN_FLAG_KERNEL_TOO_OLD (1u << 11)
/**
* FWUPD_PLUGIN_FLAG_UNKNOWN:
*

View File

@ -26,4 +26,6 @@ void fu_context_add_firmware_gtype (FuContext *self,
GPtrArray *fu_context_get_firmware_gtype_ids (FuContext *self);
GType fu_context_get_firmware_gtype_by_id (FuContext *self,
const gchar *id);
void fu_context_add_udev_subsystem (FuContext *self,
const gchar *subsystem);
GPtrArray *fu_context_get_udev_subsystems (FuContext *self);

View File

@ -58,8 +58,6 @@ void fu_context_add_runtime_version (FuContext *self,
void fu_context_add_compile_version (FuContext *self,
const gchar *component_id,
const gchar *version);
void fu_context_add_udev_subsystem (FuContext *self,
const gchar *subsystem);
const gchar *fu_context_lookup_quirk_by_id (FuContext *self,
const gchar *guid,
const gchar *key);

View File

@ -1303,6 +1303,62 @@ fu_common_string_uncamelcase (const gchar *str)
return g_string_free (tmp, FALSE);
}
static gboolean
fu_plugin_check_amdgpu_dpaux (FuPlugin *self, GError **error)
{
#ifdef __linux__
gsize bufsz = 0;
g_autofree gchar *buf = NULL;
g_auto(GStrv) lines = NULL;
/* no module support in the kernel, we can't test for amdgpu module */
if (!g_file_test ("/proc/modules", G_FILE_TEST_EXISTS))
return TRUE;
if (!g_file_get_contents ("/proc/modules", &buf, &bufsz, error))
return FALSE;
lines = g_strsplit (buf, "\n", -1);
for (guint i = 0; lines[i] != NULL; i++) {
if (g_str_has_prefix (lines[i], "amdgpu ")) {
/* released 2019! */
return fu_common_check_kernel_version ("5.2.0", error);
}
}
#endif
return TRUE;
}
/**
* fu_plugin_add_udev_subsystem:
* @self: a #FuPlugin
* @subsystem: a subsystem name, e.g. `pciport`
*
* Registers the udev subsystem to be watched by the daemon.
*
* Plugins can use this method only in fu_plugin_init()
*
* Since: 1.6.2
**/
void
fu_plugin_add_udev_subsystem (FuPlugin *self, const gchar *subsystem)
{
FuPluginPrivate *priv = GET_PRIVATE (self);
/* see https://github.com/fwupd/fwupd/issues/1121 for more details */
if (g_strcmp0 (subsystem, "drm_dp_aux_dev") == 0) {
g_autoptr(GError) error = NULL;
if (!fu_plugin_check_amdgpu_dpaux (self, &error)) {
g_warning ("failed to add subsystem: %s", error->message);
fu_plugin_add_flag (self, FWUPD_PLUGIN_FLAG_DISABLED);
fu_plugin_add_flag (self, FWUPD_PLUGIN_FLAG_KERNEL_TOO_OLD);
return;
}
}
/* proxy */
fu_context_add_udev_subsystem (priv->ctx, subsystem);
}
/**
* fu_plugin_add_firmware_gtype:
* @self: a #FuPlugin

View File

@ -116,6 +116,8 @@ void fu_plugin_add_device_gtype (FuPlugin *self,
void fu_plugin_add_firmware_gtype (FuPlugin *self,
const gchar *id,
GType gtype);
void fu_plugin_add_udev_subsystem (FuPlugin *self,
const gchar *subsystem);
gpointer fu_plugin_cache_lookup (FuPlugin *self,
const gchar *id);
void fu_plugin_cache_remove (FuPlugin *self,

View File

@ -834,6 +834,7 @@ LIBFWUPDPLUGIN_1.6.2 {
fu_i2c_device_read_full;
fu_i2c_device_set_bus_number;
fu_i2c_device_write_full;
fu_plugin_add_udev_subsystem;
fu_udev_device_get_children_with_subsystem;
fu_udev_device_set_dev;
local: *;

View File

@ -13,8 +13,7 @@
void
fu_plugin_init (FuPlugin *plugin)
{
FuContext *ctx = fu_plugin_get_context (plugin);
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_udev_subsystem (ctx, "block");
fu_plugin_add_udev_subsystem (plugin, "block");
fu_plugin_add_device_gtype (plugin, FU_TYPE_ATA_DEVICE);
}

View File

@ -17,9 +17,8 @@
void
fu_plugin_init (FuPlugin *plugin)
{
FuContext *ctx = fu_plugin_get_context (plugin);
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_udev_subsystem (ctx, "pci");
fu_plugin_add_udev_subsystem (plugin, "pci");
fu_plugin_add_device_gtype (plugin, FU_TYPE_BCM57XX_DEVICE);
fu_plugin_add_firmware_gtype (plugin, NULL, FU_TYPE_BCM57XX_FIRMWARE);
fu_plugin_add_firmware_gtype (plugin, NULL, FU_TYPE_BCM57XX_DICT_IMAGE);

View File

@ -31,8 +31,8 @@ fu_plugin_init (FuPlugin *plugin)
{
FuContext *ctx = fu_plugin_get_context (plugin);
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_udev_subsystem (ctx, "i2c-dev");
fu_context_add_udev_subsystem (ctx, "hidraw");
fu_plugin_add_udev_subsystem (plugin, "i2c-dev");
fu_plugin_add_udev_subsystem (plugin, "hidraw");
fu_plugin_add_firmware_gtype (plugin, NULL, FU_TYPE_ELANTP_FIRMWARE);
fu_context_add_quirk_key (ctx, "ElantpI2cTargetAddress");
fu_context_add_quirk_key (ctx, "ElantpIapPassword");

View File

@ -13,8 +13,7 @@
void
fu_plugin_init (FuPlugin *plugin)
{
FuContext *ctx = fu_plugin_get_context (plugin);
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_udev_subsystem (ctx, "block");
fu_plugin_add_udev_subsystem (plugin, "block");
fu_plugin_add_device_gtype (plugin, FU_TYPE_EMMC_DEVICE);
}

View File

@ -42,7 +42,7 @@ fu_plugin_init (FuPlugin *plugin)
fu_plugin_add_rule (plugin, FU_PLUGIN_RULE_CONFLICTS, "coreboot"); /* obsoleted */
fu_plugin_add_flag (plugin, FWUPD_PLUGIN_FLAG_REQUIRE_HWID);
fu_plugin_add_device_gtype (plugin, FU_TYPE_FLASHROM_LSPCON_I2C_SPI_DEVICE);
fu_context_add_udev_subsystem (ctx, "i2c");
fu_plugin_add_udev_subsystem (plugin, "i2c");
fu_context_add_quirk_key (ctx, "FlashromProgrammer");
}

View File

@ -29,7 +29,7 @@ fu_plugin_init (FuPlugin *plugin)
fu_plugin_add_firmware_gtype (plugin, NULL, FU_TYPE_EFI_FIRMWARE_VOLUME);
fu_plugin_add_firmware_gtype (plugin, NULL, FU_TYPE_IFD_BIOS);
fu_plugin_add_firmware_gtype (plugin, NULL, FU_TYPE_IFD_FIRMWARE);
fu_context_add_udev_subsystem (ctx, "pci");
fu_plugin_add_udev_subsystem (plugin, "pci");
fu_context_add_quirk_key (ctx, "IntelSpiKind");
fu_context_add_quirk_key (ctx, "IntelSpiBar");
fu_context_add_quirk_key (ctx, "IntelSpiBarProxy");

View File

@ -15,10 +15,9 @@ struct FuPluginData {
void
fu_plugin_init (FuPlugin *plugin)
{
FuContext *ctx = fu_plugin_get_context (plugin);
fu_plugin_alloc_data (plugin, sizeof (FuPluginData));
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_udev_subsystem (ctx, "iommu");
fu_plugin_add_udev_subsystem (plugin, "iommu");
}
gboolean

View File

@ -31,9 +31,8 @@ fu_plugin_startup (FuPlugin *plugin, GError **error)
void
fu_plugin_init (FuPlugin *plugin)
{
FuContext *ctx = fu_plugin_get_context (plugin);
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_udev_subsystem (ctx, "hidraw");
fu_plugin_add_udev_subsystem (plugin, "hidraw");
fu_plugin_add_rule (plugin, FU_PLUGIN_RULE_CONFLICTS, "unifying");
fu_plugin_add_device_gtype (plugin, FU_TYPE_UNIFYING_BOOTLOADER_NORDIC);
fu_plugin_add_device_gtype (plugin, FU_TYPE_UNIFYING_BOOTLOADER_TEXAS);

View File

@ -42,10 +42,9 @@ struct FuPluginData {
void
fu_plugin_init (FuPlugin *plugin)
{
FuContext *ctx = fu_plugin_get_context (plugin);
fu_plugin_alloc_data (plugin, sizeof (FuPluginData));
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_udev_subsystem (ctx, "msr");
fu_plugin_add_udev_subsystem (plugin, "msr");
}
gboolean

View File

@ -13,8 +13,7 @@
void
fu_plugin_init (FuPlugin *plugin)
{
FuContext *ctx = fu_plugin_get_context (plugin);
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_udev_subsystem (ctx, "nvme");
fu_plugin_add_udev_subsystem (plugin, "nvme");
fu_plugin_add_device_gtype (plugin, FU_TYPE_NVME_DEVICE);
}

View File

@ -13,9 +13,8 @@
void
fu_plugin_init (FuPlugin *plugin)
{
FuContext *ctx = fu_plugin_get_context (plugin);
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_udev_subsystem (ctx, "pci");
fu_plugin_add_udev_subsystem (plugin, "pci");
fu_plugin_add_rule (plugin, FU_PLUGIN_RULE_CONFLICTS, "udev");
fu_plugin_add_device_gtype (plugin, FU_TYPE_OPTIONROM_DEVICE);
}

View File

@ -24,7 +24,7 @@ fu_plugin_init (FuPlugin *plugin)
FuContext *ctx = fu_plugin_get_context (plugin);
FuPluginData *priv = fu_plugin_alloc_data (plugin, sizeof (FuPluginData));
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_udev_subsystem (ctx, "pci");
fu_plugin_add_udev_subsystem (plugin, "pci");
fu_context_add_quirk_key (ctx, "PciBcrAddr");
/* this is true except for some Atoms */

View File

@ -51,10 +51,9 @@ fu_mei_hfsts_to_string (FuPlugin *plugin, guint idt, GString *str)
void
fu_plugin_init (FuPlugin *plugin)
{
FuContext *ctx = fu_plugin_get_context (plugin);
fu_plugin_alloc_data (plugin, sizeof (FuPluginData));
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_udev_subsystem (ctx, "pci");
fu_plugin_add_udev_subsystem (plugin, "pci");
}
static FuMeiFamily

View File

@ -15,9 +15,8 @@
void
fu_plugin_init (FuPlugin *plugin)
{
FuContext *ctx = fu_plugin_get_context (plugin);
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_udev_subsystem (ctx, "hidraw");
fu_plugin_add_udev_subsystem (plugin, "hidraw");
fu_plugin_add_device_gtype (plugin, FU_TYPE_PXI_BLE_DEVICE);
fu_plugin_add_device_gtype (plugin, FU_TYPE_PXI_RECEIVER_DEVICE);
fu_plugin_add_firmware_gtype (plugin, "pixart", FU_TYPE_PXI_FIRMWARE);

View File

@ -18,7 +18,7 @@ fu_plugin_init (FuPlugin *plugin)
FuContext *ctx = fu_plugin_get_context (plugin);
fu_plugin_alloc_data (plugin, sizeof (FuPluginData));
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_udev_subsystem (ctx, "platform-integrity");
fu_plugin_add_udev_subsystem (plugin, "platform-integrity");
}
void

View File

@ -16,6 +16,6 @@ fu_plugin_init (FuPlugin *plugin)
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_quirk_key (ctx, "RealtekMstDpAuxName");
fu_context_add_udev_subsystem (ctx, "i2c");
fu_plugin_add_udev_subsystem (plugin, "i2c");
fu_plugin_add_device_gtype (plugin, FU_TYPE_REALTEK_MST_DEVICE);
}

View File

@ -21,37 +21,6 @@ struct FuPluginData {
guint drm_changed_id;
};
/* see https://github.com/fwupd/fwupd/issues/1121 for more details */
static gboolean
fu_synaptics_mst_check_amdgpu_safe (FuPlugin *plugin, GError **error)
{
gsize bufsz = 0;
g_autofree gchar *minimum_kernel = NULL;
g_autofree gchar *buf = NULL;
g_auto(GStrv) lines = NULL;
minimum_kernel = fu_plugin_get_config_value (plugin, "MinimumAmdGpuKernelVersion");
if (minimum_kernel == NULL) {
g_debug ("Ignoring kernel safety checks");
return TRUE;
}
/* no module support in the kernel, we can't test for amdgpu module */
if (!g_file_test ("/proc/modules", G_FILE_TEST_EXISTS))
return TRUE;
if (!g_file_get_contents ("/proc/modules", &buf, &bufsz, error))
return FALSE;
lines = g_strsplit (buf, "\n", -1);
for (guint i = 0; lines[i] != NULL; i++) {
if (g_str_has_prefix (lines[i], "amdgpu "))
return fu_common_check_kernel_version (minimum_kernel, error);
}
return TRUE;
}
static void
fu_plugin_synaptics_mst_device_rescan (FuPlugin *plugin, FuDevice *device)
{
@ -145,12 +114,6 @@ fu_plugin_backend_device_added (FuPlugin *plugin, FuDevice *device, GError **err
return TRUE;
}
gboolean
fu_plugin_startup (FuPlugin *plugin, GError **error)
{
return fu_synaptics_mst_check_amdgpu_safe (plugin, error);
}
gboolean
fu_plugin_update (FuPlugin *plugin,
FuDevice *device,
@ -178,8 +141,8 @@ fu_plugin_init (FuPlugin *plugin)
priv->devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_udev_subsystem (ctx, "drm"); /* used for uevent only */
fu_context_add_udev_subsystem (ctx, "drm_dp_aux_dev");
fu_plugin_add_udev_subsystem (plugin, "drm"); /* used for uevent only */
fu_plugin_add_udev_subsystem (plugin, "drm_dp_aux_dev");
fu_plugin_add_firmware_gtype (plugin, NULL, FU_TYPE_SYNAPTICS_MST_FIRMWARE);
fu_context_add_quirk_key (ctx, "SynapticsMstDeviceKind");
}

View File

@ -36,10 +36,6 @@ shared_module('fu_plugin_synaptics_mst',
],
)
install_data(['synaptics_mst.conf'],
install_dir: join_paths(sysconfdir, 'fwupd')
)
if get_option('tests')
testdatadirs = environment()
testdatadirs.set('G_TEST_SRCDIR', meson.current_source_dir())

View File

@ -1,5 +0,0 @@
[synaptics_mst]
# Minimum kernel version to allow use of this plugin on amdgpu
# It's important that all backports from this kernel have been
# made if using an older kernel
MinimumAmdGpuKernelVersion=5.2.0

View File

@ -15,10 +15,9 @@
void
fu_plugin_init (FuPlugin *plugin)
{
FuContext *ctx = fu_plugin_get_context (plugin);
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_udev_subsystem (ctx, "hidraw");
fu_context_add_udev_subsystem (ctx, "serio");
fu_plugin_add_udev_subsystem (plugin, "hidraw");
fu_plugin_add_udev_subsystem (plugin, "serio");
fu_plugin_add_device_gtype (plugin, FU_TYPE_SYNAPTICS_RMI_HID_DEVICE);
fu_plugin_add_device_gtype (plugin, FU_TYPE_SYNAPTICS_RMI_PS2_DEVICE);
fu_plugin_add_firmware_gtype (plugin, NULL, FU_TYPE_SYNAPTICS_RMI_FIRMWARE);

View File

@ -55,9 +55,8 @@ fu_plugin_device_registered (FuPlugin *plugin, FuDevice *device)
void
fu_plugin_init (FuPlugin *plugin)
{
FuContext *ctx = fu_plugin_get_context (plugin);
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_udev_subsystem (ctx, "thunderbolt");
fu_plugin_add_udev_subsystem (plugin, "thunderbolt");
fu_plugin_add_device_gtype (plugin, FU_TYPE_THUNDERBOLT_DEVICE);
fu_plugin_add_firmware_gtype (plugin, NULL, FU_TYPE_THUNDERBOLT_FIRMWARE);
fu_plugin_add_firmware_gtype (plugin, NULL, FU_TYPE_THUNDERBOLT_FIRMWARE_UPDATE);

View File

@ -18,10 +18,9 @@ struct FuPluginData {
void
fu_plugin_init (FuPlugin *plugin)
{
FuContext *ctx = fu_plugin_get_context (plugin);
fu_plugin_alloc_data (plugin, sizeof (FuPluginData));
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_context_add_udev_subsystem (ctx, "tpm");
fu_plugin_add_udev_subsystem (plugin, "tpm");
fu_plugin_add_device_gtype (plugin, FU_TYPE_TPM_DEVICE);
}

View File

@ -19,7 +19,7 @@ fu_plugin_init (FuPlugin *plugin)
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_plugin_add_device_gtype (plugin, FU_TYPE_WACOM_AES_DEVICE);
fu_plugin_add_device_gtype (plugin, FU_TYPE_WACOM_EMR_DEVICE);
fu_context_add_udev_subsystem (ctx, "hidraw");
fu_plugin_add_udev_subsystem (plugin, "hidraw");
fu_context_add_quirk_key (ctx, "WacomI2cFlashBlockSize");
fu_context_add_quirk_key (ctx, "WacomI2cFlashBaseAddr");
fu_context_add_quirk_key (ctx, "WacomI2cFlashSize");

View File

@ -1457,6 +1457,10 @@ fu_util_plugin_flag_to_string (FwupdPluginFlags plugin_flag)
/* TRANSLATORS: Failed to open plugin, hey Arch users */
return _("Plugin dependencies missing");
}
if (plugin_flag == FWUPD_PLUGIN_FLAG_KERNEL_TOO_OLD) {
/* TRANSLATORS: The kernel does not support this plugin */
return _("Running kernel is too old");
}
/* fall back for unknown types */
return fwupd_plugin_flag_to_string (plugin_flag);
@ -1483,6 +1487,7 @@ fu_util_plugin_flag_to_cli_text (FwupdPluginFlags plugin_flag)
case FWUPD_PLUGIN_FLAG_UNLOCK_REQUIRED:
case FWUPD_PLUGIN_FLAG_EFIVAR_NOT_MOUNTED:
case FWUPD_PLUGIN_FLAG_ESP_NOT_FOUND:
case FWUPD_PLUGIN_FLAG_KERNEL_TOO_OLD:
return fu_util_term_format (fu_util_plugin_flag_to_string (plugin_flag),
FU_UTIL_TERM_COLOR_RED);
default: