[media] au8522: Avoid memory leak for device config data
authorMauro Carvalho Chehab <mchehab@osg.samsung.com>
Mon, 21 Dec 2015 16:38:31 +0000 (14:38 -0200)
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>
Mon, 21 Dec 2015 19:39:32 +0000 (17:39 -0200)
commitaa37763fa4b2545a6d517333aacc98ad757a4ccd
tree1846e9bea2ee3a2300df348c5135944ad6eee349
parentc77adf214ba619ad959f37fa429aa3f1045fe0cf
[media] au8522: Avoid memory leak for device config data

As reported by kmemleak:

unreferenced object 0xffff880321e1da40 (size 32):
  comm "modprobe", pid 3309, jiffies 4295019569 (age 2359.636s)
  hex dump (first 32 bytes):
    47 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  G...............
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  backtrace:
    [<ffffffff82278c8e>] kmemleak_alloc+0x4e/0xb0
    [<ffffffff8153c08c>] kmem_cache_alloc_trace+0x1ec/0x280
    [<ffffffffa13a896a>] au8522_probe+0x19a/0xa30 [au8522_decoder]
    [<ffffffff81de0032>] i2c_device_probe+0x2b2/0x490
    [<ffffffff81ca7004>] driver_probe_device+0x454/0xd90
    [<ffffffff81ca7c1b>] __device_attach_driver+0x17b/0x230
    [<ffffffff81ca15da>] bus_for_each_drv+0x11a/0x1b0
    [<ffffffff81ca6a4d>] __device_attach+0x1cd/0x2c0
    [<ffffffff81ca7d43>] device_initial_probe+0x13/0x20
    [<ffffffff81ca451f>] bus_probe_device+0x1af/0x250
    [<ffffffff81c9e0f3>] device_add+0x943/0x13b0
    [<ffffffff81c9eb7a>] device_register+0x1a/0x20
    [<ffffffff81de8626>] i2c_new_device+0x5d6/0x8f0
    [<ffffffffa0d88ea4>] v4l2_i2c_new_subdev_board+0x1e4/0x250 [v4l2_common]
    [<ffffffffa0d88fe7>] v4l2_i2c_new_subdev+0xd7/0x110 [v4l2_common]
    [<ffffffffa13b2f76>] au0828_card_analog_fe_setup+0x2e6/0x3f0 [au0828]

Checking where the error happens:
(gdb) list *au8522_probe+0x19a
0x99a is in au8522_probe (drivers/media/dvb-frontends/au8522_decoder.c:761).
756 printk(KERN_INFO "au8522_decoder attach existing instance.\n");
757 break;
758 }
759
760 demod_config = kzalloc(sizeof(struct au8522_config), GFP_KERNEL);
761 if (demod_config == NULL) {
762 if (instance == 1)
763 kfree(state);
764 return -ENOMEM;
765 }

Shows that the error path is not being handled properly.

The are actually several issues here:

1) config free should have been calling hybrid_tuner_release_state()
function, by calling au8522_release_state();

2) config is only allocated at the digital part. On the analog one,
it is received from the caller.

A complex logic could be added to address it, however, it is simpler
to just embeed config inside the state.

Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
drivers/media/dvb-frontends/au8522_common.c
drivers/media/dvb-frontends/au8522_decoder.c
drivers/media/dvb-frontends/au8522_dig.c
drivers/media/dvb-frontends/au8522_priv.h