summaryrefslogtreecommitdiff
path: root/drivers/base/firmware_class.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/firmware_class.c')
-rw-r--r--drivers/base/firmware_class.c63
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);
}