diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-01-24 06:11:02 -0500 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-02-17 11:48:30 -0500 |
commit | 44961a03adbf16d872f0b83ec848d0759516d33f (patch) | |
tree | ba0e93fd1a473d93370d56c77416c44de6e9b3f9 /drivers | |
parent | c3bfc96ef7366aa996fb8286a36f3333a3b4ff25 (diff) |
pcmcia: avoid prod_id memleak
Reported-by: Wolfram Sang <w.sang@pengutronix.de>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pcmcia/ds.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 9968c0d3a5fb..93925f5908b8 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -237,8 +237,11 @@ static void pcmcia_release_function(struct kref *ref) | |||
237 | static void pcmcia_release_dev(struct device *dev) | 237 | static void pcmcia_release_dev(struct device *dev) |
238 | { | 238 | { |
239 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | 239 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
240 | int i; | ||
240 | dev_dbg(dev, "releasing device\n"); | 241 | dev_dbg(dev, "releasing device\n"); |
241 | pcmcia_put_socket(p_dev->socket); | 242 | pcmcia_put_socket(p_dev->socket); |
243 | for (i = 0; i < 4; i++) | ||
244 | kfree(p_dev->prod_id[i]); | ||
242 | kfree(p_dev->devname); | 245 | kfree(p_dev->devname); |
243 | kref_put(&p_dev->function_config->ref, pcmcia_release_function); | 246 | kref_put(&p_dev->function_config->ref, pcmcia_release_function); |
244 | kfree(p_dev); | 247 | kfree(p_dev); |
@@ -450,6 +453,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev) | |||
450 | for (i = 0; i < min_t(unsigned int, 4, vers1->ns); i++) { | 453 | for (i = 0; i < min_t(unsigned int, 4, vers1->ns); i++) { |
451 | char *tmp; | 454 | char *tmp; |
452 | unsigned int length; | 455 | unsigned int length; |
456 | char *new; | ||
453 | 457 | ||
454 | tmp = vers1->str + vers1->ofs[i]; | 458 | tmp = vers1->str + vers1->ofs[i]; |
455 | 459 | ||
@@ -457,13 +461,15 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev) | |||
457 | if ((length < 2) || (length > 255)) | 461 | if ((length < 2) || (length > 255)) |
458 | continue; | 462 | continue; |
459 | 463 | ||
460 | p_dev->prod_id[i] = kmalloc(sizeof(char) * length, | 464 | new = kmalloc(sizeof(char) * length, GFP_KERNEL); |
461 | GFP_KERNEL); | 465 | if (!new) |
462 | if (!p_dev->prod_id[i]) | ||
463 | continue; | 466 | continue; |
464 | 467 | ||
465 | p_dev->prod_id[i] = strncpy(p_dev->prod_id[i], | 468 | new = strncpy(new, tmp, length); |
466 | tmp, length); | 469 | |
470 | tmp = p_dev->prod_id[i]; | ||
471 | p_dev->prod_id[i] = new; | ||
472 | kfree(tmp); | ||
467 | } | 473 | } |
468 | mutex_unlock(&p_dev->socket->ops_mutex); | 474 | mutex_unlock(&p_dev->socket->ops_mutex); |
469 | } | 475 | } |
@@ -485,6 +491,7 @@ static DEFINE_MUTEX(device_add_lock); | |||
485 | struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int function) | 491 | struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int function) |
486 | { | 492 | { |
487 | struct pcmcia_device *p_dev, *tmp_dev; | 493 | struct pcmcia_device *p_dev, *tmp_dev; |
494 | int i; | ||
488 | 495 | ||
489 | s = pcmcia_get_socket(s); | 496 | s = pcmcia_get_socket(s); |
490 | if (!s) | 497 | if (!s) |
@@ -575,6 +582,8 @@ struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int fu | |||
575 | s->device_count--; | 582 | s->device_count--; |
576 | mutex_unlock(&s->ops_mutex); | 583 | mutex_unlock(&s->ops_mutex); |
577 | 584 | ||
585 | for (i = 0; i < 4; i++) | ||
586 | kfree(p_dev->prod_id[i]); | ||
578 | kfree(p_dev->devname); | 587 | kfree(p_dev->devname); |
579 | kfree(p_dev); | 588 | kfree(p_dev); |
580 | err_put: | 589 | err_put: |