kcalloc/kmalloc_array could BUILD_BUG_ON for too-big constant arguments (was Re: [PATCH] [RESEND] aic7xxx: replace kmalloc/memset by kzalloc)

2015-03-28 Thread Jeff Epler
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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] [RESEND] aic7xxx: replace kmalloc/memset by kzalloc

2015-03-26 Thread Michael Opdenacker
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.

-- 
Michael Opdenacker, CEO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
+33 484 258 098


--
To unsubscribe from this list: send the line unsubscribe linux-scsi in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] [RESEND] aic7xxx: replace kmalloc/memset by kzalloc

2015-03-26 Thread Michael Opdenacker
This replaces kmalloc + memset by a call to kzalloc

This also fixes one checkpatch.pl issue in the process.

This improvement was suggested by make coccicheck

Signed-off-by: Michael Opdenacker michael.opdenac...@free-electrons.com
Reviewed-by: Hannes Reinecke h...@suse.de
---
 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(-)

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..c4829d84b335 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 = kzalloc(sizeof(struct scb) * AHC_SCB_MAX_ALLOC,
+   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)
  

RE: [PATCH] [RESEND] aic7xxx: replace kmalloc/memset by kzalloc

2015-03-24 Thread Elliott, Robert (Server Storage)


 -Original Message-
 From: Joe Perches [mailto:j...@perches.com]
 Sent: Tuesday, March 24, 2015 3:57 PM
 To: Michael Opdenacker
 Cc: Hannes Reinecke; jbottom...@parallels.com; Elliott, Robert (Server
 Storage); linux-scsi@vger.kernel.org; linux-ker...@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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] [RESEND] aic7xxx: replace kmalloc/memset by kzalloc

2015-03-24 Thread Michael Opdenacker
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.opdenac...@free-electrons.com
 Reviewed-by: Hannes Reinecke h...@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.

-- 
Michael Opdenacker, CEO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
+33 484 258 098

--
To unsubscribe from this list: send the line unsubscribe linux-scsi in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] [RESEND] aic7xxx: replace kmalloc/memset by kzalloc

2015-03-24 Thread Joe Perches
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.opdenac...@free-electrons.com
  Reviewed-by: Hannes Reinecke h...@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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] [RESEND] aic7xxx: replace kmalloc/memset by kzalloc

2015-03-23 Thread Hannes Reinecke
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.opdenac...@free-electrons.com
Reviewed-by: Hannes Reinecke h...@suse.de

Cheers,

Hannes
-- 
Dr. Hannes ReineckezSeries  Storage
h...@suse.de   +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line unsubscribe linux-scsi in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] [RESEND] aic7xxx: replace kmalloc/memset by kzalloc

2015-03-22 Thread Michael Opdenacker
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.opdenac...@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(-)

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