mirror of https://gitee.com/openkylin/linux.git
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: Jiri Slaby <jslaby@suse.cz> Link: https://lore.kernel.org/r/20201029113222.32640-6-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
e27979dace
commit
fe6416e126
|
@ -1897,19 +1897,111 @@ 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)
|
||||
static unsigned short vt_kdgkbent(unsigned char kbdmode, unsigned char idx,
|
||||
unsigned char map)
|
||||
{
|
||||
unsigned short *key_map, val;
|
||||
unsigned long flags;
|
||||
|
||||
/* Ensure another thread doesn't free it under us */
|
||||
spin_lock_irqsave(&kbd_event_lock, flags);
|
||||
key_map = key_maps[map];
|
||||
if (key_map) {
|
||||
val = U(key_map[idx]);
|
||||
if (kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
|
||||
val = K_HOLE;
|
||||
} else
|
||||
val = idx ? K_HOLE : K_NOSUCHMAP;
|
||||
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
||||
|
||||
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[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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (KTYP(val) < NR_TYPES) {
|
||||
if (KVAL(val) > max_vals[KTYP(val)])
|
||||
return -EINVAL;
|
||||
} 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 (!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[map];
|
||||
if (key_map == NULL) {
|
||||
int j;
|
||||
|
||||
if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
|
||||
!capable(CAP_SYS_RESOURCE)) {
|
||||
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
||||
kfree(new_map);
|
||||
return -EPERM;
|
||||
}
|
||||
key_maps[map] = new_map;
|
||||
key_map = new_map;
|
||||
key_map[0] = U(K_ALLOCATED);
|
||||
for (j = 1; j < NR_KEYS; j++)
|
||||
key_map[j] = U(K_HOLE);
|
||||
keymap_count++;
|
||||
} else
|
||||
kfree(new_map);
|
||||
|
||||
oldval = U(key_map[idx]);
|
||||
if (val == oldval)
|
||||
goto out;
|
||||
|
||||
/* Attention Key */
|
||||
if ((oldval == K_SAK || val == K_SAK) && !capable(CAP_SYS_ADMIN)) {
|
||||
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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 tmp;
|
||||
ushort *key_map, *new_map, val, ov;
|
||||
unsigned long flags;
|
||||
struct kbentry kbe;
|
||||
|
||||
if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
|
||||
if (copy_from_user(&kbe, user_kbe, sizeof(struct kbentry)))
|
||||
return -EFAULT;
|
||||
|
||||
if (!capable(CAP_SYS_TTY_CONFIG))
|
||||
|
@ -1917,94 +2009,17 @@ int vt_do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm,
|
|||
|
||||
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];
|
||||
if (key_map) {
|
||||
val = U(key_map[i]);
|
||||
if (kb->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
|
||||
val = K_HOLE;
|
||||
} else
|
||||
val = (i ? K_HOLE : K_NOSUCHMAP);
|
||||
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
||||
return put_user(val, &user_kbe->kb_value);
|
||||
return put_user(vt_kdgkbent(kb->kbdmode, kbe.kb_index,
|
||||
kbe.kb_table),
|
||||
&user_kbe->kb_value);
|
||||
case KDSKBENT:
|
||||
if (!perm)
|
||||
return -EPERM;
|
||||
if (!i && v == K_NOSUCHMAP) {
|
||||
spin_lock_irqsave(&kbd_event_lock, flags);
|
||||
/* deallocate map */
|
||||
key_map = key_maps[s];
|
||||
if (s && key_map) {
|
||||
key_maps[s] = NULL;
|
||||
if (key_map[0] == U(K_ALLOCATED)) {
|
||||
kfree(key_map);
|
||||
keymap_count--;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
||||
break;
|
||||
}
|
||||
|
||||
if (KTYP(v) < NR_TYPES) {
|
||||
if (KVAL(v) > max_vals[KTYP(v)])
|
||||
return -EINVAL;
|
||||
} else
|
||||
if (kb->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;
|
||||
#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];
|
||||
if (key_map == NULL) {
|
||||
int j;
|
||||
|
||||
if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
|
||||
!capable(CAP_SYS_RESOURCE)) {
|
||||
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
||||
kfree(new_map);
|
||||
return -EPERM;
|
||||
}
|
||||
key_maps[s] = new_map;
|
||||
key_map = new_map;
|
||||
key_map[0] = U(K_ALLOCATED);
|
||||
for (j = 1; j < NR_KEYS; j++)
|
||||
key_map[j] = U(K_HOLE);
|
||||
keymap_count++;
|
||||
} else
|
||||
kfree(new_map);
|
||||
|
||||
ov = U(key_map[i]);
|
||||
if (v == ov)
|
||||
goto out;
|
||||
/*
|
||||
* Attention Key.
|
||||
*/
|
||||
if (((ov == K_SAK) || (v == 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))
|
||||
do_compute_shiftstate();
|
||||
out:
|
||||
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
||||
break;
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue