Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+7 -243
+1 -1
drivers/target/iscsi/iscsi_target_parameters.c
··· 1430 1430 u8 DataSequenceInOrder = 0; 1431 1431 u8 ErrorRecoveryLevel = 0, SessionType = 0; 1432 1432 u8 IFMarker = 0, OFMarker = 0; 1433 - u8 IFMarkInt_Reject = 0, OFMarkInt_Reject = 0; 1433 + u8 IFMarkInt_Reject = 1, OFMarkInt_Reject = 1; 1434 1434 u32 FirstBurstLength = 0, MaxBurstLength = 0; 1435 1435 struct iscsi_param *param = NULL; 1436 1436
+6 -242
drivers/target/iscsi/iscsi_target_util.c
··· 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 878 * Setup conn->if_marker and conn->of_marker values based upon 913 879 * the initial marker-less interval. (see iSCSI v19 A.2) 914 880 */ ··· 1397 1431 struct iscsi_data_count *count) 1398 1432 { 1399 1433 int data = count->data_length, rx_loop = 0, total_rx = 0, iov_len; 1400 - u32 rx_marker_val[count->ss_marker_count], rx_marker_iov = 0; 1401 - struct kvec iov[count->ss_iov_count], *iov_p; 1434 + struct kvec *iov_p; 1402 1435 struct msghdr msg; 1403 1436 1404 1437 if (!conn || !conn->sock || !conn->conn_ops) ··· 1405 1440 1406 1441 memset(&msg, 0, sizeof(struct msghdr)); 1407 1442 1408 - if (count->sync_and_steering) { 1409 - int size = 0; 1410 - u32 i, orig_iov_count = 0; 1411 - u32 orig_iov_len = 0, orig_iov_loc = 0; 1412 - u32 iov_count = 0, per_iov_bytes = 0; 1413 - u32 *rx_marker, old_rx_marker = 0; 1414 - struct kvec *iov_record; 1415 - 1416 - memset(&rx_marker_val, 0, 1417 - count->ss_marker_count * sizeof(u32)); 1418 - memset(&iov, 0, count->ss_iov_count * sizeof(struct kvec)); 1419 - 1420 - iov_record = count->iov; 1421 - orig_iov_count = count->iov_count; 1422 - rx_marker = &conn->of_marker; 1423 - 1424 - i = 0; 1425 - size = data; 1426 - orig_iov_len = iov_record[orig_iov_loc].iov_len; 1427 - while (size > 0) { 1428 - pr_debug("rx_data: #1 orig_iov_len %u," 1429 - " orig_iov_loc %u\n", orig_iov_len, orig_iov_loc); 1430 - pr_debug("rx_data: #2 rx_marker %u, size" 1431 - " %u\n", *rx_marker, size); 1432 - 1433 - if (orig_iov_len >= *rx_marker) { 1434 - iov[iov_count].iov_len = *rx_marker; 1435 - iov[iov_count++].iov_base = 1436 - (iov_record[orig_iov_loc].iov_base + 1437 - per_iov_bytes); 1438 - 1439 - iov[iov_count].iov_len = (MARKER_SIZE / 2); 1440 - iov[iov_count++].iov_base = 1441 - &rx_marker_val[rx_marker_iov++]; 1442 - iov[iov_count].iov_len = (MARKER_SIZE / 2); 1443 - iov[iov_count++].iov_base = 1444 - &rx_marker_val[rx_marker_iov++]; 1445 - old_rx_marker = *rx_marker; 1446 - 1447 - /* 1448 - * OFMarkInt is in 32-bit words. 1449 - */ 1450 - *rx_marker = (conn->conn_ops->OFMarkInt * 4); 1451 - size -= old_rx_marker; 1452 - orig_iov_len -= old_rx_marker; 1453 - per_iov_bytes += old_rx_marker; 1454 - 1455 - pr_debug("rx_data: #3 new_rx_marker" 1456 - " %u, size %u\n", *rx_marker, size); 1457 - } else { 1458 - iov[iov_count].iov_len = orig_iov_len; 1459 - iov[iov_count++].iov_base = 1460 - (iov_record[orig_iov_loc].iov_base + 1461 - per_iov_bytes); 1462 - 1463 - per_iov_bytes = 0; 1464 - *rx_marker -= orig_iov_len; 1465 - size -= orig_iov_len; 1466 - 1467 - if (size) 1468 - orig_iov_len = 1469 - iov_record[++orig_iov_loc].iov_len; 1470 - 1471 - pr_debug("rx_data: #4 new_rx_marker" 1472 - " %u, size %u\n", *rx_marker, size); 1473 - } 1474 - } 1475 - data += (rx_marker_iov * (MARKER_SIZE / 2)); 1476 - 1477 - iov_p = &iov[0]; 1478 - iov_len = iov_count; 1479 - 1480 - if (iov_count > count->ss_iov_count) { 1481 - pr_err("iov_count: %d, count->ss_iov_count:" 1482 - " %d\n", iov_count, count->ss_iov_count); 1483 - return -1; 1484 - } 1485 - if (rx_marker_iov > count->ss_marker_count) { 1486 - pr_err("rx_marker_iov: %d, count->ss_marker" 1487 - "_count: %d\n", rx_marker_iov, 1488 - count->ss_marker_count); 1489 - return -1; 1490 - } 1491 - } else { 1492 - iov_p = count->iov; 1493 - iov_len = count->iov_count; 1494 - } 1443 + iov_p = count->iov; 1444 + iov_len = count->iov_count; 1495 1445 1496 1446 while (total_rx < data) { 1497 1447 rx_loop = kernel_recvmsg(conn->sock, &msg, iov_p, iov_len, ··· 1421 1541 rx_loop, total_rx, data); 1422 1542 } 1423 1543 1424 - if (count->sync_and_steering) { 1425 - int j; 1426 - for (j = 0; j < rx_marker_iov; j++) { 1427 - pr_debug("rx_data: #5 j: %d, offset: %d\n", 1428 - j, rx_marker_val[j]); 1429 - conn->of_marker_offset = rx_marker_val[j]; 1430 - } 1431 - total_rx -= (rx_marker_iov * (MARKER_SIZE / 2)); 1432 - } 1433 - 1434 1544 return total_rx; 1435 1545 } 1436 1546 ··· 1429 1559 struct iscsi_data_count *count) 1430 1560 { 1431 1561 int data = count->data_length, total_tx = 0, tx_loop = 0, iov_len; 1432 - u32 tx_marker_val[count->ss_marker_count], tx_marker_iov = 0; 1433 - struct kvec iov[count->ss_iov_count], *iov_p; 1562 + struct kvec *iov_p; 1434 1563 struct msghdr msg; 1435 1564 1436 1565 if (!conn || !conn->sock || !conn->conn_ops) ··· 1442 1573 1443 1574 memset(&msg, 0, sizeof(struct msghdr)); 1444 1575 1445 - if (count->sync_and_steering) { 1446 - int size = 0; 1447 - u32 i, orig_iov_count = 0; 1448 - u32 orig_iov_len = 0, orig_iov_loc = 0; 1449 - u32 iov_count = 0, per_iov_bytes = 0; 1450 - u32 *tx_marker, old_tx_marker = 0; 1451 - struct kvec *iov_record; 1452 - 1453 - memset(&tx_marker_val, 0, 1454 - count->ss_marker_count * sizeof(u32)); 1455 - memset(&iov, 0, count->ss_iov_count * sizeof(struct kvec)); 1456 - 1457 - iov_record = count->iov; 1458 - orig_iov_count = count->iov_count; 1459 - tx_marker = &conn->if_marker; 1460 - 1461 - i = 0; 1462 - size = data; 1463 - orig_iov_len = iov_record[orig_iov_loc].iov_len; 1464 - while (size > 0) { 1465 - pr_debug("tx_data: #1 orig_iov_len %u," 1466 - " orig_iov_loc %u\n", orig_iov_len, orig_iov_loc); 1467 - pr_debug("tx_data: #2 tx_marker %u, size" 1468 - " %u\n", *tx_marker, size); 1469 - 1470 - if (orig_iov_len >= *tx_marker) { 1471 - iov[iov_count].iov_len = *tx_marker; 1472 - iov[iov_count++].iov_base = 1473 - (iov_record[orig_iov_loc].iov_base + 1474 - per_iov_bytes); 1475 - 1476 - tx_marker_val[tx_marker_iov] = 1477 - (size - *tx_marker); 1478 - iov[iov_count].iov_len = (MARKER_SIZE / 2); 1479 - iov[iov_count++].iov_base = 1480 - &tx_marker_val[tx_marker_iov++]; 1481 - iov[iov_count].iov_len = (MARKER_SIZE / 2); 1482 - iov[iov_count++].iov_base = 1483 - &tx_marker_val[tx_marker_iov++]; 1484 - old_tx_marker = *tx_marker; 1485 - 1486 - /* 1487 - * IFMarkInt is in 32-bit words. 1488 - */ 1489 - *tx_marker = (conn->conn_ops->IFMarkInt * 4); 1490 - size -= old_tx_marker; 1491 - orig_iov_len -= old_tx_marker; 1492 - per_iov_bytes += old_tx_marker; 1493 - 1494 - pr_debug("tx_data: #3 new_tx_marker" 1495 - " %u, size %u\n", *tx_marker, size); 1496 - pr_debug("tx_data: #4 offset %u\n", 1497 - tx_marker_val[tx_marker_iov-1]); 1498 - } else { 1499 - iov[iov_count].iov_len = orig_iov_len; 1500 - iov[iov_count++].iov_base 1501 - = (iov_record[orig_iov_loc].iov_base + 1502 - per_iov_bytes); 1503 - 1504 - per_iov_bytes = 0; 1505 - *tx_marker -= orig_iov_len; 1506 - size -= orig_iov_len; 1507 - 1508 - if (size) 1509 - orig_iov_len = 1510 - iov_record[++orig_iov_loc].iov_len; 1511 - 1512 - pr_debug("tx_data: #5 new_tx_marker" 1513 - " %u, size %u\n", *tx_marker, size); 1514 - } 1515 - } 1516 - 1517 - data += (tx_marker_iov * (MARKER_SIZE / 2)); 1518 - 1519 - iov_p = &iov[0]; 1520 - iov_len = iov_count; 1521 - 1522 - if (iov_count > count->ss_iov_count) { 1523 - pr_err("iov_count: %d, count->ss_iov_count:" 1524 - " %d\n", iov_count, count->ss_iov_count); 1525 - return -1; 1526 - } 1527 - if (tx_marker_iov > count->ss_marker_count) { 1528 - pr_err("tx_marker_iov: %d, count->ss_marker" 1529 - "_count: %d\n", tx_marker_iov, 1530 - count->ss_marker_count); 1531 - return -1; 1532 - } 1533 - } else { 1534 - iov_p = count->iov; 1535 - iov_len = count->iov_count; 1536 - } 1576 + iov_p = count->iov; 1577 + iov_len = count->iov_count; 1537 1578 1538 1579 while (total_tx < data) { 1539 1580 tx_loop = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len, ··· 1457 1678 pr_debug("tx_loop: %d, total_tx: %d, data: %d\n", 1458 1679 tx_loop, total_tx, data); 1459 1680 } 1460 - 1461 - if (count->sync_and_steering) 1462 - total_tx -= (tx_marker_iov * (MARKER_SIZE / 2)); 1463 1681 1464 1682 return total_tx; 1465 1683 } ··· 1478 1702 c.data_length = data; 1479 1703 c.type = ISCSI_RX_DATA; 1480 1704 1481 - if (conn->conn_ops->OFMarker && 1482 - (conn->conn_state >= TARG_CONN_STATE_LOGGED_IN)) { 1483 - if (iscsit_determine_sync_and_steering_counts(conn, &c) < 0) 1484 - return -1; 1485 - } 1486 - 1487 1705 return iscsit_do_rx_data(conn, &c); 1488 1706 } 1489 1707 ··· 1497 1727 c.iov_count = iov_count; 1498 1728 c.data_length = data; 1499 1729 c.type = ISCSI_TX_DATA; 1500 - 1501 - if (conn->conn_ops->IFMarker && 1502 - (conn->conn_state >= TARG_CONN_STATE_LOGGED_IN)) { 1503 - if (iscsit_determine_sync_and_steering_counts(conn, &c) < 0) 1504 - return -1; 1505 - } 1506 1730 1507 1731 return iscsit_do_tx_data(conn, &c); 1508 1732 }