Message ID | 1427041891-2694-1-git-send-email-michael.opdenacker@free-electrons.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 03/22/2015 05:31 PM, Michael Opdenacker wrote: > This replaces kmalloc + memset by a call to kzalloc > (or kcalloc when appropriate, which zeroes memory too) > > This also fixes one checkpatch.pl issue in the process. > > This improvement was suggested by "make coccicheck" > > Signed-off-by: Michael Opdenacker <michael.opdenacker@free-electrons.com> Reviewed-by: Hannes Reinecke <hare@suse.de> Cheers, Hannes
Hi, On 03/22/2015 11:59 PM, Hannes Reinecke wrote: > On 03/22/2015 05:31 PM, Michael Opdenacker wrote: >> This replaces kmalloc + memset by a call to kzalloc >> (or kcalloc when appropriate, which zeroes memory too) >> >> This also fixes one checkpatch.pl issue in the process. >> >> This improvement was suggested by "make coccicheck" >> >> Signed-off-by: Michael Opdenacker <michael.opdenacker@free-electrons.com> > Reviewed-by: Hannes Reinecke <hare@suse.de> I'm sending a version that reverts the use of kcalloc() instead of kzalloc(). For reasons I don't understand, I didn't see the end of Robert Elliott's comment that the use of kcalloc() could prevent the compiler from detecting an overflow. Michael.
On Tue, 2015-03-24 at 13:46 -0700, Michael Opdenacker wrote: > Hi, > > On 03/22/2015 11:59 PM, Hannes Reinecke wrote: > > On 03/22/2015 05:31 PM, Michael Opdenacker wrote: > >> This replaces kmalloc + memset by a call to kzalloc > >> (or kcalloc when appropriate, which zeroes memory too) > >> > >> This also fixes one checkpatch.pl issue in the process. > >> > >> This improvement was suggested by "make coccicheck" > >> > >> Signed-off-by: Michael Opdenacker <michael.opdenacker@free-electrons.com> > > Reviewed-by: Hannes Reinecke <hare@suse.de> > > I'm sending a version that reverts the use of kcalloc() instead of > kzalloc(). For reasons I don't understand, I didn't see the end of > Robert Elliott's comment that the use of kcalloc() could prevent the > compiler from detecting an overflow. I'm confused. I don't see that comment either, but the entire point of kcalloc is to prevent overflows by returning NULL when an overflow might occur. from include/linux/slab.h: /** * kmalloc_array - allocate memory for an array. * @n: number of elements. * @size: element size. * @flags: the type of memory to allocate (see kmalloc). */ static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags) { if (size != 0 && n > SIZE_MAX / size) return NULL; return __kmalloc(n * size, flags); } /** * kcalloc - allocate memory for an array. The memory is set to zero. * @n: number of elements. * @size: element size. * @flags: the type of memory to allocate (see kmalloc). */ static inline void *kcalloc(size_t n, size_t size, gfp_t flags) { return kmalloc_array(n, size, flags | __GFP_ZERO); } -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
> -----Original Message----- > From: Joe Perches [mailto:joe@perches.com] > Sent: Tuesday, March 24, 2015 3:57 PM > To: Michael Opdenacker > Cc: Hannes Reinecke; JBottomley@parallels.com; Elliott, Robert (Server > Storage); linux-scsi@vger.kernel.org; linux-kernel@vger.kernel.org > Subject: Re: [PATCH] [RESEND] aic7xxx: replace kmalloc/memset by kzalloc > > On Tue, 2015-03-24 at 13:46 -0700, Michael Opdenacker wrote: ... > > On 03/22/2015 11:59 PM, Hannes Reinecke wrote: > > > On 03/22/2015 05:31 PM, Michael Opdenacker wrote: > > >> This replaces kmalloc + memset by a call to kzalloc > > >> (or kcalloc when appropriate, which zeroes memory too) > > >> ... > > I'm sending a version that reverts the use of kcalloc() instead of > > kzalloc(). For reasons I don't understand, I didn't see the end of > > Robert Elliott's comment that the use of kcalloc() could prevent the > > compiler from detecting an overflow. > > I'm confused. I don't see that comment either, but > the entire point of kcalloc is to prevent overflows > by returning NULL when an overflow might occur. It was a reply to the original post on 2014-10-16, not the resend this month. From http://permalink.gmane.org/gmane.linux.kernel/1808168: kcalloc is helpful when one of the values is a variable that might cause the multiply to overflow during runtime. Here, two constants are being multiplied together, which can be done and checked by the compiler at compile time. Since kcalloc and kmalloc_array are both static inline functions: static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags) { if (size != 0 && n > SIZE_MAX / size) return NULL; return __kmalloc(n * size, flags); } static inline void *kcalloc(size_t n, size_t size, gfp_t flags) { return kmalloc_array(n, size, flags | __GFP_ZERO); } a compiler that detects an overflow will probably just reduce that to an inlined "return NULL." BUILD_BUG_ON could be used to trigger a compile-time error, instead of building a kernel that returns a run-time error. -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 03/24/2015 04:16 PM, Elliott, Robert (Server Storage) wrote: > > It was a reply to the original post on 2014-10-16, not the resend > this month. > > From http://permalink.gmane.org/gmane.linux.kernel/1808168: > > kcalloc is helpful when one of the values is a variable that > might cause the multiply to overflow during runtime. Here, > two constants are being multiplied together, which can > be done and checked by the compiler at compile time. > > Since kcalloc and kmalloc_array are both static inline > functions: > static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags) > { > if (size != 0 && n > SIZE_MAX / size) > return NULL; > return __kmalloc(n * size, flags); > } > static inline void *kcalloc(size_t n, size_t size, gfp_t flags) > { > return kmalloc_array(n, size, flags | __GFP_ZERO); > } > > a compiler that detects an overflow will probably just reduce > that to an inlined "return NULL." > > BUILD_BUG_ON could be used to trigger a compile-time error, > instead of building a kernel that returns a run-time error. Ok, I hope we agree to get back to kzalloc() for which the compiler won't miss size_t overflows. Thanks for the reviews! Michael.
The following is a sketch of how a macro kcalloc could BUILD_BUG_ON for overflows of two compile-time operands, or call "kcalloc_variable" for nonconstant arguments. Tested on gcc 4.7.2 only, since it's what I had to hand. I didn't do any testing beyond checking that fn2 didn't build, and that fn1/3 had plausible-looking code on x86_64. typedef unsigned long size_t; #define SIZE_MAX (~(size_t)0) typedef int gfp_t; extern void *kzalloc(size_t n, gfp_t flags); extern void *kcalloc_variable(size_t n, size_t size, gfp_t flags); #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) #define kcalloc(n, size, flags) \ __builtin_choose_expr(__builtin_constant_p((n) | (size)), \ ( \ BUILD_BUG_ON((n) > SIZE_MAX / (size)), \ kzalloc((n) * (size), (flags)) \ ), kcalloc_variable((n), (size), (flags))) void fn1() { kcalloc(3, 3, 0); } //void fn2() { kcalloc(2, ~(size_t)0, 0); }// compile-time BUILD_BUG_ON void fn3(int i) { kcalloc(2, i, 0); } Jeff -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 97f2accd3dbb..109e2c99e6c1 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -10437,14 +10437,13 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) return; } } - lstate = kmalloc(sizeof(*lstate), GFP_ATOMIC); + lstate = kzalloc(sizeof(*lstate), GFP_ATOMIC); if (lstate == NULL) { xpt_print_path(ccb->ccb_h.path); printk("Couldn't allocate lstate\n"); ccb->ccb_h.status = CAM_RESRC_UNAVAIL; return; } - memset(lstate, 0, sizeof(*lstate)); status = xpt_create_path(&lstate->path, /*periph*/NULL, xpt_path_path_id(ccb->ccb_h.path), xpt_path_target_id(ccb->ccb_h.path), diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index d5c7b193d8d3..ce96a0be3282 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -1326,10 +1326,9 @@ int ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg) { ahd->platform_data = - kmalloc(sizeof(struct ahd_platform_data), GFP_ATOMIC); + kzalloc(sizeof(struct ahd_platform_data), GFP_ATOMIC); if (ahd->platform_data == NULL) return (ENOMEM); - memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data)); ahd->platform_data->irq = AHD_LINUX_NOIRQ; ahd_lockinit(ahd); ahd->seltime = (aic79xx_seltime & 0x3) << 4; diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 10172a3af1b9..2d1c86b9d7c9 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -4464,10 +4464,9 @@ ahc_softc_init(struct ahc_softc *ahc) ahc->pause = ahc->unpause | PAUSE; /* XXX The shared scb data stuff should be deprecated */ if (ahc->scb_data == NULL) { - ahc->scb_data = kmalloc(sizeof(*ahc->scb_data), GFP_ATOMIC); + ahc->scb_data = kzalloc(sizeof(*ahc->scb_data), GFP_ATOMIC); if (ahc->scb_data == NULL) return (ENOMEM); - memset(ahc->scb_data, 0, sizeof(*ahc->scb_data)); } return (0); @@ -4780,10 +4779,10 @@ ahc_init_scbdata(struct ahc_softc *ahc) SLIST_INIT(&scb_data->sg_maps); /* Allocate SCB resources */ - scb_data->scbarray = kmalloc(sizeof(struct scb) * AHC_SCB_MAX_ALLOC, GFP_ATOMIC); + scb_data->scbarray = kcalloc(AHC_SCB_MAX_ALLOC, sizeof(struct scb), + GFP_ATOMIC); if (scb_data->scbarray == NULL) return (ENOMEM); - memset(scb_data->scbarray, 0, sizeof(struct scb) * AHC_SCB_MAX_ALLOC); /* Determine the number of hardware SCBs and initialize them */ @@ -7558,14 +7557,13 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) return; } } - lstate = kmalloc(sizeof(*lstate), GFP_ATOMIC); + lstate = kzalloc(sizeof(*lstate), GFP_ATOMIC); if (lstate == NULL) { xpt_print_path(ccb->ccb_h.path); printk("Couldn't allocate lstate\n"); ccb->ccb_h.status = CAM_RESRC_UNAVAIL; return; } - memset(lstate, 0, sizeof(*lstate)); status = xpt_create_path(&lstate->path, /*periph*/NULL, xpt_path_path_id(ccb->ccb_h.path), xpt_path_target_id(ccb->ccb_h.path), diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 88360116dbcb..a2f2c774cd6b 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -1214,10 +1214,9 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) { ahc->platform_data = - kmalloc(sizeof(struct ahc_platform_data), GFP_ATOMIC); + kzalloc(sizeof(struct ahc_platform_data), GFP_ATOMIC); if (ahc->platform_data == NULL) return (ENOMEM); - memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data)); ahc->platform_data->irq = AHC_LINUX_NOIRQ; ahc_lockinit(ahc); ahc->seltime = (aic7xxx_seltime & 0x3) << 4;
This replaces kmalloc + memset by a call to kzalloc (or kcalloc when appropriate, which zeroes memory too) This also fixes one checkpatch.pl issue in the process. This improvement was suggested by "make coccicheck" Signed-off-by: Michael Opdenacker <michael.opdenacker@free-electrons.com> --- drivers/scsi/aic7xxx/aic79xx_core.c | 3 +-- drivers/scsi/aic7xxx/aic79xx_osm.c | 3 +-- drivers/scsi/aic7xxx/aic7xxx_core.c | 10 ++++------ drivers/scsi/aic7xxx/aic7xxx_osm.c | 3 +-- 4 files changed, 7 insertions(+), 12 deletions(-)