Merge branch 'work.tty-ioctl' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull tty ioctl updates from Al Viro:
 "This is the compat_ioctl work related to tty ioctls.

  Quite a bit of dead code taken out, all tty-related stuff gone from
  fs/compat_ioctl.c. A bunch of compat bugs fixed - some still remain,
  but all more or less generic tty-related ioctls should be covered
  (remaining issues are in things like driver-private ioctls in a pcmcia
  serial card driver not getting properly handled in 32bit processes on
  64bit host, etc)"

* 'work.tty-ioctl' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (53 commits)
  kill TIOCSERGSTRUCT
  change semantics of ldisc ->compat_ioctl()
  kill TIOCSER[SG]WILD
  synclink_gt(): fix compat_ioctl()
  pty: fix compat ioctls
  compat_ioctl - kill keyboard ioctl handling
  gigaset: add ->compat_ioctl()
  vt_compat_ioctl(): clean up, use compat_ptr() properly
  gigaset: don't try to printk userland buffer contents
  dgnc: don't bother with (empty) stub for TCXONC
  dgnc: leave TIOC[GS]SOFTCAR to ldisc
  remove fallback to drivers for TIOCGICOUNT
  dgnc: break-related ioctls won't reach ->ioctl()
  kill the rest of tty COMPAT_IOCTL() entries
  dgnc: TIOCM... won't reach ->ioctl()
  isdn_tty: TCSBRK{,P} won't reach ->ioctl()
  kill capinc_tty_ioctl()
  take compat TIOC[SG]SERIAL treatment into tty_compat_ioctl()
  synclink: reduce pointless checks in ->ioctl()
  complete ->[sg]et_serial() switchover
  ...
This commit is contained in:
Linus Torvalds 2018-10-24 14:43:41 +01:00
commit 44adbac8f7
56 changed files with 779 additions and 1522 deletions

View file

@ -996,63 +996,55 @@ static void rs_unthrottle(struct tty_struct * tty)
* ------------------------------------------------------------
*/
static int get_serial_info(struct tty_struct *tty, struct serial_state *state,
struct serial_struct __user * retinfo)
static int get_serial_info(struct tty_struct *tty, struct serial_struct *ss)
{
struct serial_struct tmp;
memset(&tmp, 0, sizeof(tmp));
struct serial_state *state = tty->driver_data;
tty_lock(tty);
tmp.line = tty->index;
tmp.port = state->port;
tmp.flags = state->tport.flags;
tmp.xmit_fifo_size = state->xmit_fifo_size;
tmp.baud_base = state->baud_base;
tmp.close_delay = state->tport.close_delay;
tmp.closing_wait = state->tport.closing_wait;
tmp.custom_divisor = state->custom_divisor;
ss->line = tty->index;
ss->port = state->port;
ss->flags = state->tport.flags;
ss->xmit_fifo_size = state->xmit_fifo_size;
ss->baud_base = state->baud_base;
ss->close_delay = state->tport.close_delay;
ss->closing_wait = state->tport.closing_wait;
ss->custom_divisor = state->custom_divisor;
tty_unlock(tty);
if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
return -EFAULT;
return 0;
}
static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
struct serial_struct __user * new_info)
static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
{
struct serial_state *state = tty->driver_data;
struct tty_port *port = &state->tport;
struct serial_struct new_serial;
bool change_spd;
int retval = 0;
if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
return -EFAULT;
tty_lock(tty);
change_spd = ((new_serial.flags ^ port->flags) & ASYNC_SPD_MASK) ||
new_serial.custom_divisor != state->custom_divisor;
if (new_serial.irq || new_serial.port != state->port ||
new_serial.xmit_fifo_size != state->xmit_fifo_size) {
change_spd = ((ss->flags ^ port->flags) & ASYNC_SPD_MASK) ||
ss->custom_divisor != state->custom_divisor;
if (ss->irq || ss->port != state->port ||
ss->xmit_fifo_size != state->xmit_fifo_size) {
tty_unlock(tty);
return -EINVAL;
}
if (!serial_isroot()) {
if ((new_serial.baud_base != state->baud_base) ||
(new_serial.close_delay != port->close_delay) ||
(new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
((new_serial.flags & ~ASYNC_USR_MASK) !=
if ((ss->baud_base != state->baud_base) ||
(ss->close_delay != port->close_delay) ||
(ss->xmit_fifo_size != state->xmit_fifo_size) ||
((ss->flags & ~ASYNC_USR_MASK) !=
(port->flags & ~ASYNC_USR_MASK))) {
tty_unlock(tty);
return -EPERM;
}
port->flags = ((port->flags & ~ASYNC_USR_MASK) |
(new_serial.flags & ASYNC_USR_MASK));
state->custom_divisor = new_serial.custom_divisor;
(ss->flags & ASYNC_USR_MASK));
state->custom_divisor = ss->custom_divisor;
goto check_and_exit;
}
if (new_serial.baud_base < 9600) {
if (ss->baud_base < 9600) {
tty_unlock(tty);
return -EINVAL;
}
@ -1062,19 +1054,19 @@ static int set_serial_info(struct tty_struct *tty, struct serial_state *state,
* At this point, we start making changes.....
*/
state->baud_base = new_serial.baud_base;
state->baud_base = ss->baud_base;
port->flags = ((port->flags & ~ASYNC_FLAGS) |
(new_serial.flags & ASYNC_FLAGS));
state->custom_divisor = new_serial.custom_divisor;
port->close_delay = new_serial.close_delay * HZ/100;
port->closing_wait = new_serial.closing_wait * HZ/100;
(ss->flags & ASYNC_FLAGS));
state->custom_divisor = ss->custom_divisor;
port->close_delay = ss->close_delay * HZ/100;
port->closing_wait = ss->closing_wait * HZ/100;
port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
check_and_exit:
if (tty_port_initialized(port)) {
if (change_spd) {
/* warn about deprecation unless clearing */
if (new_serial.flags & ASYNC_SPD_MASK)
if (ss->flags & ASYNC_SPD_MASK)
dev_warn_ratelimited(tty->dev, "use of SPD flags is deprecated\n");
change_speed(tty, state, NULL);
}
@ -1084,7 +1076,6 @@ check_and_exit:
return retval;
}
/*
* get_lsr_info - get line status register info
*
@ -1224,30 +1215,19 @@ static int rs_ioctl(struct tty_struct *tty,
if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
return -ENODEV;
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
if ((cmd != TIOCSERCONFIG) &&
(cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
if (tty_io_error(tty))
return -EIO;
}
switch (cmd) {
case TIOCGSERIAL:
return get_serial_info(tty, info, argp);
case TIOCSSERIAL:
return set_serial_info(tty, info, argp);
case TIOCSERCONFIG:
return 0;
case TIOCSERGETLSR: /* Get line status register */
return get_lsr_info(info, argp);
case TIOCSERGSTRUCT:
if (copy_to_user(argp,
info, sizeof(struct serial_state)))
return -EFAULT;
return 0;
/*
* Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
* - mask passed in arg for lines of interest
@ -1288,12 +1268,6 @@ static int rs_ioctl(struct tty_struct *tty,
finish_wait(&info->tport.delta_msr_wait, &wait);
return ret;
case TIOCSERGWILD:
case TIOCSERSWILD:
/* "setserial -W" is called in Debian boot */
printk ("TIOCSER?WILD ioctl obsolete, ignored.\n");
return 0;
default:
return -ENOIOCTLCMD;
}
@ -1607,6 +1581,8 @@ static const struct tty_operations serial_ops = {
.tiocmget = rs_tiocmget,
.tiocmset = rs_tiocmset,
.get_icount = rs_get_icount,
.set_serial = set_serial_info,
.get_serial = get_serial_info,
.proc_show = rs_proc_show,
};

View file

@ -2257,44 +2257,45 @@ static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
}
} /* set_line_char */
static int cy_get_serial_info(struct cyclades_port *info,
struct serial_struct __user *retinfo)
static int cy_get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct cyclades_port *info = tty->driver_data;
struct cyclades_card *cinfo = info->card;
struct serial_struct tmp = {
.type = info->type,
.line = info->line,
.port = (info->card - cy_card) * 0x100 + info->line -
cinfo->first_line,
.irq = cinfo->irq,
.flags = info->port.flags,
.close_delay = info->port.close_delay,
.closing_wait = info->port.closing_wait,
.baud_base = info->baud,
.custom_divisor = info->custom_divisor,
};
return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
if (serial_paranoia_check(info, tty->name, "cy_ioctl"))
return -ENODEV;
ss->type = info->type;
ss->line = info->line;
ss->port = (info->card - cy_card) * 0x100 + info->line -
cinfo->first_line;
ss->irq = cinfo->irq;
ss->flags = info->port.flags;
ss->close_delay = info->port.close_delay;
ss->closing_wait = info->port.closing_wait;
ss->baud_base = info->baud;
ss->custom_divisor = info->custom_divisor;
return 0;
}
static int
cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
struct serial_struct __user *new_info)
static int cy_set_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct serial_struct new_serial;
struct cyclades_port *info = tty->driver_data;
int old_flags;
int ret;
if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
return -EFAULT;
if (serial_paranoia_check(info, tty->name, "cy_ioctl"))
return -ENODEV;
mutex_lock(&info->port.mutex);
old_flags = info->port.flags;
if (!capable(CAP_SYS_ADMIN)) {
if (new_serial.close_delay != info->port.close_delay ||
new_serial.baud_base != info->baud ||
(new_serial.flags & ASYNC_FLAGS &
if (ss->close_delay != info->port.close_delay ||
ss->baud_base != info->baud ||
(ss->flags & ASYNC_FLAGS &
~ASYNC_USR_MASK) !=
(info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))
{
@ -2302,9 +2303,9 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
return -EPERM;
}
info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) |
(new_serial.flags & ASYNC_USR_MASK);
info->baud = new_serial.baud_base;
info->custom_divisor = new_serial.custom_divisor;
(ss->flags & ASYNC_USR_MASK);
info->baud = ss->baud_base;
info->custom_divisor = ss->custom_divisor;
goto check_and_exit;
}
@ -2313,18 +2314,18 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
* At this point, we start making changes.....
*/
info->baud = new_serial.baud_base;
info->custom_divisor = new_serial.custom_divisor;
info->baud = ss->baud_base;
info->custom_divisor = ss->custom_divisor;
info->port.flags = (info->port.flags & ~ASYNC_FLAGS) |
(new_serial.flags & ASYNC_FLAGS);
info->port.close_delay = new_serial.close_delay * HZ / 100;
info->port.closing_wait = new_serial.closing_wait * HZ / 100;
(ss->flags & ASYNC_FLAGS);
info->port.close_delay = ss->close_delay * HZ / 100;
info->port.closing_wait = ss->closing_wait * HZ / 100;
check_and_exit:
if (tty_port_initialized(&info->port)) {
if ((new_serial.flags ^ old_flags) & ASYNC_SPD_MASK) {
if ((ss->flags ^ old_flags) & ASYNC_SPD_MASK) {
/* warn about deprecation unless clearing */
if (new_serial.flags & ASYNC_SPD_MASK)
if (ss->flags & ASYNC_SPD_MASK)
dev_warn_ratelimited(tty->dev, "use of SPD flags is deprecated\n");
}
cy_set_line_char(info, tty);
@ -2698,12 +2699,6 @@ cy_ioctl(struct tty_struct *tty,
case CYGETWAIT:
ret_val = info->port.closing_wait / (HZ / 100);
break;
case TIOCGSERIAL:
ret_val = cy_get_serial_info(info, argp);
break;
case TIOCSSERIAL:
ret_val = cy_set_serial_info(info, tty, argp);
break;
case TIOCSERGETLSR: /* Get line status register */
ret_val = get_lsr_info(info, argp);
break;
@ -4011,6 +4006,8 @@ static const struct tty_operations cy_ops = {
.tiocmget = cy_tiocmget,
.tiocmset = cy_tiocmset,
.get_icount = cy_get_icount,
.set_serial = cy_set_serial_info,
.get_serial = cy_get_serial_info,
.proc_show = cyclades_proc_show,
};

View file

@ -248,22 +248,29 @@ static int ipw_write_room(struct tty_struct *linux_tty)
return room;
}
static int ipwireless_get_serial_info(struct ipw_tty *tty,
struct serial_struct __user *retinfo)
static int ipwireless_get_serial_info(struct tty_struct *linux_tty,
struct serial_struct *ss)
{
struct serial_struct tmp;
struct ipw_tty *tty = linux_tty->driver_data;
memset(&tmp, 0, sizeof(tmp));
tmp.type = PORT_UNKNOWN;
tmp.line = tty->index;
tmp.baud_base = 115200;
if (!tty)
return -ENODEV;
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
return -EFAULT;
if (!tty->port.count)
return -EINVAL;
ss->type = PORT_UNKNOWN;
ss->line = tty->index;
ss->baud_base = 115200;
return 0;
}
static int ipwireless_set_serial_info(struct tty_struct *linux_tty,
struct serial_struct *ss)
{
return 0; /* Keeps the PCMCIA scripts happy. */
}
static int ipw_chars_in_buffer(struct tty_struct *linux_tty)
{
struct ipw_tty *tty = linux_tty->driver_data;
@ -386,15 +393,6 @@ static int ipw_ioctl(struct tty_struct *linux_tty,
return -EINVAL;
/* FIXME: Exactly how is the tty object locked here .. */
switch (cmd) {
case TIOCGSERIAL:
return ipwireless_get_serial_info(tty, (void __user *) arg);
case TIOCSSERIAL:
return 0; /* Keeps the PCMCIA scripts happy. */
}
if (tty->tty_type == TTYTYPE_MODEM) {
switch (cmd) {
case PPPIOCGCHAN:
@ -561,6 +559,8 @@ static const struct tty_operations tty_ops = {
.chars_in_buffer = ipw_chars_in_buffer,
.tiocmget = ipw_tiocmget,
.tiocmset = ipw_tiocmset,
.set_serial = ipwireless_set_serial_info,
.get_serial = ipwireless_get_serial_info,
};
int ipwireless_tty_init(void)

View file

@ -1091,34 +1091,33 @@ static int isicom_tiocmset(struct tty_struct *tty,
}
static int isicom_set_serial_info(struct tty_struct *tty,
struct serial_struct __user *info)
struct serial_struct *ss)
{
struct isi_port *port = tty->driver_data;
struct serial_struct newinfo;
int reconfig_port;
if (copy_from_user(&newinfo, info, sizeof(newinfo)))
return -EFAULT;
if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
return -ENODEV;
mutex_lock(&port->port.mutex);
reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) !=
(newinfo.flags & ASYNC_SPD_MASK));
(ss->flags & ASYNC_SPD_MASK));
if (!capable(CAP_SYS_ADMIN)) {
if ((newinfo.close_delay != port->port.close_delay) ||
(newinfo.closing_wait != port->port.closing_wait) ||
((newinfo.flags & ~ASYNC_USR_MASK) !=
if ((ss->close_delay != port->port.close_delay) ||
(ss->closing_wait != port->port.closing_wait) ||
((ss->flags & ~ASYNC_USR_MASK) !=
(port->port.flags & ~ASYNC_USR_MASK))) {
mutex_unlock(&port->port.mutex);
return -EPERM;
}
port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
(newinfo.flags & ASYNC_USR_MASK));
(ss->flags & ASYNC_USR_MASK));
} else {
port->port.close_delay = newinfo.close_delay;
port->port.closing_wait = newinfo.closing_wait;
port->port.close_delay = ss->close_delay;
port->port.closing_wait = ss->closing_wait;
port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
(newinfo.flags & ASYNC_FLAGS));
(ss->flags & ASYNC_FLAGS));
}
if (reconfig_port) {
unsigned long flags;
@ -1130,46 +1129,24 @@ static int isicom_set_serial_info(struct tty_struct *tty,
return 0;
}
static int isicom_get_serial_info(struct isi_port *port,
struct serial_struct __user *info)
{
struct serial_struct out_info;
mutex_lock(&port->port.mutex);
memset(&out_info, 0, sizeof(out_info));
/* out_info.type = ? */
out_info.line = port - isi_ports;
out_info.port = port->card->base;
out_info.irq = port->card->irq;
out_info.flags = port->port.flags;
/* out_info.baud_base = ? */
out_info.close_delay = port->port.close_delay;
out_info.closing_wait = port->port.closing_wait;
mutex_unlock(&port->port.mutex);
if (copy_to_user(info, &out_info, sizeof(out_info)))
return -EFAULT;
return 0;
}
static int isicom_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
static int isicom_get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct isi_port *port = tty->driver_data;
void __user *argp = (void __user *)arg;
if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
return -ENODEV;
switch (cmd) {
case TIOCGSERIAL:
return isicom_get_serial_info(port, argp);
case TIOCSSERIAL:
return isicom_set_serial_info(tty, argp);
default:
return -ENOIOCTLCMD;
}
mutex_lock(&port->port.mutex);
/* ss->type = ? */
ss->line = port - isi_ports;
ss->port = port->card->base;
ss->irq = port->card->irq;
ss->flags = port->port.flags;
/* ss->baud_base = ? */
ss->close_delay = port->port.close_delay;
ss->closing_wait = port->port.closing_wait;
mutex_unlock(&port->port.mutex);
return 0;
}
@ -1273,7 +1250,6 @@ static const struct tty_operations isicom_ops = {
.flush_chars = isicom_flush_chars,
.write_room = isicom_write_room,
.chars_in_buffer = isicom_chars_in_buffer,
.ioctl = isicom_ioctl,
.set_termios = isicom_set_termios,
.throttle = isicom_throttle,
.unthrottle = isicom_unthrottle,
@ -1284,6 +1260,8 @@ static const struct tty_operations isicom_ops = {
.tiocmget = isicom_tiocmget,
.tiocmset = isicom_tiocmset,
.break_ctl = isicom_send_break,
.get_serial = isicom_get_serial_info,
.set_serial = isicom_set_serial_info,
};
static const struct tty_port_operations isicom_port_ops = {

View file

@ -221,8 +221,8 @@ static int MoxaPortRxQueue(struct moxa_port *);
static int MoxaPortTxFree(struct moxa_port *);
static void MoxaPortTxDisable(struct moxa_port *);
static void MoxaPortTxEnable(struct moxa_port *);
static int moxa_get_serial_info(struct moxa_port *, struct serial_struct __user *);
static int moxa_set_serial_info(struct moxa_port *, struct serial_struct __user *);
static int moxa_get_serial_info(struct tty_struct *, struct serial_struct *);
static int moxa_set_serial_info(struct tty_struct *, struct serial_struct *);
static void MoxaSetFifo(struct moxa_port *port, int enable);
/*
@ -375,16 +375,6 @@ copy:
}
break;
}
case TIOCGSERIAL:
mutex_lock(&ch->port.mutex);
ret = moxa_get_serial_info(ch, argp);
mutex_unlock(&ch->port.mutex);
break;
case TIOCSSERIAL:
mutex_lock(&ch->port.mutex);
ret = moxa_set_serial_info(ch, argp);
mutex_unlock(&ch->port.mutex);
break;
default:
ret = -ENOIOCTLCMD;
}
@ -415,6 +405,8 @@ static const struct tty_operations moxa_ops = {
.break_ctl = moxa_break_ctl,
.tiocmget = moxa_tiocmget,
.tiocmset = moxa_tiocmset,
.set_serial = moxa_set_serial_info,
.get_serial = moxa_get_serial_info,
};
static const struct tty_port_operations moxa_port_ops = {
@ -2034,46 +2026,55 @@ static void MoxaPortTxEnable(struct moxa_port *port)
moxafunc(port->tableAddr, FC_SetXonState, Magic_code);
}
static int moxa_get_serial_info(struct moxa_port *info,
struct serial_struct __user *retinfo)
static int moxa_get_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct serial_struct tmp = {
.type = info->type,
.line = info->port.tty->index,
.flags = info->port.flags,
.baud_base = 921600,
.close_delay = info->port.close_delay
};
return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
struct moxa_port *info = tty->driver_data;
if (tty->index == MAX_PORTS)
return -EINVAL;
if (!info)
return -ENODEV;
mutex_lock(&info->port.mutex);
ss->type = info->type,
ss->line = info->port.tty->index,
ss->flags = info->port.flags,
ss->baud_base = 921600,
ss->close_delay = info->port.close_delay;
mutex_unlock(&info->port.mutex);
return 0;
}
static int moxa_set_serial_info(struct moxa_port *info,
struct serial_struct __user *new_info)
static int moxa_set_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
struct serial_struct new_serial;
struct moxa_port *info = tty->driver_data;
if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
return -EFAULT;
if (tty->index == MAX_PORTS)
return -EINVAL;
if (!info)
return -ENODEV;
if (new_serial.irq != 0 || new_serial.port != 0 ||
new_serial.custom_divisor != 0 ||
new_serial.baud_base != 921600)
if (ss->irq != 0 || ss->port != 0 ||
ss->custom_divisor != 0 ||
ss->baud_base != 921600)
return -EPERM;
mutex_lock(&info->port.mutex);
if (!capable(CAP_SYS_ADMIN)) {
if (((new_serial.flags & ~ASYNC_USR_MASK) !=
(info->port.flags & ~ASYNC_USR_MASK)))
if (((ss->flags & ~ASYNC_USR_MASK) !=
(info->port.flags & ~ASYNC_USR_MASK))) {
mutex_unlock(&info->port.mutex);
return -EPERM;
} else
info->port.close_delay = new_serial.close_delay * HZ / 100;
}
}
info->port.close_delay = ss->close_delay * HZ / 100;
new_serial.flags = (new_serial.flags & ~ASYNC_FLAGS);
new_serial.flags |= (info->port.flags & ASYNC_FLAGS);
MoxaSetFifo(info, ss->type == PORT_16550A);
MoxaSetFifo(info, new_serial.type == PORT_16550A);
info->type = new_serial.type;
info->type = ss->type;
mutex_unlock(&info->port.mutex);
return 0;
}

View file

@ -1207,76 +1207,90 @@ static int mxser_chars_in_buffer(struct tty_struct *tty)
* ------------------------------------------------------------
*/
static int mxser_get_serial_info(struct tty_struct *tty,
struct serial_struct __user *retinfo)
struct serial_struct *ss)
{
struct mxser_port *info = tty->driver_data;
struct serial_struct tmp = {
.type = info->type,
.line = tty->index,
.port = info->ioaddr,
.irq = info->board->irq,
.flags = info->port.flags,
.baud_base = info->baud_base,
.close_delay = info->port.close_delay,
.closing_wait = info->port.closing_wait,
.custom_divisor = info->custom_divisor,
};
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
return -EFAULT;
struct tty_port *port = &info->port;
if (tty->index == MXSER_PORTS)
return -ENOTTY;
mutex_lock(&port->mutex);
ss->type = info->type,
ss->line = tty->index,
ss->port = info->ioaddr,
ss->irq = info->board->irq,
ss->flags = info->port.flags,
ss->baud_base = info->baud_base,
ss->close_delay = info->port.close_delay,
ss->closing_wait = info->port.closing_wait,
ss->custom_divisor = info->custom_divisor,
mutex_unlock(&port->mutex);
return 0;
}
static int mxser_set_serial_info(struct tty_struct *tty,
struct serial_struct __user *new_info)
struct serial_struct *ss)
{
struct mxser_port *info = tty->driver_data;
struct tty_port *port = &info->port;
struct serial_struct new_serial;
speed_t baud;
unsigned long sl_flags;
unsigned int flags;
int retval = 0;
if (!new_info || !info->ioaddr)
return -ENODEV;
if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
return -EFAULT;
if (tty->index == MXSER_PORTS)
return -ENOTTY;
if (tty_io_error(tty))
return -EIO;
if (new_serial.irq != info->board->irq ||
new_serial.port != info->ioaddr)
mutex_lock(&port->mutex);
if (!info->ioaddr) {
mutex_unlock(&port->mutex);
return -ENODEV;
}
if (ss->irq != info->board->irq ||
ss->port != info->ioaddr) {
mutex_unlock(&port->mutex);
return -EINVAL;
}
flags = port->flags & ASYNC_SPD_MASK;
if (!capable(CAP_SYS_ADMIN)) {
if ((new_serial.baud_base != info->baud_base) ||
(new_serial.close_delay != info->port.close_delay) ||
((new_serial.flags & ~ASYNC_USR_MASK) != (info->port.flags & ~ASYNC_USR_MASK)))
if ((ss->baud_base != info->baud_base) ||
(ss->close_delay != info->port.close_delay) ||
((ss->flags & ~ASYNC_USR_MASK) != (info->port.flags & ~ASYNC_USR_MASK))) {
mutex_unlock(&port->mutex);
return -EPERM;
}
info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) |
(new_serial.flags & ASYNC_USR_MASK));
(ss->flags & ASYNC_USR_MASK));
} else {
/*
* OK, past this point, all the error checking has been done.
* At this point, we start making changes.....
*/
port->flags = ((port->flags & ~ASYNC_FLAGS) |
(new_serial.flags & ASYNC_FLAGS));
port->close_delay = new_serial.close_delay * HZ / 100;
port->closing_wait = new_serial.closing_wait * HZ / 100;
(ss->flags & ASYNC_FLAGS));
port->close_delay = ss->close_delay * HZ / 100;
port->closing_wait = ss->closing_wait * HZ / 100;
port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
(new_serial.baud_base != info->baud_base ||
new_serial.custom_divisor !=
(ss->baud_base != info->baud_base ||
ss->custom_divisor !=
info->custom_divisor)) {
if (new_serial.custom_divisor == 0)
if (ss->custom_divisor == 0) {
mutex_unlock(&port->mutex);
return -EINVAL;
baud = new_serial.baud_base / new_serial.custom_divisor;
}
baud = ss->baud_base / ss->custom_divisor;
tty_encode_baud_rate(tty, baud, baud);
}
}
info->type = new_serial.type;
info->type = ss->type;
process_txrx_fifo(info);
@ -1291,6 +1305,7 @@ static int mxser_set_serial_info(struct tty_struct *tty,
if (retval == 0)
tty_port_set_initialized(port, 1);
}
mutex_unlock(&port->mutex);
return retval;
}
@ -1660,11 +1675,9 @@ static int mxser_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct mxser_port *info = tty->driver_data;
struct tty_port *port = &info->port;
struct async_icount cnow;
unsigned long flags;
void __user *argp = (void __user *)arg;
int retval;
if (tty->index == MXSER_PORTS)
return mxser_ioctl_special(cmd, argp);
@ -1708,20 +1721,10 @@ static int mxser_ioctl(struct tty_struct *tty,
return 0;
}
if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && tty_io_error(tty))
if (cmd != TIOCMIWAIT && tty_io_error(tty))
return -EIO;
switch (cmd) {
case TIOCGSERIAL:
mutex_lock(&port->mutex);
retval = mxser_get_serial_info(tty, argp);
mutex_unlock(&port->mutex);
return retval;
case TIOCSSERIAL:
mutex_lock(&port->mutex);
retval = mxser_set_serial_info(tty, argp);
mutex_unlock(&port->mutex);
return retval;
case TIOCSERGETLSR: /* Get line status register */
return mxser_get_lsr_info(info, argp);
/*
@ -2325,6 +2328,8 @@ static const struct tty_operations mxser_ops = {
.wait_until_sent = mxser_wait_until_sent,
.tiocmget = mxser_tiocmget,
.tiocmset = mxser_tiocmset,
.set_serial = mxser_set_serial_info,
.get_serial = mxser_get_serial_info,
.get_icount = mxser_get_icount,
};

View file

@ -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
*
@ -2833,9 +2825,6 @@ static struct tty_ldisc_ops tty_ldisc_packet = {
.flush_buffer = gsmld_flush_buffer,
.read = gsmld_read,
.write = gsmld_write,
#ifdef CONFIG_COMPAT
.compat_ioctl = gsmld_compat_ioctl,
#endif
.ioctl = gsmld_ioctl,
.poll = gsmld_poll,
.receive_buf = gsmld_receive_buf,

View file

@ -134,6 +134,10 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
const unsigned char *buf, size_t nr);
static int r3964_ioctl(struct tty_struct *tty, struct file *file,
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 __poll_t r3964_poll(struct tty_struct *tty, struct file *file,
struct poll_table_struct *wait);
@ -149,6 +153,9 @@ static struct tty_ldisc_ops tty_ldisc_N_R3964 = {
.read = r3964_read,
.write = r3964_write,
.ioctl = r3964_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = r3964_compat_ioctl,
#endif
.set_termios = r3964_set_termios,
.poll = r3964_poll,
.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)
{
TRACE_L("set_termios");

View file

@ -28,6 +28,7 @@
#include <linux/mount.h>
#include <linux/file.h>
#include <linux/ioctl.h>
#include <linux/compat.h>
#undef TTY_DEBUG_HANGUP
#ifdef TTY_DEBUG_HANGUP
@ -488,6 +489,7 @@ static int pty_bsd_ioctl(struct tty_struct *tty,
return -ENOIOCTLCMD;
}
#ifdef CONFIG_COMPAT
static long pty_bsd_compat_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
@ -495,8 +497,11 @@ static long pty_bsd_compat_ioctl(struct tty_struct *tty,
* PTY ioctls don't require any special translation between 32-bit and
* 64-bit userspace, they are already compatible.
*/
return pty_bsd_ioctl(tty, cmd, arg);
return pty_bsd_ioctl(tty, cmd, (unsigned long)compat_ptr(arg));
}
#else
#define pty_bsd_compat_ioctl NULL
#endif
static int legacy_count = CONFIG_LEGACY_PTY_COUNT;
/*
@ -676,6 +681,7 @@ static int pty_unix98_ioctl(struct tty_struct *tty,
return -ENOIOCTLCMD;
}
#ifdef CONFIG_COMPAT
static long pty_unix98_compat_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
@ -683,8 +689,12 @@ static long pty_unix98_compat_ioctl(struct tty_struct *tty,
* PTY ioctls don't require any special translation between 32-bit and
* 64-bit userspace, they are already compatible.
*/
return pty_unix98_ioctl(tty, cmd, arg);
return pty_unix98_ioctl(tty, cmd,
cmd == TIOCSIG ? arg : (unsigned long)compat_ptr(arg));
}
#else
#define pty_unix98_compat_ioctl NULL
#endif
/**
* ptm_unix98_lookup - find a pty master

View file

@ -778,17 +778,13 @@ out:
return ret;
}
static int uart_get_info_user(struct tty_port *port,
struct serial_struct __user *retinfo)
static int uart_get_info_user(struct tty_struct *tty,
struct serial_struct *ss)
{
struct serial_struct tmp;
struct uart_state *state = tty->driver_data;
struct tty_port *port = &state->port;
if (uart_get_info(port, &tmp) < 0)
return -EIO;
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
return -EFAULT;
return 0;
return uart_get_info(port, ss) < 0 ? -EIO : 0;
}
static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
@ -990,16 +986,13 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
return retval;
}
static int uart_set_info_user(struct tty_struct *tty, struct uart_state *state,
struct serial_struct __user *newinfo)
static int uart_set_info_user(struct tty_struct *tty, struct serial_struct *ss)
{
struct serial_struct new_serial;
struct uart_state *state = tty->driver_data;
struct tty_port *port = &state->port;
int retval;
if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
return -EFAULT;
down_write(&tty->termios_rwsem);
/*
* This semaphore protects port->count. It is also
* very useful to prevent opens. Also, take the
@ -1008,8 +1001,9 @@ static int uart_set_info_user(struct tty_struct *tty, struct uart_state *state,
* under us.
*/
mutex_lock(&port->mutex);
retval = uart_set_info(tty, port, state, &new_serial);
retval = uart_set_info(tty, port, state, ss);
mutex_unlock(&port->mutex);
up_write(&tty->termios_rwsem);
return retval;
}
@ -1325,26 +1319,11 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
* These ioctls don't rely on the hardware to be present.
*/
switch (cmd) {
case TIOCGSERIAL:
ret = uart_get_info_user(port, uarg);
break;
case TIOCSSERIAL:
down_write(&tty->termios_rwsem);
ret = uart_set_info_user(tty, state, uarg);
up_write(&tty->termios_rwsem);
break;
case TIOCSERCONFIG:
down_write(&tty->termios_rwsem);
ret = uart_do_autoconfig(tty, state);
up_write(&tty->termios_rwsem);
break;
case TIOCSERGWILD: /* obsolete */
case TIOCSERSWILD: /* obsolete */
ret = 0;
break;
}
if (ret != -ENOIOCTLCMD)
@ -2413,6 +2392,8 @@ static const struct tty_operations uart_ops = {
#endif
.tiocmget = uart_tiocmget,
.tiocmset = uart_tiocmset,
.set_serial = uart_set_info_user,
.get_serial = uart_get_info_user,
.get_icount = uart_get_icount,
#ifdef CONFIG_CONSOLE_POLL
.poll_init = uart_poll_init,

View file

@ -2959,8 +2959,7 @@ static int mgsl_ioctl(struct tty_struct *tty,
if (mgsl_paranoia_check(info, tty->name, "mgsl_ioctl"))
return -ENODEV;
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != TIOCMIWAIT)) {
if (cmd != TIOCMIWAIT) {
if (tty_io_error(tty))
return -EIO;
}

View file

@ -1029,8 +1029,7 @@ static int ioctl(struct tty_struct *tty,
return -ENODEV;
DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != TIOCMIWAIT)) {
if (cmd != TIOCMIWAIT) {
if (tty_io_error(tty))
return -EIO;
}
@ -1186,14 +1185,13 @@ static long slgt_compat_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct slgt_info *info = tty->driver_data;
int rc = -ENOIOCTLCMD;
int rc;
if (sanity_check(info, tty->name, "compat_ioctl"))
return -ENODEV;
DBGINFO(("%s compat_ioctl() cmd=%08X\n", info->device_name, cmd));
switch (cmd) {
case MGSL_IOCSPARAMS32:
rc = set_params32(info, compat_ptr(arg));
break;
@ -1213,18 +1211,11 @@ static long slgt_compat_ioctl(struct tty_struct *tty,
case MGSL_IOCWAITGPIO:
case MGSL_IOCGXSYNC:
case MGSL_IOCGXCTRL:
case MGSL_IOCSTXIDLE:
case MGSL_IOCTXENABLE:
case MGSL_IOCRXENABLE:
case MGSL_IOCTXABORT:
case TIOCMIWAIT:
case MGSL_IOCSIF:
case MGSL_IOCSXSYNC:
case MGSL_IOCSXCTRL:
rc = ioctl(tty, cmd, arg);
rc = ioctl(tty, cmd, (unsigned long)compat_ptr(arg));
break;
default:
rc = ioctl(tty, cmd, arg);
}
DBGINFO(("%s compat_ioctl() cmd=%08X rc=%d\n", info->device_name, cmd, rc));
return rc;
}

View file

@ -1259,8 +1259,7 @@ static int ioctl(struct tty_struct *tty,
if (sanity_check(info, tty->name, "ioctl"))
return -ENODEV;
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
(cmd != TIOCMIWAIT)) {
if (cmd != TIOCMIWAIT) {
if (tty_io_error(tty))
return -EIO;
}

View file

@ -97,6 +97,7 @@
#include <linux/seq_file.h>
#include <linux/serial.h>
#include <linux/ratelimit.h>
#include <linux/compat.h>
#include <linux/uaccess.h>
@ -2292,34 +2293,6 @@ static int tioccons(struct file *file)
return 0;
}
/**
* fionbio - non blocking ioctl
* @file: file to set blocking value
* @p: user parameter
*
* Historical tty interfaces had a blocking control ioctl before
* the generic functionality existed. This piece of history is preserved
* in the expected tty API of posix OS's.
*
* Locking: none, the open file handle ensures it won't go away.
*/
static int fionbio(struct file *file, int __user *p)
{
int nonblock;
if (get_user(nonblock, p))
return -EFAULT;
spin_lock(&file->f_lock);
if (nonblock)
file->f_flags |= O_NONBLOCK;
else
file->f_flags &= ~O_NONBLOCK;
spin_unlock(&file->f_lock);
return 0;
}
/**
* tiocsetd - set line discipline
* @tty: tty device
@ -2488,22 +2461,40 @@ static int tty_tiocgicount(struct tty_struct *tty, void __user *arg)
return 0;
}
static void tty_warn_deprecated_flags(struct serial_struct __user *ss)
static int tty_tiocsserial(struct tty_struct *tty, struct serial_struct __user *ss)
{
static DEFINE_RATELIMIT_STATE(depr_flags,
DEFAULT_RATELIMIT_INTERVAL,
DEFAULT_RATELIMIT_BURST);
char comm[TASK_COMM_LEN];
struct serial_struct v;
int flags;
if (get_user(flags, &ss->flags))
return;
if (copy_from_user(&v, ss, sizeof(struct serial_struct)))
return -EFAULT;
flags &= ASYNC_DEPRECATED;
flags = v.flags & ASYNC_DEPRECATED;
if (flags && __ratelimit(&depr_flags))
pr_warn("%s: '%s' is using deprecated serial flags (with no effect): %.8x\n",
__func__, get_task_comm(comm, current), flags);
if (!tty->ops->set_serial)
return -ENOTTY;
return tty->ops->set_serial(tty, &v);
}
static int tty_tiocgserial(struct tty_struct *tty, struct serial_struct __user *ss)
{
struct serial_struct v;
int err;
memset(&v, 0, sizeof(struct serial_struct));
if (!tty->ops->get_serial)
return -ENOTTY;
err = tty->ops->get_serial(tty, &v);
if (!err && copy_to_user(ss, &v, sizeof(struct serial_struct)))
err = -EFAULT;
return err;
}
/*
@ -2566,8 +2557,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return tiocswinsz(real_tty, p);
case TIOCCONS:
return real_tty != tty ? -EINVAL : tioccons(file);
case FIONBIO:
return fionbio(file, p);
case TIOCEXCL:
set_bit(TTY_EXCLUSIVE, &tty->flags);
return 0;
@ -2622,11 +2611,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case TIOCMBIS:
return tty_tiocmset(tty, cmd, p);
case TIOCGICOUNT:
retval = tty_tiocgicount(tty, p);
/* For the moment allow fall through to the old method */
if (retval != -EINVAL)
return retval;
break;
return tty_tiocgicount(tty, p);
case TCFLSH:
switch (arg) {
case TCIFLUSH:
@ -2637,8 +2622,9 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
break;
case TIOCSSERIAL:
tty_warn_deprecated_flags(p);
break;
return tty_tiocsserial(tty, p);
case TIOCGSERIAL:
return tty_tiocgserial(tty, p);
case TIOCGPTPEER:
/* Special because the struct file is needed */
return ptm_open_peer(file, tty, (int)arg);
@ -2666,6 +2652,81 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
#ifdef CONFIG_COMPAT
struct serial_struct32 {
compat_int_t type;
compat_int_t line;
compat_uint_t port;
compat_int_t irq;
compat_int_t flags;
compat_int_t xmit_fifo_size;
compat_int_t custom_divisor;
compat_int_t baud_base;
unsigned short close_delay;
char io_type;
char reserved_char[1];
compat_int_t hub6;
unsigned short closing_wait; /* time to wait before closing */
unsigned short closing_wait2; /* no longer used... */
compat_uint_t iomem_base;
unsigned short iomem_reg_shift;
unsigned int port_high;
/* compat_ulong_t iomap_base FIXME */
compat_int_t reserved[1];
};
static int compat_tty_tiocsserial(struct tty_struct *tty,
struct serial_struct32 __user *ss)
{
static DEFINE_RATELIMIT_STATE(depr_flags,
DEFAULT_RATELIMIT_INTERVAL,
DEFAULT_RATELIMIT_BURST);
char comm[TASK_COMM_LEN];
struct serial_struct32 v32;
struct serial_struct v;
int flags;
if (copy_from_user(&v32, ss, sizeof(struct serial_struct32)))
return -EFAULT;
memcpy(&v, &v32, offsetof(struct serial_struct32, iomem_base));
v.iomem_base = compat_ptr(v32.iomem_base);
v.iomem_reg_shift = v32.iomem_reg_shift;
v.port_high = v32.port_high;
v.iomap_base = 0;
flags = v.flags & ASYNC_DEPRECATED;
if (flags && __ratelimit(&depr_flags))
pr_warn("%s: '%s' is using deprecated serial flags (with no effect): %.8x\n",
__func__, get_task_comm(comm, current), flags);
if (!tty->ops->set_serial)
return -ENOTTY;
return tty->ops->set_serial(tty, &v);
}
static int compat_tty_tiocgserial(struct tty_struct *tty,
struct serial_struct32 __user *ss)
{
struct serial_struct32 v32;
struct serial_struct v;
int err;
memset(&v, 0, sizeof(struct serial_struct));
if (!tty->ops->set_serial)
return -ENOTTY;
err = tty->ops->get_serial(tty, &v);
if (!err) {
memcpy(&v32, &v, offsetof(struct serial_struct32, iomem_base));
v32.iomem_base = (unsigned long)v.iomem_base >> 32 ?
0xfffffff : ptr_to_compat(v.iomem_base);
v32.iomem_reg_shift = v.iomem_reg_shift;
v32.port_high = v.port_high;
if (copy_to_user(ss, &v32, sizeof(struct serial_struct32)))
err = -EFAULT;
}
return err;
}
static long tty_compat_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
@ -2673,9 +2734,90 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
struct tty_ldisc *ld;
int retval = -ENOIOCTLCMD;
switch (cmd) {
case TIOCSTI:
case TIOCGWINSZ:
case TIOCSWINSZ:
case TIOCGEXCL:
case TIOCGETD:
case TIOCSETD:
case TIOCGDEV:
case TIOCMGET:
case TIOCMSET:
case TIOCMBIC:
case TIOCMBIS:
case TIOCGICOUNT:
case TIOCGPGRP:
case TIOCSPGRP:
case TIOCGSID:
case TIOCSERGETLSR:
case TIOCGRS485:
case TIOCSRS485:
#ifdef TIOCGETP
case TIOCGETP:
case TIOCSETP:
case TIOCSETN:
#endif
#ifdef TIOCGETC
case TIOCGETC:
case TIOCSETC:
#endif
#ifdef TIOCGLTC
case TIOCGLTC:
case TIOCSLTC:
#endif
case TCSETSF:
case TCSETSW:
case TCSETS:
case TCGETS:
#ifdef TCGETS2
case TCGETS2:
case TCSETSF2:
case TCSETSW2:
case TCSETS2:
#endif
case TCGETA:
case TCSETAF:
case TCSETAW:
case TCSETA:
case TIOCGLCKTRMIOS:
case TIOCSLCKTRMIOS:
#ifdef TCGETX
case TCGETX:
case TCSETX:
case TCSETXW:
case TCSETXF:
#endif
case TIOCGSOFTCAR:
case TIOCSSOFTCAR:
return tty_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
case TIOCCONS:
case TIOCEXCL:
case TIOCNXCL:
case TIOCVHANGUP:
case TIOCSBRK:
case TIOCCBRK:
case TCSBRK:
case TCSBRKP:
case TCFLSH:
case TIOCGPTPEER:
case TIOCNOTTY:
case TIOCSCTTY:
case TCXONC:
case TIOCMIWAIT:
case TIOCSERCONFIG:
return tty_ioctl(file, cmd, arg);
}
if (tty_paranoia_check(tty, file_inode(file), "tty_ioctl"))
return -EINVAL;
switch (cmd) {
case TIOCSSERIAL:
return compat_tty_tiocsserial(tty, compat_ptr(arg));
case TIOCGSERIAL:
return compat_tty_tiocgserial(tty, compat_ptr(arg));
}
if (tty->ops->compat_ioctl) {
retval = tty->ops->compat_ioctl(tty, cmd, arg);
if (retval != -ENOIOCTLCMD)
@ -2687,8 +2829,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);
else
retval = n_tty_compat_ioctl_helper(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;

View file

@ -941,19 +941,3 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
}
}
EXPORT_SYMBOL(n_tty_ioctl_helper);
#ifdef CONFIG_COMPAT
long n_tty_compat_ioctl_helper(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
switch (cmd) {
case TIOCGLCKTRMIOS:
case TIOCSLCKTRMIOS:
return tty_mode_ioctl(tty, file, cmd, (unsigned long) compat_ptr(arg));
default:
return -ENOIOCTLCMD;
}
}
EXPORT_SYMBOL(n_tty_compat_ioctl_helper);
#endif

View file

@ -1175,17 +1175,13 @@ long vt_compat_ioctl(struct tty_struct *tty,
{
struct vc_data *vc = tty->driver_data;
struct console_font_op op; /* used in multiple places here */
unsigned int console;
void __user *up = (void __user *)arg;
unsigned int console = vc->vc_num;
void __user *up = compat_ptr(arg);
int perm;
int ret = 0;
console = vc->vc_num;
if (!vc_cons_allocated(console)) { /* impossible? */
ret = -ENOIOCTLCMD;
goto out;
}
if (!vc_cons_allocated(console)) /* impossible? */
return -ENOIOCTLCMD;
/*
* To have permissions to do most of the vt ioctls, we either have
@ -1201,17 +1197,14 @@ long vt_compat_ioctl(struct tty_struct *tty,
*/
case PIO_FONTX:
case GIO_FONTX:
ret = compat_fontx_ioctl(cmd, up, perm, &op);
break;
return compat_fontx_ioctl(cmd, up, perm, &op);
case KDFONTOP:
ret = compat_kdfontop_ioctl(up, perm, &op, vc);
break;
return compat_kdfontop_ioctl(up, perm, &op, vc);
case PIO_UNIMAP:
case GIO_UNIMAP:
ret = compat_unimap_ioctl(cmd, up, perm, vc);
break;
return compat_unimap_ioctl(cmd, up, perm, vc);
/*
* all these treat 'arg' as an integer
@ -1236,21 +1229,15 @@ long vt_compat_ioctl(struct tty_struct *tty,
case VT_DISALLOCATE:
case VT_RESIZE:
case VT_RESIZEX:
goto fallback;
return vt_ioctl(tty, cmd, arg);
/*
* the rest has a compatible data structure behind arg,
* but we have to convert it to a proper 64 bit pointer.
*/
default:
arg = (unsigned long)compat_ptr(arg);
goto fallback;
return vt_ioctl(tty, cmd, (unsigned long)up);
}
out:
return ret;
fallback:
return vt_ioctl(tty, cmd, arg);
}