diff options
author | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2010-03-23 16:35:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-24 19:31:19 -0400 |
commit | 05731b979476969d4d1cbbcb535fc0f5ea90dba7 (patch) | |
tree | cc6c33e59c765dac9af39c8caa4a97f8da8f1861 | |
parent | e7bbcdf3747e3919c31cfa87853c69d178bce548 (diff) |
rtc/mc13783: fix use after free bug
This was introduced by v2.6.34-rc1~38:
4c014e8 (rtc/mc13783: protect rtc {,un}registration by mc13783 lock)
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Reported-by: Dan Carpenter <error27@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/rtc/rtc-mc13783.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/drivers/rtc/rtc-mc13783.c b/drivers/rtc/rtc-mc13783.c index d60c81b7b693..1379c7faa448 100644 --- a/drivers/rtc/rtc-mc13783.c +++ b/drivers/rtc/rtc-mc13783.c | |||
@@ -319,35 +319,38 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev) | |||
319 | { | 319 | { |
320 | int ret; | 320 | int ret; |
321 | struct mc13783_rtc *priv; | 321 | struct mc13783_rtc *priv; |
322 | struct mc13783 *mc13783; | ||
322 | int rtcrst_pending; | 323 | int rtcrst_pending; |
323 | 324 | ||
324 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 325 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
325 | if (!priv) | 326 | if (!priv) |
326 | return -ENOMEM; | 327 | return -ENOMEM; |
327 | 328 | ||
328 | priv->mc13783 = dev_get_drvdata(pdev->dev.parent); | 329 | mc13783 = dev_get_drvdata(pdev->dev.parent); |
330 | priv->mc13783 = mc13783; | ||
331 | |||
329 | platform_set_drvdata(pdev, priv); | 332 | platform_set_drvdata(pdev, priv); |
330 | 333 | ||
331 | mc13783_lock(priv->mc13783); | 334 | mc13783_lock(mc13783); |
332 | 335 | ||
333 | ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_RTCRST, | 336 | ret = mc13783_irq_request(mc13783, MC13783_IRQ_RTCRST, |
334 | mc13783_rtc_reset_handler, DRIVER_NAME, priv); | 337 | mc13783_rtc_reset_handler, DRIVER_NAME, priv); |
335 | if (ret) | 338 | if (ret) |
336 | goto err_reset_irq_request; | 339 | goto err_reset_irq_request; |
337 | 340 | ||
338 | ret = mc13783_irq_status(priv->mc13783, MC13783_IRQ_RTCRST, | 341 | ret = mc13783_irq_status(mc13783, MC13783_IRQ_RTCRST, |
339 | NULL, &rtcrst_pending); | 342 | NULL, &rtcrst_pending); |
340 | if (ret) | 343 | if (ret) |
341 | goto err_reset_irq_status; | 344 | goto err_reset_irq_status; |
342 | 345 | ||
343 | priv->valid = !rtcrst_pending; | 346 | priv->valid = !rtcrst_pending; |
344 | 347 | ||
345 | ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_1HZ, | 348 | ret = mc13783_irq_request_nounmask(mc13783, MC13783_IRQ_1HZ, |
346 | mc13783_rtc_update_handler, DRIVER_NAME, priv); | 349 | mc13783_rtc_update_handler, DRIVER_NAME, priv); |
347 | if (ret) | 350 | if (ret) |
348 | goto err_update_irq_request; | 351 | goto err_update_irq_request; |
349 | 352 | ||
350 | ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_TODA, | 353 | ret = mc13783_irq_request_nounmask(mc13783, MC13783_IRQ_TODA, |
351 | mc13783_rtc_alarm_handler, DRIVER_NAME, priv); | 354 | mc13783_rtc_alarm_handler, DRIVER_NAME, priv); |
352 | if (ret) | 355 | if (ret) |
353 | goto err_alarm_irq_request; | 356 | goto err_alarm_irq_request; |
@@ -357,22 +360,22 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev) | |||
357 | if (IS_ERR(priv->rtc)) { | 360 | if (IS_ERR(priv->rtc)) { |
358 | ret = PTR_ERR(priv->rtc); | 361 | ret = PTR_ERR(priv->rtc); |
359 | 362 | ||
360 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_TODA, priv); | 363 | mc13783_irq_free(mc13783, MC13783_IRQ_TODA, priv); |
361 | err_alarm_irq_request: | 364 | err_alarm_irq_request: |
362 | 365 | ||
363 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv); | 366 | mc13783_irq_free(mc13783, MC13783_IRQ_1HZ, priv); |
364 | err_update_irq_request: | 367 | err_update_irq_request: |
365 | 368 | ||
366 | err_reset_irq_status: | 369 | err_reset_irq_status: |
367 | 370 | ||
368 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv); | 371 | mc13783_irq_free(mc13783, MC13783_IRQ_RTCRST, priv); |
369 | err_reset_irq_request: | 372 | err_reset_irq_request: |
370 | 373 | ||
371 | platform_set_drvdata(pdev, NULL); | 374 | platform_set_drvdata(pdev, NULL); |
372 | kfree(priv); | 375 | kfree(priv); |
373 | } | 376 | } |
374 | 377 | ||
375 | mc13783_unlock(priv->mc13783); | 378 | mc13783_unlock(mc13783); |
376 | 379 | ||
377 | return ret; | 380 | return ret; |
378 | } | 381 | } |