aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/tlv320aic3x.c
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2008-08-25 06:49:20 -0400
committerTakashi Iwai <tiwai@suse.de>2008-08-25 07:49:52 -0400
commit3051e41ab7daaa59d4564f20b25dcb8c03f35f2b (patch)
tree0908f13da020b0e6e5d025caa60b1fed4c056abc /sound/soc/codecs/tlv320aic3x.c
parentc5d44423d55e3abca7b1d544af9e4c97ec203999 (diff)
ALSA: ASoC: Fix double free and memory leak in many codec drivers
Many SoC audio codec drivers have improper freeing of memory in error paths. * codec is allocated in the platform device probe function, but is not freed there in case of error. Instead it is freed in the i2c device probe function's error path. However the success or failure of both functions is not linked, so this could result in a double free (if the platform device is successfully probed, the i2c device probing fails and then the platform driver is unregistered.) * codec->private_data is allocated in many platform device probe functions but not freed in their error paths. This patch hopefully solves all these problems. Signed-off-by: Jean Delvare <khali@linux-fr.org> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/soc/codecs/tlv320aic3x.c')
-rw-r--r--sound/soc/codecs/tlv320aic3x.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index b1dce5f459db..5f9abb199435 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -1199,10 +1199,9 @@ static int aic3x_codec_probe(struct i2c_adapter *adap, int addr, int kind)
1199 client_template.addr = addr; 1199 client_template.addr = addr;
1200 1200
1201 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); 1201 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
1202 if (i2c == NULL) { 1202 if (i2c == NULL)
1203 kfree(codec);
1204 return -ENOMEM; 1203 return -ENOMEM;
1205 } 1204
1206 i2c_set_clientdata(i2c, codec); 1205 i2c_set_clientdata(i2c, codec);
1207 codec->control_data = i2c; 1206 codec->control_data = i2c;
1208 1207
@@ -1221,7 +1220,6 @@ static int aic3x_codec_probe(struct i2c_adapter *adap, int addr, int kind)
1221 return ret; 1220 return ret;
1222 1221
1223err: 1222err:
1224 kfree(codec);
1225 kfree(i2c); 1223 kfree(i2c);
1226 return ret; 1224 return ret;
1227} 1225}
@@ -1302,6 +1300,11 @@ static int aic3x_probe(struct platform_device *pdev)
1302#else 1300#else
1303 /* Add other interfaces here */ 1301 /* Add other interfaces here */
1304#endif 1302#endif
1303
1304 if (ret != 0) {
1305 kfree(codec->private_data);
1306 kfree(codec);
1307 }
1305 return ret; 1308 return ret;
1306} 1309}
1307 1310