Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: serio HIL MLC - don't deref null, don't leak and return proper error

While reviewing various users of kernel memory allocation functions I came
across drivers/input/serio/hil_mlc.c::hil_mlc_register() and noticed that:

- it calls kzalloc() but fails to check for a NULL return before use.
- it makes several allocations and if one fails it doesn't free the
previous ones.
- It doesn't return -ENOMEM in the failed memory allocation case (it just
crashes).

This patch corrects all of the above and also reworks the only caller of
this function that I could find
(drivers/input/serio/hp_sdc_mlc.c::hp_sdc_mlc_out()) so that it now checks
the return value of hil_mlc_register() and properly propagates it on
failure and I also restructured the code to remove some labels and goto's
to make it, IMHO nicer to read.

Signed-off-by: Jesper Juhl <jj@chaosbits.net>
Tested-by: Helge Deller <deller@gmx.de>
Acked-by: Helge Deller <deller@gmx.de>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

authored by

Jesper Juhl and committed by
Dmitry Torokhov
39de5210 bc95df78

+14 -9
+5
drivers/input/serio/hil_mlc.c
··· 932 932 hil_mlc_copy_di_scratch(mlc, i); 933 933 mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL); 934 934 mlc->serio[i] = mlc_serio; 935 + if (!mlc->serio[i]) { 936 + for (; i >= 0; i--) 937 + kfree(mlc->serio[i]); 938 + return -ENOMEM; 939 + } 935 940 snprintf(mlc_serio->name, sizeof(mlc_serio->name)-1, "HIL_SERIO%d", i); 936 941 snprintf(mlc_serio->phys, sizeof(mlc_serio->phys)-1, "HIL%d", i); 937 942 mlc_serio->id = hil_mlc_serio_id;
+9 -9
drivers/input/serio/hp_sdc_mlc.c
··· 305 305 static int __init hp_sdc_mlc_init(void) 306 306 { 307 307 hil_mlc *mlc = &hp_sdc_mlc; 308 + int err; 308 309 309 310 #ifdef __mc68000__ 310 311 if (!MACH_IS_HP300) ··· 324 323 mlc->out = &hp_sdc_mlc_out; 325 324 mlc->priv = &hp_sdc_mlc_priv; 326 325 327 - if (hil_mlc_register(mlc)) { 326 + err = hil_mlc_register(mlc); 327 + if (err) { 328 328 printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n"); 329 - goto err0; 329 + return err; 330 330 } 331 331 332 332 if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) { 333 333 printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n"); 334 - goto err1; 334 + if (hil_mlc_unregister(mlc)) 335 + printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" 336 + "This is bad. Could cause an oops.\n"); 337 + return -EBUSY; 335 338 } 339 + 336 340 return 0; 337 - err1: 338 - if (hil_mlc_unregister(mlc)) 339 - printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" 340 - "This is bad. Could cause an oops.\n"); 341 - err0: 342 - return -EBUSY; 343 341 } 344 342 345 343 static void __exit hp_sdc_mlc_exit(void)