Unverified Commit f299a23f authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!13275 CVE-2024-46698

Merge Pull Request from: @ci-robot 
 
PR sync from: dinglongwei <dinglongwei1@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/ROPKVTSMNL3XQADL5VNFXEF5O7A25Y3G/ 
CVE-2024-46698

Alex Deucher (1):
  video/aperture: optionally match the device in sysfb_disable()

Dan Carpenter (1):
  firmware/sysfb: fix an error code in sysfb_init()

Javier Martinez Canillas (1):
  of/platform: Disable sysfb if a simple-framebuffer node is found

Thomas Zimmermann (3):
  firmware/sysfb: Set firmware-framebuffer parent device
  firmware/sysfb: Create firmware device only for enabled PCI devices
  firmware: sysfb: Fix reference count of sysfb parent device


-- 
2.17.1
 
https://gitee.com/src-openeuler/kernel/issues/IAR4KI 
 
Link:https://gitee.com/openeuler/kernel/pulls/13275

 

Reviewed-by: default avatarWeilong Chen <chenweilong@huawei.com>
Signed-off-by: default avatarZhang Peng <zhangpeng362@huawei.com>
parents 8a039651 26580a96
Loading
Loading
Loading
Loading
+67 −7
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/pci.h>
#include <linux/platform_data/simplefb.h>
#include <linux/platform_device.h>
#include <linux/screen_info.h>
@@ -38,6 +39,8 @@ static struct platform_device *pd;
static DEFINE_MUTEX(disable_lock);
static bool disabled;

static struct device *sysfb_parent_dev(const struct screen_info *si);

static bool sysfb_unregister(void)
{
	if (IS_ERR_OR_NULL(pd))
@@ -51,6 +54,7 @@ static bool sysfb_unregister(void)

/**
 * sysfb_disable() - disable the Generic System Framebuffers support
 * @dev:	the device to check if non-NULL
 *
 * This disables the registration of system framebuffer devices that match the
 * generic drivers that make use of the system framebuffer set up by firmware.
@@ -60,18 +64,64 @@ static bool sysfb_unregister(void)
 * Context: The function can sleep. A @disable_lock mutex is acquired to serialize
 *          against sysfb_init(), that registers a system framebuffer device.
 */
void sysfb_disable(void)
void sysfb_disable(struct device *dev)
{
	struct screen_info *si = &screen_info;

	mutex_lock(&disable_lock);
	if (!dev || dev == sysfb_parent_dev(si)) {
		sysfb_unregister();
		disabled = true;
	}
	mutex_unlock(&disable_lock);
}
EXPORT_SYMBOL_GPL(sysfb_disable);

#if defined(CONFIG_PCI)
static bool sysfb_pci_dev_is_enabled(struct pci_dev *pdev)
{
	/*
	 * TODO: Try to integrate this code into the PCI subsystem
	 */
	int ret;
	u16 command;

	ret = pci_read_config_word(pdev, PCI_COMMAND, &command);
	if (ret != PCIBIOS_SUCCESSFUL)
		return false;
	if (!(command & PCI_COMMAND_MEMORY))
		return false;
	return true;
}
#else
static bool sysfb_pci_dev_is_enabled(struct pci_dev *pdev)
{
	return false;
}
#endif

static struct device *sysfb_parent_dev(const struct screen_info *si)
{
	struct pci_dev *pdev;

	pdev = screen_info_pci_dev(si);
	if (IS_ERR(pdev)) {
		return ERR_CAST(pdev);
	} else if (pdev) {
		if (!sysfb_pci_dev_is_enabled(pdev)) {
			pci_dev_put(pdev);
			return ERR_PTR(-ENODEV);
		}
		return &pdev->dev;
	}

	return NULL;
}

static __init int sysfb_init(void)
{
	struct screen_info *si = &screen_info;
	struct device *parent;
	struct simplefb_platform_data mode;
	const char *name;
	bool compatible;
@@ -85,12 +135,18 @@ static __init int sysfb_init(void)

	sysfb_apply_efi_quirks();

	parent = sysfb_parent_dev(si);
	if (IS_ERR(parent)) {
		ret = PTR_ERR(parent);
		goto unlock_mutex;
	}

	/* try to create a simple-framebuffer device */
	compatible = sysfb_parse_mode(si, &mode);
	if (compatible) {
		pd = sysfb_create_simplefb(si, &mode);
		pd = sysfb_create_simplefb(si, &mode, parent);
		if (!IS_ERR(pd))
			goto unlock_mutex;
			goto put_device;
	}

	/* if the FB is incompatible, create a legacy framebuffer device */
@@ -108,9 +164,11 @@ static __init int sysfb_init(void)
	pd = platform_device_alloc(name, 0);
	if (!pd) {
		ret = -ENOMEM;
		goto unlock_mutex;
		goto put_device;
	}

	pd->dev.parent = parent;

	sysfb_set_efifb_fwnode(pd);

	ret = platform_device_add_data(pd, si, sizeof(*si));
@@ -121,9 +179,11 @@ static __init int sysfb_init(void)
	if (ret)
		goto err;

	goto unlock_mutex;
	goto put_device;
err:
	platform_device_put(pd);
put_device:
	put_device(parent);
unlock_mutex:
	mutex_unlock(&disable_lock);
	return ret;
+4 −1
Original line number Diff line number Diff line
@@ -91,7 +91,8 @@ __init bool sysfb_parse_mode(const struct screen_info *si,
}

__init struct platform_device *sysfb_create_simplefb(const struct screen_info *si,
						     const struct simplefb_platform_data *mode)
						     const struct simplefb_platform_data *mode,
						     struct device *parent)
{
	struct platform_device *pd;
	struct resource res;
@@ -143,6 +144,8 @@ __init struct platform_device *sysfb_create_simplefb(const struct screen_info *s
	if (!pd)
		return ERR_PTR(-ENOMEM);

	pd->dev.parent = parent;

	sysfb_set_efifb_fwnode(pd);

	ret = platform_device_add_resources(pd, &res, 1);
+16 −2
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/sysfb.h>

#include "of_private.h"

@@ -621,8 +622,21 @@ static int __init of_platform_default_populate_init(void)
		}

		node = of_get_compatible_child(of_chosen, "simple-framebuffer");
		if (node) {
			/*
			 * Since a "simple-framebuffer" device is already added
			 * here, disable the Generic System Framebuffers (sysfb)
			 * to prevent it from registering another device for the
			 * system framebuffer later (e.g: using the screen_info
			 * data that may had been filled as well).
			 *
			 * This can happen for example on DT systems that do EFI
			 * booting and may provide a GOP handle to the EFI stub.
			 */
			sysfb_disable(NULL);
			of_platform_device_create(node, NULL, NULL);
			of_node_put(node);
		}

		/* Populate everything else. */
		of_platform_default_populate(NULL, NULL, NULL);
+3 −8
Original line number Diff line number Diff line
@@ -293,7 +293,7 @@ int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t si
	 * ask for this, so let's assume that a real driver for the display
	 * was already probed and prevent sysfb to register devices later.
	 */
	sysfb_disable();
	sysfb_disable(NULL);

	aperture_detach_devices(base, size);

@@ -346,15 +346,10 @@ EXPORT_SYMBOL(__aperture_remove_legacy_vga_devices);
 */
int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *name)
{
	bool primary = false;
	resource_size_t base, size;
	int bar, ret = 0;

	if (pdev == vga_default_device())
		primary = true;

	if (primary)
		sysfb_disable();
	sysfb_disable(&pdev->dev);

	for (bar = 0; bar < PCI_STD_NUM_BARS; ++bar) {
		if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
@@ -370,7 +365,7 @@ int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *na
	 * that consumes the VGA framebuffer I/O range. Remove this
	 * device as well.
	 */
	if (primary)
	if (pdev == vga_default_device())
		ret = __aperture_remove_legacy_vga_devices(pdev);

	return ret;
+6 −4
Original line number Diff line number Diff line
@@ -58,11 +58,11 @@ struct efifb_dmi_info {

#ifdef CONFIG_SYSFB

void sysfb_disable(void);
void sysfb_disable(struct device *dev);

#else /* CONFIG_SYSFB */

static inline void sysfb_disable(void)
static inline void sysfb_disable(struct device *dev)
{
}

@@ -91,7 +91,8 @@ static inline void sysfb_set_efifb_fwnode(struct platform_device *pd)
bool sysfb_parse_mode(const struct screen_info *si,
		      struct simplefb_platform_data *mode);
struct platform_device *sysfb_create_simplefb(const struct screen_info *si,
					      const struct simplefb_platform_data *mode);
					      const struct simplefb_platform_data *mode,
					      struct device *parent);

#else /* CONFIG_SYSFB_SIMPLE */

@@ -102,7 +103,8 @@ static inline bool sysfb_parse_mode(const struct screen_info *si,
}

static inline struct platform_device *sysfb_create_simplefb(const struct screen_info *si,
							    const struct simplefb_platform_data *mode)
							    const struct simplefb_platform_data *mode,
							    struct device *parent)
{
	return ERR_PTR(-EINVAL);
}