diff options
author | Jesper Juhl <jj@chaosbits.net> | 2011-03-14 07:05:56 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2011-03-23 12:36:20 -0400 |
commit | 6d1802539d218e24492c651bd0687ebfe7e14831 (patch) | |
tree | 133b05930d8272259693c1e8bcce5ce1c8d98f1b /drivers/target | |
parent | 8fc1858a42663248d5b362edc313786e0be7a639 (diff) |
[SCSI] target: Fix match_strdup() memory leaks
match_strdup() dynamically allocates memory and it is the responsabillity
of the caller to free that memory. The following three cases:
drivers/target/target_core_file.c:fd_set_configfs_dev_params()
drivers/target/target_core_iblock.c:iblock_set_configfs_dev_params()
drivers/target/target_core_configfs.c:target_core_dev_pr_store_attr_res_aptpl_metadata()
should be kfree()'ing the allocated memory once it is no longer needed.
It also makes sure to return -ENOMEM if the memory allocation in match_strdup()
should fail. For target_core_configfs.c, this patch adds kfree()'s around
Opt_initiator_fabric, Opt_initiator_node, Opt_initiator_sid, Opt_sa_res_key,
Opt_target_fabric, and Opt_target_node for the Persistent Reservations
Activate Persistence across Target Power Loss (APTPL=1) token parsing.
Signed-off-by: Jesper Juhl <jj@chaosbits.net>
Signed-off-by: Nicholas A. Bellinger <nab@linux-iscsi.org>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/target_core_configfs.c | 33 | ||||
-rw-r--r-- | drivers/target/target_core_file.c | 13 | ||||
-rw-r--r-- | drivers/target/target_core_iblock.c | 13 |
3 files changed, 52 insertions, 7 deletions
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index caf8dc18ee0a..c9254d7ad18a 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c | |||
@@ -1451,8 +1451,8 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( | |||
1451 | size_t count) | 1451 | size_t count) |
1452 | { | 1452 | { |
1453 | struct se_device *dev; | 1453 | struct se_device *dev; |
1454 | unsigned char *i_fabric, *t_fabric, *i_port = NULL, *t_port = NULL; | 1454 | unsigned char *i_fabric = NULL, *i_port = NULL, *isid = NULL; |
1455 | unsigned char *isid = NULL; | 1455 | unsigned char *t_fabric = NULL, *t_port = NULL; |
1456 | char *orig, *ptr, *arg_p, *opts; | 1456 | char *orig, *ptr, *arg_p, *opts; |
1457 | substring_t args[MAX_OPT_ARGS]; | 1457 | substring_t args[MAX_OPT_ARGS]; |
1458 | unsigned long long tmp_ll; | 1458 | unsigned long long tmp_ll; |
@@ -1488,9 +1488,17 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( | |||
1488 | switch (token) { | 1488 | switch (token) { |
1489 | case Opt_initiator_fabric: | 1489 | case Opt_initiator_fabric: |
1490 | i_fabric = match_strdup(&args[0]); | 1490 | i_fabric = match_strdup(&args[0]); |
1491 | if (!i_fabric) { | ||
1492 | ret = -ENOMEM; | ||
1493 | goto out; | ||
1494 | } | ||
1491 | break; | 1495 | break; |
1492 | case Opt_initiator_node: | 1496 | case Opt_initiator_node: |
1493 | i_port = match_strdup(&args[0]); | 1497 | i_port = match_strdup(&args[0]); |
1498 | if (!i_port) { | ||
1499 | ret = -ENOMEM; | ||
1500 | goto out; | ||
1501 | } | ||
1494 | if (strlen(i_port) > PR_APTPL_MAX_IPORT_LEN) { | 1502 | if (strlen(i_port) > PR_APTPL_MAX_IPORT_LEN) { |
1495 | printk(KERN_ERR "APTPL metadata initiator_node=" | 1503 | printk(KERN_ERR "APTPL metadata initiator_node=" |
1496 | " exceeds PR_APTPL_MAX_IPORT_LEN: %d\n", | 1504 | " exceeds PR_APTPL_MAX_IPORT_LEN: %d\n", |
@@ -1501,6 +1509,10 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( | |||
1501 | break; | 1509 | break; |
1502 | case Opt_initiator_sid: | 1510 | case Opt_initiator_sid: |
1503 | isid = match_strdup(&args[0]); | 1511 | isid = match_strdup(&args[0]); |
1512 | if (!isid) { | ||
1513 | ret = -ENOMEM; | ||
1514 | goto out; | ||
1515 | } | ||
1504 | if (strlen(isid) > PR_REG_ISID_LEN) { | 1516 | if (strlen(isid) > PR_REG_ISID_LEN) { |
1505 | printk(KERN_ERR "APTPL metadata initiator_isid" | 1517 | printk(KERN_ERR "APTPL metadata initiator_isid" |
1506 | "= exceeds PR_REG_ISID_LEN: %d\n", | 1518 | "= exceeds PR_REG_ISID_LEN: %d\n", |
@@ -1511,6 +1523,10 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( | |||
1511 | break; | 1523 | break; |
1512 | case Opt_sa_res_key: | 1524 | case Opt_sa_res_key: |
1513 | arg_p = match_strdup(&args[0]); | 1525 | arg_p = match_strdup(&args[0]); |
1526 | if (!arg_p) { | ||
1527 | ret = -ENOMEM; | ||
1528 | goto out; | ||
1529 | } | ||
1514 | ret = strict_strtoull(arg_p, 0, &tmp_ll); | 1530 | ret = strict_strtoull(arg_p, 0, &tmp_ll); |
1515 | if (ret < 0) { | 1531 | if (ret < 0) { |
1516 | printk(KERN_ERR "strict_strtoull() failed for" | 1532 | printk(KERN_ERR "strict_strtoull() failed for" |
@@ -1547,9 +1563,17 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( | |||
1547 | */ | 1563 | */ |
1548 | case Opt_target_fabric: | 1564 | case Opt_target_fabric: |
1549 | t_fabric = match_strdup(&args[0]); | 1565 | t_fabric = match_strdup(&args[0]); |
1566 | if (!t_fabric) { | ||
1567 | ret = -ENOMEM; | ||
1568 | goto out; | ||
1569 | } | ||
1550 | break; | 1570 | break; |
1551 | case Opt_target_node: | 1571 | case Opt_target_node: |
1552 | t_port = match_strdup(&args[0]); | 1572 | t_port = match_strdup(&args[0]); |
1573 | if (!t_port) { | ||
1574 | ret = -ENOMEM; | ||
1575 | goto out; | ||
1576 | } | ||
1553 | if (strlen(t_port) > PR_APTPL_MAX_TPORT_LEN) { | 1577 | if (strlen(t_port) > PR_APTPL_MAX_TPORT_LEN) { |
1554 | printk(KERN_ERR "APTPL metadata target_node=" | 1578 | printk(KERN_ERR "APTPL metadata target_node=" |
1555 | " exceeds PR_APTPL_MAX_TPORT_LEN: %d\n", | 1579 | " exceeds PR_APTPL_MAX_TPORT_LEN: %d\n", |
@@ -1592,6 +1616,11 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata( | |||
1592 | i_port, isid, mapped_lun, t_port, tpgt, target_lun, | 1616 | i_port, isid, mapped_lun, t_port, tpgt, target_lun, |
1593 | res_holder, all_tg_pt, type); | 1617 | res_holder, all_tg_pt, type); |
1594 | out: | 1618 | out: |
1619 | kfree(i_fabric); | ||
1620 | kfree(i_port); | ||
1621 | kfree(isid); | ||
1622 | kfree(t_fabric); | ||
1623 | kfree(t_port); | ||
1595 | kfree(orig); | 1624 | kfree(orig); |
1596 | return (ret == 0) ? count : ret; | 1625 | return (ret == 0) ? count : ret; |
1597 | } | 1626 | } |
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 190ca8ac2498..7850c6ae06e4 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c | |||
@@ -536,15 +536,26 @@ static ssize_t fd_set_configfs_dev_params( | |||
536 | token = match_token(ptr, tokens, args); | 536 | token = match_token(ptr, tokens, args); |
537 | switch (token) { | 537 | switch (token) { |
538 | case Opt_fd_dev_name: | 538 | case Opt_fd_dev_name: |
539 | arg_p = match_strdup(&args[0]); | ||
540 | if (!arg_p) { | ||
541 | ret = -ENOMEM; | ||
542 | break; | ||
543 | } | ||
539 | snprintf(fd_dev->fd_dev_name, FD_MAX_DEV_NAME, | 544 | snprintf(fd_dev->fd_dev_name, FD_MAX_DEV_NAME, |
540 | "%s", match_strdup(&args[0])); | 545 | "%s", arg_p); |
546 | kfree(arg_p); | ||
541 | printk(KERN_INFO "FILEIO: Referencing Path: %s\n", | 547 | printk(KERN_INFO "FILEIO: Referencing Path: %s\n", |
542 | fd_dev->fd_dev_name); | 548 | fd_dev->fd_dev_name); |
543 | fd_dev->fbd_flags |= FBDF_HAS_PATH; | 549 | fd_dev->fbd_flags |= FBDF_HAS_PATH; |
544 | break; | 550 | break; |
545 | case Opt_fd_dev_size: | 551 | case Opt_fd_dev_size: |
546 | arg_p = match_strdup(&args[0]); | 552 | arg_p = match_strdup(&args[0]); |
553 | if (!arg_p) { | ||
554 | ret = -ENOMEM; | ||
555 | break; | ||
556 | } | ||
547 | ret = strict_strtoull(arg_p, 0, &fd_dev->fd_dev_size); | 557 | ret = strict_strtoull(arg_p, 0, &fd_dev->fd_dev_size); |
558 | kfree(arg_p); | ||
548 | if (ret < 0) { | 559 | if (ret < 0) { |
549 | printk(KERN_ERR "strict_strtoull() failed for" | 560 | printk(KERN_ERR "strict_strtoull() failed for" |
550 | " fd_dev_size=\n"); | 561 | " fd_dev_size=\n"); |
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 3df570db0e4f..96d98cc8f85b 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c | |||
@@ -468,7 +468,7 @@ static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba, | |||
468 | const char *page, ssize_t count) | 468 | const char *page, ssize_t count) |
469 | { | 469 | { |
470 | struct iblock_dev *ib_dev = se_dev->se_dev_su_ptr; | 470 | struct iblock_dev *ib_dev = se_dev->se_dev_su_ptr; |
471 | char *orig, *ptr, *opts; | 471 | char *orig, *ptr, *arg_p, *opts; |
472 | substring_t args[MAX_OPT_ARGS]; | 472 | substring_t args[MAX_OPT_ARGS]; |
473 | int ret = 0, arg, token; | 473 | int ret = 0, arg, token; |
474 | 474 | ||
@@ -491,9 +491,14 @@ static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba, | |||
491 | ret = -EEXIST; | 491 | ret = -EEXIST; |
492 | goto out; | 492 | goto out; |
493 | } | 493 | } |
494 | 494 | arg_p = match_strdup(&args[0]); | |
495 | ret = snprintf(ib_dev->ibd_udev_path, SE_UDEV_PATH_LEN, | 495 | if (!arg_p) { |
496 | "%s", match_strdup(&args[0])); | 496 | ret = -ENOMEM; |
497 | break; | ||
498 | } | ||
499 | snprintf(ib_dev->ibd_udev_path, SE_UDEV_PATH_LEN, | ||
500 | "%s", arg_p); | ||
501 | kfree(arg_p); | ||
497 | printk(KERN_INFO "IBLOCK: Referencing UDEV path: %s\n", | 502 | printk(KERN_INFO "IBLOCK: Referencing UDEV path: %s\n", |
498 | ib_dev->ibd_udev_path); | 503 | ib_dev->ibd_udev_path); |
499 | ib_dev->ibd_flags |= IBDF_HAS_UDEV_PATH; | 504 | ib_dev->ibd_flags |= IBDF_HAS_UDEV_PATH; |