vt: lock the accent table
PATCH 1/2 vt: lock the accent table
From: Alan Cox <[email protected]>
First step to debletcherising the vt console layer - pick a victim and fix the locking
This is a nice simple object with its own rules so lets pick it out for treatment. The user of the table already has a lock so we will also use the same lock for updates.
Signed-off-by Alan Cox <[email protected]>
---
drivers/tty/vt/keyboard.c | 162 +++++++++++++++++++++++++++++++++++++++++++++ drivers/tty/vt/vt_ioctl.c | 81 +---------------------- include/linux/vt_kern.h | 3 + 3 files changed, 168 insertions(+), 78 deletions(-)
drivers/tty/vt/keyboard.c +162 -0
@@ -1452,3 +1452,165 @@ int __init kbd_init(void)return 0 ; } + +/* Ioctl support code */ + +/** +* vt_do_diacrit - diacritical table updates +* @cmd: ioctl request +* @up: pointer to user data for ioctl +* @perm: permissions check computed by caller +* +* Update the diacritical tables atomically and safely. Lock them +* against simultaneous keypresses +*/ +int vt_do_diacrit (unsigned int cmd,void __user *up,int perm) +{ +struct kbdiacrs __user *a = up; +unsigned long flags; +int asize; +int ret =0 ; + +switch (cmd) { +case KDGKBDIACR : + { +struct kbdiacr *diacr; +int i; + + diacr =kmalloc (MAX_DIACR *sizeof (struct kbdiacr ), +GFP_KERNEL ); +if (diacr ==NULL ) +return -ENOMEM ; + +/* Lock the diacriticals table, make a copy and then +copy it after we unlock */ +spin_lock_irqsave (&kbd_event_lock, flags); + + asize = accent_table_size; +for (i =0 ; i < asize; i++) { + diacr[i].diacr =conv_uni_to_8bit ( + accent_table[i].diacr); + diacr[i].base =conv_uni_to_8bit ( + accent_table[i].base); + diacr[i].result =conv_uni_to_8bit ( + accent_table[i].result); + } +spin_unlock_irqrestore (&kbd_event_lock, flags); + +if (put_user (asize, &a->kb_cnt)) + ret = -EFAULT ; +else if (copy_to_user (a->kbdiacr, diacr, + asize *sizeof (struct kbdiacr ))) + ret = -EFAULT ; +kfree (diacr); +return ret; + } +case KDGKBDIACRUC : + { +struct kbdiacrsuc __user *a = up; +void *buf; + + buf =kmalloc (MAX_DIACR *sizeof (struct kbdiacruc ), +GFP_KERNEL ); +if (buf ==NULL ) +return -ENOMEM ; + +/* Lock the diacriticals table, make a copy and then +copy it after we unlock */ +spin_lock_irqsave (&kbd_event_lock, flags); + + asize = accent_table_size; +memcpy (buf, accent_table, asize *sizeof (struct kbdiacruc )); + +spin_unlock_irqrestore (&kbd_event_lock, flags); + +if (put_user (asize, &a->kb_cnt)) + ret = -EFAULT ; +else if (copy_to_user (a->kbdiacruc, buf, + asize*sizeof (struct kbdiacruc ))) + ret = -EFAULT ; +kfree (buf); +return ret; + } + +case KDSKBDIACR : + { +struct kbdiacrs __user *a = up; +struct kbdiacr *diacr =NULL ; +unsigned int ct; +int i; + +if (!perm) +return -EPERM ; +if (get_user (ct, &a->kb_cnt)) +return -EFAULT ; +if (ct >=MAX_DIACR ) +return -EINVAL ; + +if (ct) { + diacr =kmalloc (sizeof (struct kbdiacr ) * ct, +GFP_KERNEL ); +if (diacr ==NULL ) +return -ENOMEM ; + +if (copy_from_user (diacr, a->kbdiacr, +sizeof (struct kbdiacr ) * ct)) { +kfree (diacr); +return -EFAULT ; + } + } + +spin_lock_irqsave (&kbd_event_lock, flags); + accent_table_size = ct; +for (i =0 ; i < ct; i++) { + accent_table[i].diacr = +conv_8bit_to_uni (diacr[i].diacr); + accent_table[i].base = +conv_8bit_to_uni (diacr[i].base); + accent_table[i].result = +conv_8bit_to_uni (diacr[i].result); + } +spin_unlock_irqrestore (&kbd_event_lock, flags); +kfree (diacr); +return 0 ; + } + +case KDSKBDIACRUC : + { +struct kbdiacrsuc __user *a = up; +unsigned int ct; +void *buf =NULL ; + +if (!perm) +return -EPERM ; + +if (get_user (ct, &a->kb_cnt)) +return -EFAULT ; + +if (ct >=MAX_DIACR ) +return -EINVAL ; + +if (ct) { + buf =kmalloc (ct *sizeof (struct kbdiacruc ), +GFP_KERNEL ); +if (buf ==NULL ) +return -ENOMEM ; + +if (copy_from_user (buf, a->kbdiacruc, + ct *sizeof (struct kbdiacruc ))) { +kfree (buf); +return -EFAULT ; + } + } +spin_lock_irqsave (&kbd_event_lock, flags); +if (ct) +memcpy (accent_table, buf, + ct *sizeof (struct kbdiacruc )); + accent_table_size = ct; +spin_unlock_irqrestore (&kbd_event_lock, flags); +kfree (buf); +return 0 ; + } + } +return ret; +}
drivers/tty/vt/vt_ioctl.c +3 -78
92 lines not on this page · raw message
include/linux/vt_kern.h +3 -0
@@ -167,4 +167,7 @@ extern int unregister_vt_notifier(struct notifier_block *nb);extern void hide_boot_cursor (bool hide); +/* keyboard provided interfaces */ +extern int vt_do_diacrit (unsigned int cmd,void __user *up,int eperm); +#endif /* _VT_KERN_H */
PATCH 2/2 vt: tidy a few bits of checkpatch noise
From: Alan Cox <[email protected]>
Signed-off-by Alan Cox <[email protected]>
---
drivers/tty/vt/keyboard.c | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-)
drivers/tty/vt/keyboard.c +9 -9
@@ -55,8 +55,8 @@ extern void ctrl_alt_del(void);/* * Some laptops take the 789uiojklm,. keys as number pad when NumLock is on. * This seems a good reason to start with NumLock off. On HIL keyboards -* of PARISC machines however there is no NumLock key and everyone expects the keypad -* to be used for numbers. +* of PARISC machines however there is no NumLock key and everyone expects the +* keypad to be used for numbers. */ #if defined(CONFIG_PARISC ) && (defined(CONFIG_KEYBOARD_HIL ) || defined(CONFIG_KEYBOARD_HIL_OLD ))
@@ -1404,14 +1404,14 @@ static void kbd_start(struct input_handle *handle)static const struct input_device_id kbd_ids[] = { { - .flags =INPUT_DEVICE_ID_MATCH_EVBIT , - .evbit = {BIT_MASK (EV_KEY ) }, - }, + .flags =INPUT_DEVICE_ID_MATCH_EVBIT , + .evbit = {BIT_MASK (EV_KEY ) }, + }, { - .flags =INPUT_DEVICE_ID_MATCH_EVBIT , - .evbit = {BIT_MASK (EV_SND ) }, - }, + .flags =INPUT_DEVICE_ID_MATCH_EVBIT , + .evbit = {BIT_MASK (EV_SND ) }, + }, { },/* Terminating entry */ };
@@ -1433,7 +1433,7 @@ int __init kbd_init(void)int i;int error; -for (i =0 ; i <MAX_NR_CONSOLES ; i++) { +for (i =0 ; i <MAX_NR_CONSOLES ; i++) { kbd_table[i].ledflagstate =KBD_DEFLEDS ; kbd_table[i].default_ledflagstate =KBD_DEFLEDS ; kbd_table[i].ledmode =LED_SHOW_FLAGS ;