Commit 59833696 authored by Hans de Goede's avatar Hans de Goede Committed by Joerg Roedel

iommu/vt-d: dmar: replace WARN_TAINT with pr_warn + add_taint

Quoting from the comment describing the WARN functions in
include/asm-generic/bug.h:

 * WARN(), WARN_ON(), WARN_ON_ONCE, and so on can be used to report
 * significant kernel issues that need prompt attention if they should ever
 * appear at runtime.
 *
 * Do not use these macros when checking for invalid external inputs

The (buggy) firmware tables which the dmar code was calling WARN_TAINT
for really are invalid external inputs. They are not under the kernel's
control and the issues in them cannot be fixed by a kernel update.
So logging a backtrace, which invites bug reports to be filed about this,
is not helpful.

Some distros, e.g. Fedora, have tools watching for the kernel backtraces
logged by the WARN macros and offer the user an option to file a bug for
this when these are encountered. The WARN_TAINT in warn_invalid_dmar()
+ another iommu WARN_TAINT, addressed in another patch, have lead to over
a 100 bugs being filed this way.

This commit replaces the WARN_TAINT("...") calls, with
pr_warn(FW_BUG "...") + add_taint(TAINT_FIRMWARE_WORKAROUND, ...) calls
avoiding the backtrace and thus also avoiding bug-reports being filed
about this against the kernel.

Fixes: fd0c8894 ("intel-iommu: Set a more specific taint flag for invalid BIOS DMAR tables")
Fixes: e625b4a9 ("iommu/vt-d: Parse ANDD records")
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
Acked-by: default avatarLu Baolu <baolu.lu@linux.intel.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20200309140138.3753-2-hdegoede@redhat.com
BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1564895
parent f5152416
...@@ -441,12 +441,13 @@ static int __init dmar_parse_one_andd(struct acpi_dmar_header *header, ...@@ -441,12 +441,13 @@ static int __init dmar_parse_one_andd(struct acpi_dmar_header *header,
/* Check for NUL termination within the designated length */ /* Check for NUL termination within the designated length */
if (strnlen(andd->device_name, header->length - 8) == header->length - 8) { if (strnlen(andd->device_name, header->length - 8) == header->length - 8) {
WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND, pr_warn(FW_BUG
"Your BIOS is broken; ANDD object name is not NUL-terminated\n" "Your BIOS is broken; ANDD object name is not NUL-terminated\n"
"BIOS vendor: %s; Ver: %s; Product Version: %s\n", "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
dmi_get_system_info(DMI_BIOS_VENDOR), dmi_get_system_info(DMI_BIOS_VENDOR),
dmi_get_system_info(DMI_BIOS_VERSION), dmi_get_system_info(DMI_BIOS_VERSION),
dmi_get_system_info(DMI_PRODUCT_VERSION)); dmi_get_system_info(DMI_PRODUCT_VERSION));
add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
return -EINVAL; return -EINVAL;
} }
pr_info("ANDD device: %x name: %s\n", andd->device_number, pr_info("ANDD device: %x name: %s\n", andd->device_number,
...@@ -472,14 +473,14 @@ static int dmar_parse_one_rhsa(struct acpi_dmar_header *header, void *arg) ...@@ -472,14 +473,14 @@ static int dmar_parse_one_rhsa(struct acpi_dmar_header *header, void *arg)
return 0; return 0;
} }
} }
WARN_TAINT( pr_warn(FW_BUG
1, TAINT_FIRMWARE_WORKAROUND,
"Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n" "Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n"
"BIOS vendor: %s; Ver: %s; Product Version: %s\n", "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
drhd->reg_base_addr, drhd->reg_base_addr,
dmi_get_system_info(DMI_BIOS_VENDOR), dmi_get_system_info(DMI_BIOS_VENDOR),
dmi_get_system_info(DMI_BIOS_VERSION), dmi_get_system_info(DMI_BIOS_VERSION),
dmi_get_system_info(DMI_PRODUCT_VERSION)); dmi_get_system_info(DMI_PRODUCT_VERSION));
add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
return 0; return 0;
} }
...@@ -828,14 +829,14 @@ int __init dmar_table_init(void) ...@@ -828,14 +829,14 @@ int __init dmar_table_init(void)
static void warn_invalid_dmar(u64 addr, const char *message) static void warn_invalid_dmar(u64 addr, const char *message)
{ {
WARN_TAINT_ONCE( pr_warn_once(FW_BUG
1, TAINT_FIRMWARE_WORKAROUND,
"Your BIOS is broken; DMAR reported at address %llx%s!\n" "Your BIOS is broken; DMAR reported at address %llx%s!\n"
"BIOS vendor: %s; Ver: %s; Product Version: %s\n", "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
addr, message, addr, message,
dmi_get_system_info(DMI_BIOS_VENDOR), dmi_get_system_info(DMI_BIOS_VENDOR),
dmi_get_system_info(DMI_BIOS_VERSION), dmi_get_system_info(DMI_BIOS_VERSION),
dmi_get_system_info(DMI_PRODUCT_VERSION)); dmi_get_system_info(DMI_PRODUCT_VERSION));
add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
} }
static int __ref static int __ref
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment