Centos-kernel-stream-9/kernel/rh_messages.c

416 lines
13 KiB
C
Raw Normal View History

/*
* The following functions are used by Red Hat to indicate to users that
* hardware and drivers are unsupported, or have limited support in RHEL major
* and minor releases. These functions output loud warning messages to the end
* user and should be USED WITH CAUTION.
*
* Any use of these functions _MUST_ be documented in the RHEL Release Notes,
* and have approval of management.
*
* Generally, the process of disabling a driver or device in RHEL requires the
* driver or device to be marked as 'deprecated' in all existing releases, and
* then either 'unmaintained' or 'disabled' in a future release.
*
* In general, deprecated and unmaintained drivers continue to receive security
* related fixes until they are disabled.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include "rh_messages.h"
/**
* mark_hardware_unmaintained() - Mark hardware as unmaintained.
* @driver_name: driver name
* @fmt: format for device description
* @...: args for device description
*
* Called to notify users that the device will no longer be tested on a routine
* basis and driver code associated with this device is no longer being updated.
* Red Hat may, at their own discretion, fix security-related and critical
* issues. Support for this device will be disabled in a future major release
* and users deploying this device should plan to replace the device in
* production systems.
*
* This function should be used when the driver's usage can be tied to a
* specific hardware device. For example, a network device driver loading on a
* specific device that is no longer maintained by the manufacturer.
*
* Reserved for Internal Red Hat use only.
*/
void __maybe_unused mark_hardware_unmaintained(const char *driver_name, char *fmt, ...)
{
char device_description[DEV_DESC_LEN];
va_list args;
va_start(args, fmt);
vsnprintf(device_description, DEV_DESC_LEN, fmt, args);
pr_crit(RH_UNMAINT_HW, driver_name, device_description);
va_end(args);
}
EXPORT_SYMBOL(mark_hardware_unmaintained);
/**
* mark_hardware_deprecated() - Mark hardware as deprecated.
* @driver_name: driver name
* @fmt: format for device description
* @...: args for device description
*
* Called to notify users that support for the device is planned to be
* unmaintained in a future major release, and will eventually be disabled in a
* future major release. This device should not be used in new production
* environments and users should replace the device in production systems.
*
* This function should be used when the driver's usage can be tied to a
* specific hardware device. For example, a network device driver loading on a
* specific device that is no longer maintained by the manufacturer.
*
* Reserved for Internal Red Hat use only.
*/
void __maybe_unused mark_hardware_deprecated(const char *driver_name, char *fmt, ...)
{
char device_description[DEV_DESC_LEN];
va_list args;
va_start(args, fmt);
vsnprintf(device_description, DEV_DESC_LEN, fmt, args);
pr_crit(RH_DEPRECATED_HW, driver_name, device_description);
va_end(args);
}
/**
* mark_hardware_disabled() - Mark a driver as removed.
* @driver_name: driver name
* @fmt: format for device description
* @...: args for device description
*
* Called to notify users that a device's support has been completely disabled
* and no future support updates will occur. This device cannot be used in new
* production environments, and users must replace the device in production
* systems.
*
* This function should be used when the driver's usage can be tied to a
* specific hardware device. For example, a network device driver loading on a
* specific device that is no longer maintained by the manufacturer.
*
* Reserved for Internal Red Hat use only.
*/
static void __maybe_unused mark_hardware_disabled(const char *driver_name, char *fmt, ...)
{
char device_description[DEV_DESC_LEN];
va_list args;
va_start(args, fmt);
vsnprintf(device_description, DEV_DESC_LEN, fmt, args);
pr_crit(RH_DISABLED_HW, driver_name, device_description);
va_end(args);
}
#ifdef CONFIG_PCI
/**
* pci_hw_deprecated() - Mark a PCI device deprecated.
* @dev: the PCI device structure to match against
*
* Called to check if this @dev is in the list of deprecated devices.
*
* Reserved for Internal Red Hat use only.
*/
static void __maybe_unused pci_hw_deprecated(struct pci_dev *dev)
{
const struct pci_device_id *ret = pci_match_id(rh_deprecated_pci_devices, dev);
if (!ret)
return;
mark_hardware_deprecated(dev_driver_string(&dev->dev), "%04X:%04X @ %s",
dev->vendor, dev->device, pci_name(dev));
}
/**
* pci_hw_unmaintained() - Mark a PCI device unmaintained.
* @dev: the PCI device structure to match against
*
* Called to check if this @dev is in the list of unmaintained devices.
*
* Reserved for Internal Red Hat use only.
*/
static void pci_hw_unmaintained(struct pci_dev *dev)
{
const struct pci_device_id *ret = pci_match_id(rh_unmaintained_pci_devices, dev);
if (!ret)
return;
mark_hardware_unmaintained(dev_driver_string(&dev->dev), "%04X:%04X @ %s",
dev->vendor, dev->device, pci_name(dev));
}
/**
* pci_hw_disabled() - Mark a PCI device disabled.
* @dev: the PCI device structure to match against
*
* Called to check if this @dev is in the list of disabled devices.
*
* Reserved for Internal Red Hat use only.
*/
static bool __maybe_unused pci_hw_disabled(struct pci_dev *dev)
{
const struct pci_device_id *ret = pci_match_id(rh_disabled_pci_devices, dev);
if (!ret)
return false;
mark_hardware_disabled(dev_driver_string(&dev->dev), "%04X:%04X @ %s",
dev->vendor, dev->device, pci_name(dev));
return true;
}
#endif
/**
* driver_unmaintained() - check to see if a driver is unmaintained
* @module_name: module name
*
* Called to notify users that a driver will no longer be tested on a routine
* basis and the driver code is no longer being updated. Red Hat may fix
* security-related and critical issues. Support for this driver will be
* disabled in a future major release, and users should replace any affected
* devices in production systems.
*
* This function should be used when a driver's usage cannot be tied to a
* specific hardware device. For example, a network virtual interface driver
* or a higher level storage layer driver that is no longer maintained
* upstream.
*
* Reserved for Internal Red Hat use only.
*/
static void __maybe_unused driver_unmaintained(const char* module_name)
{
int i = 0;
while (rh_unmaintained_drivers[i]) {
if (strcmp(rh_unmaintained_drivers[i], module_name) == 0) {
pr_crit(RH_UNMAINT_DR, module_name);
return;
}
i++;
}
}
/**
* driver_deprecated() - check to see if a driver is deprecated
* @driver_name: module name
*
* Called to notify users that support for this driver is planned to be
* unmaintained in a future major release, and will eventually be disabled in a
* future major release. This driver should not be used in new production
* environments and users should replace any affected devices in production
* systems.
*
* This function should be used when a driver's usage cannot be tied to a
* specific hardware device. For example, a network virtual interface driver
* or a higher level storage layer driver that is no longer maintained
* upstream.
*
* Reserved for Internal Red Hat use only.
*/
static void __maybe_unused driver_deprecated(const char* module_name)
{
int i = 0;
while (rh_deprecated_drivers[i]) {
if (strcmp(rh_deprecated_drivers[i], module_name) == 0) {
pr_crit(RH_DEPRECATED_DR, module_name);
return;
}
i++;
}
}
/* There is no driver_disabled() function. Disabled drivers are configured off ;). */
/**
* init_fn_unmaintained - check to see if a built-in driver is unmaintained.
* @fn_name: module's module_init function name
*
* Called to notify users that a built-in driver will no longer be tested on a routine
* basis and the built-in driver code is no longer being updated. Red Hat may fix
* security-related and critical issues. Support for this built-in driver will be
* disabled in a future major release, and users should replace any affected
* devices in production systems.
*
* This function should be used when a built-in driver's usage cannot be tied
* to a specific hardware device. For example, a network virtual interface
* driver or a higher level storage layer driver that is no longer maintained
* upstream.
*
* Reserved for Internal Red Hat use only.
*/
static void __maybe_unused init_fn_unmaintained(char* fn_name)
{
int i = 0;
while (rh_unmaintained_init_fns[i]) {
if (strcmp(rh_unmaintained_init_fns[i], fn_name) == 0) {
pr_crit(RH_UNMAINT_DR, fn_name);
return;
}
i++;
}
}
/**
* init_fn_deprecated() - check to see if a built-in driver is deprecated
* @fn_name: module's module_init function name
*
* Called to notify users that support for this built-in driver is planned to be
* unmaintained in a future major release, and will eventually be disabled in a
* future major release. This driver should not be used in new production
* environments and users should replace any affected devices in production
* systems.
*
* This function should be used when a built-in driver's usage cannot be tied
* to a specific hardware device. For example, a network virtual interface
* driver or a higher level storage layer driver that is no longer maintained
* upstream.
*
* Reserved for Internal Red Hat use only.
*/
static void __maybe_unused init_fn_deprecated(char* fn_name)
{
int i = 0;
while (rh_deprecated_init_fns[i]) {
if (strcmp(rh_deprecated_init_fns[i], fn_name) == 0) {
pr_crit(RH_DEPRECATED_DR, fn_name);
return;
}
i++;
}
}
/**
* mark_tech_preview() - Mark driver or kernel subsystem as 'Tech Preview'
* @msg: Driver or kernel subsystem name
*
* Called to minimize the support status of a new driver. This does TAINT the
* kernel. Calling this function indicates that the driver or subsystem has
* had limited testing and is not marked for full support within this RHEL
* minor release. The next RHEL minor release may contain full support for
* this driver. Red Hat does not guarantee that bugs reported against this
* driver or subsystem will be resolved.
*
* Reserved for Internal Red Hat use only.
*/
void __maybe_unused mark_tech_preview(const char *msg, struct module *mod)
{
const char *str = NULL;
if (msg)
str = msg;
#ifdef CONFIG_MODULES
else if (mod)
str = mod->name;
#endif
pr_warn(RH_TECH_PREVIEW, (str ? str : "kernel"));
add_taint(TAINT_AUX, LOCKDEP_STILL_OK);
#ifdef CONFIG_MODULES
if (mod)
mod->taints |= (1U << TAINT_AUX);
#endif
}
EXPORT_SYMBOL(mark_tech_preview);
/**
* mark_partner_supported() - Mark driver or kernel subsystem as 'Partner Supported'
* @msg: Driver or kernel subsystem name
*
* Called to minimize the support status of a new driver. This does TAINT the
* kernel. Calling this function indicates that the driver or subsystem
* is not supported directly by Red Hat but by a partner engineer.
*
* Reserved for Internal Red Hat use only.
*/
void __maybe_unused mark_partner_supported(const char *msg, struct module *mod)
{
const char *str = NULL;
if (msg)
str = msg;
#ifdef CONFIG_MODULES
else if (mod)
str = mod->name;
#endif
pr_warn(RH_PARTNER_SUPPORTED, (str ? str : "kernel"));
add_taint(TAINT_PARTNER_SUPPORTED, LOCKDEP_STILL_OK);
#ifdef CONFIG_MODULES
if (mod)
mod->taints |= (1U << TAINT_PARTNER_SUPPORTED);
#endif
}
EXPORT_SYMBOL(mark_partner_supported);
/*
*
* Functions called by 'main' kernel code.
*
*/
#ifdef CONFIG_PCI
/**
* pci_rh_check_status - checks the status of a PCI device.
* @pci_dev: PCI device to be examined
*
* This function is called by the PCI driver subsystem to check the status of a
* PCI device.
*
* This function returns true if the PCI device is disabled, and false otherwise.
*
* Reserved for Internal Red Hat use only.
*/
bool __maybe_unused pci_rh_check_status(struct pci_dev *pci_dev)
{
if (pci_dev->driver->driver.owner != NULL) {
if (!test_bit(TAINT_OOT_MODULE, &pci_dev->driver->driver.owner->taints)) {
pci_hw_unmaintained(pci_dev);
pci_hw_deprecated(pci_dev);
return pci_hw_disabled(pci_dev);
}
}
return false;
}
#endif
/** module_rh_check_status - checks the status of a module.
* @module_name: Name of module to be examined
*
* This function is called by the module loading code to check the status of a
* module.
*
* Reserved for Internal Red Hat use only.
*/
void __maybe_unused module_rh_check_status(const char * module_name)
{
driver_unmaintained(module_name);
driver_deprecated(module_name);
}
/**
* init_rh_check_status - checks the status of a built-in module.
* @fn_name: init function of module to be examined
*
* This function is called by the init code to check the status of a built-in module.
* When a module is built-in, the module_init() function is converted into an initcall.
* The initcall is the called during boot with the other system initcalls.
*
* Reserved for Internal Red Hat use only.
*/
void __maybe_unused init_rh_check_status(char *fn_name)
{
init_fn_deprecated(fn_name);
init_fn_unmaintained(fn_name);
}