tile-srom and krealloc with __GFP_ZERO defect
Hello Chris,
There is a defect in krealloc with __GFP_ZERO so this code in drivers/chat/tile-srom.c may not work properly:
drivers/char/tile-srom.c- for (i = 0; ; i++) {
drivers/char/tile-srom.c- int devhdl;
drivers/char/tile-srom.c- char buf[20];
drivers/char/tile-srom.c- struct srom_dev *new_srom_devices = drivers/char/tile-srom.c- krealloc(srom_devices, (i+1) * sizeof(struct srom_dev), drivers/char/tile-srom.c: GFP_KERNEL | __GFP_ZERO); drivers/char/tile-srom.c- if (!new_srom_devices) { drivers/char/tile-srom.c- result = -ENOMEM; drivers/char/tile-srom.c- goto fail_mem; drivers/char/tile-srom.c- }
drivers/char/tile-srom.c- srom_devices = new_srom_devices;
http://linux-kernel.vger.kernel.narkive.com/xyiQV3vf/slab-krealloc-with-gfp-zero-defect
possible krealloc with __GFP_ZERO defects
(forwarding to the maintainers of other uses)
Quoted 15 lines · Joe Perches
There is a defect in krealloc with
__GFP_ZEROso this code indrivers/chat/tile-srom.cmay not work properly:drivers/char/tile-srom.c- for (i = 0; ; i++) {
drivers/char/tile-srom.c- int devhdl;
drivers/char/tile-srom.c- char buf[20];
drivers/char/tile-srom.c- structsrom_dev*new_srom_devices= drivers/char/tile-srom.c- krealloc(srom_devices, (i+1) *sizeof(struct srom_dev), drivers/char/tile-srom.c: GFP_KERNEL |__GFP_ZERO); drivers/char/tile-srom.c- if (!new_srom_devices) { drivers/char/tile-srom.c- result =-ENOMEM; drivers/char/tile-srom.c- gotofail_mem; drivers/char/tile-srom.c- }
drivers/char/tile-srom.c- srom_devices =new_srom_devices;
Quoted 1 line
http://linux-kernel.vger.kernel.narkive.com/xyiQV3vf/slab-krealloc-with-gfp-zero-defect
Here are the other in-tree uses that may not work properly
$ grep-2.5.4 -rP --include=*.[ch] -n "krealloc[^;]+__GFP_ZERO" * drivers/firmware/efi/capsule-loader.c:87: temp_page = krealloc(cap_info->pages, pages_needed * sizeof(void *), GFP_KERNEL | __GFP_ZERO); drivers/char/tile-srom.c:375: krealloc(srom_devices, (i+1) * sizeof(struct srom_dev), GFP_KERNEL | __GFP_ZERO); drivers/input/touchscreen/cyttsp4_core.c:521: p = krealloc(si->btn, si->si_ofs.btn_keys_size, GFP_KERNEL|__GFP_ZERO); drivers/input/touchscreen/cyttsp4_core.c:565: p = krealloc(si->xy_mode, si->si_ofs.mode_size, GFP_KERNEL|__GFP_ZERO); drivers/input/touchscreen/cyttsp4_core.c:570: p = krealloc(si->xy_data, si->si_ofs.data_size, GFP_KERNEL|__GFP_ZERO); drivers/input/touchscreen/cyttsp4_core.c:575: p = krealloc(si->btn_rec_data, si->si_ofs.btn_rec_size * si->si_ofs.num_btns, GFP_KERNEL|__GFP_ZERO); sound/hda/array.c:28: nlist = krealloc(array->list, size, GFP_KERNEL | __GFP_ZERO); sound/core/info.c:342: char *nbuf = krealloc(buf->buffer, PAGE_ALIGN(next), GFP_KERNEL | __GFP_ZERO);
PATCH 1/1 tile-srom: avoid krealloc(... __GFP_ZERO) pattern
Joe Perches points out [1] that this pattern isn't currently safe. This driver doesn't really need the zeroing semantic anyway; by restructuring the code slightly we can initialize all the fields of the structure up front instead.
[1] https://lkml.kernel.org/r/[email protected]
--- drivers/char/tile-srom.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-)
drivers/char/tile-srom.c +15 -13
@@ -331,13 +331,11 @@ static const struct file_operations srom_fops = {/** * srom_setup_minor() - Initialize per-minor information. * @srom: Per-device SROM state. -* @index: Device to set up. +* @devhdl: Partition device handle. */ -static int srom_setup_minor (struct srom_dev *srom,int index) +static int srom_setup_minor (struct srom_dev *srom,int devhdl) { -struct device *dev; -int devhdl = srom->hv_devhdl; - + srom->hv_devhdl = devhdl;mutex_init (&srom->lock); if (_srom_read(devhdl, &srom->total_size,
@@ -350,9 +348,7 @@ static int srom_setup_minor(struct srom_dev *srom, int index) SROM_PAGE_SIZE_OFF, sizeof(srom->page_size)) < 0)return -EIO ; - dev =device_create (srom_class, &srom_parent->dev, -MKDEV (srom_major, index), srom,"%d" , index); -return PTR_ERR_OR_ZERO (dev); +return 0 ; }/** srom_init() - Initialize the driver's module. */
@@ -365,7 +361,7 @@ static int srom_init(void)* Start with a plausible number of partitions; the krealloc() call * below will yield about log(srom_devs) additional allocations. */ - srom_devices =kzalloc (4 *sizeof (struct srom_dev ),GFP_KERNEL ); + srom_devices =kmalloc (4 *sizeof (struct srom_dev ),GFP_KERNEL );/* Discover the number of srom partitions. */ for (i =0 ; ; i++) {
@@ -373,7 +369,7 @@ static int srom_init(void)char buf[20 ];struct srom_dev *new_srom_devices =krealloc (srom_devices, (i+1 ) *sizeof (struct srom_dev ), -GFP_KERNEL | __GFP_ZERO); +GFP_KERNEL );if (!new_srom_devices) { result = -ENOMEM ; goto fail_mem;
@@ -387,7 +383,9 @@ static int srom_init(void) i, devhdl);break ; } - srom_devices[i].hv_devhdl = devhdl; + result =srom_setup_minor (&srom_devices[i], devhdl); +if (result !=0 ) + goto fail_mem; } srom_devs = i;
@@ -431,9 +429,13 @@ static int srom_init(void) srom_class->dev_groups = srom_dev_groups; srom_class->devnode = srom_devnode; -/* Do per-partition initialization */ +/* Create per-partition devices */ for (i =0 ; i < srom_devs; i++) { - result =srom_setup_minor (srom_devices + i, i); +struct device *dev = +device_create (srom_class, &srom_parent->dev, +MKDEV (srom_major, i), srom_devices + i, +"%d" , i); + result =PTR_ERR_OR_ZERO (dev);if (result <0 ) goto fail_class; }
Signature · 1 line
2.7.2
Re: possible krealloc with __GFP_ZERO defects
In reply to Joe PerchesQuoted 22 lines · Joe Perches
(forwarding to the maintainers of other uses)
Quoted 15 lines · Joe Perches
There is a defect in krealloc with
__GFP_ZEROso this code indrivers/chat/tile-srom.cmay not work properly:drivers/char/tile-srom.c- for (i = 0; ; i++) {
drivers/char/tile-srom.c- int devhdl;
drivers/char/tile-srom.c- char buf[20];
drivers/char/tile-srom.c- structsrom_dev*new_srom_devices= drivers/char/tile-srom.c- krealloc(srom_devices, (i+1) *sizeof(struct srom_dev), drivers/char/tile-srom.c: GFP_KERNEL |__GFP_ZERO); drivers/char/tile-srom.c- if (!new_srom_devices) { drivers/char/tile-srom.c- result =-ENOMEM; drivers/char/tile-srom.c- gotofail_mem; drivers/char/tile-srom.c- }
drivers/char/tile-srom.c- srom_devices =new_srom_devices;Quoted 1 line
http://linux-kernel.vger.kernel.narkive.com/xyiQV3vf/slab-krealloc-with-gfp-zero-defect
Here are the other in-tree uses that may not work properly
Quoted 16 lines
$ grep-2.5.4 -rP --include=*.[ch] -n "krealloc[^;]+__GFP_ZERO" * drivers/firmware/efi/capsule-loader.c:87: temp_page = krealloc(cap_info->pages, pages_needed * sizeof(void *), GFP_KERNEL | __GFP_ZERO); drivers/char/tile-srom.c:375: krealloc(srom_devices, (i+1) * sizeof(struct srom_dev), GFP_KERNEL | __GFP_ZERO); drivers/input/touchscreen/cyttsp4_core.c:521: p = krealloc(si->btn, si->si_ofs.btn_keys_size, GFP_KERNEL|__GFP_ZERO); drivers/input/touchscreen/cyttsp4_core.c:565: p = krealloc(si->xy_mode, si->si_ofs.mode_size, GFP_KERNEL|__GFP_ZERO); drivers/input/touchscreen/cyttsp4_core.c:570: p = krealloc(si->xy_data, si->si_ofs.data_size, GFP_KERNEL|__GFP_ZERO); drivers/input/touchscreen/cyttsp4_core.c:575: p = krealloc(si->btn_rec_data, si->si_ofs.btn_rec_size * si->si_ofs.num_btns, GFP_KERNEL|__GFP_ZERO); sound/hda/array.c:28: nlist = krealloc(array->list, size, GFP_KERNEL | __GFP_ZERO); sound/core/info.c:342: char *nbuf = krealloc(buf->buffer, PAGE_ALIGN(next), GFP_KERNEL | __GFP_ZERO);
Isn't this a bug in krealloc()?
Re: possible krealloc with __GFP_ZERO defects
Quoted 40 lines · Matt Fleming
Quoted 23 lines · Joe Perches
(forwarding to the maintainers of other uses)
Quoted 16 lines · Joe Perches
There is a defect in krealloc with
__GFP_ZEROso this code indrivers/chat/tile-srom.cmay not work properly:drivers/char/tile-srom.c- for (i = 0; ; i++) {
drivers/char/tile-srom.c- int devhdl;
drivers/char/tile-srom.c- char buf[20];
drivers/char/tile-srom.c- structsrom_dev*new_srom_devices= drivers/char/tile-srom.c- krealloc(srom_devices, (i+1) *sizeof(struct srom_dev), drivers/char/tile-srom.c: GFP_KERNEL |__GFP_ZERO); drivers/char/tile-srom.c- if (!new_srom_devices) { drivers/char/tile-srom.c- result =-ENOMEM; drivers/char/tile-srom.c- gotofail_mem; drivers/char/tile-srom.c- }
drivers/char/tile-srom.c- srom_devices =new_srom_devices;Quoted 1 line
http://linux-kernel.vger.kernel.narkive.com/xyiQV3vf/slab-krealloc-with-gfp-zero-defect
Here are the other in-tree uses that may not work properly
Quoted 16 lines
$ grep-2.5.4 -rP --include=*.[ch] -n "krealloc[^;]+__GFP_ZERO" * drivers/firmware/efi/capsule-loader.c:87: temp_page = krealloc(cap_info->pages, pages_needed * sizeof(void *), GFP_KERNEL | __GFP_ZERO); drivers/char/tile-srom.c:375: krealloc(srom_devices, (i+1) * sizeof(struct srom_dev), GFP_KERNEL | __GFP_ZERO); drivers/input/touchscreen/cyttsp4_core.c:521: p = krealloc(si->btn, si->si_ofs.btn_keys_size, GFP_KERNEL|__GFP_ZERO); drivers/input/touchscreen/cyttsp4_core.c:565: p = krealloc(si->xy_mode, si->si_ofs.mode_size, GFP_KERNEL|__GFP_ZERO); drivers/input/touchscreen/cyttsp4_core.c:570: p = krealloc(si->xy_data, si->si_ofs.data_size, GFP_KERNEL|__GFP_ZERO); drivers/input/touchscreen/cyttsp4_core.c:575: p = krealloc(si->btn_rec_data, si->si_ofs.btn_rec_size * si->si_ofs.num_btns, GFP_KERNEL|__GFP_ZERO); sound/hda/array.c:28: nlist = krealloc(array->list, size, GFP_KERNEL | __GFP_ZERO); sound/core/info.c:342: char *nbuf = krealloc(buf->buffer, PAGE_ALIGN(next), GFP_KERNEL | __GFP_ZERO);
Quoted 1 line
Isn't this a bug in
krealloc()?
Yes. Reported 3+ years ago.
http://linux-kernel.vger.kernel.narkive.com/xyiQV3vf/slab-krealloc-with-gfp-zero-defect
This sequence can return non-zeroed memory from the padding area of the original allocation.
ptr = kzalloc(foo, GFP_KERNEL);
if (!ptr)
...new_ptr = krealloc(ptr, foo + bar, GFP_KERNEL | __GFP_ZERO);
If the realloc size is within the first actual allocation then the additional memory is not zeroed.
If the realloc size is not within the original allocation size, any non-zeroed padding from the original allocation is overwriting newly allocated zeroed memory.
Maybe someone more familiar with the alignment & padding can add the proper memset(,0,) for the __GFP_ZERO cases and also optimize kmalloc_track_caller to not use __GFP_ZERO, memcpy the current (non padded) size and zero the newly returned remainder if necessary.