diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-09-16 04:44:54 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-09-16 15:37:18 -0400 |
commit | 2ff017f5b4299e24a7f22d9a336dd162bf52bb54 (patch) | |
tree | 71b896a42d7576dd751abf65adbf85f4a7726641 /drivers/target/iscsi | |
parent | 784eb99ebad91db4c8c231c4b17f203147ab827b (diff) |
iscsi-target: Disable markers + remove dangerous local scope array usage
This patch makes iscsi-target explictly disable OFMarker=Yes and IFMarker=yes
parameter key usage during iscsi login by setting IFMarkInt_Reject and
OFMarkInt_Reject values in iscsi_enforce_integrity_rules() to effectively
disable iscsi marker usage. With this patch, an initiator proposer asking
to enable either marker parameter keys will be issued a 'No' response, and
the target sets OFMarkInt + IFMarkInt parameter key response to 'Irrelevant'.
With markers disabled during iscsi login, this patch removes the problematic
on-stack local-scope array for marker intervals in iscsit_do_rx_data() +
iscsit_do_tx_data(), and other related marker code in iscsi_target_util.c.
This fixes a potentional stack smashing scenario with small range markers
enabled and a large MRDSL as reported by DanC here:
[bug report] target: stack can be smashed
http://www.spinics.net/lists/target-devel/msg00453.html
Reported-by: Dan Carpenter <error27@gmail.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target/iscsi')
-rw-r--r-- | drivers/target/iscsi/iscsi_target_parameters.c | 2 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_util.c | 248 |
2 files changed, 7 insertions, 243 deletions
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c index 497b2e718a76..5b773160200f 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.c +++ b/drivers/target/iscsi/iscsi_target_parameters.c | |||
@@ -1430,7 +1430,7 @@ static int iscsi_enforce_integrity_rules( | |||
1430 | u8 DataSequenceInOrder = 0; | 1430 | u8 DataSequenceInOrder = 0; |
1431 | u8 ErrorRecoveryLevel = 0, SessionType = 0; | 1431 | u8 ErrorRecoveryLevel = 0, SessionType = 0; |
1432 | u8 IFMarker = 0, OFMarker = 0; | 1432 | u8 IFMarker = 0, OFMarker = 0; |
1433 | u8 IFMarkInt_Reject = 0, OFMarkInt_Reject = 0; | 1433 | u8 IFMarkInt_Reject = 1, OFMarkInt_Reject = 1; |
1434 | u32 FirstBurstLength = 0, MaxBurstLength = 0; | 1434 | u32 FirstBurstLength = 0, MaxBurstLength = 0; |
1435 | struct iscsi_param *param = NULL; | 1435 | struct iscsi_param *param = NULL; |
1436 | 1436 | ||
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index a0d23bc0fc98..1d1b4fe33e43 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c | |||
@@ -875,40 +875,6 @@ void iscsit_inc_session_usage_count(struct iscsi_session *sess) | |||
875 | } | 875 | } |
876 | 876 | ||
877 | /* | 877 | /* |
878 | * Used before iscsi_do[rx,tx]_data() to determine iov and [rx,tx]_marker | ||
879 | * array counts needed for sync and steering. | ||
880 | */ | ||
881 | static int iscsit_determine_sync_and_steering_counts( | ||
882 | struct iscsi_conn *conn, | ||
883 | struct iscsi_data_count *count) | ||
884 | { | ||
885 | u32 length = count->data_length; | ||
886 | u32 marker, markint; | ||
887 | |||
888 | count->sync_and_steering = 1; | ||
889 | |||
890 | marker = (count->type == ISCSI_RX_DATA) ? | ||
891 | conn->of_marker : conn->if_marker; | ||
892 | markint = (count->type == ISCSI_RX_DATA) ? | ||
893 | (conn->conn_ops->OFMarkInt * 4) : | ||
894 | (conn->conn_ops->IFMarkInt * 4); | ||
895 | count->ss_iov_count = count->iov_count; | ||
896 | |||
897 | while (length > 0) { | ||
898 | if (length >= marker) { | ||
899 | count->ss_iov_count += 3; | ||
900 | count->ss_marker_count += 2; | ||
901 | |||
902 | length -= marker; | ||
903 | marker = markint; | ||
904 | } else | ||
905 | length = 0; | ||
906 | } | ||
907 | |||
908 | return 0; | ||
909 | } | ||
910 | |||
911 | /* | ||
912 | * Setup conn->if_marker and conn->of_marker values based upon | 878 | * Setup conn->if_marker and conn->of_marker values based upon |
913 | * the initial marker-less interval. (see iSCSI v19 A.2) | 879 | * the initial marker-less interval. (see iSCSI v19 A.2) |
914 | */ | 880 | */ |
@@ -1431,8 +1397,7 @@ static int iscsit_do_rx_data( | |||
1431 | struct iscsi_data_count *count) | 1397 | struct iscsi_data_count *count) |
1432 | { | 1398 | { |
1433 | int data = count->data_length, rx_loop = 0, total_rx = 0, iov_len; | 1399 | int data = count->data_length, rx_loop = 0, total_rx = 0, iov_len; |
1434 | u32 rx_marker_val[count->ss_marker_count], rx_marker_iov = 0; | 1400 | struct kvec *iov_p; |
1435 | struct kvec iov[count->ss_iov_count], *iov_p; | ||
1436 | struct msghdr msg; | 1401 | struct msghdr msg; |
1437 | 1402 | ||
1438 | if (!conn || !conn->sock || !conn->conn_ops) | 1403 | if (!conn || !conn->sock || !conn->conn_ops) |
@@ -1440,93 +1405,8 @@ static int iscsit_do_rx_data( | |||
1440 | 1405 | ||
1441 | memset(&msg, 0, sizeof(struct msghdr)); | 1406 | memset(&msg, 0, sizeof(struct msghdr)); |
1442 | 1407 | ||
1443 | if (count->sync_and_steering) { | 1408 | iov_p = count->iov; |
1444 | int size = 0; | 1409 | iov_len = count->iov_count; |
1445 | u32 i, orig_iov_count = 0; | ||
1446 | u32 orig_iov_len = 0, orig_iov_loc = 0; | ||
1447 | u32 iov_count = 0, per_iov_bytes = 0; | ||
1448 | u32 *rx_marker, old_rx_marker = 0; | ||
1449 | struct kvec *iov_record; | ||
1450 | |||
1451 | memset(&rx_marker_val, 0, | ||
1452 | count->ss_marker_count * sizeof(u32)); | ||
1453 | memset(&iov, 0, count->ss_iov_count * sizeof(struct kvec)); | ||
1454 | |||
1455 | iov_record = count->iov; | ||
1456 | orig_iov_count = count->iov_count; | ||
1457 | rx_marker = &conn->of_marker; | ||
1458 | |||
1459 | i = 0; | ||
1460 | size = data; | ||
1461 | orig_iov_len = iov_record[orig_iov_loc].iov_len; | ||
1462 | while (size > 0) { | ||
1463 | pr_debug("rx_data: #1 orig_iov_len %u," | ||
1464 | " orig_iov_loc %u\n", orig_iov_len, orig_iov_loc); | ||
1465 | pr_debug("rx_data: #2 rx_marker %u, size" | ||
1466 | " %u\n", *rx_marker, size); | ||
1467 | |||
1468 | if (orig_iov_len >= *rx_marker) { | ||
1469 | iov[iov_count].iov_len = *rx_marker; | ||
1470 | iov[iov_count++].iov_base = | ||
1471 | (iov_record[orig_iov_loc].iov_base + | ||
1472 | per_iov_bytes); | ||
1473 | |||
1474 | iov[iov_count].iov_len = (MARKER_SIZE / 2); | ||
1475 | iov[iov_count++].iov_base = | ||
1476 | &rx_marker_val[rx_marker_iov++]; | ||
1477 | iov[iov_count].iov_len = (MARKER_SIZE / 2); | ||
1478 | iov[iov_count++].iov_base = | ||
1479 | &rx_marker_val[rx_marker_iov++]; | ||
1480 | old_rx_marker = *rx_marker; | ||
1481 | |||
1482 | /* | ||
1483 | * OFMarkInt is in 32-bit words. | ||
1484 | */ | ||
1485 | *rx_marker = (conn->conn_ops->OFMarkInt * 4); | ||
1486 | size -= old_rx_marker; | ||
1487 | orig_iov_len -= old_rx_marker; | ||
1488 | per_iov_bytes += old_rx_marker; | ||
1489 | |||
1490 | pr_debug("rx_data: #3 new_rx_marker" | ||
1491 | " %u, size %u\n", *rx_marker, size); | ||
1492 | } else { | ||
1493 | iov[iov_count].iov_len = orig_iov_len; | ||
1494 | iov[iov_count++].iov_base = | ||
1495 | (iov_record[orig_iov_loc].iov_base + | ||
1496 | per_iov_bytes); | ||
1497 | |||
1498 | per_iov_bytes = 0; | ||
1499 | *rx_marker -= orig_iov_len; | ||
1500 | size -= orig_iov_len; | ||
1501 | |||
1502 | if (size) | ||
1503 | orig_iov_len = | ||
1504 | iov_record[++orig_iov_loc].iov_len; | ||
1505 | |||
1506 | pr_debug("rx_data: #4 new_rx_marker" | ||
1507 | " %u, size %u\n", *rx_marker, size); | ||
1508 | } | ||
1509 | } | ||
1510 | data += (rx_marker_iov * (MARKER_SIZE / 2)); | ||
1511 | |||
1512 | iov_p = &iov[0]; | ||
1513 | iov_len = iov_count; | ||
1514 | |||
1515 | if (iov_count > count->ss_iov_count) { | ||
1516 | pr_err("iov_count: %d, count->ss_iov_count:" | ||
1517 | " %d\n", iov_count, count->ss_iov_count); | ||
1518 | return -1; | ||
1519 | } | ||
1520 | if (rx_marker_iov > count->ss_marker_count) { | ||
1521 | pr_err("rx_marker_iov: %d, count->ss_marker" | ||
1522 | "_count: %d\n", rx_marker_iov, | ||
1523 | count->ss_marker_count); | ||
1524 | return -1; | ||
1525 | } | ||
1526 | } else { | ||
1527 | iov_p = count->iov; | ||
1528 | iov_len = count->iov_count; | ||
1529 | } | ||
1530 | 1410 | ||
1531 | while (total_rx < data) { | 1411 | while (total_rx < data) { |
1532 | rx_loop = kernel_recvmsg(conn->sock, &msg, iov_p, iov_len, | 1412 | rx_loop = kernel_recvmsg(conn->sock, &msg, iov_p, iov_len, |
@@ -1541,16 +1421,6 @@ static int iscsit_do_rx_data( | |||
1541 | rx_loop, total_rx, data); | 1421 | rx_loop, total_rx, data); |
1542 | } | 1422 | } |
1543 | 1423 | ||
1544 | if (count->sync_and_steering) { | ||
1545 | int j; | ||
1546 | for (j = 0; j < rx_marker_iov; j++) { | ||
1547 | pr_debug("rx_data: #5 j: %d, offset: %d\n", | ||
1548 | j, rx_marker_val[j]); | ||
1549 | conn->of_marker_offset = rx_marker_val[j]; | ||
1550 | } | ||
1551 | total_rx -= (rx_marker_iov * (MARKER_SIZE / 2)); | ||
1552 | } | ||
1553 | |||
1554 | return total_rx; | 1424 | return total_rx; |
1555 | } | 1425 | } |
1556 | 1426 | ||
@@ -1559,8 +1429,7 @@ static int iscsit_do_tx_data( | |||
1559 | struct iscsi_data_count *count) | 1429 | struct iscsi_data_count *count) |
1560 | { | 1430 | { |
1561 | int data = count->data_length, total_tx = 0, tx_loop = 0, iov_len; | 1431 | int data = count->data_length, total_tx = 0, tx_loop = 0, iov_len; |
1562 | u32 tx_marker_val[count->ss_marker_count], tx_marker_iov = 0; | 1432 | struct kvec *iov_p; |
1563 | struct kvec iov[count->ss_iov_count], *iov_p; | ||
1564 | struct msghdr msg; | 1433 | struct msghdr msg; |
1565 | 1434 | ||
1566 | if (!conn || !conn->sock || !conn->conn_ops) | 1435 | if (!conn || !conn->sock || !conn->conn_ops) |
@@ -1573,98 +1442,8 @@ static int iscsit_do_tx_data( | |||
1573 | 1442 | ||
1574 | memset(&msg, 0, sizeof(struct msghdr)); | 1443 | memset(&msg, 0, sizeof(struct msghdr)); |
1575 | 1444 | ||
1576 | if (count->sync_and_steering) { | 1445 | iov_p = count->iov; |
1577 | int size = 0; | 1446 | iov_len = count->iov_count; |
1578 | u32 i, orig_iov_count = 0; | ||
1579 | u32 orig_iov_len = 0, orig_iov_loc = 0; | ||
1580 | u32 iov_count = 0, per_iov_bytes = 0; | ||
1581 | u32 *tx_marker, old_tx_marker = 0; | ||
1582 | struct kvec *iov_record; | ||
1583 | |||
1584 | memset(&tx_marker_val, 0, | ||
1585 | count->ss_marker_count * sizeof(u32)); | ||
1586 | memset(&iov, 0, count->ss_iov_count * sizeof(struct kvec)); | ||
1587 | |||
1588 | iov_record = count->iov; | ||
1589 | orig_iov_count = count->iov_count; | ||
1590 | tx_marker = &conn->if_marker; | ||
1591 | |||
1592 | i = 0; | ||
1593 | size = data; | ||
1594 | orig_iov_len = iov_record[orig_iov_loc].iov_len; | ||
1595 | while (size > 0) { | ||
1596 | pr_debug("tx_data: #1 orig_iov_len %u," | ||
1597 | " orig_iov_loc %u\n", orig_iov_len, orig_iov_loc); | ||
1598 | pr_debug("tx_data: #2 tx_marker %u, size" | ||
1599 | " %u\n", *tx_marker, size); | ||
1600 | |||
1601 | if (orig_iov_len >= *tx_marker) { | ||
1602 | iov[iov_count].iov_len = *tx_marker; | ||
1603 | iov[iov_count++].iov_base = | ||
1604 | (iov_record[orig_iov_loc].iov_base + | ||
1605 | per_iov_bytes); | ||
1606 | |||
1607 | tx_marker_val[tx_marker_iov] = | ||
1608 | (size - *tx_marker); | ||
1609 | iov[iov_count].iov_len = (MARKER_SIZE / 2); | ||
1610 | iov[iov_count++].iov_base = | ||
1611 | &tx_marker_val[tx_marker_iov++]; | ||
1612 | iov[iov_count].iov_len = (MARKER_SIZE / 2); | ||
1613 | iov[iov_count++].iov_base = | ||
1614 | &tx_marker_val[tx_marker_iov++]; | ||
1615 | old_tx_marker = *tx_marker; | ||
1616 | |||
1617 | /* | ||
1618 | * IFMarkInt is in 32-bit words. | ||
1619 | */ | ||
1620 | *tx_marker = (conn->conn_ops->IFMarkInt * 4); | ||
1621 | size -= old_tx_marker; | ||
1622 | orig_iov_len -= old_tx_marker; | ||
1623 | per_iov_bytes += old_tx_marker; | ||
1624 | |||
1625 | pr_debug("tx_data: #3 new_tx_marker" | ||
1626 | " %u, size %u\n", *tx_marker, size); | ||
1627 | pr_debug("tx_data: #4 offset %u\n", | ||
1628 | tx_marker_val[tx_marker_iov-1]); | ||
1629 | } else { | ||
1630 | iov[iov_count].iov_len = orig_iov_len; | ||
1631 | iov[iov_count++].iov_base | ||
1632 | = (iov_record[orig_iov_loc].iov_base + | ||
1633 | per_iov_bytes); | ||
1634 | |||
1635 | per_iov_bytes = 0; | ||
1636 | *tx_marker -= orig_iov_len; | ||
1637 | size -= orig_iov_len; | ||
1638 | |||
1639 | if (size) | ||
1640 | orig_iov_len = | ||
1641 | iov_record[++orig_iov_loc].iov_len; | ||
1642 | |||
1643 | pr_debug("tx_data: #5 new_tx_marker" | ||
1644 | " %u, size %u\n", *tx_marker, size); | ||
1645 | } | ||
1646 | } | ||
1647 | |||
1648 | data += (tx_marker_iov * (MARKER_SIZE / 2)); | ||
1649 | |||
1650 | iov_p = &iov[0]; | ||
1651 | iov_len = iov_count; | ||
1652 | |||
1653 | if (iov_count > count->ss_iov_count) { | ||
1654 | pr_err("iov_count: %d, count->ss_iov_count:" | ||
1655 | " %d\n", iov_count, count->ss_iov_count); | ||
1656 | return -1; | ||
1657 | } | ||
1658 | if (tx_marker_iov > count->ss_marker_count) { | ||
1659 | pr_err("tx_marker_iov: %d, count->ss_marker" | ||
1660 | "_count: %d\n", tx_marker_iov, | ||
1661 | count->ss_marker_count); | ||
1662 | return -1; | ||
1663 | } | ||
1664 | } else { | ||
1665 | iov_p = count->iov; | ||
1666 | iov_len = count->iov_count; | ||
1667 | } | ||
1668 | 1447 | ||
1669 | while (total_tx < data) { | 1448 | while (total_tx < data) { |
1670 | tx_loop = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len, | 1449 | tx_loop = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len, |
@@ -1679,9 +1458,6 @@ static int iscsit_do_tx_data( | |||
1679 | tx_loop, total_tx, data); | 1458 | tx_loop, total_tx, data); |
1680 | } | 1459 | } |
1681 | 1460 | ||
1682 | if (count->sync_and_steering) | ||
1683 | total_tx -= (tx_marker_iov * (MARKER_SIZE / 2)); | ||
1684 | |||
1685 | return total_tx; | 1461 | return total_tx; |
1686 | } | 1462 | } |
1687 | 1463 | ||
@@ -1702,12 +1478,6 @@ int rx_data( | |||
1702 | c.data_length = data; | 1478 | c.data_length = data; |
1703 | c.type = ISCSI_RX_DATA; | 1479 | c.type = ISCSI_RX_DATA; |
1704 | 1480 | ||
1705 | if (conn->conn_ops->OFMarker && | ||
1706 | (conn->conn_state >= TARG_CONN_STATE_LOGGED_IN)) { | ||
1707 | if (iscsit_determine_sync_and_steering_counts(conn, &c) < 0) | ||
1708 | return -1; | ||
1709 | } | ||
1710 | |||
1711 | return iscsit_do_rx_data(conn, &c); | 1481 | return iscsit_do_rx_data(conn, &c); |
1712 | } | 1482 | } |
1713 | 1483 | ||
@@ -1728,12 +1498,6 @@ int tx_data( | |||
1728 | c.data_length = data; | 1498 | c.data_length = data; |
1729 | c.type = ISCSI_TX_DATA; | 1499 | c.type = ISCSI_TX_DATA; |
1730 | 1500 | ||
1731 | if (conn->conn_ops->IFMarker && | ||
1732 | (conn->conn_state >= TARG_CONN_STATE_LOGGED_IN)) { | ||
1733 | if (iscsit_determine_sync_and_steering_counts(conn, &c) < 0) | ||
1734 | return -1; | ||
1735 | } | ||
1736 | |||
1737 | return iscsit_do_tx_data(conn, &c); | 1501 | return iscsit_do_tx_data(conn, &c); |
1738 | } | 1502 | } |
1739 | 1503 | ||