Skip to content

Commit

Permalink
treewide: Use struct_size() for kmalloc()-family
Browse files Browse the repository at this point in the history
One of the more common cases of allocation size calculations is finding
the size of a structure that has a zero-sized array at the end, along
with memory for some number of elements for that array. For example:

struct foo {
    int stuff;
    void *entry[];
};

instance = kmalloc(sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL);

Instead of leaving these open-coded and prone to type mistakes, we can
now use the new struct_size() helper:

instance = kmalloc(struct_size(instance, entry, count), GFP_KERNEL);

This patch makes the changes for kmalloc()-family (and kvmalloc()-family)
uses. It was done via automatic conversion with manual review for the
"CHECKME" non-standard cases noted below, using the following Coccinelle
script:

// pkey_cache = kmalloc(sizeof *pkey_cache + tprops->pkey_tbl_len *
//                      sizeof *pkey_cache->table, GFP_KERNEL);
@@
identifier alloc =~ "kmalloc|kzalloc|kvmalloc|kvzalloc";
expression GFP;
identifier VAR, ELEMENT;
expression COUNT;
@@

- alloc(sizeof(*VAR) + COUNT * sizeof(*VAR->ELEMENT), GFP)
+ alloc(struct_size(VAR, ELEMENT, COUNT), GFP)

// mr = kzalloc(sizeof(*mr) + m * sizeof(mr->map[0]), GFP_KERNEL);
@@
identifier alloc =~ "kmalloc|kzalloc|kvmalloc|kvzalloc";
expression GFP;
identifier VAR, ELEMENT;
expression COUNT;
@@

- alloc(sizeof(*VAR) + COUNT * sizeof(VAR->ELEMENT[0]), GFP)
+ alloc(struct_size(VAR, ELEMENT, COUNT), GFP)

// Same pattern, but can't trivially locate the trailing element name,
// or variable name.
@@
identifier alloc =~ "kmalloc|kzalloc|kvmalloc|kvzalloc";
expression GFP;
expression SOMETHING, COUNT, ELEMENT;
@@

- alloc(sizeof(SOMETHING) + COUNT * sizeof(ELEMENT), GFP)
+ alloc(CHECKME_struct_size(&SOMETHING, ELEMENT, COUNT), GFP)

Signed-off-by: Kees Cook <[email protected]>
  • Loading branch information
kees committed Jun 6, 2018
1 parent 2509b56 commit acafe7e
Show file tree
Hide file tree
Showing 53 changed files with 89 additions and 116 deletions.
4 changes: 2 additions & 2 deletions drivers/clk/bcm/clk-iproc-asiu.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,8 @@ void __init iproc_asiu_setup(struct device_node *node,
if (WARN_ON(!asiu))
return;

asiu->clk_data = kzalloc(sizeof(*asiu->clk_data->hws) * num_clks +
sizeof(*asiu->clk_data), GFP_KERNEL);
asiu->clk_data = kzalloc(struct_size(asiu->clk_data, hws, num_clks),
GFP_KERNEL);
if (WARN_ON(!asiu->clk_data))
goto err_clks;
asiu->clk_data->num = num_clks;
Expand Down
3 changes: 1 addition & 2 deletions drivers/clk/bcm/clk-iproc-pll.c
Original file line number Diff line number Diff line change
Expand Up @@ -744,8 +744,7 @@ void iproc_pll_clk_setup(struct device_node *node,
if (WARN_ON(!pll))
return;

clk_data = kzalloc(sizeof(*clk_data->hws) * num_clks +
sizeof(*clk_data), GFP_KERNEL);
clk_data = kzalloc(struct_size(clk_data, hws, num_clks), GFP_KERNEL);
if (WARN_ON(!clk_data))
goto err_clk_data;
clk_data->num = num_clks;
Expand Down
3 changes: 1 addition & 2 deletions drivers/clk/berlin/bg2.c
Original file line number Diff line number Diff line change
Expand Up @@ -509,8 +509,7 @@ static void __init berlin2_clock_setup(struct device_node *np)
u8 avpll_flags = 0;
int n, ret;

clk_data = kzalloc(sizeof(*clk_data) +
sizeof(*clk_data->hws) * MAX_CLKS, GFP_KERNEL);
clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
if (!clk_data)
return;
clk_data->num = MAX_CLKS;
Expand Down
3 changes: 1 addition & 2 deletions drivers/clk/berlin/bg2q.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,7 @@ static void __init berlin2q_clock_setup(struct device_node *np)
struct clk_hw **hws;
int n, ret;

clk_data = kzalloc(sizeof(*clk_data) +
sizeof(*clk_data->hws) * MAX_CLKS, GFP_KERNEL);
clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
if (!clk_data)
return;
clk_data->num = MAX_CLKS;
Expand Down
3 changes: 1 addition & 2 deletions drivers/clk/clk-asm9260.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,7 @@ static void __init asm9260_acc_init(struct device_node *np)
int n;
u32 accuracy = 0;

clk_data = kzalloc(sizeof(*clk_data) +
sizeof(*clk_data->hws) * MAX_CLKS, GFP_KERNEL);
clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
if (!clk_data)
return;
clk_data->num = MAX_CLKS;
Expand Down
6 changes: 3 additions & 3 deletions drivers/clk/clk-aspeed.c
Original file line number Diff line number Diff line change
Expand Up @@ -627,9 +627,9 @@ static void __init aspeed_cc_init(struct device_node *np)
if (!scu_base)
return;

aspeed_clk_data = kzalloc(sizeof(*aspeed_clk_data) +
sizeof(*aspeed_clk_data->hws) * ASPEED_NUM_CLKS,
GFP_KERNEL);
aspeed_clk_data = kzalloc(struct_size(aspeed_clk_data, hws,
ASPEED_NUM_CLKS),
GFP_KERNEL);
if (!aspeed_clk_data)
return;

Expand Down
6 changes: 3 additions & 3 deletions drivers/clk/clk-clps711x.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ static struct clps711x_clk * __init _clps711x_clk_init(void __iomem *base,
if (!base)
return ERR_PTR(-ENOMEM);

clps711x_clk = kzalloc(sizeof(*clps711x_clk) +
sizeof(*clps711x_clk->clk_data.hws) * CLPS711X_CLK_MAX,
GFP_KERNEL);
clps711x_clk = kzalloc(struct_size(clps711x_clk, clk_data.hws,
CLPS711X_CLK_MAX),
GFP_KERNEL);
if (!clps711x_clk)
return ERR_PTR(-ENOMEM);

Expand Down
4 changes: 2 additions & 2 deletions drivers/clk/clk-efm32gg.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ static void __init efm32gg_cmu_init(struct device_node *np)
void __iomem *base;
struct clk_hw **hws;

clk_data = kzalloc(sizeof(*clk_data) +
sizeof(*clk_data->hws) * CMU_MAX_CLKS, GFP_KERNEL);
clk_data = kzalloc(struct_size(clk_data, hws, CMU_MAX_CLKS),
GFP_KERNEL);

if (!clk_data)
return;
Expand Down
6 changes: 3 additions & 3 deletions drivers/clk/clk-gemini.c
Original file line number Diff line number Diff line change
Expand Up @@ -399,9 +399,9 @@ static void __init gemini_cc_init(struct device_node *np)
int ret;
int i;

gemini_clk_data = kzalloc(sizeof(*gemini_clk_data) +
sizeof(*gemini_clk_data->hws) * GEMINI_NUM_CLKS,
GFP_KERNEL);
gemini_clk_data = kzalloc(struct_size(gemini_clk_data, hws,
GEMINI_NUM_CLKS),
GFP_KERNEL);
if (!gemini_clk_data)
return;

Expand Down
5 changes: 2 additions & 3 deletions drivers/clk/clk-stm32h7.c
Original file line number Diff line number Diff line change
Expand Up @@ -1201,9 +1201,8 @@ static void __init stm32h7_rcc_init(struct device_node *np)
const char *hse_clk, *lse_clk, *i2s_clk;
struct regmap *pdrm;

clk_data = kzalloc(sizeof(*clk_data) +
sizeof(*clk_data->hws) * STM32H7_MAX_CLKS,
GFP_KERNEL);
clk_data = kzalloc(struct_size(clk_data, hws, STM32H7_MAX_CLKS),
GFP_KERNEL);
if (!clk_data)
return;

Expand Down
5 changes: 2 additions & 3 deletions drivers/clk/clk-stm32mp1.c
Original file line number Diff line number Diff line change
Expand Up @@ -2060,9 +2060,8 @@ static int stm32_rcc_init(struct device_node *np,

max_binding = data->maxbinding;

clk_data = kzalloc(sizeof(*clk_data) +
sizeof(*clk_data->hws) * max_binding,
GFP_KERNEL);
clk_data = kzalloc(struct_size(clk_data, hws, max_binding),
GFP_KERNEL);
if (!clk_data)
return -ENOMEM;

Expand Down
3 changes: 1 addition & 2 deletions drivers/clk/samsung/clk-exynos-clkout.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask)
int ret;
int i;

clkout = kzalloc(sizeof(*clkout) +
sizeof(*clkout->data.hws) * EXYNOS_CLKOUT_NR_CLKS,
clkout = kzalloc(struct_size(clkout, data.hws, EXYNOS_CLKOUT_NR_CLKS),
GFP_KERNEL);
if (!clkout)
return;
Expand Down
2 changes: 1 addition & 1 deletion drivers/dax/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
if (!count)
return ERR_PTR(-EINVAL);

dev_dax = kzalloc(sizeof(*dev_dax) + sizeof(*res) * count, GFP_KERNEL);
dev_dax = kzalloc(struct_size(dev_dax, res, count), GFP_KERNEL);
if (!dev_dax)
return ERR_PTR(-ENOMEM);

Expand Down
9 changes: 3 additions & 6 deletions drivers/dma/edma.c
Original file line number Diff line number Diff line change
Expand Up @@ -1074,8 +1074,7 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
return NULL;
}

edesc = kzalloc(sizeof(*edesc) + sg_len * sizeof(edesc->pset[0]),
GFP_ATOMIC);
edesc = kzalloc(struct_size(edesc, pset, sg_len), GFP_ATOMIC);
if (!edesc)
return NULL;

Expand Down Expand Up @@ -1192,8 +1191,7 @@ static struct dma_async_tx_descriptor *edma_prep_dma_memcpy(
nslots = 2;
}

edesc = kzalloc(sizeof(*edesc) + nslots * sizeof(edesc->pset[0]),
GFP_ATOMIC);
edesc = kzalloc(struct_size(edesc, pset, nslots), GFP_ATOMIC);
if (!edesc)
return NULL;

Expand Down Expand Up @@ -1315,8 +1313,7 @@ static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
}
}

edesc = kzalloc(sizeof(*edesc) + nslots * sizeof(edesc->pset[0]),
GFP_ATOMIC);
edesc = kzalloc(struct_size(edesc, pset, nslots), GFP_ATOMIC);
if (!edesc)
return NULL;

Expand Down
2 changes: 1 addition & 1 deletion drivers/dma/moxart-dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ static struct dma_async_tx_descriptor *moxart_prep_slave_sg(
return NULL;
}

d = kzalloc(sizeof(*d) + sg_len * sizeof(d->sg[0]), GFP_ATOMIC);
d = kzalloc(struct_size(d, sg, sg_len), GFP_ATOMIC);
if (!d)
return NULL;

Expand Down
2 changes: 1 addition & 1 deletion drivers/dma/omap-dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -917,7 +917,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
}

/* Now allocate and setup the descriptor. */
d = kzalloc(sizeof(*d) + sglen * sizeof(d->sg[0]), GFP_ATOMIC);
d = kzalloc(struct_size(d, sg, sglen), GFP_ATOMIC);
if (!d)
return NULL;

Expand Down
4 changes: 2 additions & 2 deletions drivers/dma/sa11x0-dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ static struct dma_async_tx_descriptor *sa11x0_dma_prep_slave_sg(
}
}

txd = kzalloc(sizeof(*txd) + j * sizeof(txd->sg[0]), GFP_ATOMIC);
txd = kzalloc(struct_size(txd, sg, j), GFP_ATOMIC);
if (!txd) {
dev_dbg(chan->device->dev, "vchan %p: kzalloc failed\n", &c->vc);
return NULL;
Expand Down Expand Up @@ -627,7 +627,7 @@ static struct dma_async_tx_descriptor *sa11x0_dma_prep_dma_cyclic(
if (sglen == 0)
return NULL;

txd = kzalloc(sizeof(*txd) + sglen * sizeof(txd->sg[0]), GFP_ATOMIC);
txd = kzalloc(struct_size(txd, sg, sglen), GFP_ATOMIC);
if (!txd) {
dev_dbg(chan->device->dev, "vchan %p: kzalloc failed\n", &c->vc);
return NULL;
Expand Down
2 changes: 1 addition & 1 deletion drivers/dma/sh/usb-dmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ static int usb_dmac_desc_alloc(struct usb_dmac_chan *chan, unsigned int sg_len,
struct usb_dmac_desc *desc;
unsigned long flags;

desc = kzalloc(sizeof(*desc) + sg_len * sizeof(desc->sg[0]), gfp);
desc = kzalloc(struct_size(desc, sg, sg_len), gfp);
if (!desc)
return -ENOMEM;

Expand Down
3 changes: 1 addition & 2 deletions drivers/firewire/core-topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,7 @@ static struct fw_node *fw_node_create(u32 sid, int port_count, int color)
{
struct fw_node *node;

node = kzalloc(sizeof(*node) + port_count * sizeof(node->ports[0]),
GFP_ATOMIC);
node = kzalloc(struct_size(node, ports, port_count), GFP_ATOMIC);
if (node == NULL)
return NULL;

Expand Down
3 changes: 1 addition & 2 deletions drivers/gpio/gpiolib.c
Original file line number Diff line number Diff line change
Expand Up @@ -4022,8 +4022,7 @@ struct gpio_descs *__must_check gpiod_get_array(struct device *dev,
if (count < 0)
return ERR_PTR(count);

descs = kzalloc(sizeof(*descs) + sizeof(descs->desc[0]) * count,
GFP_KERNEL);
descs = kzalloc(struct_size(descs, desc, count), GFP_KERNEL);
if (!descs)
return ERR_PTR(-ENOMEM);

Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -779,8 +779,8 @@ nvkm_perfdom_new(struct nvkm_pm *pm, const char *name, u32 mask,

sdom = spec;
while (sdom->signal_nr) {
dom = kzalloc(sizeof(*dom) + sdom->signal_nr *
sizeof(*dom->signal), GFP_KERNEL);
dom = kzalloc(struct_size(dom, signal, sdom->signal_nr),
GFP_KERNEL);
if (!dom)
return -ENOMEM;

Expand Down
2 changes: 1 addition & 1 deletion drivers/hwspinlock/omap_hwspinlock.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ static int omap_hwspinlock_probe(struct platform_device *pdev)

num_locks = i * 32; /* actual number of locks in this device */

bank = kzalloc(sizeof(*bank) + num_locks * sizeof(*hwlock), GFP_KERNEL);
bank = kzalloc(struct_size(bank, lock, num_locks), GFP_KERNEL);
if (!bank) {
ret = -ENOMEM;
goto iounmap_base;
Expand Down
2 changes: 1 addition & 1 deletion drivers/hwspinlock/u8500_hsem.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ static int u8500_hsem_probe(struct platform_device *pdev)
/* clear all interrupts */
writel(0xFFFF, io_base + HSEM_ICRALL);

bank = kzalloc(sizeof(*bank) + num_locks * sizeof(*hwlock), GFP_KERNEL);
bank = kzalloc(struct_size(bank, lock, num_locks), GFP_KERNEL);
if (!bank) {
ret = -ENOMEM;
goto iounmap_base;
Expand Down
5 changes: 3 additions & 2 deletions drivers/infiniband/core/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1157,8 +1157,9 @@ static void ib_cache_update(struct ib_device *device,
goto err;
}

pkey_cache = kmalloc(sizeof *pkey_cache + tprops->pkey_tbl_len *
sizeof *pkey_cache->table, GFP_KERNEL);
pkey_cache = kmalloc(struct_size(pkey_cache, table,
tprops->pkey_tbl_len),
GFP_KERNEL);
if (!pkey_cache)
goto err;

Expand Down
4 changes: 2 additions & 2 deletions drivers/infiniband/core/cm.c
Original file line number Diff line number Diff line change
Expand Up @@ -4298,8 +4298,8 @@ static void cm_add_one(struct ib_device *ib_device)
int count = 0;
u8 i;

cm_dev = kzalloc(sizeof(*cm_dev) + sizeof(*port) *
ib_device->phys_port_cnt, GFP_KERNEL);
cm_dev = kzalloc(struct_size(cm_dev, port, ib_device->phys_port_cnt),
GFP_KERNEL);
if (!cm_dev)
return;

Expand Down
2 changes: 1 addition & 1 deletion drivers/infiniband/core/multicast.c
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,7 @@ static void mcast_add_one(struct ib_device *device)
int i;
int count = 0;

dev = kmalloc(sizeof *dev + device->phys_port_cnt * sizeof *port,
dev = kmalloc(struct_size(dev, port, device->phys_port_cnt),
GFP_KERNEL);
if (!dev)
return;
Expand Down
4 changes: 2 additions & 2 deletions drivers/infiniband/core/uverbs_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2756,8 +2756,8 @@ static struct ib_uflow_resources *flow_resources_alloc(size_t num_specs)
struct ib_uflow_resources *resources;

resources =
kmalloc(sizeof(*resources) +
num_specs * sizeof(*resources->collection), GFP_KERNEL);
kmalloc(struct_size(resources, collection, num_specs),
GFP_KERNEL);

if (!resources)
return NULL;
Expand Down
21 changes: 10 additions & 11 deletions drivers/infiniband/core/uverbs_ioctl_merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,7 @@ static struct uverbs_method_spec *build_method_with_attrs(const struct uverbs_me
if (max_attr_buckets >= 0)
num_attr_buckets = max_attr_buckets + 1;

method = kzalloc(sizeof(*method) +
num_attr_buckets * sizeof(*method->attr_buckets),
method = kzalloc(struct_size(method, attr_buckets, num_attr_buckets),
GFP_KERNEL);
if (!method)
return ERR_PTR(-ENOMEM);
Expand Down Expand Up @@ -446,9 +445,9 @@ static struct uverbs_object_spec *build_object_with_methods(const struct uverbs_
if (max_method_buckets >= 0)
num_method_buckets = max_method_buckets + 1;

object = kzalloc(sizeof(*object) +
num_method_buckets *
sizeof(*object->method_buckets), GFP_KERNEL);
object = kzalloc(struct_size(object, method_buckets,
num_method_buckets),
GFP_KERNEL);
if (!object)
return ERR_PTR(-ENOMEM);

Expand All @@ -469,8 +468,8 @@ static struct uverbs_object_spec *build_object_with_methods(const struct uverbs_
if (methods_max_bucket < 0)
continue;

hash = kzalloc(sizeof(*hash) +
sizeof(*hash->methods) * (methods_max_bucket + 1),
hash = kzalloc(struct_size(hash, methods,
methods_max_bucket + 1),
GFP_KERNEL);
if (!hash) {
res = -ENOMEM;
Expand Down Expand Up @@ -579,8 +578,8 @@ struct uverbs_root_spec *uverbs_alloc_spec_tree(unsigned int num_trees,
if (max_object_buckets >= 0)
num_objects_buckets = max_object_buckets + 1;

root_spec = kzalloc(sizeof(*root_spec) +
num_objects_buckets * sizeof(*root_spec->object_buckets),
root_spec = kzalloc(struct_size(root_spec, object_buckets,
num_objects_buckets),
GFP_KERNEL);
if (!root_spec)
return ERR_PTR(-ENOMEM);
Expand All @@ -603,8 +602,8 @@ struct uverbs_root_spec *uverbs_alloc_spec_tree(unsigned int num_trees,
if (objects_max_bucket < 0)
continue;

hash = kzalloc(sizeof(*hash) +
sizeof(*hash->objects) * (objects_max_bucket + 1),
hash = kzalloc(struct_size(hash, objects,
objects_max_bucket + 1),
GFP_KERNEL);
if (!hash) {
res = -ENOMEM;
Expand Down
4 changes: 2 additions & 2 deletions drivers/infiniband/hw/mthca/mthca_memfree.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
obj_per_chunk = MTHCA_TABLE_CHUNK_SIZE / obj_size;
num_icm = DIV_ROUND_UP(nobj, obj_per_chunk);

table = kmalloc(sizeof *table + num_icm * sizeof *table->icm, GFP_KERNEL);
table = kmalloc(struct_size(table, icm, num_icm), GFP_KERNEL);
if (!table)
return NULL;

Expand Down Expand Up @@ -529,7 +529,7 @@ struct mthca_user_db_table *mthca_init_user_db_tab(struct mthca_dev *dev)
return NULL;

npages = dev->uar_table.uarc_size / MTHCA_ICM_PAGE_SIZE;
db_tab = kmalloc(sizeof *db_tab + npages * sizeof *db_tab->page, GFP_KERNEL);
db_tab = kmalloc(struct_size(db_tab, page, npages), GFP_KERNEL);
if (!db_tab)
return ERR_PTR(-ENOMEM);

Expand Down
Loading

0 comments on commit acafe7e

Please sign in to comment.