drivers/char/i8k.c | 4 ++++ include/linux/i8k.h | 22 ++++++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index 40cc0cf2ded6..e4b1613543ed 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c @@ -326,6 +326,10 @@ i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg) if (!argp) return -EINVAL; + /* We had some bad 64-bit confusion */ + if ((arg >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) == 8) + arg -= 4 << _IOC_SIZESHIFT; + switch (cmd) { case I8K_BIOS_VERSION: val = i8k_get_bios_version(); diff --git a/include/linux/i8k.h b/include/linux/i8k.h index 1c45ba505115..650f4015c89c 100644 --- a/include/linux/i8k.h +++ b/include/linux/i8k.h @@ -20,14 +20,24 @@ #define I8K_PROC "/proc/i8k" #define I8K_PROC_FMT "1.0" +/* + * For hysterical raisins we expose the wrong size to user space + * in the ioctl numbering. The actual real data size is "int". + */ +#ifdef __KERNEL__ +#define borked_i8k_arg int +#else +#define borked_i8k_arg size_t +#endif + #define I8K_BIOS_VERSION _IOR ('i', 0x80, int) /* broken: meant 4 bytes */ #define I8K_MACHINE_ID _IOR ('i', 0x81, int) /* broken: meant 16 bytes */ -#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_POWER_STATUS _IOR ('i', 0x82, borked_i8k_arg) +#define I8K_FN_STATUS _IOR ('i', 0x83, borked_i8k_arg) +#define I8K_GET_TEMP _IOR ('i', 0x84, borked_i8k_arg) +#define I8K_GET_SPEED _IOWR('i', 0x85, borked_i8k_arg) +#define I8K_GET_FAN _IOWR('i', 0x86, borked_i8k_arg) +#define I8K_SET_FAN _IOWR('i', 0x87, borked_i8k_arg) #define I8K_FAN_LEFT 1 #define I8K_FAN_RIGHT 0