From: Benjamin LaHaise The patch below makes kmalloc() fail at compile time for swapped flags and size arguments when the flags are a constant. It will also fail at runtime (non-constant flags) due to the size being too large. This is done by adding a new flag, __GFP_VALID, which is checked for in kmalloc(), that results in the size being too large. Signed-off-by: Benoit Boissinot Signed-off-by: Andrew Morton --- arch/s390/appldata/appldata_os.c | 2 +- arch/s390/mm/extmem.c | 6 +++--- drivers/net/b44.c | 2 +- drivers/s390/net/claw.c | 10 +++++----- drivers/scsi/aic7xxx/aic79xx_osm.h | 2 +- drivers/scsi/pluto.c | 2 +- include/linux/gfp.h | 16 +++++++++------- include/linux/slab.h | 4 ++++ mm/slab.c | 2 +- 9 files changed, 26 insertions(+), 20 deletions(-) diff -puN include/linux/gfp.h~make-kmalloc-fail-for-swapped-size--gfp-flags include/linux/gfp.h --- devel/include/linux/gfp.h~make-kmalloc-fail-for-swapped-size--gfp-flags 2005-09-12 03:34:46.000000000 -0700 +++ devel-akpm/include/linux/gfp.h 2005-09-12 03:34:46.000000000 -0700 @@ -48,6 +48,7 @@ struct vm_area_struct; #define __GFP_NOMEMALLOC 0x10000u /* Don't use emergency reserves */ #define __GFP_NORECLAIM 0x20000u /* No realy zone reclaim during allocation */ #define __GFP_HARDWALL 0x40000u /* Enforce hardwall cpuset memory allocs */ +#define __GFP_VALID 0x80000000u /* valid GFP flags */ #define __GFP_BITS_SHIFT 20 /* Room for 20 __GFP_FOO bits */ #define __GFP_BITS_MASK ((1 << __GFP_BITS_SHIFT) - 1) @@ -58,13 +59,14 @@ struct vm_area_struct; __GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \ __GFP_NOMEMALLOC|__GFP_NORECLAIM|__GFP_HARDWALL) -#define GFP_ATOMIC (__GFP_HIGH) -#define GFP_NOIO (__GFP_WAIT) -#define GFP_NOFS (__GFP_WAIT | __GFP_IO) -#define GFP_KERNEL (__GFP_WAIT | __GFP_IO | __GFP_FS) -#define GFP_USER (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL) -#define GFP_HIGHUSER (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL | \ - __GFP_HIGHMEM) +#define GFP_ATOMIC (__GFP_VALID | __GFP_HIGH) +#define GFP_NOIO (__GFP_VALID | __GFP_WAIT) +#define GFP_NOFS (__GFP_VALID | __GFP_WAIT | __GFP_IO) +#define GFP_KERNEL (__GFP_VALID | __GFP_WAIT | __GFP_IO | __GFP_FS) +#define GFP_USER (__GFP_VALID | __GFP_WAIT | __GFP_IO | __GFP_FS | \ + __GFP_HARDWALL) +#define GFP_HIGHUSER (__GFP_VALID | __GFP_WAIT | __GFP_IO | __GFP_FS | \ + __GFP_HIGHMEM | __GFP_HARDWALL) /* Flag - indicates that the buffer will be suitable for DMA. Ignored on some platforms, used as appropriate on others */ diff -puN include/linux/slab.h~make-kmalloc-fail-for-swapped-size--gfp-flags include/linux/slab.h --- devel/include/linux/slab.h~make-kmalloc-fail-for-swapped-size--gfp-flags 2005-09-12 03:34:46.000000000 -0700 +++ devel-akpm/include/linux/slab.h 2005-09-12 03:34:46.000000000 -0700 @@ -78,6 +78,10 @@ extern void *__kmalloc(size_t, unsigned static inline void *kmalloc(size_t size, unsigned int __nocast flags) { + if (__builtin_constant_p(flags) && !(flags & __GFP_VALID)) { + extern void __your_kmalloc_flags_are_not_valid(void); + __your_kmalloc_flags_are_not_valid(); + } if (__builtin_constant_p(size)) { int i = 0; #define CACHE(x) \ diff -puN mm/slab.c~make-kmalloc-fail-for-swapped-size--gfp-flags mm/slab.c --- devel/mm/slab.c~make-kmalloc-fail-for-swapped-size--gfp-flags 2005-09-12 03:34:46.000000000 -0700 +++ devel-akpm/mm/slab.c 2005-09-12 03:34:46.000000000 -0700 @@ -2159,7 +2159,7 @@ static int cache_grow(kmem_cache_t *cach /* Be lazy and only check for valid flags here, * keeping it out of the critical path in kmem_cache_alloc(). */ - if (flags & ~(SLAB_DMA|SLAB_LEVEL_MASK|SLAB_NO_GROW)) + if (flags & ~(SLAB_DMA|SLAB_LEVEL_MASK|SLAB_NO_GROW|__GFP_VALID)) BUG(); if (flags & SLAB_NO_GROW) return 0; diff -puN drivers/scsi/aic7xxx/aic79xx_osm.h~make-kmalloc-fail-for-swapped-size--gfp-flags drivers/scsi/aic7xxx/aic79xx_osm.h --- devel/drivers/scsi/aic7xxx/aic79xx_osm.h~make-kmalloc-fail-for-swapped-size--gfp-flags 2005-09-12 03:34:46.000000000 -0700 +++ devel-akpm/drivers/scsi/aic7xxx/aic79xx_osm.h 2005-09-12 03:34:46.000000000 -0700 @@ -404,7 +404,7 @@ struct ahd_platform_data { /************************** OS Utility Wrappers *******************************/ #define printf printk #define M_NOWAIT GFP_ATOMIC -#define M_WAITOK 0 +#define M_WAITOK GFP_KERNEL #define malloc(size, type, flags) kmalloc(size, flags) #define free(ptr, type) kfree(ptr) diff -puN arch/s390/mm/extmem.c~make-kmalloc-fail-for-swapped-size--gfp-flags arch/s390/mm/extmem.c --- devel/arch/s390/mm/extmem.c~make-kmalloc-fail-for-swapped-size--gfp-flags 2005-09-12 03:34:46.000000000 -0700 +++ devel-akpm/arch/s390/mm/extmem.c 2005-09-12 03:34:46.000000000 -0700 @@ -172,8 +172,8 @@ dcss_diag_translate_rc (int vm_rc) { static int query_segment_type (struct dcss_segment *seg) { - struct qin64 *qin = kmalloc (sizeof(struct qin64), GFP_DMA); - struct qout64 *qout = kmalloc (sizeof(struct qout64), GFP_DMA); + struct qin64 *qin = kmalloc (sizeof(struct qin64), GFP_DMA|GFP_KERNEL); + struct qout64 *qout = kmalloc (sizeof(struct qout64), GFP_DMA|GFP_KERNEL); int diag_cc, rc, i; unsigned long dummy, vmrc; @@ -332,7 +332,7 @@ static int __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long *end) { struct dcss_segment *seg = kmalloc(sizeof(struct dcss_segment), - GFP_DMA); + GFP_DMA|GFP_KERNEL); int dcss_command, rc, diag_cc; if (seg == NULL) { diff -puN arch/s390/appldata/appldata_os.c~make-kmalloc-fail-for-swapped-size--gfp-flags arch/s390/appldata/appldata_os.c --- devel/arch/s390/appldata/appldata_os.c~make-kmalloc-fail-for-swapped-size--gfp-flags 2005-09-12 03:34:46.000000000 -0700 +++ devel-akpm/arch/s390/appldata/appldata_os.c 2005-09-12 03:34:46.000000000 -0700 @@ -194,7 +194,7 @@ static int __init appldata_os_init(void) P_DEBUG("sizeof(os) = %i, sizeof(os_cpu) = %lu\n", size, sizeof(struct appldata_os_per_cpu)); - appldata_os_data = kmalloc(size, GFP_DMA); + appldata_os_data = kmalloc(size, GFP_DMA|GFP_KERNEL); if (appldata_os_data == NULL) { P_ERROR("No memory for %s!\n", ops.name); rc = -ENOMEM; diff -puN drivers/net/b44.c~make-kmalloc-fail-for-swapped-size--gfp-flags drivers/net/b44.c --- devel/drivers/net/b44.c~make-kmalloc-fail-for-swapped-size--gfp-flags 2005-09-12 03:34:46.000000000 -0700 +++ devel-akpm/drivers/net/b44.c 2005-09-12 03:34:46.000000000 -0700 @@ -633,7 +633,7 @@ static int b44_alloc_rx_skb(struct b44 * /* Sigh... */ pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE); dev_kfree_skb_any(skb); - skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA); + skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_ATOMIC|GFP_DMA); if (skb == NULL) return -ENOMEM; mapping = pci_map_single(bp->pdev, skb->data, diff -puN drivers/s390/net/claw.c~make-kmalloc-fail-for-swapped-size--gfp-flags drivers/s390/net/claw.c --- devel/drivers/s390/net/claw.c~make-kmalloc-fail-for-swapped-size--gfp-flags 2005-09-12 03:34:46.000000000 -0700 +++ devel-akpm/drivers/s390/net/claw.c 2005-09-12 03:34:46.000000000 -0700 @@ -2199,7 +2199,7 @@ init_ccw_bk(struct net_device *dev) */ if (privptr->p_buff_ccw==NULL) { privptr->p_buff_ccw= - (void *)__get_free_pages(__GFP_DMA, + (void *)__get_free_pages(__GFP_DMA|GFP_KERNEL, (int)pages_to_order_of_mag(ccw_pages_required )); if (privptr->p_buff_ccw==NULL) { printk(KERN_INFO "%s: %s() " @@ -2355,7 +2355,7 @@ init_ccw_bk(struct net_device *dev) if (privptr->p_buff_write==NULL) { if (privptr->p_env->write_size < PAGE_SIZE) { privptr->p_buff_write= - (void *)__get_free_pages(__GFP_DMA, + (void *)__get_free_pages(__GFP_DMA|GFP_KERNEL, (int)pages_to_order_of_mag(claw_write_pages )); if (privptr->p_buff_write==NULL) { printk(KERN_INFO "%s: %s() __get_free_pages for write" @@ -2414,7 +2414,7 @@ init_ccw_bk(struct net_device *dev) { privptr->p_write_free_chain=NULL; for (i = 0; i< privptr->p_env->write_buffers ; i++) { - p_buff=(void *)__get_free_pages(__GFP_DMA, + p_buff=(void *)__get_free_pages(__GFP_DMA|GFP_KERNEL, (int)pages_to_order_of_mag( privptr->p_buff_pages_perwrite) ); #ifdef IOTRACE @@ -2490,7 +2490,7 @@ init_ccw_bk(struct net_device *dev) if (privptr->p_buff_read==NULL) { if (privptr->p_env->read_size < PAGE_SIZE) { privptr->p_buff_read= - (void *)__get_free_pages(__GFP_DMA, + (void *)__get_free_pages(__GFP_DMA|GFP_KERNEL, (int)pages_to_order_of_mag(claw_read_pages) ); if (privptr->p_buff_read==NULL) { printk(KERN_INFO "%s: %s() " @@ -2604,7 +2604,7 @@ init_ccw_bk(struct net_device *dev) dev->name,__FUNCTION__); #endif for (i=0 ; i< privptr->p_env->read_buffers ; i++) { - p_buff = (void *)__get_free_pages(__GFP_DMA, + p_buff = (void *)__get_free_pages(__GFP_DMA|GFP_KERNEL, (int)pages_to_order_of_mag(privptr->p_buff_pages_perread) ); if (p_buff==NULL) { printk(KERN_INFO "%s: %s() __get_free_pages for read " diff -puN drivers/scsi/pluto.c~make-kmalloc-fail-for-swapped-size--gfp-flags drivers/scsi/pluto.c --- devel/drivers/scsi/pluto.c~make-kmalloc-fail-for-swapped-size--gfp-flags 2005-09-12 03:34:46.000000000 -0700 +++ devel-akpm/drivers/scsi/pluto.c 2005-09-12 03:34:46.000000000 -0700 @@ -116,7 +116,7 @@ int __init pluto_detect(Scsi_Host_Templa #endif return 0; } - fcs = (struct ctrl_inquiry *) kmalloc (sizeof (struct ctrl_inquiry) * fcscount, GFP_DMA); + fcs = (struct ctrl_inquiry *) kmalloc (sizeof (struct ctrl_inquiry) * fcscount, GFP_DMA|GFP_KERNEL); if (!fcs) { printk ("PLUTO: Not enough memory to probe\n"); return 0; _