summary refs log tree commit diff
path: root/drivers/tty/tty_io.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2018-09-13 22:12:15 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2018-10-13 00:50:53 -0400
commitf0193d3ea73b966b5dbfa272c8228d743b8856ef (patch)
treec882a171c8706f274a7e09d8f7297c36ed750e34 /drivers/tty/tty_io.c
parent7ee329655189f32f0c17e0bad60c23a69b003e9e (diff)
downloadlinux-f0193d3ea73b966b5dbfa272c8228d743b8856ef.tar.gz
change semantics of ldisc ->compat_ioctl()
First of all, make it return int.  Returning long when native method
had never allowed that is ridiculous and inconvenient.

More importantly, change the caller; if ldisc ->compat_ioctl() is NULL
or returns -ENOIOCTLCMD, tty_compat_ioctl() will try to feed cmd and
compat_ptr(arg) to ldisc's native ->ioctl().

That simplifies ->compat_ioctl() instances quite a bit - they only
need to deal with ioctls that are neither generic tty ones (those
would get shunted off to tty_ioctl()) nor simple compat pointer ones.

Note that something like TCFLSH won't reach ->compat_ioctl(),
even if ldisc ->ioctl() does handle it - it will be recognized
earlier and passed to tty_ioctl() (and ultimately - ldisc ->ioctl()).

For many ldiscs it means that NULL ->compat_ioctl() does the
right thing.  Those where it won't serve (see e.g. n_r3964.c) are
also easily dealt with - we need to handle the numeric-argument
ioctls (calling the native instance) and, if such would exist,
the ioctls that need layout conversion, etc.

All in-tree ldiscs dealt with.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'drivers/tty/tty_io.c')
-rw-r--r--drivers/tty/tty_io.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 1a55c3e20299..cd8df45f09d9 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -2824,6 +2824,9 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
 		return hung_up_tty_compat_ioctl(file, cmd, arg);
 	if (ld->ops->compat_ioctl)
 		retval = ld->ops->compat_ioctl(tty, file, cmd, arg);
+	if (retval == -ENOIOCTLCMD && ld->ops->ioctl)
+		retval = ld->ops->ioctl(tty, file,
+				(unsigned long)compat_ptr(cmd), arg);
 	tty_ldisc_deref(ld);
 
 	return retval;