2003-09-07 06:22:55

by Matthew Wilcox

[permalink] [raw]
Subject: [PATCH] use size_t for the broken ioctl numbers


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


2003-09-07 16:48:43

by Andreas Schwab

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers

Matthew Wilcox <[email protected]> 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, [email protected]
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."

2003-09-07 17:37:27

by Andreas Schwab

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers

Linus Torvalds <[email protected]> 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, [email protected]
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."

2003-09-07 17:29:38

by Linus Torvalds

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers


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

2003-09-07 21:28:47

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers

Andreas Schwab wrote:
> Linus Torvalds <[email protected]> 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 <><

2003-09-07 23:15:40

by Linus Torvalds

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers


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

2003-09-07 23:21:49

by Linus Torvalds

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers


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

2003-09-08 12:39:10

by Andries Brouwer

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers

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

2003-09-08 13:03:31

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers

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)

2003-09-08 13:38:55

by Andreas Schwab

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers

Arnd Bergmann <[email protected]> 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, [email protected]
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."

2003-09-08 13:36:15

by Andries Brouwer

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers

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

2003-09-08 15:36:59

by Ingo Oeser

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers

On Sunday 07 September 2003 19:34, Andreas Schwab wrote:
> Linus Torvalds <[email protected]> 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


2003-09-08 16:12:48

by Linus Torvalds

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers


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

2003-09-08 18:41:30

by Andries Brouwer

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers

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.]

2003-09-08 18:54:42

by Linus Torvalds

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers


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

2003-09-08 19:34:29

by Randy.Dunlap

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers

On Mon, 8 Sep 2003 20:40:23 +0200 Andries Brouwer <[email protected]> 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

2003-09-08 19:53:36

by Jeff Garzik

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers

On Mon, Sep 08, 2003 at 12:28:53PM -0700, Randy.Dunlap wrote:
> On Mon, 8 Sep 2003 20:40:23 +0200 Andries Brouwer <[email protected]> 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



2003-09-08 20:16:18

by Linus Torvalds

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers


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

2003-09-08 20:43:47

by Linus Torvalds

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers


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
([email protected], 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

2003-09-08 20:27:52

by Dave Jones

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers

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

2003-09-08 20:29:36

by Andries Brouwer

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers

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!

2003-09-08 21:53:52

by Jeff Garzik

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers

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


2003-09-08 22:26:27

by Dave Jones

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers

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

2003-09-09 11:40:14

by Jens Axboe

[permalink] [raw]
Subject: Re: [PATCH] use size_t for the broken ioctl numbers

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