diff mbox

[RESEND] aic7xxx: replace kmalloc/memset by kzalloc

Message ID 1427041891-2694-1-git-send-email-michael.opdenacker@free-electrons.com (mailing list archive)
State New, archived
Headers show

Commit Message

Michael Opdenacker March 22, 2015, 4:31 p.m. UTC
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(-)

Comments

Hannes Reinecke March 23, 2015, 6:59 a.m. UTC | #1
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
Michael Opdenacker March 24, 2015, 8:46 p.m. UTC | #2
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.
Joe Perches March 24, 2015, 8:57 p.m. UTC | #3
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
Elliott, Robert (Server Storage) March 24, 2015, 11:16 p.m. UTC | #4
> -----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
Michael Opdenacker March 27, 2015, 12:38 a.m. UTC | #5
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.
Jeff Epler March 27, 2015, 7:48 p.m. UTC | #6
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 mbox

Patch

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;