Skip to content

Commit bfb2456

Browse files
Jiri Slaby (SUSE)gregkh
authored andcommitted
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>
1 parent 1c7736d commit bfb2456

1 file changed

Lines changed: 37 additions & 53 deletions

File tree

drivers/tty/vt/keyboard.c

Lines changed: 37 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,10 +1566,9 @@ static bool kbd_match(struct input_handler *handler, struct input_dev *dev)
15661566
static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
15671567
const struct input_device_id *id)
15681568
{
1569-
struct input_handle *handle;
15701569
int error;
15711570

1572-
handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
1571+
struct input_handle __free(kfree) *handle = kzalloc(sizeof(*handle), GFP_KERNEL);
15731572
if (!handle)
15741573
return -ENOMEM;
15751574

@@ -1579,18 +1578,18 @@ static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
15791578

15801579
error = input_register_handle(handle);
15811580
if (error)
1582-
goto err_free_handle;
1581+
return error;
15831582

15841583
error = input_open_device(handle);
15851584
if (error)
15861585
goto err_unregister_handle;
15871586

1587+
retain_and_null_ptr(handle);
1588+
15881589
return 0;
15891590

15901591
err_unregister_handle:
15911592
input_unregister_handle(handle);
1592-
err_free_handle:
1593-
kfree(handle);
15941593
return error;
15951594
}
15961595

@@ -1683,17 +1682,15 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
16831682
{
16841683
unsigned long flags;
16851684
int asize;
1686-
int ret = 0;
16871685

16881686
switch (cmd) {
16891687
case KDGKBDIACR:
16901688
{
16911689
struct kbdiacrs __user *a = udp;
1692-
struct kbdiacr *dia;
16931690
int i;
16941691

1695-
dia = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacr),
1696-
GFP_KERNEL);
1692+
struct kbdiacr __free(kfree) *dia = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacr),
1693+
GFP_KERNEL);
16971694
if (!dia)
16981695
return -ENOMEM;
16991696

@@ -1713,20 +1710,17 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
17131710
spin_unlock_irqrestore(&kbd_event_lock, flags);
17141711

17151712
if (put_user(asize, &a->kb_cnt))
1716-
ret = -EFAULT;
1717-
else if (copy_to_user(a->kbdiacr, dia,
1718-
asize * sizeof(struct kbdiacr)))
1719-
ret = -EFAULT;
1720-
kfree(dia);
1721-
return ret;
1713+
return -EFAULT;
1714+
if (copy_to_user(a->kbdiacr, dia, asize * sizeof(struct kbdiacr)))
1715+
return -EFAULT;
1716+
return 0;
17221717
}
17231718
case KDGKBDIACRUC:
17241719
{
17251720
struct kbdiacrsuc __user *a = udp;
1726-
void *buf;
17271721

1728-
buf = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacruc),
1729-
GFP_KERNEL);
1722+
void __free(kfree) *buf = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacruc),
1723+
GFP_KERNEL);
17301724
if (buf == NULL)
17311725
return -ENOMEM;
17321726

@@ -1740,18 +1734,17 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
17401734
spin_unlock_irqrestore(&kbd_event_lock, flags);
17411735

17421736
if (put_user(asize, &a->kb_cnt))
1743-
ret = -EFAULT;
1744-
else if (copy_to_user(a->kbdiacruc, buf,
1745-
asize*sizeof(struct kbdiacruc)))
1746-
ret = -EFAULT;
1747-
kfree(buf);
1748-
return ret;
1737+
return -EFAULT;
1738+
if (copy_to_user(a->kbdiacruc, buf, asize * sizeof(struct kbdiacruc)))
1739+
return -EFAULT;
1740+
1741+
return 0;
17491742
}
17501743

17511744
case KDSKBDIACR:
17521745
{
17531746
struct kbdiacrs __user *a = udp;
1754-
struct kbdiacr *dia = NULL;
1747+
struct kbdiacr __free(kfree) *dia = NULL;
17551748
unsigned int ct;
17561749
int i;
17571750

@@ -1780,15 +1773,15 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
17801773
conv_8bit_to_uni(dia[i].result);
17811774
}
17821775
spin_unlock_irqrestore(&kbd_event_lock, flags);
1783-
kfree(dia);
1776+
17841777
return 0;
17851778
}
17861779

17871780
case KDSKBDIACRUC:
17881781
{
17891782
struct kbdiacrsuc __user *a = udp;
17901783
unsigned int ct;
1791-
void *buf = NULL;
1784+
void __free(kfree) *buf = NULL;
17921785

17931786
if (!perm)
17941787
return -EPERM;
@@ -1811,11 +1804,10 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
18111804
ct * sizeof(struct kbdiacruc));
18121805
accent_table_size = ct;
18131806
spin_unlock_irqrestore(&kbd_event_lock, flags);
1814-
kfree(buf);
18151807
return 0;
18161808
}
18171809
}
1818-
return ret;
1810+
return 0;
18191811
}
18201812

18211813
/**
@@ -1934,7 +1926,7 @@ static int vt_kdskbent(unsigned char kbdmode, unsigned char idx,
19341926
unsigned char map, unsigned short val)
19351927
{
19361928
unsigned long flags;
1937-
unsigned short *key_map, *new_map, oldval;
1929+
unsigned short *key_map, oldval;
19381930

19391931
if (!idx && val == K_NOSUCHMAP) {
19401932
spin_lock_irqsave(&kbd_event_lock, flags);
@@ -1965,7 +1957,7 @@ static int vt_kdskbent(unsigned char kbdmode, unsigned char idx,
19651957
return 0;
19661958
#endif
19671959

1968-
new_map = kmalloc(sizeof(plain_map), GFP_KERNEL);
1960+
unsigned short __free(kfree) *new_map = kmalloc(sizeof(plain_map), GFP_KERNEL);
19691961
if (!new_map)
19701962
return -ENOMEM;
19711963

@@ -1977,17 +1969,14 @@ static int vt_kdskbent(unsigned char kbdmode, unsigned char idx,
19771969
if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
19781970
!capable(CAP_SYS_RESOURCE)) {
19791971
spin_unlock_irqrestore(&kbd_event_lock, flags);
1980-
kfree(new_map);
19811972
return -EPERM;
19821973
}
1983-
key_maps[map] = new_map;
1984-
key_map = new_map;
1974+
key_map = key_maps[map] = no_free_ptr(new_map);
19851975
key_map[0] = U(K_ALLOCATED);
19861976
for (j = 1; j < NR_KEYS; j++)
19871977
key_map[j] = U(K_HOLE);
19881978
keymap_count++;
1989-
} else
1990-
kfree(new_map);
1979+
}
19911980

19921981
oldval = U(key_map[idx]);
19931982
if (val == oldval)
@@ -2050,8 +2039,6 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
20502039
{
20512040
unsigned char kb_func;
20522041
unsigned long flags;
2053-
char *kbs;
2054-
int ret;
20552042

20562043
if (get_user(kb_func, &user_kdgkb->kb_func))
20572044
return -EFAULT;
@@ -2063,42 +2050,39 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
20632050
/* size should have been a struct member */
20642051
ssize_t len = sizeof(user_kdgkb->kb_string);
20652052

2066-
kbs = kmalloc(len, GFP_KERNEL);
2053+
char __free(kfree) *kbs = kmalloc(len, GFP_KERNEL);
20672054
if (!kbs)
20682055
return -ENOMEM;
20692056

20702057
spin_lock_irqsave(&func_buf_lock, flags);
20712058
len = strscpy(kbs, func_table[kb_func] ? : "", len);
20722059
spin_unlock_irqrestore(&func_buf_lock, flags);
20732060

2074-
if (len < 0) {
2075-
ret = -ENOSPC;
2076-
break;
2077-
}
2078-
ret = copy_to_user(user_kdgkb->kb_string, kbs, len + 1) ?
2079-
-EFAULT : 0;
2080-
break;
2061+
if (len < 0)
2062+
return -ENOSPC;
2063+
2064+
if (copy_to_user(user_kdgkb->kb_string, kbs, len + 1))
2065+
return -EFAULT;
2066+
2067+
return 0;
20812068
}
20822069
case KDSKBSENT:
20832070
if (!perm || !capable(CAP_SYS_TTY_CONFIG))
20842071
return -EPERM;
20852072

2086-
kbs = strndup_user(user_kdgkb->kb_string,
2087-
sizeof(user_kdgkb->kb_string));
2073+
char __free(kfree) *kbs = strndup_user(user_kdgkb->kb_string,
2074+
sizeof(user_kdgkb->kb_string));
20882075
if (IS_ERR(kbs))
20892076
return PTR_ERR(kbs);
20902077

20912078
spin_lock_irqsave(&func_buf_lock, flags);
20922079
kbs = vt_kdskbsent(kbs, kb_func);
20932080
spin_unlock_irqrestore(&func_buf_lock, flags);
20942081

2095-
ret = 0;
2096-
break;
2082+
return 0;
20972083
}
20982084

2099-
kfree(kbs);
2100-
2101-
return ret;
2085+
return 0;
21022086
}
21032087

21042088
int vt_do_kdskled(unsigned int console, int cmd, unsigned long arg, int perm)

0 commit comments

Comments
 (0)