mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-19 18:41:01 -04:00
tty: vt/keyboard: use __free()
The vt/keyboard code can use __free to ensure the temporary buffers are freed. Perform the switch. And even one non-temporary in kbd_connect(). There are fail paths, so ensure the buffer is freed in them and not when returning 0 -- by retain_and_null_ptr(). Signed-off-by: Jiri Slaby (SUSE) <jirislaby@kernel.org> Link: https://patch.msgid.link/20251119100140.830761-7-jirislaby@kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
1c7736dc68
commit
bfb24564b5
@@ -1566,10 +1566,9 @@ static bool kbd_match(struct input_handler *handler, struct input_dev *dev)
|
|||||||
static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
|
static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
|
||||||
const struct input_device_id *id)
|
const struct input_device_id *id)
|
||||||
{
|
{
|
||||||
struct input_handle *handle;
|
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
|
struct input_handle __free(kfree) *handle = kzalloc(sizeof(*handle), GFP_KERNEL);
|
||||||
if (!handle)
|
if (!handle)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@@ -1579,18 +1578,18 @@ static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
|
|||||||
|
|
||||||
error = input_register_handle(handle);
|
error = input_register_handle(handle);
|
||||||
if (error)
|
if (error)
|
||||||
goto err_free_handle;
|
return error;
|
||||||
|
|
||||||
error = input_open_device(handle);
|
error = input_open_device(handle);
|
||||||
if (error)
|
if (error)
|
||||||
goto err_unregister_handle;
|
goto err_unregister_handle;
|
||||||
|
|
||||||
|
retain_and_null_ptr(handle);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_unregister_handle:
|
err_unregister_handle:
|
||||||
input_unregister_handle(handle);
|
input_unregister_handle(handle);
|
||||||
err_free_handle:
|
|
||||||
kfree(handle);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1683,17 +1682,15 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
|
|||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int asize;
|
int asize;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case KDGKBDIACR:
|
case KDGKBDIACR:
|
||||||
{
|
{
|
||||||
struct kbdiacrs __user *a = udp;
|
struct kbdiacrs __user *a = udp;
|
||||||
struct kbdiacr *dia;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
dia = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacr),
|
struct kbdiacr __free(kfree) *dia = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacr),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!dia)
|
if (!dia)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@@ -1713,20 +1710,17 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
|
|||||||
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
||||||
|
|
||||||
if (put_user(asize, &a->kb_cnt))
|
if (put_user(asize, &a->kb_cnt))
|
||||||
ret = -EFAULT;
|
return -EFAULT;
|
||||||
else if (copy_to_user(a->kbdiacr, dia,
|
if (copy_to_user(a->kbdiacr, dia, asize * sizeof(struct kbdiacr)))
|
||||||
asize * sizeof(struct kbdiacr)))
|
return -EFAULT;
|
||||||
ret = -EFAULT;
|
return 0;
|
||||||
kfree(dia);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
case KDGKBDIACRUC:
|
case KDGKBDIACRUC:
|
||||||
{
|
{
|
||||||
struct kbdiacrsuc __user *a = udp;
|
struct kbdiacrsuc __user *a = udp;
|
||||||
void *buf;
|
|
||||||
|
|
||||||
buf = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacruc),
|
void __free(kfree) *buf = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacruc),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@@ -1740,18 +1734,17 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
|
|||||||
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
||||||
|
|
||||||
if (put_user(asize, &a->kb_cnt))
|
if (put_user(asize, &a->kb_cnt))
|
||||||
ret = -EFAULT;
|
return -EFAULT;
|
||||||
else if (copy_to_user(a->kbdiacruc, buf,
|
if (copy_to_user(a->kbdiacruc, buf, asize * sizeof(struct kbdiacruc)))
|
||||||
asize*sizeof(struct kbdiacruc)))
|
return -EFAULT;
|
||||||
ret = -EFAULT;
|
|
||||||
kfree(buf);
|
return 0;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case KDSKBDIACR:
|
case KDSKBDIACR:
|
||||||
{
|
{
|
||||||
struct kbdiacrs __user *a = udp;
|
struct kbdiacrs __user *a = udp;
|
||||||
struct kbdiacr *dia = NULL;
|
struct kbdiacr __free(kfree) *dia = NULL;
|
||||||
unsigned int ct;
|
unsigned int ct;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -1780,7 +1773,7 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
|
|||||||
conv_8bit_to_uni(dia[i].result);
|
conv_8bit_to_uni(dia[i].result);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
||||||
kfree(dia);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1788,7 +1781,7 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
|
|||||||
{
|
{
|
||||||
struct kbdiacrsuc __user *a = udp;
|
struct kbdiacrsuc __user *a = udp;
|
||||||
unsigned int ct;
|
unsigned int ct;
|
||||||
void *buf = NULL;
|
void __free(kfree) *buf = NULL;
|
||||||
|
|
||||||
if (!perm)
|
if (!perm)
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
@@ -1811,11 +1804,10 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
|
|||||||
ct * sizeof(struct kbdiacruc));
|
ct * sizeof(struct kbdiacruc));
|
||||||
accent_table_size = ct;
|
accent_table_size = ct;
|
||||||
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
||||||
kfree(buf);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1934,7 +1926,7 @@ static int vt_kdskbent(unsigned char kbdmode, unsigned char idx,
|
|||||||
unsigned char map, unsigned short val)
|
unsigned char map, unsigned short val)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned short *key_map, *new_map, oldval;
|
unsigned short *key_map, oldval;
|
||||||
|
|
||||||
if (!idx && val == K_NOSUCHMAP) {
|
if (!idx && val == K_NOSUCHMAP) {
|
||||||
spin_lock_irqsave(&kbd_event_lock, flags);
|
spin_lock_irqsave(&kbd_event_lock, flags);
|
||||||
@@ -1965,7 +1957,7 @@ static int vt_kdskbent(unsigned char kbdmode, unsigned char idx,
|
|||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
new_map = kmalloc(sizeof(plain_map), GFP_KERNEL);
|
unsigned short __free(kfree) *new_map = kmalloc(sizeof(plain_map), GFP_KERNEL);
|
||||||
if (!new_map)
|
if (!new_map)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@@ -1977,17 +1969,14 @@ static int vt_kdskbent(unsigned char kbdmode, unsigned char idx,
|
|||||||
if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
|
if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
|
||||||
!capable(CAP_SYS_RESOURCE)) {
|
!capable(CAP_SYS_RESOURCE)) {
|
||||||
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
spin_unlock_irqrestore(&kbd_event_lock, flags);
|
||||||
kfree(new_map);
|
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
key_maps[map] = new_map;
|
key_map = key_maps[map] = no_free_ptr(new_map);
|
||||||
key_map = new_map;
|
|
||||||
key_map[0] = U(K_ALLOCATED);
|
key_map[0] = U(K_ALLOCATED);
|
||||||
for (j = 1; j < NR_KEYS; j++)
|
for (j = 1; j < NR_KEYS; j++)
|
||||||
key_map[j] = U(K_HOLE);
|
key_map[j] = U(K_HOLE);
|
||||||
keymap_count++;
|
keymap_count++;
|
||||||
} else
|
}
|
||||||
kfree(new_map);
|
|
||||||
|
|
||||||
oldval = U(key_map[idx]);
|
oldval = U(key_map[idx]);
|
||||||
if (val == oldval)
|
if (val == oldval)
|
||||||
@@ -2050,8 +2039,6 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
|
|||||||
{
|
{
|
||||||
unsigned char kb_func;
|
unsigned char kb_func;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
char *kbs;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (get_user(kb_func, &user_kdgkb->kb_func))
|
if (get_user(kb_func, &user_kdgkb->kb_func))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
@@ -2063,7 +2050,7 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
|
|||||||
/* size should have been a struct member */
|
/* size should have been a struct member */
|
||||||
ssize_t len = sizeof(user_kdgkb->kb_string);
|
ssize_t len = sizeof(user_kdgkb->kb_string);
|
||||||
|
|
||||||
kbs = kmalloc(len, GFP_KERNEL);
|
char __free(kfree) *kbs = kmalloc(len, GFP_KERNEL);
|
||||||
if (!kbs)
|
if (!kbs)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@@ -2071,20 +2058,20 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
|
|||||||
len = strscpy(kbs, func_table[kb_func] ? : "", len);
|
len = strscpy(kbs, func_table[kb_func] ? : "", len);
|
||||||
spin_unlock_irqrestore(&func_buf_lock, flags);
|
spin_unlock_irqrestore(&func_buf_lock, flags);
|
||||||
|
|
||||||
if (len < 0) {
|
if (len < 0)
|
||||||
ret = -ENOSPC;
|
return -ENOSPC;
|
||||||
break;
|
|
||||||
}
|
if (copy_to_user(user_kdgkb->kb_string, kbs, len + 1))
|
||||||
ret = copy_to_user(user_kdgkb->kb_string, kbs, len + 1) ?
|
return -EFAULT;
|
||||||
-EFAULT : 0;
|
|
||||||
break;
|
return 0;
|
||||||
}
|
}
|
||||||
case KDSKBSENT:
|
case KDSKBSENT:
|
||||||
if (!perm || !capable(CAP_SYS_TTY_CONFIG))
|
if (!perm || !capable(CAP_SYS_TTY_CONFIG))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
kbs = strndup_user(user_kdgkb->kb_string,
|
char __free(kfree) *kbs = strndup_user(user_kdgkb->kb_string,
|
||||||
sizeof(user_kdgkb->kb_string));
|
sizeof(user_kdgkb->kb_string));
|
||||||
if (IS_ERR(kbs))
|
if (IS_ERR(kbs))
|
||||||
return PTR_ERR(kbs);
|
return PTR_ERR(kbs);
|
||||||
|
|
||||||
@@ -2092,13 +2079,10 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
|
|||||||
kbs = vt_kdskbsent(kbs, kb_func);
|
kbs = vt_kdskbsent(kbs, kb_func);
|
||||||
spin_unlock_irqrestore(&func_buf_lock, flags);
|
spin_unlock_irqrestore(&func_buf_lock, flags);
|
||||||
|
|
||||||
ret = 0;
|
return 0;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(kbs);
|
return 0;
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int vt_do_kdskled(unsigned int console, int cmd, unsigned long arg, int perm)
|
int vt_do_kdskled(unsigned int console, int cmd, unsigned long arg, int perm)
|
||||||
|
|||||||
Reference in New Issue
Block a user