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

vt: keyboard, extract vt_kdgkbent and vt_kdskbent



Split vt_do_kdsk_ioctl into three functions:
* getter (KDGKBENT/vt_kdgkbent)
* setter (KDSKBENT/vt_kdskbent)
* switch-case helper (vt_do_kdsk_ioctl)

This eliminates the need of ugly one-letter macros as we use parameters
now:
* i aka tmp.kb_index -> idx
* s aka tmp.kb_table -> map
* v aka tmp.kb_value -> val

Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
Link: https://lore.kernel.org/r/20201029113222.32640-6-jslaby@suse.cz


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e27979da
Loading
Loading
Loading
Loading
+102 −87
Original line number Diff line number Diff line
@@ -1897,74 +1897,67 @@ int vt_do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc,
	return kc;
}

#define i (tmp.kb_index)
#define s (tmp.kb_table)
#define v (tmp.kb_value)

int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
						int console)
static unsigned short vt_kdgkbent(unsigned char kbdmode, unsigned char idx,
		unsigned char map)
{
	struct kbd_struct *kb = kbd_table + console;
	struct kbentry tmp;
	ushort *key_map, *new_map, val, ov;
	unsigned short *key_map, val;
	unsigned long flags;

	if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
		return -EFAULT;

	if (!capable(CAP_SYS_TTY_CONFIG))
		perm = 0;

	switch (cmd) {
	case KDGKBENT:
	/* Ensure another thread doesn't free it under us */
	spin_lock_irqsave(&kbd_event_lock, flags);
		key_map = key_maps[s];
	key_map = key_maps[map];
	if (key_map) {
		    val = U(key_map[i]);
		    if (kb->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
		val = U(key_map[idx]);
		if (kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
			val = K_HOLE;
	} else
		    val = (i ? K_HOLE : K_NOSUCHMAP);
		val = idx ? K_HOLE : K_NOSUCHMAP;
	spin_unlock_irqrestore(&kbd_event_lock, flags);
		return put_user(val, &user_kbe->kb_value);
	case KDSKBENT:
		if (!perm)
			return -EPERM;
		if (!i && v == K_NOSUCHMAP) {

	return val;
}

static int vt_kdskbent(unsigned char kbdmode, unsigned char idx,
		unsigned char map, unsigned short val)
{
	unsigned long flags;
	unsigned short *key_map, *new_map, oldval;

	if (!idx && val == K_NOSUCHMAP) {
		spin_lock_irqsave(&kbd_event_lock, flags);
		/* deallocate map */
			key_map = key_maps[s];
			if (s && key_map) {
			    key_maps[s] = NULL;
		key_map = key_maps[map];
		if (map && key_map) {
			key_maps[map] = NULL;
			if (key_map[0] == U(K_ALLOCATED)) {
				kfree(key_map);
				keymap_count--;
			}
		}
		spin_unlock_irqrestore(&kbd_event_lock, flags);
			break;

		return 0;
	}

		if (KTYP(v) < NR_TYPES) {
		    if (KVAL(v) > max_vals[KTYP(v)])
	if (KTYP(val) < NR_TYPES) {
		if (KVAL(val) > max_vals[KTYP(val)])
			return -EINVAL;
		} else
		    if (kb->kbdmode != VC_UNICODE)
	} else if (kbdmode != VC_UNICODE)
		return -EINVAL;

	/* ++Geert: non-PC keyboards may generate keycode zero */
#if !defined(__mc68000__) && !defined(__powerpc__)
	/* assignment to entry 0 only tests validity of args */
		if (!i)
			break;
	if (!idx)
		return 0;
#endif

	new_map = kmalloc(sizeof(plain_map), GFP_KERNEL);
	if (!new_map)
		return -ENOMEM;

	spin_lock_irqsave(&kbd_event_lock, flags);
		key_map = key_maps[s];
	key_map = key_maps[map];
	if (key_map == NULL) {
		int j;

@@ -1974,7 +1967,7 @@ int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
			kfree(new_map);
			return -EPERM;
		}
			key_maps[s] = new_map;
		key_maps[map] = new_map;
		key_map = new_map;
		key_map[0] = U(K_ALLOCATED);
		for (j = 1; j < NR_KEYS; j++)
@@ -1983,28 +1976,50 @@ int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
	} else
		kfree(new_map);

		ov = U(key_map[i]);
		if (v == ov)
	oldval = U(key_map[idx]);
	if (val == oldval)
		goto out;
		/*
		 * Attention Key.
		 */
		if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN)) {

	/* Attention Key */
	if ((oldval == K_SAK || val == K_SAK) && !capable(CAP_SYS_ADMIN)) {
		spin_unlock_irqrestore(&kbd_event_lock, flags);
		return -EPERM;
	}
		key_map[i] = U(v);
		if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))

	key_map[idx] = U(val);
	if (!map && (KTYP(oldval) == KT_SHIFT || KTYP(val) == KT_SHIFT))
		do_compute_shiftstate();
out:
	spin_unlock_irqrestore(&kbd_event_lock, flags);
		break;

	return 0;
}

int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
						int console)
{
	struct kbd_struct *kb = kbd_table + console;
	struct kbentry kbe;

	if (copy_from_user(&kbe, user_kbe, sizeof(struct kbentry)))
		return -EFAULT;

	if (!capable(CAP_SYS_TTY_CONFIG))
		perm = 0;

	switch (cmd) {
	case KDGKBENT:
		return put_user(vt_kdgkbent(kb->kbdmode, kbe.kb_index,
					kbe.kb_table),
				&user_kbe->kb_value);
	case KDSKBENT:
		if (!perm)
			return -EPERM;
		return vt_kdskbent(kb->kbdmode, kbe.kb_index, kbe.kb_table,
				kbe.kb_value);
	}
	return 0;
}
#undef i
#undef s
#undef v

/* FIXME: This one needs untangling */
int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)