forked from Minki/linux
vt_ioctl: move K* ioctls to a separate function
We create a new vt_k_ioctl here and move there all the K* ioctls. This makes vt_ioctl significantly smaller. Signed-off-by: Jiri Slaby <jslaby@suse.cz> Link: https://lore.kernel.org/r/20200615074910.19267-31-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
eca734d8f0
commit
832a62ab6b
@ -241,133 +241,15 @@ int vt_waitactive(int n)
|
||||
#define GPLAST 0x3df
|
||||
#define GPNUM (GPLAST - GPFIRST + 1)
|
||||
|
||||
|
||||
|
||||
static inline int
|
||||
do_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op)
|
||||
{
|
||||
struct consolefontdesc cfdarg;
|
||||
int i;
|
||||
|
||||
if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc)))
|
||||
return -EFAULT;
|
||||
|
||||
switch (cmd) {
|
||||
case PIO_FONTX:
|
||||
if (!perm)
|
||||
return -EPERM;
|
||||
op->op = KD_FONT_OP_SET;
|
||||
op->flags = KD_FONT_FLAG_OLD;
|
||||
op->width = 8;
|
||||
op->height = cfdarg.charheight;
|
||||
op->charcount = cfdarg.charcount;
|
||||
op->data = cfdarg.chardata;
|
||||
return con_font_op(vc_cons[fg_console].d, op);
|
||||
case GIO_FONTX: {
|
||||
op->op = KD_FONT_OP_GET;
|
||||
op->flags = KD_FONT_FLAG_OLD;
|
||||
op->width = 8;
|
||||
op->height = cfdarg.charheight;
|
||||
op->charcount = cfdarg.charcount;
|
||||
op->data = cfdarg.chardata;
|
||||
i = con_font_op(vc_cons[fg_console].d, op);
|
||||
if (i)
|
||||
return i;
|
||||
cfdarg.charheight = op->height;
|
||||
cfdarg.charcount = op->charcount;
|
||||
if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int
|
||||
do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc)
|
||||
{
|
||||
struct unimapdesc tmp;
|
||||
|
||||
if (copy_from_user(&tmp, user_ud, sizeof tmp))
|
||||
return -EFAULT;
|
||||
switch (cmd) {
|
||||
case PIO_UNIMAP:
|
||||
if (!perm)
|
||||
return -EPERM;
|
||||
return con_set_unimap(vc, tmp.entry_ct, tmp.entries);
|
||||
case GIO_UNIMAP:
|
||||
if (!perm && fg_console != vc->vc_num)
|
||||
return -EPERM;
|
||||
return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* deallocate a single console, if possible (leave 0) */
|
||||
static int vt_disallocate(unsigned int vc_num)
|
||||
{
|
||||
struct vc_data *vc = NULL;
|
||||
int ret = 0;
|
||||
|
||||
console_lock();
|
||||
if (vt_busy(vc_num))
|
||||
ret = -EBUSY;
|
||||
else if (vc_num)
|
||||
vc = vc_deallocate(vc_num);
|
||||
console_unlock();
|
||||
|
||||
if (vc && vc_num >= MIN_NR_CONSOLES)
|
||||
tty_port_put(&vc->port);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* deallocate all unused consoles, but leave 0 */
|
||||
static void vt_disallocate_all(void)
|
||||
{
|
||||
struct vc_data *vc[MAX_NR_CONSOLES];
|
||||
int i;
|
||||
|
||||
console_lock();
|
||||
for (i = 1; i < MAX_NR_CONSOLES; i++)
|
||||
if (!vt_busy(i))
|
||||
vc[i] = vc_deallocate(i);
|
||||
else
|
||||
vc[i] = NULL;
|
||||
console_unlock();
|
||||
|
||||
for (i = 1; i < MAX_NR_CONSOLES; i++) {
|
||||
if (vc[i] && i >= MIN_NR_CONSOLES)
|
||||
tty_port_put(&vc[i]->port);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We handle the console-specific ioctl's here. We allow the
|
||||
* capability to modify any console, not just the fg_console.
|
||||
*/
|
||||
int vt_ioctl(struct tty_struct *tty,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
static int vt_k_ioctl(struct tty_struct *tty, unsigned int cmd,
|
||||
unsigned long arg, bool perm)
|
||||
{
|
||||
struct vc_data *vc = tty->driver_data;
|
||||
struct console_font_op op; /* used in multiple places here */
|
||||
unsigned int console = vc->vc_num;
|
||||
void __user *up = (void __user *)arg;
|
||||
int i, perm;
|
||||
unsigned int console = vc->vc_num;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* To have permissions to do most of the vt ioctls, we either have
|
||||
* to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
|
||||
*/
|
||||
perm = 0;
|
||||
if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
|
||||
perm = 1;
|
||||
|
||||
switch (cmd) {
|
||||
case TIOCLINUX:
|
||||
return tioclinux(tty, arg);
|
||||
case KIOCSOUND:
|
||||
if (!perm)
|
||||
return -EPERM;
|
||||
@ -387,7 +269,7 @@ int vt_ioctl(struct tty_struct *tty,
|
||||
return -EPERM;
|
||||
{
|
||||
unsigned int ticks, count;
|
||||
|
||||
|
||||
/*
|
||||
* Generate the tone for the appropriate number of ticks.
|
||||
* If the time is zero, turn off sound ourselves.
|
||||
@ -433,11 +315,11 @@ int vt_ioctl(struct tty_struct *tty,
|
||||
#endif
|
||||
|
||||
/* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */
|
||||
|
||||
|
||||
case KDKBDREP:
|
||||
{
|
||||
struct kbd_repeat kbrep;
|
||||
|
||||
|
||||
if (!capable(CAP_SYS_TTY_CONFIG))
|
||||
return -EPERM;
|
||||
|
||||
@ -573,6 +455,157 @@ int vt_ioctl(struct tty_struct *tty,
|
||||
spin_unlock_irq(&vt_spawn_con.lock);
|
||||
break;
|
||||
|
||||
case KDFONTOP: {
|
||||
struct console_font_op op;
|
||||
|
||||
if (copy_from_user(&op, up, sizeof(op)))
|
||||
return -EFAULT;
|
||||
if (!perm && op.op != KD_FONT_OP_GET)
|
||||
return -EPERM;
|
||||
ret = con_font_op(vc, &op);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (copy_to_user(up, &op, sizeof(op)))
|
||||
return -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int do_fontx_ioctl(int cmd,
|
||||
struct consolefontdesc __user *user_cfd, int perm,
|
||||
struct console_font_op *op)
|
||||
{
|
||||
struct consolefontdesc cfdarg;
|
||||
int i;
|
||||
|
||||
if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc)))
|
||||
return -EFAULT;
|
||||
|
||||
switch (cmd) {
|
||||
case PIO_FONTX:
|
||||
if (!perm)
|
||||
return -EPERM;
|
||||
op->op = KD_FONT_OP_SET;
|
||||
op->flags = KD_FONT_FLAG_OLD;
|
||||
op->width = 8;
|
||||
op->height = cfdarg.charheight;
|
||||
op->charcount = cfdarg.charcount;
|
||||
op->data = cfdarg.chardata;
|
||||
return con_font_op(vc_cons[fg_console].d, op);
|
||||
case GIO_FONTX: {
|
||||
op->op = KD_FONT_OP_GET;
|
||||
op->flags = KD_FONT_FLAG_OLD;
|
||||
op->width = 8;
|
||||
op->height = cfdarg.charheight;
|
||||
op->charcount = cfdarg.charcount;
|
||||
op->data = cfdarg.chardata;
|
||||
i = con_font_op(vc_cons[fg_console].d, op);
|
||||
if (i)
|
||||
return i;
|
||||
cfdarg.charheight = op->height;
|
||||
cfdarg.charcount = op->charcount;
|
||||
if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud,
|
||||
int perm, struct vc_data *vc)
|
||||
{
|
||||
struct unimapdesc tmp;
|
||||
|
||||
if (copy_from_user(&tmp, user_ud, sizeof tmp))
|
||||
return -EFAULT;
|
||||
switch (cmd) {
|
||||
case PIO_UNIMAP:
|
||||
if (!perm)
|
||||
return -EPERM;
|
||||
return con_set_unimap(vc, tmp.entry_ct, tmp.entries);
|
||||
case GIO_UNIMAP:
|
||||
if (!perm && fg_console != vc->vc_num)
|
||||
return -EPERM;
|
||||
return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct),
|
||||
tmp.entries);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* deallocate a single console, if possible (leave 0) */
|
||||
static int vt_disallocate(unsigned int vc_num)
|
||||
{
|
||||
struct vc_data *vc = NULL;
|
||||
int ret = 0;
|
||||
|
||||
console_lock();
|
||||
if (vt_busy(vc_num))
|
||||
ret = -EBUSY;
|
||||
else if (vc_num)
|
||||
vc = vc_deallocate(vc_num);
|
||||
console_unlock();
|
||||
|
||||
if (vc && vc_num >= MIN_NR_CONSOLES)
|
||||
tty_port_put(&vc->port);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* deallocate all unused consoles, but leave 0 */
|
||||
static void vt_disallocate_all(void)
|
||||
{
|
||||
struct vc_data *vc[MAX_NR_CONSOLES];
|
||||
int i;
|
||||
|
||||
console_lock();
|
||||
for (i = 1; i < MAX_NR_CONSOLES; i++)
|
||||
if (!vt_busy(i))
|
||||
vc[i] = vc_deallocate(i);
|
||||
else
|
||||
vc[i] = NULL;
|
||||
console_unlock();
|
||||
|
||||
for (i = 1; i < MAX_NR_CONSOLES; i++) {
|
||||
if (vc[i] && i >= MIN_NR_CONSOLES)
|
||||
tty_port_put(&vc[i]->port);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We handle the console-specific ioctl's here. We allow the
|
||||
* capability to modify any console, not just the fg_console.
|
||||
*/
|
||||
int vt_ioctl(struct tty_struct *tty,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct vc_data *vc = tty->driver_data;
|
||||
struct console_font_op op; /* used in multiple places here */
|
||||
void __user *up = (void __user *)arg;
|
||||
int i, perm;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* To have permissions to do most of the vt ioctls, we either have
|
||||
* to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
|
||||
*/
|
||||
perm = 0;
|
||||
if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
|
||||
perm = 1;
|
||||
|
||||
ret = vt_k_ioctl(tty, cmd, arg, perm);
|
||||
if (ret != -ENOIOCTLCMD)
|
||||
return ret;
|
||||
|
||||
switch (cmd) {
|
||||
case TIOCLINUX:
|
||||
return tioclinux(tty, arg);
|
||||
case VT_SETMODE:
|
||||
{
|
||||
struct vt_mode tmp;
|
||||
@ -922,19 +955,6 @@ int vt_ioctl(struct tty_struct *tty,
|
||||
break;
|
||||
#endif
|
||||
|
||||
case KDFONTOP: {
|
||||
if (copy_from_user(&op, up, sizeof(op)))
|
||||
return -EFAULT;
|
||||
if (!perm && op.op != KD_FONT_OP_GET)
|
||||
return -EPERM;
|
||||
ret = con_font_op(vc, &op);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (copy_to_user(up, &op, sizeof(op)))
|
||||
return -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
case PIO_SCRNMAP:
|
||||
if (!perm)
|
||||
return -EPERM;
|
||||
|
Loading…
Reference in New Issue
Block a user