Commit 4001d7b7 authored by Alan Cox's avatar Alan Cox Committed by Greg Kroah-Hartman

vt: push down the tty lock so we can see what is left to tackle

At this point we have the tty_lock guarding a couple of oddities, plus the
translation and unimap still.

We also extend the console_lock in a couple of spots where coverage is wrong
and switch vcs_open to use the right lock !

[Fixed the locking issue Jiri reported]
Signed-off-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent edab558f
...@@ -608,10 +608,10 @@ vcs_open(struct inode *inode, struct file *filp) ...@@ -608,10 +608,10 @@ vcs_open(struct inode *inode, struct file *filp)
unsigned int currcons = iminor(inode) & 127; unsigned int currcons = iminor(inode) & 127;
int ret = 0; int ret = 0;
tty_lock(); console_lock();
if(currcons && !vc_cons_allocated(currcons-1)) if(currcons && !vc_cons_allocated(currcons-1))
ret = -ENXIO; ret = -ENXIO;
tty_unlock(); console_unlock();
return ret; return ret;
} }
......
...@@ -281,7 +281,6 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -281,7 +281,6 @@ int vt_ioctl(struct tty_struct *tty,
console = vc->vc_num; console = vc->vc_num;
tty_lock();
if (!vc_cons_allocated(console)) { /* impossible? */ if (!vc_cons_allocated(console)) { /* impossible? */
ret = -ENOIOCTLCMD; ret = -ENOIOCTLCMD;
...@@ -299,16 +298,18 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -299,16 +298,18 @@ int vt_ioctl(struct tty_struct *tty,
switch (cmd) { switch (cmd) {
case TIOCLINUX: case TIOCLINUX:
tty_lock();
ret = tioclinux(tty, arg); ret = tioclinux(tty, arg);
tty_unlock();
break; break;
case KIOCSOUND: case KIOCSOUND:
if (!perm) if (!perm)
goto eperm; return -EPERM;
/* /*
* The use of PIT_TICK_RATE is historic, it used to be * The use of PIT_TICK_RATE is historic, it used to be
* the platform-dependent CLOCK_TICK_RATE between 2.6.12 * the platform-dependent CLOCK_TICK_RATE between 2.6.12
* and 2.6.36, which was a minor but unfortunate ABI * and 2.6.36, which was a minor but unfortunate ABI
* change. * change. kd_mksound is locked by the input layer.
*/ */
if (arg) if (arg)
arg = PIT_TICK_RATE / arg; arg = PIT_TICK_RATE / arg;
...@@ -317,7 +318,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -317,7 +318,7 @@ int vt_ioctl(struct tty_struct *tty,
case KDMKTONE: case KDMKTONE:
if (!perm) if (!perm)
goto eperm; return -EPERM;
{ {
unsigned int ticks, count; unsigned int ticks, count;
...@@ -335,7 +336,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -335,7 +336,7 @@ int vt_ioctl(struct tty_struct *tty,
case KDGKBTYPE: case KDGKBTYPE:
/* /*
* this is naive. * this is naïve.
*/ */
ucval = KB_101; ucval = KB_101;
ret = put_user(ucval, (char __user *)arg); ret = put_user(ucval, (char __user *)arg);
...@@ -353,6 +354,8 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -353,6 +354,8 @@ int vt_ioctl(struct tty_struct *tty,
/* /*
* KDADDIO and KDDELIO may be able to add ports beyond what * KDADDIO and KDDELIO may be able to add ports beyond what
* we reject here, but to be safe... * we reject here, but to be safe...
*
* These are locked internally via sys_ioperm
*/ */
if (arg < GPFIRST || arg > GPLAST) { if (arg < GPFIRST || arg > GPLAST) {
ret = -EINVAL; ret = -EINVAL;
...@@ -375,7 +378,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -375,7 +378,7 @@ int vt_ioctl(struct tty_struct *tty,
struct kbd_repeat kbrep; struct kbd_repeat kbrep;
if (!capable(CAP_SYS_TTY_CONFIG)) if (!capable(CAP_SYS_TTY_CONFIG))
goto eperm; return -EPERM;
if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) { if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) {
ret = -EFAULT; ret = -EFAULT;
...@@ -399,7 +402,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -399,7 +402,7 @@ int vt_ioctl(struct tty_struct *tty,
* need to restore their engine state. --BenH * need to restore their engine state. --BenH
*/ */
if (!perm) if (!perm)
goto eperm; return -EPERM;
switch (arg) { switch (arg) {
case KD_GRAPHICS: case KD_GRAPHICS:
break; break;
...@@ -412,6 +415,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -412,6 +415,7 @@ int vt_ioctl(struct tty_struct *tty,
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
/* FIXME: this needs the console lock extending */
if (vc->vc_mode == (unsigned char) arg) if (vc->vc_mode == (unsigned char) arg)
break; break;
vc->vc_mode = (unsigned char) arg; vc->vc_mode = (unsigned char) arg;
...@@ -443,7 +447,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -443,7 +447,7 @@ int vt_ioctl(struct tty_struct *tty,
case KDSKBMODE: case KDSKBMODE:
if (!perm) if (!perm)
goto eperm; return -EPERM;
ret = vt_do_kdskbmode(console, arg); ret = vt_do_kdskbmode(console, arg);
if (ret == 0) if (ret == 0)
tty_ldisc_flush(tty); tty_ldisc_flush(tty);
...@@ -512,7 +516,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -512,7 +516,7 @@ int vt_ioctl(struct tty_struct *tty,
case KDSIGACCEPT: case KDSIGACCEPT:
{ {
if (!perm || !capable(CAP_KILL)) if (!perm || !capable(CAP_KILL))
goto eperm; return -EPERM;
if (!valid_signal(arg) || arg < 1 || arg == SIGKILL) if (!valid_signal(arg) || arg < 1 || arg == SIGKILL)
ret = -EINVAL; ret = -EINVAL;
else { else {
...@@ -530,7 +534,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -530,7 +534,7 @@ int vt_ioctl(struct tty_struct *tty,
struct vt_mode tmp; struct vt_mode tmp;
if (!perm) if (!perm)
goto eperm; return -EPERM;
if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) { if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) {
ret = -EFAULT; ret = -EFAULT;
goto out; goto out;
...@@ -576,6 +580,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -576,6 +580,7 @@ int vt_ioctl(struct tty_struct *tty,
struct vt_stat __user *vtstat = up; struct vt_stat __user *vtstat = up;
unsigned short state, mask; unsigned short state, mask;
/* Review: FIXME: Console lock ? */
if (put_user(fg_console + 1, &vtstat->v_active)) if (put_user(fg_console + 1, &vtstat->v_active))
ret = -EFAULT; ret = -EFAULT;
else { else {
...@@ -593,6 +598,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -593,6 +598,7 @@ int vt_ioctl(struct tty_struct *tty,
* Returns the first available (non-opened) console. * Returns the first available (non-opened) console.
*/ */
case VT_OPENQRY: case VT_OPENQRY:
/* FIXME: locking ? - but then this is a stupid API */
for (i = 0; i < MAX_NR_CONSOLES; ++i) for (i = 0; i < MAX_NR_CONSOLES; ++i)
if (! VT_IS_IN_USE(i)) if (! VT_IS_IN_USE(i))
break; break;
...@@ -606,7 +612,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -606,7 +612,7 @@ int vt_ioctl(struct tty_struct *tty,
*/ */
case VT_ACTIVATE: case VT_ACTIVATE:
if (!perm) if (!perm)
goto eperm; return -EPERM;
if (arg == 0 || arg > MAX_NR_CONSOLES) if (arg == 0 || arg > MAX_NR_CONSOLES)
ret = -ENXIO; ret = -ENXIO;
else { else {
...@@ -625,7 +631,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -625,7 +631,7 @@ int vt_ioctl(struct tty_struct *tty,
struct vt_setactivate vsa; struct vt_setactivate vsa;
if (!perm) if (!perm)
goto eperm; return -EPERM;
if (copy_from_user(&vsa, (struct vt_setactivate __user *)arg, if (copy_from_user(&vsa, (struct vt_setactivate __user *)arg,
sizeof(struct vt_setactivate))) { sizeof(struct vt_setactivate))) {
...@@ -653,6 +659,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -653,6 +659,7 @@ int vt_ioctl(struct tty_struct *tty,
if (ret) if (ret)
break; break;
/* Commence switch and lock */ /* Commence switch and lock */
/* Review set_console locks */
set_console(vsa.console); set_console(vsa.console);
} }
break; break;
...@@ -663,11 +670,14 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -663,11 +670,14 @@ int vt_ioctl(struct tty_struct *tty,
*/ */
case VT_WAITACTIVE: case VT_WAITACTIVE:
if (!perm) if (!perm)
goto eperm; return -EPERM;
if (arg == 0 || arg > MAX_NR_CONSOLES) if (arg == 0 || arg > MAX_NR_CONSOLES)
ret = -ENXIO; ret = -ENXIO;
else else {
tty_lock();
ret = vt_waitactive(arg); ret = vt_waitactive(arg);
tty_unlock();
}
break; break;
/* /*
...@@ -682,16 +692,17 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -682,16 +692,17 @@ int vt_ioctl(struct tty_struct *tty,
*/ */
case VT_RELDISP: case VT_RELDISP:
if (!perm) if (!perm)
goto eperm; return -EPERM;
console_lock();
if (vc->vt_mode.mode != VT_PROCESS) { if (vc->vt_mode.mode != VT_PROCESS) {
console_unlock();
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
/* /*
* Switching-from response * Switching-from response
*/ */
console_lock();
if (vc->vt_newvt >= 0) { if (vc->vt_newvt >= 0) {
if (arg == 0) if (arg == 0)
/* /*
...@@ -768,7 +779,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -768,7 +779,7 @@ int vt_ioctl(struct tty_struct *tty,
ushort ll,cc; ushort ll,cc;
if (!perm) if (!perm)
goto eperm; return -EPERM;
if (get_user(ll, &vtsizes->v_rows) || if (get_user(ll, &vtsizes->v_rows) ||
get_user(cc, &vtsizes->v_cols)) get_user(cc, &vtsizes->v_cols))
ret = -EFAULT; ret = -EFAULT;
...@@ -779,6 +790,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -779,6 +790,7 @@ int vt_ioctl(struct tty_struct *tty,
if (vc) { if (vc) {
vc->vc_resize_user = 1; vc->vc_resize_user = 1;
/* FIXME: review v tty lock */
vc_resize(vc_cons[i].d, cc, ll); vc_resize(vc_cons[i].d, cc, ll);
} }
} }
...@@ -792,7 +804,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -792,7 +804,7 @@ int vt_ioctl(struct tty_struct *tty,
struct vt_consize __user *vtconsize = up; struct vt_consize __user *vtconsize = up;
ushort ll,cc,vlin,clin,vcol,ccol; ushort ll,cc,vlin,clin,vcol,ccol;
if (!perm) if (!perm)
goto eperm; return -EPERM;
if (!access_ok(VERIFY_READ, vtconsize, if (!access_ok(VERIFY_READ, vtconsize,
sizeof(struct vt_consize))) { sizeof(struct vt_consize))) {
ret = -EFAULT; ret = -EFAULT;
...@@ -848,7 +860,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -848,7 +860,7 @@ int vt_ioctl(struct tty_struct *tty,
case PIO_FONT: { case PIO_FONT: {
if (!perm) if (!perm)
goto eperm; return -EPERM;
op.op = KD_FONT_OP_SET; op.op = KD_FONT_OP_SET;
op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */ op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */
op.width = 8; op.width = 8;
...@@ -889,7 +901,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -889,7 +901,7 @@ int vt_ioctl(struct tty_struct *tty,
case PIO_FONTRESET: case PIO_FONTRESET:
{ {
if (!perm) if (!perm)
goto eperm; return -EPERM;
#ifdef BROKEN_GRAPHICS_PROGRAMS #ifdef BROKEN_GRAPHICS_PROGRAMS
/* With BROKEN_GRAPHICS_PROGRAMS defined, the default /* With BROKEN_GRAPHICS_PROGRAMS defined, the default
...@@ -915,7 +927,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -915,7 +927,7 @@ int vt_ioctl(struct tty_struct *tty,
break; break;
} }
if (!perm && op.op != KD_FONT_OP_GET) if (!perm && op.op != KD_FONT_OP_GET)
goto eperm; return -EPERM;
ret = con_font_op(vc, &op); ret = con_font_op(vc, &op);
if (ret) if (ret)
break; break;
...@@ -927,50 +939,65 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -927,50 +939,65 @@ int vt_ioctl(struct tty_struct *tty,
case PIO_SCRNMAP: case PIO_SCRNMAP:
if (!perm) if (!perm)
ret = -EPERM; ret = -EPERM;
else else {
tty_lock();
ret = con_set_trans_old(up); ret = con_set_trans_old(up);
tty_unlock();
}
break; break;
case GIO_SCRNMAP: case GIO_SCRNMAP:
tty_lock();
ret = con_get_trans_old(up); ret = con_get_trans_old(up);
tty_unlock();
break; break;
case PIO_UNISCRNMAP: case PIO_UNISCRNMAP:
if (!perm) if (!perm)
ret = -EPERM; ret = -EPERM;
else else {
tty_lock();
ret = con_set_trans_new(up); ret = con_set_trans_new(up);
tty_unlock();
}
break; break;
case GIO_UNISCRNMAP: case GIO_UNISCRNMAP:
tty_lock();
ret = con_get_trans_new(up); ret = con_get_trans_new(up);
tty_unlock();
break; break;
case PIO_UNIMAPCLR: case PIO_UNIMAPCLR:
{ struct unimapinit ui; { struct unimapinit ui;
if (!perm) if (!perm)
goto eperm; return -EPERM;
ret = copy_from_user(&ui, up, sizeof(struct unimapinit)); ret = copy_from_user(&ui, up, sizeof(struct unimapinit));
if (ret) if (ret)
ret = -EFAULT; ret = -EFAULT;
else else {
tty_lock();
con_clear_unimap(vc, &ui); con_clear_unimap(vc, &ui);
tty_unlock();
}
break; break;
} }
case PIO_UNIMAP: case PIO_UNIMAP:
case GIO_UNIMAP: case GIO_UNIMAP:
tty_lock();
ret = do_unimap_ioctl(cmd, up, perm, vc); ret = do_unimap_ioctl(cmd, up, perm, vc);
tty_unlock();
break; break;
case VT_LOCKSWITCH: case VT_LOCKSWITCH:
if (!capable(CAP_SYS_TTY_CONFIG)) if (!capable(CAP_SYS_TTY_CONFIG))
goto eperm; return -EPERM;
vt_dont_switch = 1; vt_dont_switch = 1;
break; break;
case VT_UNLOCKSWITCH: case VT_UNLOCKSWITCH:
if (!capable(CAP_SYS_TTY_CONFIG)) if (!capable(CAP_SYS_TTY_CONFIG))
goto eperm; return -EPERM;
vt_dont_switch = 0; vt_dont_switch = 0;
break; break;
case VT_GETHIFONTMASK: case VT_GETHIFONTMASK:
...@@ -984,11 +1011,7 @@ int vt_ioctl(struct tty_struct *tty, ...@@ -984,11 +1011,7 @@ int vt_ioctl(struct tty_struct *tty,
ret = -ENOIOCTLCMD; ret = -ENOIOCTLCMD;
} }
out: out:
tty_unlock();
return ret; return ret;
eperm:
ret = -EPERM;
goto out;
} }
void reset_vc(struct vc_data *vc) void reset_vc(struct vc_data *vc)
...@@ -1150,8 +1173,6 @@ long vt_compat_ioctl(struct tty_struct *tty, ...@@ -1150,8 +1173,6 @@ long vt_compat_ioctl(struct tty_struct *tty,
console = vc->vc_num; console = vc->vc_num;
tty_lock();
if (!vc_cons_allocated(console)) { /* impossible? */ if (!vc_cons_allocated(console)) { /* impossible? */
ret = -ENOIOCTLCMD; ret = -ENOIOCTLCMD;
goto out; goto out;
...@@ -1180,7 +1201,9 @@ long vt_compat_ioctl(struct tty_struct *tty, ...@@ -1180,7 +1201,9 @@ long vt_compat_ioctl(struct tty_struct *tty,
case PIO_UNIMAP: case PIO_UNIMAP:
case GIO_UNIMAP: case GIO_UNIMAP:
tty_lock();
ret = compat_unimap_ioctl(cmd, up, perm, vc); ret = compat_unimap_ioctl(cmd, up, perm, vc);
tty_unlock();
break; break;
/* /*
...@@ -1217,11 +1240,9 @@ long vt_compat_ioctl(struct tty_struct *tty, ...@@ -1217,11 +1240,9 @@ long vt_compat_ioctl(struct tty_struct *tty,
goto fallback; goto fallback;
} }
out: out:
tty_unlock();
return ret; return ret;
fallback: fallback:
tty_unlock();
return vt_ioctl(tty, cmd, arg); return vt_ioctl(tty, cmd, arg);
} }
...@@ -1407,6 +1428,7 @@ int vt_move_to_console(unsigned int vt, int alloc) ...@@ -1407,6 +1428,7 @@ int vt_move_to_console(unsigned int vt, int alloc)
return -EIO; return -EIO;
} }
console_unlock(); console_unlock();
/* Review: I don't see why we need tty_lock here FIXME */
tty_lock(); tty_lock();
if (vt_waitactive(vt + 1)) { if (vt_waitactive(vt + 1)) {
pr_debug("Suspend: Can't switch VCs."); pr_debug("Suspend: Can't switch VCs.");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment