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 | |
| 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>
| -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 | ||
