diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-26 15:07:37 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-26 15:07:37 -0700 |
commit | 8d7804a2f03dbd34940fcb426450c730adf29dae (patch) | |
tree | 749f33776e38f734b81c2a93275b6bf76e96f74e /drivers/base/firmware_class.c | |
parent | d87823813fe498fdd47894bd28e460a9dee8d771 (diff) | |
parent | 0e6c861f73ec42ab5c89fda9892f2173c7aaf6cf (diff) |
Merge tag 'driver-core-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core updates from Greg KH:
"Here is the driver core / firmware changes for 4.2-rc1.
A number of small changes all over the place in the driver core, and
in the firmware subsystem. Nothing really major, full details in the
shortlog. Some of it is a bit of churn, given that the platform
driver probing changes was found to not work well, so they were
reverted.
All of these have been in linux-next for a while with no reported
issues"
* tag 'driver-core-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (31 commits)
Revert "base/platform: Only insert MEM and IO resources"
Revert "base/platform: Continue on insert_resource() error"
Revert "of/platform: Use platform_device interface"
Revert "base/platform: Remove code duplication"
firmware: add missing kfree for work on async call
fs: sysfs: don't pass count == 0 to bin file readers
base:dd - Fix for typo in comment to function driver_deferred_probe_trigger().
base/platform: Remove code duplication
of/platform: Use platform_device interface
base/platform: Continue on insert_resource() error
base/platform: Only insert MEM and IO resources
firmware: use const for remaining firmware names
firmware: fix possible use after free on name on asynchronous request
firmware: check for file truncation on direct firmware loading
firmware: fix __getname() missing failure check
drivers: of/base: move of_init to driver_init
drivers/base: cacheinfo: fix annoying typo when DT nodes are absent
sysfs: disambiguate between "error code" and "failure" in comments
driver-core: fix build for !CONFIG_MODULES
driver-core: make __device_attach() static
...
Diffstat (limited to 'drivers/base/firmware_class.c')
-rw-r--r-- | drivers/base/firmware_class.c | 63 |
1 files changed, 47 insertions, 16 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 171841ad1008..9c4288362a8e 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -150,17 +150,17 @@ struct firmware_buf { int page_array_size; struct list_head pending_list; #endif - char fw_id[]; + const char *fw_id; }; struct fw_cache_entry { struct list_head list; - char name[]; + const char *name; }; struct fw_name_devm { unsigned long magic; - char name[]; + const char *name; }; #define to_fwbuf(d) container_of(d, struct firmware_buf, ref) @@ -181,13 +181,17 @@ static struct firmware_buf *__allocate_fw_buf(const char *fw_name, { struct firmware_buf *buf; - buf = kzalloc(sizeof(*buf) + strlen(fw_name) + 1, GFP_ATOMIC); - + buf = kzalloc(sizeof(*buf), GFP_ATOMIC); if (!buf) - return buf; + return NULL; + + buf->fw_id = kstrdup_const(fw_name, GFP_ATOMIC); + if (!buf->fw_id) { + kfree(buf); + return NULL; + } kref_init(&buf->ref); - strcpy(buf->fw_id, fw_name); buf->fwc = fwc; init_completion(&buf->completion); #ifdef CONFIG_FW_LOADER_USER_HELPER @@ -257,6 +261,7 @@ static void __fw_free_buf(struct kref *ref) } else #endif vfree(buf->data); + kfree_const(buf->fw_id); kfree(buf); } @@ -320,9 +325,13 @@ fail: static int fw_get_filesystem_firmware(struct device *device, struct firmware_buf *buf) { - int i; + int i, len; int rc = -ENOENT; - char *path = __getname(); + char *path; + + path = __getname(); + if (!path) + return -ENOMEM; for (i = 0; i < ARRAY_SIZE(fw_path); i++) { struct file *file; @@ -331,7 +340,12 @@ static int fw_get_filesystem_firmware(struct device *device, if (!fw_path[i][0]) continue; - snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id); + len = snprintf(path, PATH_MAX, "%s/%s", + fw_path[i], buf->fw_id); + if (len >= PATH_MAX) { + rc = -ENAMETOOLONG; + break; + } file = filp_open(path, O_RDONLY, 0); if (IS_ERR(file)) @@ -392,6 +406,7 @@ static void fw_name_devm_release(struct device *dev, void *res) if (fwn->magic == (unsigned long)&fw_cache) pr_debug("%s: fw_name-%s devm-%p released\n", __func__, fwn->name, res); + kfree_const(fwn->name); } static int fw_devm_match(struct device *dev, void *res, @@ -422,13 +437,17 @@ static int fw_add_devm_name(struct device *dev, const char *name) if (fwn) return 1; - fwn = devres_alloc(fw_name_devm_release, sizeof(struct fw_name_devm) + - strlen(name) + 1, GFP_KERNEL); + fwn = devres_alloc(fw_name_devm_release, sizeof(struct fw_name_devm), + GFP_KERNEL); if (!fwn) return -ENOMEM; + fwn->name = kstrdup_const(name, GFP_KERNEL); + if (!fwn->name) { + kfree(fwn); + return -ENOMEM; + } fwn->magic = (unsigned long)&fw_cache; - strcpy(fwn->name, name); devres_add(dev, fwn); return 0; @@ -1247,6 +1266,7 @@ static void request_firmware_work_func(struct work_struct *work) put_device(fw_work->device); /* taken in request_firmware_nowait() */ module_put(fw_work->module); + kfree_const(fw_work->name); kfree(fw_work); } @@ -1286,7 +1306,11 @@ request_firmware_nowait( return -ENOMEM; fw_work->module = module; - fw_work->name = name; + fw_work->name = kstrdup_const(name, gfp); + if (!fw_work->name) { + kfree(fw_work); + return -ENOMEM; + } fw_work->device = device; fw_work->context = context; fw_work->cont = cont; @@ -1294,6 +1318,7 @@ request_firmware_nowait( (uevent ? FW_OPT_UEVENT : FW_OPT_USERHELPER); if (!try_module_get(module)) { + kfree_const(fw_work->name); kfree(fw_work); return -EFAULT; } @@ -1384,11 +1409,16 @@ static struct fw_cache_entry *alloc_fw_cache_entry(const char *name) { struct fw_cache_entry *fce; - fce = kzalloc(sizeof(*fce) + strlen(name) + 1, GFP_ATOMIC); + fce = kzalloc(sizeof(*fce), GFP_ATOMIC); if (!fce) goto exit; - strcpy(fce->name, name); + fce->name = kstrdup_const(name, GFP_ATOMIC); + if (!fce->name) { + kfree(fce); + fce = NULL; + goto exit; + } exit: return fce; } @@ -1428,6 +1458,7 @@ found: static void free_fw_cache_entry(struct fw_cache_entry *fce) { + kfree_const(fce->name); kfree(fce); } |