Commit 3051e41a authored by Jean Delvare's avatar Jean Delvare Committed by Takashi Iwai

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: default avatarJean Delvare <khali@linux-fr.org>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent c5d44423
...@@ -562,10 +562,9 @@ static int ak4535_codec_probe(struct i2c_adapter *adap, int addr, int kind) ...@@ -562,10 +562,9 @@ static int ak4535_codec_probe(struct i2c_adapter *adap, int addr, int kind)
client_template.addr = addr; client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
if (i2c == NULL) { if (i2c == NULL)
kfree(codec);
return -ENOMEM; return -ENOMEM;
}
i2c_set_clientdata(i2c, codec); i2c_set_clientdata(i2c, codec);
codec->control_data = i2c; codec->control_data = i2c;
...@@ -583,7 +582,6 @@ static int ak4535_codec_probe(struct i2c_adapter *adap, int addr, int kind) ...@@ -583,7 +582,6 @@ static int ak4535_codec_probe(struct i2c_adapter *adap, int addr, int kind)
return ret; return ret;
err: err:
kfree(codec);
kfree(i2c); kfree(i2c);
return ret; return ret;
} }
...@@ -660,6 +658,11 @@ static int ak4535_probe(struct platform_device *pdev) ...@@ -660,6 +658,11 @@ static int ak4535_probe(struct platform_device *pdev)
#else #else
/* Add other interfaces here */ /* Add other interfaces here */
#endif #endif
if (ret != 0) {
kfree(codec->private_data);
kfree(codec);
}
return ret; return ret;
} }
......
...@@ -1199,10 +1199,9 @@ static int aic3x_codec_probe(struct i2c_adapter *adap, int addr, int kind) ...@@ -1199,10 +1199,9 @@ static int aic3x_codec_probe(struct i2c_adapter *adap, int addr, int kind)
client_template.addr = addr; client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
if (i2c == NULL) { if (i2c == NULL)
kfree(codec);
return -ENOMEM; return -ENOMEM;
}
i2c_set_clientdata(i2c, codec); i2c_set_clientdata(i2c, codec);
codec->control_data = i2c; codec->control_data = i2c;
...@@ -1221,7 +1220,6 @@ static int aic3x_codec_probe(struct i2c_adapter *adap, int addr, int kind) ...@@ -1221,7 +1220,6 @@ static int aic3x_codec_probe(struct i2c_adapter *adap, int addr, int kind)
return ret; return ret;
err: err:
kfree(codec);
kfree(i2c); kfree(i2c);
return ret; return ret;
} }
...@@ -1302,6 +1300,11 @@ static int aic3x_probe(struct platform_device *pdev) ...@@ -1302,6 +1300,11 @@ static int aic3x_probe(struct platform_device *pdev)
#else #else
/* Add other interfaces here */ /* Add other interfaces here */
#endif #endif
if (ret != 0) {
kfree(codec->private_data);
kfree(codec);
}
return ret; return ret;
} }
......
...@@ -729,10 +729,9 @@ static int uda1380_codec_probe(struct i2c_adapter *adap, int addr, int kind) ...@@ -729,10 +729,9 @@ static int uda1380_codec_probe(struct i2c_adapter *adap, int addr, int kind)
client_template.addr = addr; client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
if (i2c == NULL) { if (i2c == NULL)
kfree(codec);
return -ENOMEM; return -ENOMEM;
}
i2c_set_clientdata(i2c, codec); i2c_set_clientdata(i2c, codec);
codec->control_data = i2c; codec->control_data = i2c;
...@@ -750,7 +749,6 @@ static int uda1380_codec_probe(struct i2c_adapter *adap, int addr, int kind) ...@@ -750,7 +749,6 @@ static int uda1380_codec_probe(struct i2c_adapter *adap, int addr, int kind)
return ret; return ret;
err: err:
kfree(codec);
kfree(i2c); kfree(i2c);
return ret; return ret;
} }
...@@ -817,6 +815,9 @@ static int uda1380_probe(struct platform_device *pdev) ...@@ -817,6 +815,9 @@ static int uda1380_probe(struct platform_device *pdev)
#else #else
/* Add other interfaces here */ /* Add other interfaces here */
#endif #endif
if (ret != 0)
kfree(codec);
return ret; return ret;
} }
......
...@@ -693,10 +693,9 @@ static int wm8510_codec_probe(struct i2c_adapter *adap, int addr, int kind) ...@@ -693,10 +693,9 @@ static int wm8510_codec_probe(struct i2c_adapter *adap, int addr, int kind)
client_template.addr = addr; client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
if (i2c == NULL) { if (i2c == NULL)
kfree(codec);
return -ENOMEM; return -ENOMEM;
}
i2c_set_clientdata(i2c, codec); i2c_set_clientdata(i2c, codec);
codec->control_data = i2c; codec->control_data = i2c;
...@@ -714,7 +713,6 @@ static int wm8510_codec_probe(struct i2c_adapter *adap, int addr, int kind) ...@@ -714,7 +713,6 @@ static int wm8510_codec_probe(struct i2c_adapter *adap, int addr, int kind)
return ret; return ret;
err: err:
kfree(codec);
kfree(i2c); kfree(i2c);
return ret; return ret;
} }
...@@ -782,6 +780,9 @@ static int wm8510_probe(struct platform_device *pdev) ...@@ -782,6 +780,9 @@ static int wm8510_probe(struct platform_device *pdev)
#else #else
/* Add other interfaces here */ /* Add other interfaces here */
#endif #endif
if (ret != 0)
kfree(codec);
return ret; return ret;
} }
......
...@@ -596,10 +596,9 @@ static int wm8731_codec_probe(struct i2c_adapter *adap, int addr, int kind) ...@@ -596,10 +596,9 @@ static int wm8731_codec_probe(struct i2c_adapter *adap, int addr, int kind)
client_template.addr = addr; client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
if (i2c == NULL) { if (i2c == NULL)
kfree(codec);
return -ENOMEM; return -ENOMEM;
}
i2c_set_clientdata(i2c, codec); i2c_set_clientdata(i2c, codec);
codec->control_data = i2c; codec->control_data = i2c;
...@@ -617,7 +616,6 @@ static int wm8731_codec_probe(struct i2c_adapter *adap, int addr, int kind) ...@@ -617,7 +616,6 @@ static int wm8731_codec_probe(struct i2c_adapter *adap, int addr, int kind)
return ret; return ret;
err: err:
kfree(codec);
kfree(i2c); kfree(i2c);
return ret; return ret;
} }
...@@ -693,6 +691,11 @@ static int wm8731_probe(struct platform_device *pdev) ...@@ -693,6 +691,11 @@ static int wm8731_probe(struct platform_device *pdev)
#else #else
/* Add other interfaces here */ /* Add other interfaces here */
#endif #endif
if (ret != 0) {
kfree(codec->private_data);
kfree(codec);
}
return ret; return ret;
} }
......
...@@ -869,10 +869,9 @@ static int wm8750_codec_probe(struct i2c_adapter *adap, int addr, int kind) ...@@ -869,10 +869,9 @@ static int wm8750_codec_probe(struct i2c_adapter *adap, int addr, int kind)
client_template.addr = addr; client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
if (i2c == NULL) { if (i2c == NULL)
kfree(codec);
return -ENOMEM; return -ENOMEM;
}
i2c_set_clientdata(i2c, codec); i2c_set_clientdata(i2c, codec);
codec->control_data = i2c; codec->control_data = i2c;
...@@ -890,7 +889,6 @@ static int wm8750_codec_probe(struct i2c_adapter *adap, int addr, int kind) ...@@ -890,7 +889,6 @@ static int wm8750_codec_probe(struct i2c_adapter *adap, int addr, int kind)
return ret; return ret;
err: err:
kfree(codec);
kfree(i2c); kfree(i2c);
return ret; return ret;
} }
...@@ -966,6 +964,10 @@ static int wm8750_probe(struct platform_device *pdev) ...@@ -966,6 +964,10 @@ static int wm8750_probe(struct platform_device *pdev)
/* Add other interfaces here */ /* Add other interfaces here */
#endif #endif
if (ret != 0) {
kfree(codec->private_data);
kfree(codec);
}
return ret; return ret;
} }
......
...@@ -1661,10 +1661,9 @@ static int wm8753_codec_probe(struct i2c_adapter *adap, int addr, int kind) ...@@ -1661,10 +1661,9 @@ static int wm8753_codec_probe(struct i2c_adapter *adap, int addr, int kind)
client_template.addr = addr; client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
if (!i2c) { if (!i2c)
kfree(codec);
return -ENOMEM; return -ENOMEM;
}
i2c_set_clientdata(i2c, codec); i2c_set_clientdata(i2c, codec);
codec->control_data = i2c; codec->control_data = i2c;
...@@ -1683,7 +1682,6 @@ static int wm8753_codec_probe(struct i2c_adapter *adap, int addr, int kind) ...@@ -1683,7 +1682,6 @@ static int wm8753_codec_probe(struct i2c_adapter *adap, int addr, int kind)
return ret; return ret;
err: err:
kfree(codec);
kfree(i2c); kfree(i2c);
return ret; return ret;
} }
...@@ -1760,6 +1758,11 @@ static int wm8753_probe(struct platform_device *pdev) ...@@ -1760,6 +1758,11 @@ static int wm8753_probe(struct platform_device *pdev)
#else #else
/* Add other interfaces here */ /* Add other interfaces here */
#endif #endif
if (ret != 0) {
kfree(codec->private_data);
kfree(codec);
}
return ret; return ret;
} }
......
...@@ -1500,10 +1500,9 @@ static int wm8990_codec_probe(struct i2c_adapter *adap, int addr, int kind) ...@@ -1500,10 +1500,9 @@ static int wm8990_codec_probe(struct i2c_adapter *adap, int addr, int kind)
client_template.addr = addr; client_template.addr = addr;
i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
if (i2c == NULL) { if (i2c == NULL)
kfree(codec);
return -ENOMEM; return -ENOMEM;
}
i2c_set_clientdata(i2c, codec); i2c_set_clientdata(i2c, codec);
codec->control_data = i2c; codec->control_data = i2c;
...@@ -1521,7 +1520,6 @@ static int wm8990_codec_probe(struct i2c_adapter *adap, int addr, int kind) ...@@ -1521,7 +1520,6 @@ static int wm8990_codec_probe(struct i2c_adapter *adap, int addr, int kind)
return ret; return ret;
err: err:
kfree(codec);
kfree(i2c); kfree(i2c);
return ret; return ret;
} }
...@@ -1595,6 +1593,11 @@ static int wm8990_probe(struct platform_device *pdev) ...@@ -1595,6 +1593,11 @@ static int wm8990_probe(struct platform_device *pdev)
#else #else
/* Add other interfaces here */ /* Add other interfaces here */
#endif #endif
if (ret != 0) {
kfree(codec->private_data);
kfree(codec);
}
return ret; return ret;
} }
......
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