Commit 39de5210 authored by Jesper Juhl's avatar Jesper Juhl Committed by Dmitry Torokhov

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: default avatarJesper Juhl <jj@chaosbits.net>
Tested-by: default avatarHelge Deller <deller@gmx.de>
Acked-by: default avatarHelge Deller <deller@gmx.de>
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent bc95df78
...@@ -932,6 +932,11 @@ int hil_mlc_register(hil_mlc *mlc) ...@@ -932,6 +932,11 @@ int hil_mlc_register(hil_mlc *mlc)
hil_mlc_copy_di_scratch(mlc, i); hil_mlc_copy_di_scratch(mlc, i);
mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL); mlc_serio = kzalloc(sizeof(*mlc_serio), GFP_KERNEL);
mlc->serio[i] = mlc_serio; mlc->serio[i] = mlc_serio;
if (!mlc->serio[i]) {
for (; i >= 0; i--)
kfree(mlc->serio[i]);
return -ENOMEM;
}
snprintf(mlc_serio->name, sizeof(mlc_serio->name)-1, "HIL_SERIO%d", i); snprintf(mlc_serio->name, sizeof(mlc_serio->name)-1, "HIL_SERIO%d", i);
snprintf(mlc_serio->phys, sizeof(mlc_serio->phys)-1, "HIL%d", i); snprintf(mlc_serio->phys, sizeof(mlc_serio->phys)-1, "HIL%d", i);
mlc_serio->id = hil_mlc_serio_id; mlc_serio->id = hil_mlc_serio_id;
......
...@@ -305,6 +305,7 @@ static void hp_sdc_mlc_out(hil_mlc *mlc) ...@@ -305,6 +305,7 @@ static void hp_sdc_mlc_out(hil_mlc *mlc)
static int __init hp_sdc_mlc_init(void) static int __init hp_sdc_mlc_init(void)
{ {
hil_mlc *mlc = &hp_sdc_mlc; hil_mlc *mlc = &hp_sdc_mlc;
int err;
#ifdef __mc68000__ #ifdef __mc68000__
if (!MACH_IS_HP300) if (!MACH_IS_HP300)
...@@ -323,22 +324,21 @@ static int __init hp_sdc_mlc_init(void) ...@@ -323,22 +324,21 @@ static int __init hp_sdc_mlc_init(void)
mlc->out = &hp_sdc_mlc_out; mlc->out = &hp_sdc_mlc_out;
mlc->priv = &hp_sdc_mlc_priv; mlc->priv = &hp_sdc_mlc_priv;
if (hil_mlc_register(mlc)) { err = hil_mlc_register(mlc);
if (err) {
printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n"); printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n");
goto err0; return err;
} }
if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) { if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) {
printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n"); printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n");
goto err1; if (hil_mlc_unregister(mlc))
printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
"This is bad. Could cause an oops.\n");
return -EBUSY;
} }
return 0; return 0;
err1:
if (hil_mlc_unregister(mlc))
printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
"This is bad. Could cause an oops.\n");
err0:
return -EBUSY;
} }
static void __exit hp_sdc_mlc_exit(void) static void __exit hp_sdc_mlc_exit(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment