* [PATCH] ASoC: Fix double free and memory leak in many codec drivers
@ 2008-08-25 10:49 Mark Brown
2008-08-25 11:53 ` Takashi Iwai
0 siblings, 1 reply; 5+ messages in thread
From: Mark Brown @ 2008-08-25 10:49 UTC (permalink / raw)
To: Takashi Iwai; +Cc: Jean Delvare, alsa-devel, Mark Brown
From: Jean Delvare <khali@linux-fr.org>
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>
---
sound/soc/codecs/ak4535.c | 11 +++++++----
sound/soc/codecs/tlv320aic3x.c | 11 +++++++----
sound/soc/codecs/uda1380.c | 9 +++++----
sound/soc/codecs/wm8510.c | 9 +++++----
sound/soc/codecs/wm8731.c | 11 +++++++----
sound/soc/codecs/wm8750.c | 10 ++++++----
sound/soc/codecs/wm8753.c | 11 +++++++----
sound/soc/codecs/wm8990.c | 11 +++++++----
8 files changed, 51 insertions(+), 32 deletions(-)
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index b26003c..7da9f46 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -562,10 +562,9 @@ static int ak4535_codec_probe(struct i2c_adapter *adap, int addr, int kind)
client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
- if (i2c == NULL) {
- kfree(codec);
+ if (i2c == NULL)
return -ENOMEM;
- }
+
i2c_set_clientdata(i2c, codec);
codec->control_data = i2c;
@@ -583,7 +582,6 @@ static int ak4535_codec_probe(struct i2c_adapter *adap, int addr, int kind)
return ret;
err:
- kfree(codec);
kfree(i2c);
return ret;
}
@@ -660,6 +658,11 @@ static int ak4535_probe(struct platform_device *pdev)
#else
/* Add other interfaces here */
#endif
+
+ if (ret != 0) {
+ kfree(codec->private_data);
+ kfree(codec);
+ }
return ret;
}
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index b1dce5f..5f9abb1 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)
client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
- if (i2c == NULL) {
- kfree(codec);
+ if (i2c == NULL)
return -ENOMEM;
- }
+
i2c_set_clientdata(i2c, codec);
codec->control_data = i2c;
@@ -1221,7 +1220,6 @@ static int aic3x_codec_probe(struct i2c_adapter *adap, int addr, int kind)
return ret;
err:
- kfree(codec);
kfree(i2c);
return ret;
}
@@ -1302,6 +1300,11 @@ static int aic3x_probe(struct platform_device *pdev)
#else
/* Add other interfaces here */
#endif
+
+ if (ret != 0) {
+ kfree(codec->private_data);
+ kfree(codec);
+ }
return ret;
}
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index a52d6d9..807318f 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -729,10 +729,9 @@ static int uda1380_codec_probe(struct i2c_adapter *adap, int addr, int kind)
client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
- if (i2c == NULL) {
- kfree(codec);
+ if (i2c == NULL)
return -ENOMEM;
- }
+
i2c_set_clientdata(i2c, codec);
codec->control_data = i2c;
@@ -750,7 +749,6 @@ static int uda1380_codec_probe(struct i2c_adapter *adap, int addr, int kind)
return ret;
err:
- kfree(codec);
kfree(i2c);
return ret;
}
@@ -817,6 +815,9 @@ static int uda1380_probe(struct platform_device *pdev)
#else
/* Add other interfaces here */
#endif
+
+ if (ret != 0)
+ kfree(codec);
return ret;
}
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 67325fd..3d998e6 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -693,10 +693,9 @@ static int wm8510_codec_probe(struct i2c_adapter *adap, int addr, int kind)
client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
- if (i2c == NULL) {
- kfree(codec);
+ if (i2c == NULL)
return -ENOMEM;
- }
+
i2c_set_clientdata(i2c, codec);
codec->control_data = i2c;
@@ -714,7 +713,6 @@ static int wm8510_codec_probe(struct i2c_adapter *adap, int addr, int kind)
return ret;
err:
- kfree(codec);
kfree(i2c);
return ret;
}
@@ -782,6 +780,9 @@ static int wm8510_probe(struct platform_device *pdev)
#else
/* Add other interfaces here */
#endif
+
+ if (ret != 0)
+ kfree(codec);
return ret;
}
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 369d39c..9402fca 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -596,10 +596,9 @@ static int wm8731_codec_probe(struct i2c_adapter *adap, int addr, int kind)
client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
- if (i2c == NULL) {
- kfree(codec);
+ if (i2c == NULL)
return -ENOMEM;
- }
+
i2c_set_clientdata(i2c, codec);
codec->control_data = i2c;
@@ -617,7 +616,6 @@ static int wm8731_codec_probe(struct i2c_adapter *adap, int addr, int kind)
return ret;
err:
- kfree(codec);
kfree(i2c);
return ret;
}
@@ -693,6 +691,11 @@ static int wm8731_probe(struct platform_device *pdev)
#else
/* Add other interfaces here */
#endif
+
+ if (ret != 0) {
+ kfree(codec->private_data);
+ kfree(codec);
+ }
return ret;
}
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index c6a8edf..dd1f554 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -869,10 +869,9 @@ static int wm8750_codec_probe(struct i2c_adapter *adap, int addr, int kind)
client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
- if (i2c == NULL) {
- kfree(codec);
+ if (i2c == NULL)
return -ENOMEM;
- }
+
i2c_set_clientdata(i2c, codec);
codec->control_data = i2c;
@@ -890,7 +889,6 @@ static int wm8750_codec_probe(struct i2c_adapter *adap, int addr, int kind)
return ret;
err:
- kfree(codec);
kfree(i2c);
return ret;
}
@@ -966,6 +964,10 @@ static int wm8750_probe(struct platform_device *pdev)
/* Add other interfaces here */
#endif
+ if (ret != 0) {
+ kfree(codec->private_data);
+ kfree(codec);
+ }
return ret;
}
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index dc7b18f..5761164 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -1660,10 +1660,9 @@ static int wm8753_codec_probe(struct i2c_adapter *adap, int addr, int kind)
client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
- if (!i2c) {
- kfree(codec);
+ if (!i2c)
return -ENOMEM;
- }
+
i2c_set_clientdata(i2c, codec);
codec->control_data = i2c;
@@ -1682,7 +1681,6 @@ static int wm8753_codec_probe(struct i2c_adapter *adap, int addr, int kind)
return ret;
err:
- kfree(codec);
kfree(i2c);
return ret;
}
@@ -1759,6 +1757,11 @@ static int wm8753_probe(struct platform_device *pdev)
#else
/* Add other interfaces here */
#endif
+
+ if (ret != 0) {
+ kfree(codec->private_data);
+ kfree(codec);
+ }
return ret;
}
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index e44153f..dd995ef 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -1500,10 +1500,9 @@ static int wm8990_codec_probe(struct i2c_adapter *adap, int addr, int kind)
client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
- if (i2c == NULL) {
- kfree(codec);
+ if (i2c == NULL)
return -ENOMEM;
- }
+
i2c_set_clientdata(i2c, codec);
codec->control_data = i2c;
@@ -1521,7 +1520,6 @@ static int wm8990_codec_probe(struct i2c_adapter *adap, int addr, int kind)
return ret;
err:
- kfree(codec);
kfree(i2c);
return ret;
}
@@ -1595,6 +1593,11 @@ static int wm8990_probe(struct platform_device *pdev)
#else
/* Add other interfaces here */
#endif
+
+ if (ret != 0) {
+ kfree(codec->private_data);
+ kfree(codec);
+ }
return ret;
}
--
1.5.6.3
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH] ASoC: Fix double free and memory leak in many codec drivers
2008-08-25 10:49 [PATCH] ASoC: Fix double free and memory leak in many codec drivers Mark Brown
@ 2008-08-25 11:53 ` Takashi Iwai
2008-08-25 12:11 ` Mark Brown
0 siblings, 1 reply; 5+ messages in thread
From: Takashi Iwai @ 2008-08-25 11:53 UTC (permalink / raw)
To: Mark Brown; +Cc: Jean Delvare, alsa-devel
At Mon, 25 Aug 2008 11:49:20 +0100,
Mark Brown wrote:
>
> From: Jean Delvare <khali@linux-fr.org>
>
> 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>
This looks like a 2.6.27 material, right?
I applied to for-linus branch now. Thanks.
Takashi
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] ASoC: Fix double free and memory leak in many codec drivers
2008-08-25 11:53 ` Takashi Iwai
@ 2008-08-25 12:11 ` Mark Brown
2008-08-26 12:19 ` Takashi Iwai
0 siblings, 1 reply; 5+ messages in thread
From: Mark Brown @ 2008-08-25 12:11 UTC (permalink / raw)
To: Takashi Iwai; +Cc: Jean Delvare, alsa-devel
On Mon, Aug 25, 2008 at 01:53:10PM +0200, Takashi Iwai wrote:
> This looks like a 2.6.27 material, right?
Ideally, yes.
> I applied to for-linus branch now. Thanks.
Thanks.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] ASoC: Fix double free and memory leak in many codec drivers
2008-08-25 12:11 ` Mark Brown
@ 2008-08-26 12:19 ` Takashi Iwai
2008-08-26 12:23 ` Jean Delvare
0 siblings, 1 reply; 5+ messages in thread
From: Takashi Iwai @ 2008-08-26 12:19 UTC (permalink / raw)
To: Mark Brown; +Cc: Jean Delvare, alsa-devel
At Mon, 25 Aug 2008 13:11:49 +0100,
Mark Brown wrote:
>
> On Mon, Aug 25, 2008 at 01:53:10PM +0200, Takashi Iwai wrote:
>
> > This looks like a 2.6.27 material, right?
>
> Ideally, yes.
FYI, it was merged to the upstream.
thanks,
Takashi
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] ASoC: Fix double free and memory leak in many codec drivers
2008-08-26 12:19 ` Takashi Iwai
@ 2008-08-26 12:23 ` Jean Delvare
0 siblings, 0 replies; 5+ messages in thread
From: Jean Delvare @ 2008-08-26 12:23 UTC (permalink / raw)
To: Takashi Iwai; +Cc: alsa-devel, Mark Brown
On Tue, 26 Aug 2008 14:19:40 +0200, Takashi Iwai wrote:
> At Mon, 25 Aug 2008 13:11:49 +0100,
> Mark Brown wrote:
> >
> > On Mon, Aug 25, 2008 at 01:53:10PM +0200, Takashi Iwai wrote:
> >
> > > This looks like a 2.6.27 material, right?
> >
> > Ideally, yes.
>
> FYI, it was merged to the upstream.
Great, thanks Takashi.
--
Jean Delvare
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2008-08-26 12:23 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-25 10:49 [PATCH] ASoC: Fix double free and memory leak in many codec drivers Mark Brown
2008-08-25 11:53 ` Takashi Iwai
2008-08-25 12:11 ` Mark Brown
2008-08-26 12:19 ` Takashi Iwai
2008-08-26 12:23 ` Jean Delvare
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.