mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 16:54:21 +00:00 
			
		
		
		
	Driver core fixes for 5.9-rc5
Here are some small driver core and debugfs fixes for 5.9-rc5 Included in here are: - firmware loader memory leak fix - firmware loader testing fixes for non-EFI systems - device link locking fixes found by lockdep - kobject_del() bugfix that has been affecting some callers - debugfs minor fix All of these have been in linux-next for a while with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCX13Zhw8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ylfNQCfX4Bx9J1aLGr0/MOBwlXXEycChE0AmwQ9rXa7 u5Przdz+fMr1mLyNBaY5 =4kmo -----END PGP SIGNATURE----- Merge tag 'driver-core-5.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core Pull driver core fixes from Greg KH: "Here are some small driver core and debugfs fixes for 5.9-rc5 Included in here are: - firmware loader memory leak fix - firmware loader testing fixes for non-EFI systems - device link locking fixes found by lockdep - kobject_del() bugfix that has been affecting some callers - debugfs minor fix All of these have been in linux-next for a while with no reported issues" * tag 'driver-core-5.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: test_firmware: Test platform fw loading on non-EFI systems PM: <linux/device.h>: fix @em_pd kernel-doc warning kobject: Drop unneeded conditional in __kobject_del() driver core: Fix device_pm_lock() locking for device links MAINTAINERS: Add the security document to SECURITY CONTACT driver code: print symbolic error code debugfs: Fix module state check condition kobject: Restore old behaviour of kobject_del(NULL) firmware_loader: fix memory leak for paged buffer
This commit is contained in:
		
						commit
						20a7b6be05
					
				
					 9 changed files with 39 additions and 27 deletions
				
			
		|  | @ -15577,6 +15577,7 @@ F:	include/uapi/linux/sed* | |||
| SECURITY CONTACT | ||||
| M:	Security Officers <security@kernel.org> | ||||
| S:	Supported | ||||
| F:	Documentation/admin-guide/security-bugs.rst | ||||
| 
 | ||||
| SECURITY SUBSYSTEM | ||||
| M:	James Morris <jmorris@namei.org> | ||||
|  |  | |||
|  | @ -807,9 +807,7 @@ static void device_link_put_kref(struct device_link *link) | |||
| void device_link_del(struct device_link *link) | ||||
| { | ||||
| 	device_links_write_lock(); | ||||
| 	device_pm_lock(); | ||||
| 	device_link_put_kref(link); | ||||
| 	device_pm_unlock(); | ||||
| 	device_links_write_unlock(); | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(device_link_del); | ||||
|  | @ -830,7 +828,6 @@ void device_link_remove(void *consumer, struct device *supplier) | |||
| 		return; | ||||
| 
 | ||||
| 	device_links_write_lock(); | ||||
| 	device_pm_lock(); | ||||
| 
 | ||||
| 	list_for_each_entry(link, &supplier->links.consumers, s_node) { | ||||
| 		if (link->consumer == consumer) { | ||||
|  | @ -839,7 +836,6 @@ void device_link_remove(void *consumer, struct device *supplier) | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	device_pm_unlock(); | ||||
| 	device_links_write_unlock(); | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(device_link_remove); | ||||
|  | @ -4237,10 +4233,10 @@ int dev_err_probe(const struct device *dev, int err, const char *fmt, ...) | |||
| 	vaf.va = &args; | ||||
| 
 | ||||
| 	if (err != -EPROBE_DEFER) { | ||||
| 		dev_err(dev, "error %d: %pV", err, &vaf); | ||||
| 		dev_err(dev, "error %pe: %pV", ERR_PTR(err), &vaf); | ||||
| 	} else { | ||||
| 		device_set_deferred_probe_reason(dev, &vaf); | ||||
| 		dev_dbg(dev, "error %d: %pV", err, &vaf); | ||||
| 		dev_dbg(dev, "error %pe: %pV", ERR_PTR(err), &vaf); | ||||
| 	} | ||||
| 
 | ||||
| 	va_end(args); | ||||
|  |  | |||
|  | @ -142,10 +142,12 @@ int assign_fw(struct firmware *fw, struct device *device, u32 opt_flags); | |||
| void fw_free_paged_buf(struct fw_priv *fw_priv); | ||||
| int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed); | ||||
| int fw_map_paged_buf(struct fw_priv *fw_priv); | ||||
| bool fw_is_paged_buf(struct fw_priv *fw_priv); | ||||
| #else | ||||
| static inline void fw_free_paged_buf(struct fw_priv *fw_priv) {} | ||||
| static inline int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed) { return -ENXIO; } | ||||
| static inline int fw_map_paged_buf(struct fw_priv *fw_priv) { return -ENXIO; } | ||||
| static inline bool fw_is_paged_buf(struct fw_priv *fw_priv) { return false; } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* __FIRMWARE_LOADER_H */ | ||||
|  |  | |||
|  | @ -252,9 +252,11 @@ static void __free_fw_priv(struct kref *ref) | |||
| 	list_del(&fw_priv->list); | ||||
| 	spin_unlock(&fwc->lock); | ||||
| 
 | ||||
| 	fw_free_paged_buf(fw_priv); /* free leftover pages */ | ||||
| 	if (!fw_priv->allocated_size) | ||||
| 	if (fw_is_paged_buf(fw_priv)) | ||||
| 		fw_free_paged_buf(fw_priv); | ||||
| 	else if (!fw_priv->allocated_size) | ||||
| 		vfree(fw_priv->data); | ||||
| 
 | ||||
| 	kfree_const(fw_priv->fw_name); | ||||
| 	kfree(fw_priv); | ||||
| } | ||||
|  | @ -268,6 +270,11 @@ static void free_fw_priv(struct fw_priv *fw_priv) | |||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_FW_LOADER_PAGED_BUF | ||||
| bool fw_is_paged_buf(struct fw_priv *fw_priv) | ||||
| { | ||||
| 	return fw_priv->is_paged_buf; | ||||
| } | ||||
| 
 | ||||
| void fw_free_paged_buf(struct fw_priv *fw_priv) | ||||
| { | ||||
| 	int i; | ||||
|  | @ -275,6 +282,8 @@ void fw_free_paged_buf(struct fw_priv *fw_priv) | |||
| 	if (!fw_priv->pages) | ||||
| 		return; | ||||
| 
 | ||||
| 	vunmap(fw_priv->data); | ||||
| 
 | ||||
| 	for (i = 0; i < fw_priv->nr_pages; i++) | ||||
| 		__free_page(fw_priv->pages[i]); | ||||
| 	kvfree(fw_priv->pages); | ||||
|  | @ -328,10 +337,6 @@ int fw_map_paged_buf(struct fw_priv *fw_priv) | |||
| 	if (!fw_priv->data) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	/* page table is no longer needed after mapping, let's free */ | ||||
| 	kvfree(fw_priv->pages); | ||||
| 	fw_priv->pages = NULL; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
|  |  | |||
|  | @ -16,9 +16,9 @@ | |||
| 
 | ||||
| /* Exported for use by lib/test_firmware.c only */ | ||||
| LIST_HEAD(efi_embedded_fw_list); | ||||
| EXPORT_SYMBOL_GPL(efi_embedded_fw_list); | ||||
| 
 | ||||
| static bool checked_for_fw; | ||||
| EXPORT_SYMBOL_NS_GPL(efi_embedded_fw_list, TEST_FIRMWARE); | ||||
| bool efi_embedded_fw_checked; | ||||
| EXPORT_SYMBOL_NS_GPL(efi_embedded_fw_checked, TEST_FIRMWARE); | ||||
| 
 | ||||
| static const struct dmi_system_id * const embedded_fw_table[] = { | ||||
| #ifdef CONFIG_TOUCHSCREEN_DMI | ||||
|  | @ -116,14 +116,14 @@ void __init efi_check_for_embedded_firmwares(void) | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	checked_for_fw = true; | ||||
| 	efi_embedded_fw_checked = true; | ||||
| } | ||||
| 
 | ||||
| int efi_get_embedded_fw(const char *name, const u8 **data, size_t *size) | ||||
| { | ||||
| 	struct efi_embedded_fw *iter, *fw = NULL; | ||||
| 
 | ||||
| 	if (!checked_for_fw) { | ||||
| 	if (!efi_embedded_fw_checked) { | ||||
| 		pr_warn("Warning %s called while we did not check for embedded fw\n", | ||||
| 			__func__); | ||||
| 		return -ENOENT; | ||||
|  |  | |||
|  | @ -177,7 +177,7 @@ static int open_proxy_open(struct inode *inode, struct file *filp) | |||
| 		goto out; | ||||
| 
 | ||||
| 	if (!fops_get(real_fops)) { | ||||
| #ifdef MODULE | ||||
| #ifdef CONFIG_MODULES | ||||
| 		if (real_fops->owner && | ||||
| 		    real_fops->owner->state == MODULE_STATE_GOING) | ||||
| 			goto out; | ||||
|  | @ -312,7 +312,7 @@ static int full_proxy_open(struct inode *inode, struct file *filp) | |||
| 		goto out; | ||||
| 
 | ||||
| 	if (!fops_get(real_fops)) { | ||||
| #ifdef MODULE | ||||
| #ifdef CONFIG_MODULES | ||||
| 		if (real_fops->owner && | ||||
| 		    real_fops->owner->state == MODULE_STATE_GOING) | ||||
| 			goto out; | ||||
|  |  | |||
|  | @ -8,8 +8,8 @@ | |||
| #define EFI_EMBEDDED_FW_PREFIX_LEN		8 | ||||
| 
 | ||||
| /*
 | ||||
|  * This struct and efi_embedded_fw_list are private to the efi-embedded fw | ||||
|  * implementation they are in this header for use by lib/test_firmware.c only! | ||||
|  * This struct is private to the efi-embedded fw implementation. | ||||
|  * They are in this header for use by lib/test_firmware.c only! | ||||
|  */ | ||||
| struct efi_embedded_fw { | ||||
| 	struct list_head list; | ||||
|  | @ -18,8 +18,6 @@ struct efi_embedded_fw { | |||
| 	size_t length; | ||||
| }; | ||||
| 
 | ||||
| extern struct list_head efi_embedded_fw_list; | ||||
| 
 | ||||
| /**
 | ||||
|  * struct efi_embedded_fw_desc - This struct is used by the EFI embedded-fw | ||||
|  *                               code to search for embedded firmwares. | ||||
|  |  | |||
|  | @ -604,9 +604,6 @@ static void __kobject_del(struct kobject *kobj) | |||
| 	struct kernfs_node *sd; | ||||
| 	const struct kobj_type *ktype; | ||||
| 
 | ||||
| 	if (!kobj) | ||||
| 		return; | ||||
| 
 | ||||
| 	sd = kobj->sd; | ||||
| 	ktype = get_ktype(kobj); | ||||
| 
 | ||||
|  | @ -637,8 +634,12 @@ static void __kobject_del(struct kobject *kobj) | |||
|  */ | ||||
| void kobject_del(struct kobject *kobj) | ||||
| { | ||||
| 	struct kobject *parent = kobj->parent; | ||||
| 	struct kobject *parent; | ||||
| 
 | ||||
| 	if (!kobj) | ||||
| 		return; | ||||
| 
 | ||||
| 	parent = kobj->parent; | ||||
| 	__kobject_del(kobj); | ||||
| 	kobject_put(parent); | ||||
| } | ||||
|  |  | |||
|  | @ -26,6 +26,8 @@ | |||
| #include <linux/vmalloc.h> | ||||
| #include <linux/efi_embedded_fw.h> | ||||
| 
 | ||||
| MODULE_IMPORT_NS(TEST_FIRMWARE); | ||||
| 
 | ||||
| #define TEST_FIRMWARE_NAME	"test-firmware.bin" | ||||
| #define TEST_FIRMWARE_NUM_REQS	4 | ||||
| #define TEST_FIRMWARE_BUF_SIZE	SZ_1K | ||||
|  | @ -489,6 +491,9 @@ out: | |||
| static DEVICE_ATTR_WO(trigger_request); | ||||
| 
 | ||||
| #ifdef CONFIG_EFI_EMBEDDED_FIRMWARE | ||||
| extern struct list_head efi_embedded_fw_list; | ||||
| extern bool efi_embedded_fw_checked; | ||||
| 
 | ||||
| static ssize_t trigger_request_platform_store(struct device *dev, | ||||
| 					      struct device_attribute *attr, | ||||
| 					      const char *buf, size_t count) | ||||
|  | @ -501,6 +506,7 @@ static ssize_t trigger_request_platform_store(struct device *dev, | |||
| 	}; | ||||
| 	struct efi_embedded_fw efi_embedded_fw; | ||||
| 	const struct firmware *firmware = NULL; | ||||
| 	bool saved_efi_embedded_fw_checked; | ||||
| 	char *name; | ||||
| 	int rc; | ||||
| 
 | ||||
|  | @ -513,6 +519,8 @@ static ssize_t trigger_request_platform_store(struct device *dev, | |||
| 	efi_embedded_fw.data = (void *)test_data; | ||||
| 	efi_embedded_fw.length = sizeof(test_data); | ||||
| 	list_add(&efi_embedded_fw.list, &efi_embedded_fw_list); | ||||
| 	saved_efi_embedded_fw_checked = efi_embedded_fw_checked; | ||||
| 	efi_embedded_fw_checked = true; | ||||
| 
 | ||||
| 	pr_info("loading '%s'\n", name); | ||||
| 	rc = firmware_request_platform(&firmware, name, dev); | ||||
|  | @ -530,6 +538,7 @@ static ssize_t trigger_request_platform_store(struct device *dev, | |||
| 	rc = count; | ||||
| 
 | ||||
| out: | ||||
| 	efi_embedded_fw_checked = saved_efi_embedded_fw_checked; | ||||
| 	release_firmware(firmware); | ||||
| 	list_del(&efi_embedded_fw.list); | ||||
| 	kfree(name); | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Linus Torvalds
						Linus Torvalds