linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] use size_t for the broken ioctl numbers
@ 2003-09-07  6:22 Matthew Wilcox
  2003-09-07 16:48 ` Andreas Schwab
  2003-09-08 12:38 ` Andries Brouwer
  0 siblings, 2 replies; 24+ messages in thread
From: Matthew Wilcox @ 2003-09-07  6:22 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel


Clearly it's too late to change the ioctl definitions, but we can at
least stop people from copying them and making the same mistake.

Index: Documentation/ioctl-number.txt
===================================================================
RCS file: /var/cvs/linux-2.6/Documentation/ioctl-number.txt,v
retrieving revision 1.1
diff -u -p -r1.1 ioctl-number.txt
--- Documentation/ioctl-number.txt	29 Jul 2003 17:00:10 -0000	1.1
+++ Documentation/ioctl-number.txt	7 Sep 2003 06:21:24 -0000
@@ -30,7 +30,9 @@ I'll register one for you.
 The second argument to _IO, _IOW, _IOR, or _IOWR is a sequence number
 to distinguish ioctls from each other.  The third argument to _IOW,
 _IOR, or _IOWR is the type of the data going into the kernel or coming
-out of the kernel (e.g.  'int' or 'struct foo').
+out of the kernel (e.g.  'int' or 'struct foo').  NOTE!  Do NOT use
+sizeof(arg) as the third argument as this results in your ioctl thinking
+it passes an argument of type size_t.
 
 Some devices use their major number as the identifier; this is OK, as
 long as it is unique.  Some devices are irregular and don't follow any
Index: include/linux/coda.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/linux/coda.h,v
retrieving revision 1.1
diff -u -p -r1.1 coda.h
--- include/linux/coda.h	29 Jul 2003 17:02:11 -0000	1.1
+++ include/linux/coda.h	7 Sep 2003 06:19:03 -0000
@@ -324,7 +324,7 @@ struct coda_statfs {
 #define VC_MAXMSGSIZE      sizeof(union inputArgs)+sizeof(union outputArgs) +\
                             VC_MAXDATASIZE  
 
-#define CIOC_KERNEL_VERSION _IOWR('c', 10, sizeof (int))
+#define CIOC_KERNEL_VERSION _IOWR('c', 10, size_t)
 
 #if 0
 #define CODA_KERNEL_VERSION 0 /* don't care about kernel version number */
Index: include/linux/fs.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/linux/fs.h,v
retrieving revision 1.3
diff -u -p -r1.3 fs.h
--- include/linux/fs.h	23 Aug 2003 02:47:23 -0000	1.3
+++ include/linux/fs.h	7 Sep 2003 06:19:03 -0000
@@ -188,15 +188,18 @@ extern int leases_enable, dir_notify_ena
 #define BLKSSZGET  _IO(0x12,104)/* get block device sector size */
 #if 0
 #define BLKPG      _IO(0x12,105)/* See blkpg.h */
-#define BLKELVGET  _IOR(0x12,106,sizeof(blkelv_ioctl_arg_t))/* elevator get */
-#define BLKELVSET  _IOW(0x12,107,sizeof(blkelv_ioctl_arg_t))/* elevator set */
+
+/* Some people are morons.  Do not use sizeof! */
+
+#define BLKELVGET  _IOR(0x12,106,size_t)/* elevator get */
+#define BLKELVSET  _IOW(0x12,107,size_t)/* elevator set */
 /* This was here just to show that the number is taken -
    probably all these _IO(0x12,*) ioctls should be moved to blkpg.h. */
 #endif
 /* A jump here: 108-111 have been used for various private purposes. */
-#define BLKBSZGET  _IOR(0x12,112,sizeof(int))
-#define BLKBSZSET  _IOW(0x12,113,sizeof(int))
-#define BLKGETSIZE64 _IOR(0x12,114,sizeof(u64))	/* return device size in bytes (u64 *arg) */
+#define BLKBSZGET  _IOR(0x12,112,size_t)
+#define BLKBSZSET  _IOW(0x12,113,size_t)
+#define BLKGETSIZE64 _IOR(0x12,114,size_t)	/* return device size in bytes (u64 *arg) */
 
 #define BMAP_IOCTL 1		/* obsolete - kept for compatibility */
 #define FIBMAP	   _IO(0x00,1)	/* bmap access */
Index: include/linux/i8k.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/linux/i8k.h,v
retrieving revision 1.1
diff -u -p -r1.1 i8k.h
--- include/linux/i8k.h	29 Jul 2003 17:02:12 -0000	1.1
+++ include/linux/i8k.h	7 Sep 2003 06:19:03 -0000
@@ -22,12 +22,12 @@
 
 #define I8K_BIOS_VERSION	_IOR ('i', 0x80, 4)
 #define I8K_MACHINE_ID		_IOR ('i', 0x81, 16)
-#define I8K_POWER_STATUS	_IOR ('i', 0x82, sizeof(int))
-#define I8K_FN_STATUS		_IOR ('i', 0x83, sizeof(int))
-#define I8K_GET_TEMP		_IOR ('i', 0x84, sizeof(int))
-#define I8K_GET_SPEED		_IOWR('i', 0x85, sizeof(int))
-#define I8K_GET_FAN		_IOWR('i', 0x86, sizeof(int))
-#define I8K_SET_FAN		_IOWR('i', 0x87, sizeof(int)*2)
+#define I8K_POWER_STATUS	_IOR ('i', 0x82, size_t)
+#define I8K_FN_STATUS		_IOR ('i', 0x83, size_t)
+#define I8K_GET_TEMP		_IOR ('i', 0x84, size_t)
+#define I8K_GET_SPEED		_IOWR('i', 0x85, size_t)
+#define I8K_GET_FAN		_IOWR('i', 0x86, size_t)
+#define I8K_SET_FAN		_IOWR('i', 0x87, size_t)
 
 #define I8K_FAN_LEFT		1
 #define I8K_FAN_RIGHT		0
Index: include/linux/if_pppox.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/linux/if_pppox.h,v
retrieving revision 1.1
diff -u -p -r1.1 if_pppox.h
--- include/linux/if_pppox.h	29 Jul 2003 17:02:12 -0000	1.1
+++ include/linux/if_pppox.h	7 Sep 2003 06:19:03 -0000
@@ -67,9 +67,9 @@ struct sockaddr_pppox { 
  *
  ********************************************************************/
 
-#define PPPOEIOCSFWD	_IOW(0xB1 ,0, sizeof(struct sockaddr_pppox))
+#define PPPOEIOCSFWD	_IOW(0xB1 ,0, size_t)
 #define PPPOEIOCDFWD	_IO(0xB1 ,1)
-/*#define PPPOEIOCGFWD	_IOWR(0xB1,2, sizeof(struct sockaddr_pppox))*/
+/*#define PPPOEIOCGFWD	_IOWR(0xB1,2, size_t)*/
 
 /* Codes to identify message types */
 #define PADI_CODE	0x09
Index: include/linux/input.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/linux/input.h,v
retrieving revision 1.8
diff -u -p -r1.8 input.h
--- include/linux/input.h	23 Aug 2003 02:57:02 -0000	1.8
+++ include/linux/input.h	7 Sep 2003 06:19:03 -0000
@@ -73,7 +73,7 @@ struct input_absinfo {
 #define EVIOCGABS(abs)		_IOR('E', 0x40 + abs, struct input_absinfo)		/* get abs value/limits */
 #define EVIOCSABS(abs)		_IOW('E', 0xc0 + abs, struct input_absinfo)		/* set abs value/limits */
 
-#define EVIOCSFF		_IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect))	/* send a force effect to a force feedback device */
+#define EVIOCSFF		_IOC(_IOC_WRITE, 'E', 0x80, size_t)	/* send a force effect to a force feedback device */
 #define EVIOCRMFF		_IOW('E', 0x81, int)			/* Erase a force effect */
 #define EVIOCGEFFECTS		_IOR('E', 0x84, int)			/* Report number of effects playable at the same time */
 
Index: include/linux/matroxfb.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/linux/matroxfb.h,v
retrieving revision 1.1
diff -u -p -r1.1 matroxfb.h
--- include/linux/matroxfb.h	29 Jul 2003 17:02:13 -0000	1.1
+++ include/linux/matroxfb.h	7 Sep 2003 06:19:03 -0000
@@ -15,21 +15,21 @@ struct matroxioc_output_mode {
 #define MATROXFB_OUTPUT_MODE_NTSC	0x0002
 #define MATROXFB_OUTPUT_MODE_MONITOR	0x0080
 };
-#define MATROXFB_SET_OUTPUT_MODE	_IOW('n',0xFA,sizeof(struct matroxioc_output_mode))
-#define MATROXFB_GET_OUTPUT_MODE	_IOWR('n',0xFA,sizeof(struct matroxioc_output_mode))
+#define MATROXFB_SET_OUTPUT_MODE	_IOW('n',0xFA,size_t)
+#define MATROXFB_GET_OUTPUT_MODE	_IOWR('n',0xFA,size_t)
 
 /* bitfield */
 #define MATROXFB_OUTPUT_CONN_PRIMARY	(1 << MATROXFB_OUTPUT_PRIMARY)
 #define MATROXFB_OUTPUT_CONN_SECONDARY	(1 << MATROXFB_OUTPUT_SECONDARY)
 #define MATROXFB_OUTPUT_CONN_DFP	(1 << MATROXFB_OUTPUT_DFP)
 /* connect these outputs to this framebuffer */
-#define MATROXFB_SET_OUTPUT_CONNECTION	_IOW('n',0xF8,sizeof(__u32))
+#define MATROXFB_SET_OUTPUT_CONNECTION	_IOW('n',0xF8,size_t)
 /* which outputs are connected to this framebuffer */
-#define MATROXFB_GET_OUTPUT_CONNECTION	_IOR('n',0xF8,sizeof(__u32))
+#define MATROXFB_GET_OUTPUT_CONNECTION	_IOR('n',0xF8,size_t)
 /* which outputs are available for this framebuffer */
-#define MATROXFB_GET_AVAILABLE_OUTPUTS	_IOR('n',0xF9,sizeof(__u32))
+#define MATROXFB_GET_AVAILABLE_OUTPUTS	_IOR('n',0xF9,size_t)
 /* which outputs exist on this framebuffer */
-#define MATROXFB_GET_ALL_OUTPUTS	_IOR('n',0xFB,sizeof(__u32))
+#define MATROXFB_GET_ALL_OUTPUTS	_IOR('n',0xFB,size_t)
 
 enum matroxfb_ctrl_id {
   MATROXFB_CID_TESTOUT	 = V4L2_CID_PRIVATE_BASE,
Index: include/linux/pmu.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/linux/pmu.h,v
retrieving revision 1.1
diff -u -p -r1.1 pmu.h
--- include/linux/pmu.h	29 Jul 2003 17:02:14 -0000	1.1
+++ include/linux/pmu.h	7 Sep 2003 06:19:03 -0000
@@ -107,15 +107,15 @@ enum {
 /* no param */
 #define PMU_IOC_SLEEP		_IO('B', 0)
 /* out param: u32*	backlight value: 0 to 15 */
-#define PMU_IOC_GET_BACKLIGHT	_IOR('B', 1, sizeof(__u32*))
+#define PMU_IOC_GET_BACKLIGHT	_IOR('B', 1, size_t)
 /* in param: u32	backlight value: 0 to 15 */
-#define PMU_IOC_SET_BACKLIGHT	_IOW('B', 2, sizeof(__u32))
+#define PMU_IOC_SET_BACKLIGHT	_IOW('B', 2, size_t)
 /* out param: u32*	PMU model */
-#define PMU_IOC_GET_MODEL	_IOR('B', 3, sizeof(__u32*))
+#define PMU_IOC_GET_MODEL	_IOR('B', 3, size_t)
 /* out param: u32*	has_adb: 0 or 1 */
-#define PMU_IOC_HAS_ADB		_IOR('B', 4, sizeof(__u32*)) 
+#define PMU_IOC_HAS_ADB		_IOR('B', 4, size_t) 
 /* out param: u32*	can_sleep: 0 or 1 */
-#define PMU_IOC_CAN_SLEEP	_IOR('B', 5, sizeof(__u32*)) 
+#define PMU_IOC_CAN_SLEEP	_IOR('B', 5, size_t) 
 /* no param */
 #define PMU_IOC_GRAB_BACKLIGHT	_IOR('B', 6, 0) 
 
Index: include/linux/radeonfb.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/linux/radeonfb.h,v
retrieving revision 1.1
diff -u -p -r1.1 radeonfb.h
--- include/linux/radeonfb.h	29 Jul 2003 17:02:14 -0000	1.1
+++ include/linux/radeonfb.h	7 Sep 2003 06:19:03 -0000
@@ -8,8 +8,8 @@
 #define ATY_RADEON_CRT_ON	0x00000002
 
 
-#define FBIO_RADEON_GET_MIRROR	_IOR('@', 3, sizeof(__u32*))
-#define FBIO_RADEON_SET_MIRROR	_IOW('@', 4, sizeof(__u32*))
+#define FBIO_RADEON_GET_MIRROR	_IOR('@', 3, size_t)
+#define FBIO_RADEON_SET_MIRROR	_IOW('@', 4, size_t)
 
 #endif
 

-- 
"It's not Hollywood.  War is real, war is primarily not about defeat or
victory, it is about death.  I've seen thousands and thousands of dead bodies.
Do you think I want to have an academic debate on this subject?" -- Robert Fisk

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-07  6:22 [PATCH] use size_t for the broken ioctl numbers Matthew Wilcox
@ 2003-09-07 16:48 ` Andreas Schwab
  2003-09-07 17:29   ` Linus Torvalds
  2003-09-08 12:38 ` Andries Brouwer
  1 sibling, 1 reply; 24+ messages in thread
From: Andreas Schwab @ 2003-09-07 16:48 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: Linus Torvalds, linux-kernel

Matthew Wilcox <willy@debian.org> writes:

> Index: include/linux/i8k.h
> ===================================================================
> RCS file: /var/cvs/linux-2.6/include/linux/i8k.h,v
> retrieving revision 1.1
> diff -u -p -r1.1 i8k.h
> --- include/linux/i8k.h	29 Jul 2003 17:02:12 -0000	1.1
> +++ include/linux/i8k.h	7 Sep 2003 06:19:03 -0000
> @@ -22,12 +22,12 @@
>  
>  #define I8K_BIOS_VERSION	_IOR ('i', 0x80, 4)
>  #define I8K_MACHINE_ID		_IOR ('i', 0x81, 16)

These should probably be changed to use int instead of the number.

Here is a patch that enforces the use of types in the third argument.  It
requires gcc >= 3.1 for the check to work, I couldn't find a method for
previous versions.  This is tested on ia64, both 2.4.21 and 2.6.0-test4
(the former does not have asm-arm26, asm-h8300 and asm-v850, and latter
does not have asm-mips64 and asm-s390x, so you get some rejects in either
case).

Andreas.

--- include/asm-alpha/ioctl.h.~1~	1996-03-24 11:09:36.000000000 +0100
+++ include/asm-alpha/ioctl.h	2003-09-07 16:35:59.000000000 +0200
@@ -43,11 +43,18 @@
 	  ((nr)   << _IOC_NRSHIFT) |		\
 	  ((size) << _IOC_SIZESHIFT)))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a parse error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) ((void)__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode them.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- include/asm-arm/ioctl.h.~1~	2003-09-07 16:38:05.000000000 +0200
+++ include/asm-arm/ioctl.h	2003-09-07 16:38:22.000000000 +0200
@@ -51,11 +51,18 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a parse error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) ((void)__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode ioctl numbers.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- include/asm-arm26/ioctl.h.~1~	2003-08-23 01:57:53.000000000 +0200
+++ include/asm-arm26/ioctl.h	2003-09-07 18:39:32.000000000 +0200
@@ -51,11 +51,18 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a syntax error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) (__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode ioctl numbers.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- include/asm-cris/ioctl.h.~1~	2001-02-09 01:32:44.000000000 +0100
+++ include/asm-cris/ioctl.h	2003-09-07 16:36:36.000000000 +0200
@@ -53,11 +53,18 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a parse error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) ((void)__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode ioctl numbers.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- include/asm-h8300/ioctl.h.~1~	2003-08-23 01:56:17.000000000 +0200
+++ include/asm-h8300/ioctl.h	2003-09-07 18:41:08.000000000 +0200
@@ -57,11 +57,18 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a syntax error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) (__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode ioctl numbers.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- include/asm-i386/ioctl.h.~1~	1995-11-15 08:15:02.000000000 +0100
+++ include/asm-i386/ioctl.h	2003-09-07 16:38:54.000000000 +0200
@@ -52,11 +52,18 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a parse error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) ((void)__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode ioctl numbers.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- include/asm-ia64/ioctl.h.~1~	2000-02-07 03:42:40.000000000 +0100
+++ include/asm-ia64/ioctl.h	2003-09-07 16:39:19.000000000 +0200
@@ -54,11 +54,18 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a parse error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) ((void)__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode ioctl numbers.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- include/asm-m68k/ioctl.h.~1~	1997-04-24 04:01:27.000000000 +0200
+++ include/asm-m68k/ioctl.h	2003-09-07 16:39:40.000000000 +0200
@@ -57,11 +57,18 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a parse error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) ((void)__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode ioctl numbers.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- include/asm-mips/ioctl.h.~1~	2001-07-02 22:56:40.000000000 +0200
+++ include/asm-mips/ioctl.h	2003-09-07 16:43:02.000000000 +0200
@@ -62,11 +62,18 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a parse error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) ((void)__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode them.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- include/asm-mips64/ioctl.h.~1~	2001-09-09 19:43:02.000000000 +0200
+++ include/asm-mips64/ioctl.h	2003-09-07 16:41:13.000000000 +0200
@@ -65,11 +65,18 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a parse error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) ((void)__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode them.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- include/asm-parisc/ioctl.h.~1~	2000-12-05 21:29:39.000000000 +0100
+++ include/asm-parisc/ioctl.h	2003-09-07 16:41:35.000000000 +0200
@@ -44,11 +44,18 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a parse error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) ((void)__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode ioctl numbers.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- include/asm-ppc/ioctl.h.~1~	2003-06-13 16:51:38.000000000 +0200
+++ include/asm-ppc/ioctl.h	2003-09-07 16:43:42.000000000 +0200
@@ -37,11 +37,18 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a parse error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) ((void)__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode them.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- include/asm-ppc64/ioctl.h.~1~	2002-08-03 02:39:45.000000000 +0200
+++ include/asm-ppc64/ioctl.h	2003-09-07 16:42:26.000000000 +0200
@@ -42,11 +42,18 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a parse error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) ((void)__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode them.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- include/asm-s390/ioctl.h.~1~	2000-05-12 20:41:44.000000000 +0200
+++ include/asm-s390/ioctl.h	2003-09-07 16:43:20.000000000 +0200
@@ -55,11 +55,18 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a parse error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) ((void)__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode ioctl numbers.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- include/asm-s390x/ioctl.h.~1~	2001-02-13 23:13:44.000000000 +0100
+++ include/asm-s390x/ioctl.h	2003-09-07 16:42:08.000000000 +0200
@@ -55,11 +55,18 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a parse error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) ((void)__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode ioctl numbers.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- include/asm-sh/ioctl.h.~1~	2001-10-15 22:36:48.000000000 +0200
+++ include/asm-sh/ioctl.h	2003-09-07 16:40:30.000000000 +0200
@@ -52,11 +52,18 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a parse error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) ((void)__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode ioctl numbers.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- include/asm-sparc/ioctl.h.~1~	2003-06-13 16:51:38.000000000 +0200
+++ include/asm-sparc/ioctl.h	2003-09-07 16:42:42.000000000 +0200
@@ -42,10 +42,17 @@
          ((nr)   << _IOC_NRSHIFT) | \
          ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a parse error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) ((void)__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 #define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)  _IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)  _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)  _IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)  _IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* Used to decode ioctl numbers in drivers despite the leading underscore... */
 #define _IOC_DIR(nr)    \
--- include/asm-sparc64/ioctl.h.~1~	2003-06-13 16:51:38.000000000 +0200
+++ include/asm-sparc64/ioctl.h	2003-09-07 16:43:59.000000000 +0200
@@ -42,10 +42,17 @@
          ((nr)   << _IOC_NRSHIFT) | \
          ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a parse error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) ((void)__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 #define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)  _IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)  _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)  _IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)  _IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* Used to decode ioctl numbers in drivers despite the leading underscore... */
 #define _IOC_DIR(nr)    \
--- include/asm-v850/ioctl.h.~1~	2003-08-23 01:52:59.000000000 +0200
+++ include/asm-v850/ioctl.h	2003-09-07 18:42:51.000000000 +0200
@@ -57,11 +57,18 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a syntax error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) (__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode ioctl numbers.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
--- include/asm-x86_64/ioctl.h.~1~	2002-11-29 00:53:15.000000000 +0100
+++ include/asm-x86_64/ioctl.h	2003-09-07 16:41:51.000000000 +0200
@@ -52,11 +52,18 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+/* This gives a parse error when T is not a type. */
+#define _IOC_CHECK_TYPE(t) ((void)__builtin_types_compatible_p(t, void))
+#else
+#define _IOC_CHECK_TYPE(t) ((void)0)
+#endif
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_CHECK_TYPE(size),sizeof(size)))
 
 /* used to decode ioctl numbers.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-07 16:48 ` Andreas Schwab
@ 2003-09-07 17:29   ` Linus Torvalds
  2003-09-07 17:34     ` Andreas Schwab
  0 siblings, 1 reply; 24+ messages in thread
From: Linus Torvalds @ 2003-09-07 17:29 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Matthew Wilcox, linux-kernel


On Sun, 7 Sep 2003, Andreas Schwab wrote:
> 
> Here is a patch that enforces the use of types in the third argument.  It
> requires gcc >= 3.1 for the check to work, I couldn't find a method for
> previous versions.

Ehh, what's wrong with the obvious approach: declare a dummy variable. If 
it's not a type, then the declaration won't work.

Ie, change the (sizeof(x)) to something like

	({ x __dummy; sizeof(__dummy); })

which should work with all compiler versions.

Anything that requires a new compiler is always a big dodgy as a sanity 
check. People who don't have the new compiler won't be testing it, so 
they'll just continually break it for people who _do_. Aggravation 
nightmare.

		Linus


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-07 17:29   ` Linus Torvalds
@ 2003-09-07 17:34     ` Andreas Schwab
  2003-09-08 13:10       ` Ingo Oeser
  0 siblings, 1 reply; 24+ messages in thread
From: Andreas Schwab @ 2003-09-07 17:34 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Matthew Wilcox, linux-kernel

Linus Torvalds <torvalds@osdl.org> writes:

> On Sun, 7 Sep 2003, Andreas Schwab wrote:
>> 
>> Here is a patch that enforces the use of types in the third argument.  It
>> requires gcc >= 3.1 for the check to work, I couldn't find a method for
>> previous versions.
>
> Ehh, what's wrong with the obvious approach: declare a dummy variable. If 
> it's not a type, then the declaration won't work.
>
> Ie, change the (sizeof(x)) to something like
>
> 	({ x __dummy; sizeof(__dummy); })
>
> which should work with all compiler versions.

This won't work with array types, eg. in <linux/random.h>:

#define RNDGETPOOL	_IOR( 'R', 0x02, int [2] )

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-07  6:22 [PATCH] use size_t for the broken ioctl numbers Matthew Wilcox
  2003-09-07 16:48 ` Andreas Schwab
@ 2003-09-08 12:38 ` Andries Brouwer
  2003-09-08 15:13   ` Linus Torvalds
  2003-09-09 11:40   ` Jens Axboe
  1 sibling, 2 replies; 24+ messages in thread
From: Andries Brouwer @ 2003-09-08 12:38 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: Linus Torvalds, linux-kernel

On Sun, Sep 07, 2003 at 07:22:48AM +0100, Matthew Wilcox wrote:

> Clearly it's too late to change the ioctl definitions, but we can at
> least stop people from copying them and making the same mistake.

> -#define BLKELVSET  _IOW(0x12,107,sizeof(blkelv_ioctl_arg_t))/* elevator set */
> +#define BLKELVSET  _IOW(0x12,107,size_t)/* elevator set */

Here we lose information - I don't like that.
Often it is important to know what kind of argument an ioctl has,
and that info should be easy to find.

I see other parts of this thread discuss the question on how to force people
to do things right in new cases. For old cases, instead of throwing out
the information that a blkelv_ioctl_arg_t is involved, I would like to write

#define BLKELVSET  _IOW_BAD(0x12,107,blkelv_ioctl_arg_t)

with

#define _IOW_BAD( ... ) _IOW(..., sizeof(...))

(with s/_IOW/_IOW_NOCK/ in case _IOW is changed so as to check).

Andries


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-07 17:34     ` Andreas Schwab
@ 2003-09-08 13:10       ` Ingo Oeser
  0 siblings, 0 replies; 24+ messages in thread
From: Ingo Oeser @ 2003-09-08 13:10 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Linus Torvalds, Matthew Wilcox, linux-kernel

On Sunday 07 September 2003 19:34, Andreas Schwab wrote:
> Linus Torvalds <torvalds@osdl.org> writes:
> > 	({ x __dummy; sizeof(__dummy); })
> >
> > which should work with all compiler versions.
>
> This won't work with array types, eg. in <linux/random.h>:
>
> #define RNDGETPOOL	_IOR( 'R', 0x02, int [2] )

It would, if you did this 

#define RNDGETPOOL _IOR('R', 0x02, struct { int x[2];})

I would vote for simply forbidding arrays in this situation (which the compile 
error will handle as well ;-)). Just another case of "Doctor it hurts!"

Regards

Ingo Oeser



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-08 12:38 ` Andries Brouwer
@ 2003-09-08 15:13   ` Linus Torvalds
  2003-09-08 18:40     ` Andries Brouwer
  2003-09-09 11:40   ` Jens Axboe
  1 sibling, 1 reply; 24+ messages in thread
From: Linus Torvalds @ 2003-09-08 15:13 UTC (permalink / raw)
  To: Andries Brouwer; +Cc: Matthew Wilcox, linux-kernel


On Mon, 8 Sep 2003, Andries Brouwer wrote:
> 
> > -#define BLKELVSET  _IOW(0x12,107,sizeof(blkelv_ioctl_arg_t))/* elevator set */
> > +#define BLKELVSET  _IOW(0x12,107,size_t)/* elevator set */
> 
> Here we lose information - I don't like that.
> Often it is important to know what kind of argument an ioctl has,
> and that info should be easy to find.

In the ones I converted I added a comment. That should be sufficient, and 
if anybody cares strongly, a patch to me to add comments to the ones 
Matthew converted will also be applied.

I'd _much_ rather have a comment than make up some new "bad define" thing.

		Linus


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-08 15:13   ` Linus Torvalds
@ 2003-09-08 18:40     ` Andries Brouwer
  2003-09-08 18:54       ` Linus Torvalds
  2003-09-08 19:28       ` Randy.Dunlap
  0 siblings, 2 replies; 24+ messages in thread
From: Andries Brouwer @ 2003-09-08 18:40 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Andries Brouwer, Matthew Wilcox, linux-kernel

On Mon, Sep 08, 2003 at 08:13:53AM -0700, Linus Torvalds wrote:

> I'd _much_ rather have a comment than make up some new "bad define" thing.

Pity.

(It is not important, but having the type formally visible
makes it easier to do automatic verification of contexts like
	FOOIOCTL:
	    {
		struct foo_arg *uarg = (struct foo_arg *) arg;
		err = handle_fooioctl(fd, uarg);
		break;
	    }
One might even wish to generate them automatically.
I think relegating the type to a comment is a microstep in the wrong direction.)

Andries



[That reminds me - you announced sparse, a source checker.
Is it available for non bk users? I haven't seen a URL.]


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-08 18:40     ` Andries Brouwer
@ 2003-09-08 18:54       ` Linus Torvalds
  2003-09-08 19:28       ` Randy.Dunlap
  1 sibling, 0 replies; 24+ messages in thread
From: Linus Torvalds @ 2003-09-08 18:54 UTC (permalink / raw)
  To: Andries Brouwer; +Cc: Matthew Wilcox, linux-kernel


On Mon, 8 Sep 2003, Andries Brouwer wrote:

> On Mon, Sep 08, 2003 at 08:13:53AM -0700, Linus Torvalds wrote:
> 
> > I'd _much_ rather have a comment than make up some new "bad define" thing.
> 
> Pity.

Note that Arnd's "extra-anal check" added a XXX_BAD() define after all, 
and I ended up accepting that one, because it had a totally valid usage: 
it fixed a real issue not with bad type passing, but with passing types 
that are too _big_. 

I fixed two cases that I found where this was the case, there might be
others (I did a maxconfig, but on SMP. There might be some UP-only driver
that is affected by this).

But I'm too lazy to go back and fix up the older fixes, so..

		Linus


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-08 18:40     ` Andries Brouwer
  2003-09-08 18:54       ` Linus Torvalds
@ 2003-09-08 19:28       ` Randy.Dunlap
  2003-09-08 19:53         ` Jeff Garzik
  2003-09-08 20:27         ` Andries Brouwer
  1 sibling, 2 replies; 24+ messages in thread
From: Randy.Dunlap @ 2003-09-08 19:28 UTC (permalink / raw)
  To: Andries Brouwer; +Cc: torvalds, aebr, willy, linux-kernel

On Mon, 8 Sep 2003 20:40:23 +0200 Andries Brouwer <aebr@win.tue.nl> wrote:

| [That reminds me - you announced sparse, a source checker.
| Is it available for non bk users? I haven't seen a URL.]

Dave Jones puts snapshots of it at
http://www.codemonkey.org.uk/projects/sparse/

--
~Randy

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-08 19:28       ` Randy.Dunlap
@ 2003-09-08 19:53         ` Jeff Garzik
  2003-09-08 20:15           ` Linus Torvalds
  2003-09-08 20:27         ` Andries Brouwer
  1 sibling, 1 reply; 24+ messages in thread
From: Jeff Garzik @ 2003-09-08 19:53 UTC (permalink / raw)
  To: Randy.Dunlap; +Cc: Andries Brouwer, torvalds, willy, linux-kernel

On Mon, Sep 08, 2003 at 12:28:53PM -0700, Randy.Dunlap wrote:
> On Mon, 8 Sep 2003 20:40:23 +0200 Andries Brouwer <aebr@win.tue.nl> wrote:
> 
> | [That reminds me - you announced sparse, a source checker.
> | Is it available for non bk users? I haven't seen a URL.]
> 
> Dave Jones puts snapshots of it at
> http://www.codemonkey.org.uk/projects/sparse/

I should send Linus my snapshot script ;-)

	Jeff




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-08 19:53         ` Jeff Garzik
@ 2003-09-08 20:15           ` Linus Torvalds
  2003-09-08 20:26             ` Dave Jones
  0 siblings, 1 reply; 24+ messages in thread
From: Linus Torvalds @ 2003-09-08 20:15 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Randy.Dunlap, Andries Brouwer, willy, linux-kernel


On Mon, 8 Sep 2003, Jeff Garzik wrote:
> 
> I should send Linus my snapshot script ;-)

Oh, please don't. I wouldn't use it anyway.

I'm a big believer in avoiding unnecessary work - especially stuff I'm not
good at. And maintaining automated scripts falls under that description. 
I'm a total disaster when it comes to MIS-like things.

		Linus


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-08 20:15           ` Linus Torvalds
@ 2003-09-08 20:26             ` Dave Jones
  2003-09-08 21:53               ` Jeff Garzik
  0 siblings, 1 reply; 24+ messages in thread
From: Dave Jones @ 2003-09-08 20:26 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Jeff Garzik, Randy.Dunlap, Andries Brouwer, willy, linux-kernel

On Mon, Sep 08, 2003 at 01:15:26PM -0700, Linus Torvalds wrote:
 > On Mon, 8 Sep 2003, Jeff Garzik wrote:
 > > I should send Linus my snapshot script ;-)
 > Oh, please don't. I wouldn't use it anyway.
 > 
 > I'm a big believer in avoiding unnecessary work - especially stuff I'm not
 > good at. And maintaining automated scripts falls under that description. 
 > I'm a total disaster when it comes to MIS-like things.
 
Then the snapshot robot will continue to make them available for
non-bk users at http://www.codemonkey.org.uk/projects/sparse

Right now, it deletes snapshots after a week. I figure anyone who wanted
to find regressions, or step back through the history could extract it
from the bk web frontend (or use bk).  If anyone would prefer me to keep
them there longer, shout and I'll change the script.

		Dave

-- 
 Dave Jones     http://www.codemonkey.org.uk

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-08 19:28       ` Randy.Dunlap
  2003-09-08 19:53         ` Jeff Garzik
@ 2003-09-08 20:27         ` Andries Brouwer
  2003-09-08 20:43           ` Linus Torvalds
  1 sibling, 1 reply; 24+ messages in thread
From: Andries Brouwer @ 2003-09-08 20:27 UTC (permalink / raw)
  To: Randy.Dunlap; +Cc: Andries Brouwer, torvalds, willy, linux-kernel

On Mon, Sep 08, 2003 at 12:28:53PM -0700, Randy.Dunlap wrote:

> | [That reminds me - you announced sparse, a source checker.
> | Is it available for non bk users? I haven't seen a URL.]
> 
> Dave Jones puts snapshots of it at
> http://www.codemonkey.org.uk/projects/sparse/

Got it. Thanks!


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-08 20:27         ` Andries Brouwer
@ 2003-09-08 20:43           ` Linus Torvalds
  0 siblings, 0 replies; 24+ messages in thread
From: Linus Torvalds @ 2003-09-08 20:43 UTC (permalink / raw)
  To: Andries Brouwer; +Cc: Randy.Dunlap, willy, linux-kernel


On Mon, 8 Sep 2003, Andries Brouwer wrote:
> 
> Got it. Thanks!

Side notes:

 - Jeff made a mailing list if you're really interested in sparse 
   (majordomo@vger.kernel.org, the list name is "linux-sparse")

 - most of the warnings right now seem to be "bad constant expression" due 
   to the adoption of C99 variable-sized arrays in <linux/bitmap.h>. I 
   don't much like it.

 - the rest are mostly due to the address space checks. Some of them are 
   likely trivial to fix, but the most interesting ones (in the networking 
   code) are because the networking code re-uses the same data structures 
   for both kernel and user addresses. David said he'd fix it a long time 
   ago, but he never got around to it..

Finally:

 - it's not seriously usable yet. It's _almost_ there, but especially the 
   networking thing has kept me from being very motivated lately. I've 
   documented some of the preprocessor limitations in the "validation" 
   tests.

Have fun.

		Linus


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-08 20:26             ` Dave Jones
@ 2003-09-08 21:53               ` Jeff Garzik
  2003-09-08 22:25                 ` Dave Jones
  0 siblings, 1 reply; 24+ messages in thread
From: Jeff Garzik @ 2003-09-08 21:53 UTC (permalink / raw)
  To: Dave Jones
  Cc: Linus Torvalds, Randy.Dunlap, Andries Brouwer, willy, linux-kernel

Dave Jones wrote:
> Then the snapshot robot will continue to make them available for
> non-bk users at http://www.codemonkey.org.uk/projects/sparse

Cool, thanks!


> Right now, it deletes snapshots after a week. I figure anyone who wanted
> to find regressions, or step back through the history could extract it
> from the bk web frontend (or use bk).  If anyone would prefer me to keep
> them there longer, shout and I'll change the script.

Any chance you can dump the top-of-tree key and changelog too? 
Something like

	cd sparse
	bk changes -k | head -1 > sparse-2003-09-08.key
	bk changes > sparse-2003-09-08.log



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-08 21:53               ` Jeff Garzik
@ 2003-09-08 22:25                 ` Dave Jones
  0 siblings, 0 replies; 24+ messages in thread
From: Dave Jones @ 2003-09-08 22:25 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: Linus Torvalds, Randy.Dunlap, Andries Brouwer, willy, linux-kernel

On Mon, Sep 08, 2003 at 05:53:38PM -0400, Jeff Garzik wrote:

 > Any chance you can dump the top-of-tree key and changelog too? 
 > Something like
 > 
 > 	cd sparse
 > 	bk changes -k | head -1 > sparse-2003-09-08.key
 > 	bk changes > sparse-2003-09-08.log

Done.

		Dave

-- 
 Dave Jones     http://www.codemonkey.org.uk

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-08 12:38 ` Andries Brouwer
  2003-09-08 15:13   ` Linus Torvalds
@ 2003-09-09 11:40   ` Jens Axboe
  1 sibling, 0 replies; 24+ messages in thread
From: Jens Axboe @ 2003-09-09 11:40 UTC (permalink / raw)
  To: Andries Brouwer; +Cc: Matthew Wilcox, Linus Torvalds, linux-kernel

On Mon, Sep 08 2003, Andries Brouwer wrote:
> On Sun, Sep 07, 2003 at 07:22:48AM +0100, Matthew Wilcox wrote:
> 
> > Clearly it's too late to change the ioctl definitions, but we can at
> > least stop people from copying them and making the same mistake.
> 
> > -#define BLKELVSET  _IOW(0x12,107,sizeof(blkelv_ioctl_arg_t))/* elevator set */
> > +#define BLKELVSET  _IOW(0x12,107,size_t)/* elevator set */
> 
> Here we lose information - I don't like that.
> Often it is important to know what kind of argument an ioctl has,
> and that info should be easy to find.

Just kill them, they are not used.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-08 13:03         ` Arnd Bergmann
  2003-09-08 13:33           ` Andreas Schwab
@ 2003-09-08 13:35           ` Andries Brouwer
  1 sibling, 0 replies; 24+ messages in thread
From: Andries Brouwer @ 2003-09-08 13:35 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Linus Torvalds, Andreas Schwab, linux-kernel, Matthew Wilcox

On Mon, Sep 08, 2003 at 03:03:20PM +0200, Arnd Bergmann wrote:

> +#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
> +#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
> +#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
> +#define _IOR_BAD(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
> +#define _IOW_BAD(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
> +#define _IOWR_BAD(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))

Yes, good.
Then I have another trivial request: change the identifier used for the third parameter.
Since it is called "size" people think that it is a size.
The new checking will hit them, but still, it would be good to use
the correct identifiers. What about "argtype"?

Andries


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-08 13:03         ` Arnd Bergmann
@ 2003-09-08 13:33           ` Andreas Schwab
  2003-09-08 13:35           ` Andries Brouwer
  1 sibling, 0 replies; 24+ messages in thread
From: Andreas Schwab @ 2003-09-08 13:33 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Linus Torvalds, linux-kernel, Matthew Wilcox

Arnd Bergmann <arnd@arndb.de> writes:

> --- 1.1/include/asm-i386/ioctl.h	Tue Feb  5 18:39:44 2002
> +++ edited/include/asm-i386/ioctl.h	Mon Sep  8 13:21:28 2003
> @@ -52,11 +52,21 @@
>  	 ((nr)   << _IOC_NRSHIFT) | \
>  	 ((size) << _IOC_SIZESHIFT))
>  
> +/* provoke compile error for invalid uses of size argument */
> +extern int __invalid_size_argument_for_IOC;
> +#define _IOC_TYPECHECK(t) \
> +	((sizeof(t) == sizeof(t[1]) && \
> +	  sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
> +	  sizeof(t) : __invalid_size_argument_for_IOC)

This will fail when compiled unoptimized, which means that glibc could not
use <asm/ioctls.h> any more.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-07 23:21       ` Linus Torvalds
@ 2003-09-08 13:03         ` Arnd Bergmann
  2003-09-08 13:33           ` Andreas Schwab
  2003-09-08 13:35           ` Andries Brouwer
  0 siblings, 2 replies; 24+ messages in thread
From: Arnd Bergmann @ 2003-09-08 13:03 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Andreas Schwab, linux-kernel, Matthew Wilcox

On Monday 08 September 2003 01:21, Linus Torvalds wrote:

> In fact, what you'd want to do is not just verify that it compiles, but
> also verify that the object code matches.

I have checked now that the object code for arch/s390/kernel/compat_ioctl.o
remains identical and that the whole kernel compiles for s390 and i386,
after fixing the broken ioctl numbers.

> Because there _is_ one case where adding the [1] will still compile, but
> generate wrong code: if the "size" argument to the _IOx() was not a type,
> but a real actual array.

Yes, there had to be a catch. The new version below catches that error
too, making that a link time failure and also checks that the size
field does not overflow.

	Arnd <><

--- 1.1/include/asm-i386/ioctl.h	Tue Feb  5 18:39:44 2002
+++ edited/include/asm-i386/ioctl.h	Mon Sep  8 13:21:28 2003
@@ -52,11 +52,21 @@
 	 ((nr)   << _IOC_NRSHIFT) | \
 	 ((size) << _IOC_SIZESHIFT))
 
+/* provoke compile error for invalid uses of size argument */
+extern int __invalid_size_argument_for_IOC;
+#define _IOC_TYPECHECK(t) \
+	((sizeof(t) == sizeof(t[1]) && \
+	  sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
+	  sizeof(t) : __invalid_size_argument_for_IOC)
+
 /* used to create numbers */
 #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
-#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
-#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
-#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
+#define _IOR_BAD(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW_BAD(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOWR_BAD(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
 
 /* used to decode ioctl numbers.. */
 #define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-07 23:15     ` Linus Torvalds
@ 2003-09-07 23:21       ` Linus Torvalds
  2003-09-08 13:03         ` Arnd Bergmann
  0 siblings, 1 reply; 24+ messages in thread
From: Linus Torvalds @ 2003-09-07 23:21 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Andreas Schwab, linux-kernel, Matthew Wilcox


On Sun, 7 Sep 2003, Linus Torvalds wrote:
> 
> On Sun, 7 Sep 2003, Arnd Bergmann wrote:
> > 
> > How about changing (sizeof(x)) to (sizeof(x[1]))?
> > It will result in "parse error before `['" when x is not
> > a type or an array type.
> 
> That sounds like a clever thing to do. Have you tested it with a full 
> configuration?

In fact, what you'd want to do is not just verify that it compiles, but 
also verify that the object code matches.

Because there _is_ one case where adding the [1] will still compile, but
generate wrong code: if the "size" argument to the _IOx() was not a type,
but a real actual array.

Now, that would have been a bug (or at least a misfeature) before too, but 
the point of this whole thread was that some people used the _IOx() macros 
incorrectly, so maybe such broken usage actually exists..

			Linus


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
  2003-09-07 21:28   ` Arnd Bergmann
@ 2003-09-07 23:15     ` Linus Torvalds
  2003-09-07 23:21       ` Linus Torvalds
  0 siblings, 1 reply; 24+ messages in thread
From: Linus Torvalds @ 2003-09-07 23:15 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Andreas Schwab, linux-kernel, Matthew Wilcox


On Sun, 7 Sep 2003, Arnd Bergmann wrote:
> 
> How about changing (sizeof(x)) to (sizeof(x[1]))?
> It will result in "parse error before `['" when x is not
> a type or an array type.

That sounds like a clever thing to do. Have you tested it with a full 
configuration?

		Linus


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] use size_t for the broken ioctl numbers
       [not found] ` <tbPO.7j9.5@gated-at.bofh.it>
@ 2003-09-07 21:28   ` Arnd Bergmann
  2003-09-07 23:15     ` Linus Torvalds
  0 siblings, 1 reply; 24+ messages in thread
From: Arnd Bergmann @ 2003-09-07 21:28 UTC (permalink / raw)
  To: Andreas Schwab, linux-kernel, Matthew Wilcox, Linus Torvalds

Andreas Schwab wrote:
> Linus Torvalds <torvalds@osdl.org> writes:
>> Ie, change the (sizeof(x)) to something like
>>
>>      ({ x __dummy; sizeof(__dummy); })
>>
>> which should work with all compiler versions.
> 
> This won't work with array types, eg. in <linux/random.h>:
> 
> #define RNDGETPOOL    _IOR( 'R', 0x02, int [2] )

How about changing (sizeof(x)) to (sizeof(x[1]))?
It will result in "parse error before `['" when x is not
a type or an array type.

        Arnd <><

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2003-09-09 11:40 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-09-07  6:22 [PATCH] use size_t for the broken ioctl numbers Matthew Wilcox
2003-09-07 16:48 ` Andreas Schwab
2003-09-07 17:29   ` Linus Torvalds
2003-09-07 17:34     ` Andreas Schwab
2003-09-08 13:10       ` Ingo Oeser
2003-09-08 12:38 ` Andries Brouwer
2003-09-08 15:13   ` Linus Torvalds
2003-09-08 18:40     ` Andries Brouwer
2003-09-08 18:54       ` Linus Torvalds
2003-09-08 19:28       ` Randy.Dunlap
2003-09-08 19:53         ` Jeff Garzik
2003-09-08 20:15           ` Linus Torvalds
2003-09-08 20:26             ` Dave Jones
2003-09-08 21:53               ` Jeff Garzik
2003-09-08 22:25                 ` Dave Jones
2003-09-08 20:27         ` Andries Brouwer
2003-09-08 20:43           ` Linus Torvalds
2003-09-09 11:40   ` Jens Axboe
     [not found] <tbGb.75d.15@gated-at.bofh.it>
     [not found] ` <tbPO.7j9.5@gated-at.bofh.it>
2003-09-07 21:28   ` Arnd Bergmann
2003-09-07 23:15     ` Linus Torvalds
2003-09-07 23:21       ` Linus Torvalds
2003-09-08 13:03         ` Arnd Bergmann
2003-09-08 13:33           ` Andreas Schwab
2003-09-08 13:35           ` Andries Brouwer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).