Commit 832a62ab authored by Jiri Slaby's avatar Jiri Slaby Committed by Greg Kroah-Hartman
Browse files

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: default avatarJiri Slaby <jslaby@suse.cz>
Link: https://lore.kernel.org/r/20200615074910.19267-31-jslaby@suse.cz


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent eca734d8
Loading
Loading
Loading
Loading
+157 −137
Original line number Diff line number Diff line
@@ -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;
@@ -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;