diff options
author | Jan Beulich <JBeulich@suse.com> | 2012-12-20 05:31:11 -0500 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2013-02-19 15:16:52 -0500 |
commit | 9d092603cc306ee6edfe917bf9ab8beb5f32d7bc (patch) | |
tree | b3a2c673762e0c5c9cff298cf34376f887641f66 /drivers/block/xen-blkback | |
parent | 836dc9e3fbbab0c30aa6e664417225f5c1fb1c39 (diff) |
xen-blkback: do not leak mode property
"be->mode" is obtained from xenbus_read(), which does a kmalloc() for
the message body. The short string is never released, so do it along
with freeing "be" itself, and make sure the string isn't kept when
backend_changed() doesn't complete successfully (which made it
desirable to slightly re-structure that function, so that the error
cleanup can be done in one place).
Reported-by: Olaf Hering <olaf@aepfle.de>
CC: stable@vger.kernel.org
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/block/xen-blkback')
-rw-r--r-- | drivers/block/xen-blkback/xenbus.c | 49 |
1 files changed, 24 insertions, 25 deletions
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 63980722db41..5e237f630c47 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c | |||
@@ -367,6 +367,7 @@ static int xen_blkbk_remove(struct xenbus_device *dev) | |||
367 | be->blkif = NULL; | 367 | be->blkif = NULL; |
368 | } | 368 | } |
369 | 369 | ||
370 | kfree(be->mode); | ||
370 | kfree(be); | 371 | kfree(be); |
371 | dev_set_drvdata(&dev->dev, NULL); | 372 | dev_set_drvdata(&dev->dev, NULL); |
372 | return 0; | 373 | return 0; |
@@ -502,6 +503,7 @@ static void backend_changed(struct xenbus_watch *watch, | |||
502 | = container_of(watch, struct backend_info, backend_watch); | 503 | = container_of(watch, struct backend_info, backend_watch); |
503 | struct xenbus_device *dev = be->dev; | 504 | struct xenbus_device *dev = be->dev; |
504 | int cdrom = 0; | 505 | int cdrom = 0; |
506 | unsigned long handle; | ||
505 | char *device_type; | 507 | char *device_type; |
506 | 508 | ||
507 | DPRINTK(""); | 509 | DPRINTK(""); |
@@ -521,10 +523,10 @@ static void backend_changed(struct xenbus_watch *watch, | |||
521 | return; | 523 | return; |
522 | } | 524 | } |
523 | 525 | ||
524 | if ((be->major || be->minor) && | 526 | if (be->major | be->minor) { |
525 | ((be->major != major) || (be->minor != minor))) { | 527 | if (be->major != major || be->minor != minor) |
526 | pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n", | 528 | pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n", |
527 | be->major, be->minor, major, minor); | 529 | be->major, be->minor, major, minor); |
528 | return; | 530 | return; |
529 | } | 531 | } |
530 | 532 | ||
@@ -542,36 +544,33 @@ static void backend_changed(struct xenbus_watch *watch, | |||
542 | kfree(device_type); | 544 | kfree(device_type); |
543 | } | 545 | } |
544 | 546 | ||
545 | if (be->major == 0 && be->minor == 0) { | 547 | /* Front end dir is a number, which is used as the handle. */ |
546 | /* Front end dir is a number, which is used as the handle. */ | 548 | err = strict_strtoul(strrchr(dev->otherend, '/') + 1, 0, &handle); |
547 | 549 | if (err) | |
548 | char *p = strrchr(dev->otherend, '/') + 1; | 550 | return; |
549 | long handle; | ||
550 | err = strict_strtoul(p, 0, &handle); | ||
551 | if (err) | ||
552 | return; | ||
553 | 551 | ||
554 | be->major = major; | 552 | be->major = major; |
555 | be->minor = minor; | 553 | be->minor = minor; |
556 | 554 | ||
557 | err = xen_vbd_create(be->blkif, handle, major, minor, | 555 | err = xen_vbd_create(be->blkif, handle, major, minor, |
558 | (NULL == strchr(be->mode, 'w')), cdrom); | 556 | !strchr(be->mode, 'w'), cdrom); |
559 | if (err) { | ||
560 | be->major = 0; | ||
561 | be->minor = 0; | ||
562 | xenbus_dev_fatal(dev, err, "creating vbd structure"); | ||
563 | return; | ||
564 | } | ||
565 | 557 | ||
558 | if (err) | ||
559 | xenbus_dev_fatal(dev, err, "creating vbd structure"); | ||
560 | else { | ||
566 | err = xenvbd_sysfs_addif(dev); | 561 | err = xenvbd_sysfs_addif(dev); |
567 | if (err) { | 562 | if (err) { |
568 | xen_vbd_free(&be->blkif->vbd); | 563 | xen_vbd_free(&be->blkif->vbd); |
569 | be->major = 0; | ||
570 | be->minor = 0; | ||
571 | xenbus_dev_fatal(dev, err, "creating sysfs entries"); | 564 | xenbus_dev_fatal(dev, err, "creating sysfs entries"); |
572 | return; | ||
573 | } | 565 | } |
566 | } | ||
574 | 567 | ||
568 | if (err) { | ||
569 | kfree(be->mode); | ||
570 | be->mode = NULL; | ||
571 | be->major = 0; | ||
572 | be->minor = 0; | ||
573 | } else { | ||
575 | /* We're potentially connected now */ | 574 | /* We're potentially connected now */ |
576 | xen_update_blkif_status(be->blkif); | 575 | xen_update_blkif_status(be->blkif); |
577 | } | 576 | } |