aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2014-11-20 23:50:07 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2014-12-16 04:22:30 -0500
commit6bf6ca7515c1df06f5c03737537f5e0eb191e29e (patch)
tree05745df06630e6ba0d94724a70ee14db4f55416f /drivers/target
parenta0b3b9b2409b409c677f7eb1e0485b816a5848f7 (diff)
iscsi-target: Fail connection on short sendmsg writes
This patch changes iscsit_do_tx_data() to fail on short writes when kernel_sendmsg() returns a value different than requested transfer length, returning -EPIPE and thus causing a connection reset to occur. This avoids a potential bug in the original code where a short write would result in kernel_sendmsg() being called again with the original iovec base + length. In practice this has not been an issue because iscsit_do_tx_data() is only used for transferring 48 byte headers + 4 byte digests, along with seldom used control payloads from NOPIN + TEXT_RSP + REJECT with less than 32k of data. So following Al's audit of iovec consumers, go ahead and fail the connection on short writes for now, and remove the bogus logic ahead of his proper upstream fix. Reported-by: Al Viro <viro@zeniv.linux.org.uk> Cc: David S. Miller <davem@davemloft.net> Cc: <stable@vger.kernel.org> # v3.1+ Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c26
1 files changed, 11 insertions, 15 deletions
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index ce87ce9bdb9c..0b68c2ebce95 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -1358,15 +1358,15 @@ static int iscsit_do_tx_data(
1358 struct iscsi_conn *conn, 1358 struct iscsi_conn *conn,
1359 struct iscsi_data_count *count) 1359 struct iscsi_data_count *count)
1360{ 1360{
1361 int data = count->data_length, total_tx = 0, tx_loop = 0, iov_len; 1361 int ret, iov_len;
1362 struct kvec *iov_p; 1362 struct kvec *iov_p;
1363 struct msghdr msg; 1363 struct msghdr msg;
1364 1364
1365 if (!conn || !conn->sock || !conn->conn_ops) 1365 if (!conn || !conn->sock || !conn->conn_ops)
1366 return -1; 1366 return -1;
1367 1367
1368 if (data <= 0) { 1368 if (count->data_length <= 0) {
1369 pr_err("Data length is: %d\n", data); 1369 pr_err("Data length is: %d\n", count->data_length);
1370 return -1; 1370 return -1;
1371 } 1371 }
1372 1372
@@ -1375,20 +1375,16 @@ static int iscsit_do_tx_data(
1375 iov_p = count->iov; 1375 iov_p = count->iov;
1376 iov_len = count->iov_count; 1376 iov_len = count->iov_count;
1377 1377
1378 while (total_tx < data) { 1378 ret = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len,
1379 tx_loop = kernel_sendmsg(conn->sock, &msg, iov_p, iov_len, 1379 count->data_length);
1380 (data - total_tx)); 1380 if (ret != count->data_length) {
1381 if (tx_loop <= 0) { 1381 pr_err("Unexpected ret: %d send data %d\n",
1382 pr_debug("tx_loop: %d total_tx %d\n", 1382 ret, count->data_length);
1383 tx_loop, total_tx); 1383 return -EPIPE;
1384 return tx_loop;
1385 }
1386 total_tx += tx_loop;
1387 pr_debug("tx_loop: %d, total_tx: %d, data: %d\n",
1388 tx_loop, total_tx, data);
1389 } 1384 }
1385 pr_debug("ret: %d, sent data: %d\n", ret, count->data_length);
1390 1386
1391 return total_tx; 1387 return ret;
1392} 1388}
1393 1389
1394int rx_data( 1390int rx_data(