On Sat, Sep 08, 2018 at 04:28:12PM +0200, Arnd Bergmann wrote: > These are all handled by the random driver, so instead of listing > each ioctl, we can just use the same function to deal with both > native and compat commands. Umm... I don't think it's right - > .unlocked_ioctl = random_ioctl, > + .compat_ioctl = random_ioctl, ->compat_ioctl() gets called in error = f.file->f_op->compat_ioctl(f.file, cmd, arg); so you do *NOT* get compat_ptr() for those - they have to do it on their own. It's not hard to provide a proper compat_ioctl() instance for that one, but this is not it. What you need in drivers/char/random.c part of that one is something like diff --git a/drivers/char/random.c b/drivers/char/random.c index bf5f99fc36f1..1de75c784cf6 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1954,10 +1954,9 @@ static ssize_t random_write(struct file *file, const char __user *buffer, return (ssize_t)count; } -static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg) +static long __random_ioctl(struct file *f, unsigned int cmd, int __user *p) { int size, ent_count; - int __user *p = (int __user *)arg; int retval; switch (cmd) { @@ -2011,6 +2010,18 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg) } } +static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg) +{ + return __random_ioctl(f, cmd, (int __user *)arg); +} + +#ifdef CONFIG_COMPAT +static long compat_random_ioctl(struct file *f, unsigned int cmd, unsigned long arg) +{ + return __random_ioctl(f, cmd, compat_ptr(arg)); +} +#endif + static int random_fasync(int fd, struct file *filp, int on) { return fasync_helper(fd, filp, on, &fasync); @@ -2021,6 +2032,9 @@ const struct file_operations random_fops = { .write = random_write, .poll = random_poll, .unlocked_ioctl = random_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = compat_random_ioctl, +#endif .fasync = random_fasync, .llseek = noop_llseek, };