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>
This commit is contained in:
parent
7ee3296551
commit
f0193d3ea7
@ -821,6 +821,7 @@ static int __init hci_uart_init(void)
|
|||||||
hci_uart_ldisc.read = hci_uart_tty_read;
|
hci_uart_ldisc.read = hci_uart_tty_read;
|
||||||
hci_uart_ldisc.write = hci_uart_tty_write;
|
hci_uart_ldisc.write = hci_uart_tty_write;
|
||||||
hci_uart_ldisc.ioctl = hci_uart_tty_ioctl;
|
hci_uart_ldisc.ioctl = hci_uart_tty_ioctl;
|
||||||
|
hci_uart_ldisc.compat_ioctl = hci_uart_tty_ioctl;
|
||||||
hci_uart_ldisc.poll = hci_uart_tty_poll;
|
hci_uart_ldisc.poll = hci_uart_tty_poll;
|
||||||
hci_uart_ldisc.receive_buf = hci_uart_tty_receive;
|
hci_uart_ldisc.receive_buf = hci_uart_tty_receive;
|
||||||
hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup;
|
hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup;
|
||||||
|
@ -226,7 +226,7 @@ static int serport_ldisc_ioctl(struct tty_struct *tty, struct file *file,
|
|||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
#define COMPAT_SPIOCSTYPE _IOW('q', 0x01, compat_ulong_t)
|
#define COMPAT_SPIOCSTYPE _IOW('q', 0x01, compat_ulong_t)
|
||||||
static long serport_ldisc_compat_ioctl(struct tty_struct *tty,
|
static int serport_ldisc_compat_ioctl(struct tty_struct *tty,
|
||||||
struct file *file,
|
struct file *file,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
#include <linux/tcp.h>
|
#include <linux/tcp.h>
|
||||||
#include <linux/semaphore.h>
|
#include <linux/semaphore.h>
|
||||||
#include <linux/compat.h>
|
|
||||||
#include <linux/refcount.h>
|
#include <linux/refcount.h>
|
||||||
|
|
||||||
#define SIXPACK_VERSION "Revision: 0.3.0"
|
#define SIXPACK_VERSION "Revision: 0.3.0"
|
||||||
@ -752,23 +751,6 @@ static int sixpack_ioctl(struct tty_struct *tty, struct file *file,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
|
||||||
static long sixpack_compat_ioctl(struct tty_struct * tty, struct file * file,
|
|
||||||
unsigned int cmd, unsigned long arg)
|
|
||||||
{
|
|
||||||
switch (cmd) {
|
|
||||||
case SIOCGIFNAME:
|
|
||||||
case SIOCGIFENCAP:
|
|
||||||
case SIOCSIFENCAP:
|
|
||||||
case SIOCSIFHWADDR:
|
|
||||||
return sixpack_ioctl(tty, file, cmd,
|
|
||||||
(unsigned long)compat_ptr(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
return -ENOIOCTLCMD;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static struct tty_ldisc_ops sp_ldisc = {
|
static struct tty_ldisc_ops sp_ldisc = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.magic = TTY_LDISC_MAGIC,
|
.magic = TTY_LDISC_MAGIC,
|
||||||
@ -776,9 +758,6 @@ static struct tty_ldisc_ops sp_ldisc = {
|
|||||||
.open = sixpack_open,
|
.open = sixpack_open,
|
||||||
.close = sixpack_close,
|
.close = sixpack_close,
|
||||||
.ioctl = sixpack_ioctl,
|
.ioctl = sixpack_ioctl,
|
||||||
#ifdef CONFIG_COMPAT
|
|
||||||
.compat_ioctl = sixpack_compat_ioctl,
|
|
||||||
#endif
|
|
||||||
.receive_buf = sixpack_receive_buf,
|
.receive_buf = sixpack_receive_buf,
|
||||||
.write_wakeup = sixpack_write_wakeup,
|
.write_wakeup = sixpack_write_wakeup,
|
||||||
};
|
};
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
#include <linux/if_arp.h>
|
#include <linux/if_arp.h>
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <linux/compat.h>
|
|
||||||
|
|
||||||
#include <net/ax25.h>
|
#include <net/ax25.h>
|
||||||
|
|
||||||
@ -875,23 +874,6 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
|
||||||
static long mkiss_compat_ioctl(struct tty_struct *tty, struct file *file,
|
|
||||||
unsigned int cmd, unsigned long arg)
|
|
||||||
{
|
|
||||||
switch (cmd) {
|
|
||||||
case SIOCGIFNAME:
|
|
||||||
case SIOCGIFENCAP:
|
|
||||||
case SIOCSIFENCAP:
|
|
||||||
case SIOCSIFHWADDR:
|
|
||||||
return mkiss_ioctl(tty, file, cmd,
|
|
||||||
(unsigned long)compat_ptr(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
return -ENOIOCTLCMD;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle the 'receiver data ready' interrupt.
|
* Handle the 'receiver data ready' interrupt.
|
||||||
* This function is called by the 'tty_io' module in the kernel when
|
* This function is called by the 'tty_io' module in the kernel when
|
||||||
@ -966,9 +948,6 @@ static struct tty_ldisc_ops ax_ldisc = {
|
|||||||
.open = mkiss_open,
|
.open = mkiss_open,
|
||||||
.close = mkiss_close,
|
.close = mkiss_close,
|
||||||
.ioctl = mkiss_ioctl,
|
.ioctl = mkiss_ioctl,
|
||||||
#ifdef CONFIG_COMPAT
|
|
||||||
.compat_ioctl = mkiss_compat_ioctl,
|
|
||||||
#endif
|
|
||||||
.receive_buf = mkiss_receive_buf,
|
.receive_buf = mkiss_receive_buf,
|
||||||
.write_wakeup = mkiss_write_wakeup
|
.write_wakeup = mkiss_write_wakeup
|
||||||
};
|
};
|
||||||
|
@ -79,7 +79,6 @@
|
|||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
#include <linux/if_arp.h>
|
#include <linux/if_arp.h>
|
||||||
#include <linux/if_slip.h>
|
#include <linux/if_slip.h>
|
||||||
#include <linux/compat.h>
|
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
@ -1167,27 +1166,6 @@ static int slip_ioctl(struct tty_struct *tty, struct file *file,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
|
||||||
static long slip_compat_ioctl(struct tty_struct *tty, struct file *file,
|
|
||||||
unsigned int cmd, unsigned long arg)
|
|
||||||
{
|
|
||||||
switch (cmd) {
|
|
||||||
case SIOCGIFNAME:
|
|
||||||
case SIOCGIFENCAP:
|
|
||||||
case SIOCSIFENCAP:
|
|
||||||
case SIOCSIFHWADDR:
|
|
||||||
case SIOCSKEEPALIVE:
|
|
||||||
case SIOCGKEEPALIVE:
|
|
||||||
case SIOCSOUTFILL:
|
|
||||||
case SIOCGOUTFILL:
|
|
||||||
return slip_ioctl(tty, file, cmd,
|
|
||||||
(unsigned long)compat_ptr(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
return -ENOIOCTLCMD;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* VSV changes start here */
|
/* VSV changes start here */
|
||||||
#ifdef CONFIG_SLIP_SMART
|
#ifdef CONFIG_SLIP_SMART
|
||||||
/* function do_ioctl called from net/core/dev.c
|
/* function do_ioctl called from net/core/dev.c
|
||||||
@ -1280,9 +1258,6 @@ static struct tty_ldisc_ops sl_ldisc = {
|
|||||||
.close = slip_close,
|
.close = slip_close,
|
||||||
.hangup = slip_hangup,
|
.hangup = slip_hangup,
|
||||||
.ioctl = slip_ioctl,
|
.ioctl = slip_ioctl,
|
||||||
#ifdef CONFIG_COMPAT
|
|
||||||
.compat_ioctl = slip_compat_ioctl,
|
|
||||||
#endif
|
|
||||||
.receive_buf = slip_receive_buf,
|
.receive_buf = slip_receive_buf,
|
||||||
.write_wakeup = slip_write_wakeup,
|
.write_wakeup = slip_write_wakeup,
|
||||||
};
|
};
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
#include <linux/lapb.h>
|
#include <linux/lapb.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
#include <linux/compat.h>
|
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <net/x25device.h>
|
#include <net/x25device.h>
|
||||||
#include "x25_asy.h"
|
#include "x25_asy.h"
|
||||||
@ -703,21 +702,6 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
|
||||||
static long x25_asy_compat_ioctl(struct tty_struct *tty, struct file *file,
|
|
||||||
unsigned int cmd, unsigned long arg)
|
|
||||||
{
|
|
||||||
switch (cmd) {
|
|
||||||
case SIOCGIFNAME:
|
|
||||||
case SIOCSIFHWADDR:
|
|
||||||
return x25_asy_ioctl(tty, file, cmd,
|
|
||||||
(unsigned long)compat_ptr(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
return -ENOIOCTLCMD;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int x25_asy_open_dev(struct net_device *dev)
|
static int x25_asy_open_dev(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct x25_asy *sl = netdev_priv(dev);
|
struct x25_asy *sl = netdev_priv(dev);
|
||||||
@ -769,9 +753,6 @@ static struct tty_ldisc_ops x25_ldisc = {
|
|||||||
.open = x25_asy_open_tty,
|
.open = x25_asy_open_tty,
|
||||||
.close = x25_asy_close_tty,
|
.close = x25_asy_close_tty,
|
||||||
.ioctl = x25_asy_ioctl,
|
.ioctl = x25_asy_ioctl,
|
||||||
#ifdef CONFIG_COMPAT
|
|
||||||
.compat_ioctl = x25_asy_compat_ioctl,
|
|
||||||
#endif
|
|
||||||
.receive_buf = x25_asy_receive_buf,
|
.receive_buf = x25_asy_receive_buf,
|
||||||
.write_wakeup = x25_asy_write_wakeup,
|
.write_wakeup = x25_asy_write_wakeup,
|
||||||
};
|
};
|
||||||
|
@ -2614,14 +2614,6 @@ static int gsmld_ioctl(struct tty_struct *tty, struct file *file,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
|
||||||
static long gsmld_compat_ioctl(struct tty_struct *tty, struct file *file,
|
|
||||||
unsigned int cmd, unsigned long arg)
|
|
||||||
{
|
|
||||||
return gsmld_ioctl(tty, file, cmd, arg);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Network interface
|
* Network interface
|
||||||
*
|
*
|
||||||
@ -2833,9 +2825,6 @@ static struct tty_ldisc_ops tty_ldisc_packet = {
|
|||||||
.flush_buffer = gsmld_flush_buffer,
|
.flush_buffer = gsmld_flush_buffer,
|
||||||
.read = gsmld_read,
|
.read = gsmld_read,
|
||||||
.write = gsmld_write,
|
.write = gsmld_write,
|
||||||
#ifdef CONFIG_COMPAT
|
|
||||||
.compat_ioctl = gsmld_compat_ioctl,
|
|
||||||
#endif
|
|
||||||
.ioctl = gsmld_ioctl,
|
.ioctl = gsmld_ioctl,
|
||||||
.poll = gsmld_poll,
|
.poll = gsmld_poll,
|
||||||
.receive_buf = gsmld_receive_buf,
|
.receive_buf = gsmld_receive_buf,
|
||||||
|
@ -134,6 +134,10 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
|
|||||||
const unsigned char *buf, size_t nr);
|
const unsigned char *buf, size_t nr);
|
||||||
static int r3964_ioctl(struct tty_struct *tty, struct file *file,
|
static int r3964_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
unsigned int cmd, unsigned long arg);
|
unsigned int cmd, unsigned long arg);
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
static int r3964_compat_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
#endif
|
||||||
static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old);
|
static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old);
|
||||||
static __poll_t r3964_poll(struct tty_struct *tty, struct file *file,
|
static __poll_t r3964_poll(struct tty_struct *tty, struct file *file,
|
||||||
struct poll_table_struct *wait);
|
struct poll_table_struct *wait);
|
||||||
@ -149,6 +153,9 @@ static struct tty_ldisc_ops tty_ldisc_N_R3964 = {
|
|||||||
.read = r3964_read,
|
.read = r3964_read,
|
||||||
.write = r3964_write,
|
.write = r3964_write,
|
||||||
.ioctl = r3964_ioctl,
|
.ioctl = r3964_ioctl,
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
.compat_ioctl = r3964_compat_ioctl,
|
||||||
|
#endif
|
||||||
.set_termios = r3964_set_termios,
|
.set_termios = r3964_set_termios,
|
||||||
.poll = r3964_poll,
|
.poll = r3964_poll,
|
||||||
.receive_buf = r3964_receive_buf,
|
.receive_buf = r3964_receive_buf,
|
||||||
@ -1210,6 +1217,21 @@ static int r3964_ioctl(struct tty_struct *tty, struct file *file,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
static int r3964_compat_ioctl(struct tty_struct *tty, struct file *file,
|
||||||
|
unsigned int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
switch (cmd) {
|
||||||
|
case R3964_ENABLE_SIGNALS:
|
||||||
|
case R3964_SETPRIORITY:
|
||||||
|
case R3964_USE_BCC:
|
||||||
|
return r3964_ioctl(tty, file, cmd, arg);
|
||||||
|
default:
|
||||||
|
return -ENOIOCTLCMD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old)
|
static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old)
|
||||||
{
|
{
|
||||||
TRACE_L("set_termios");
|
TRACE_L("set_termios");
|
||||||
|
@ -2824,6 +2824,9 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
|
|||||||
return hung_up_tty_compat_ioctl(file, cmd, arg);
|
return hung_up_tty_compat_ioctl(file, cmd, arg);
|
||||||
if (ld->ops->compat_ioctl)
|
if (ld->ops->compat_ioctl)
|
||||||
retval = ld->ops->compat_ioctl(tty, file, cmd, arg);
|
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);
|
tty_ldisc_deref(ld);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -54,11 +54,17 @@
|
|||||||
* low-level driver can "grab" an ioctl request before the line
|
* low-level driver can "grab" an ioctl request before the line
|
||||||
* discpline has a chance to see it.
|
* discpline has a chance to see it.
|
||||||
*
|
*
|
||||||
* long (*compat_ioctl)(struct tty_struct * tty, struct file * file,
|
* int (*compat_ioctl)(struct tty_struct * tty, struct file * file,
|
||||||
* unsigned int cmd, unsigned long arg);
|
* unsigned int cmd, unsigned long arg);
|
||||||
*
|
*
|
||||||
* Process ioctl calls from 32-bit process on 64-bit system
|
* Process ioctl calls from 32-bit process on 64-bit system
|
||||||
*
|
*
|
||||||
|
* NOTE: only ioctls that are neither "pointer to compatible
|
||||||
|
* structure" nor tty-generic. Something private that takes
|
||||||
|
* an integer or a pointer to wordsize-sensitive structure
|
||||||
|
* belongs here, but most of ldiscs will happily leave
|
||||||
|
* it NULL.
|
||||||
|
*
|
||||||
* void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
|
* void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
|
||||||
*
|
*
|
||||||
* This function notifies the line discpline that a change has
|
* This function notifies the line discpline that a change has
|
||||||
@ -184,7 +190,7 @@ struct tty_ldisc_ops {
|
|||||||
const unsigned char *buf, size_t nr);
|
const unsigned char *buf, size_t nr);
|
||||||
int (*ioctl)(struct tty_struct *tty, struct file *file,
|
int (*ioctl)(struct tty_struct *tty, struct file *file,
|
||||||
unsigned int cmd, unsigned long arg);
|
unsigned int cmd, unsigned long arg);
|
||||||
long (*compat_ioctl)(struct tty_struct *tty, struct file *file,
|
int (*compat_ioctl)(struct tty_struct *tty, struct file *file,
|
||||||
unsigned int cmd, unsigned long arg);
|
unsigned int cmd, unsigned long arg);
|
||||||
void (*set_termios)(struct tty_struct *tty, struct ktermios *old);
|
void (*set_termios)(struct tty_struct *tty, struct ktermios *old);
|
||||||
__poll_t (*poll)(struct tty_struct *, struct file *,
|
__poll_t (*poll)(struct tty_struct *, struct file *,
|
||||||
|
@ -465,6 +465,7 @@ static struct tty_ldisc_ops nci_uart_ldisc = {
|
|||||||
.receive_buf = nci_uart_tty_receive,
|
.receive_buf = nci_uart_tty_receive,
|
||||||
.write_wakeup = nci_uart_tty_wakeup,
|
.write_wakeup = nci_uart_tty_wakeup,
|
||||||
.ioctl = nci_uart_tty_ioctl,
|
.ioctl = nci_uart_tty_ioctl,
|
||||||
|
.compat_ioctl = nci_uart_tty_ioctl,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init nci_uart_init(void)
|
static int __init nci_uart_init(void)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user