Index: sys/ioccom.h =================================================================== RCS file: /cvs/src/sys/sys/ioccom.h,v retrieving revision 1.5 diff -u -p -r1.5 ioccom.h --- sys/ioccom.h 22 Mar 2013 21:22:05 -0000 1.5 +++ sys/ioccom.h 12 Nov 2019 01:50:40 -0000 @@ -46,7 +46,7 @@ #define IOCGROUP(x) (((x) >> 8) & 0xff) #define IOCPARM_MAX PAGE_SIZE /* max size of ioctl args */ - /* no parameters */ + /* no parameters - DEPRECATED */ #define IOC_VOID (unsigned long)0x20000000 /* copy parameters out */ #define IOC_OUT (unsigned long)0x40000000 @@ -54,12 +54,10 @@ #define IOC_IN (unsigned long)0x80000000 /* copy parameters in and out */ #define IOC_INOUT (IOC_IN|IOC_OUT) - /* mask for IN/OUT/VOID */ -#define IOC_DIRMASK (unsigned long)0xe0000000 #define _IOC(inout,group,num,len) \ (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num)) -#define _IO(g,n) _IOC(IOC_VOID, (g), (n), 0) +#define _IO(g,n) _IOC(0, (g), (n), 0) #define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t)) #define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t)) /* this should be _IORW, but stdio got there first */ Index: kern/sys_generic.c =================================================================== RCS file: /cvs/src/sys/kern/sys_generic.c,v retrieving revision 1.126 diff -u -p -r1.126 sys_generic.c --- kern/sys_generic.c 3 Oct 2019 18:47:19 -0000 1.126 +++ kern/sys_generic.c 12 Nov 2019 01:50:40 -0000 @@ -407,6 +407,7 @@ sys_ioctl(struct proc *p, void *v, regis u_long com = SCARG(uap, com); int error = 0; u_int size = 0; + u_int dir; caddr_t data, memp = NULL; int tmp; #define STK_PARAMS 128 @@ -424,6 +425,15 @@ sys_ioctl(struct proc *p, void *v, regis } } + /* + * Prepare to reuse the IOC_VOID flag. The kernel may be + * built with a src/ioccom.h that doesn't set it, while + * userland may still be running binaries with it set. + * IOC_VOID was set when no data direction was set, so it + * is^Wwas redundant. + */ + + CLR(com, IOC_VOID); error = pledge_ioctl(p, com, fp); if (error) goto out; @@ -454,7 +464,10 @@ sys_ioctl(struct proc *p, void *v, regis data = memp; } else data = (caddr_t)stkbuf; - if (com&IOC_IN) { + dir = com & IOC_INOUT; + if (dir == 0) + *(caddr_t *)data = SCARG(uap, data); + else if (ISSET(dir, IOC_IN)) { if (size) { error = copyin(SCARG(uap, data), data, size); if (error) { @@ -462,14 +475,13 @@ sys_ioctl(struct proc *p, void *v, regis } } else *(caddr_t *)data = SCARG(uap, data); - } else if ((com&IOC_OUT) && size) + } else if (ISSET(dir, IOC_OUT) && size) { /* * Zero the buffer so the user always * gets back something deterministic. */ memset(data, 0, size); - else if (com&IOC_VOID) - *(caddr_t *)data = SCARG(uap, data); + } switch (com) {