Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending

Pull SCSI target fixes from Nicholas Bellinger:
"Mostly minor fixes this time around. The highlights include:

- iscsi-target CHAP authentication fixes to enforce explicit key
values (Tejas Vaykole + rahul.rane)
- fix a long-standing OOPs in target-core when a alua configfs
attribute is accessed after port symlink has been removed.
(Sebastian Herbszt)
- fix a v3.10.y iscsi-target regression causing the login reject
status class/detail to be ignored (Christoph Vu-Brugier)
- fix a v3.10.y iscsi-target regression to avoid rejecting an
existing ITT during Data-Out when data-direction is wrong (Santosh
Kulkarni + Arshad Hussain)
- fix a iscsi-target related shutdown deadlock on UP kernels (Mikulas
Patocka)
- fix a v3.16-rc1 build issue with vhost-scsi + !CONFIG_NET (MST)"

* git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
iscsi-target: fix iscsit_del_np deadlock on unload
iovec: move memcpy_from/toiovecend to lib/iovec.c
iscsi-target: Avoid rejecting incorrect ITT for Data-Out
tcm_loop: Fix memory leak in tcm_loop_submission_work error path
iscsi-target: Explicily clear login response PDU in exception path
target: Fix left-over se_lun->lun_sep pointer OOPs
iscsi-target; Enforce 1024 byte maximum for CHAP_C key value
iscsi-target: Convert chap_server_compute_md5 to use kstrtoul

+1 -1
drivers/target/iscsi/iscsi_target.c
··· 1309 1309 if (cmd->data_direction != DMA_TO_DEVICE) { 1310 1310 pr_err("Command ITT: 0x%08x received DataOUT for a" 1311 1311 " NON-WRITE command.\n", cmd->init_task_tag); 1312 - return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf); 1312 + return iscsit_dump_data_payload(conn, payload_length, 1); 1313 1313 } 1314 1314 se_cmd = &cmd->se_cmd; 1315 1315 iscsit_mod_dataout_timer(cmd);
+11 -3
drivers/target/iscsi/iscsi_target_auth.c
··· 174 174 char *nr_out_ptr, 175 175 unsigned int *nr_out_len) 176 176 { 177 - char *endptr; 178 177 unsigned long id; 179 178 unsigned char id_as_uchar; 180 179 unsigned char digest[MD5_SIGNATURE_SIZE]; ··· 319 320 } 320 321 321 322 if (type == HEX) 322 - id = simple_strtoul(&identifier[2], &endptr, 0); 323 + ret = kstrtoul(&identifier[2], 0, &id); 323 324 else 324 - id = simple_strtoul(identifier, &endptr, 0); 325 + ret = kstrtoul(identifier, 0, &id); 326 + 327 + if (ret < 0) { 328 + pr_err("kstrtoul() failed for CHAP identifier: %d\n", ret); 329 + goto out; 330 + } 325 331 if (id > 255) { 326 332 pr_err("chap identifier: %lu greater than 255\n", id); 327 333 goto out; ··· 353 349 strlen(challenge)); 354 350 if (!challenge_len) { 355 351 pr_err("Unable to convert incoming challenge\n"); 352 + goto out; 353 + } 354 + if (challenge_len > 1024) { 355 + pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n"); 356 356 goto out; 357 357 } 358 358 /*
+7 -6
drivers/target/iscsi/iscsi_target_login.c
··· 1216 1216 static int __iscsi_target_login_thread(struct iscsi_np *np) 1217 1217 { 1218 1218 u8 *buffer, zero_tsih = 0; 1219 - int ret = 0, rc, stop; 1219 + int ret = 0, rc; 1220 1220 struct iscsi_conn *conn = NULL; 1221 1221 struct iscsi_login *login; 1222 1222 struct iscsi_portal_group *tpg = NULL; ··· 1230 1230 if (np->np_thread_state == ISCSI_NP_THREAD_RESET) { 1231 1231 np->np_thread_state = ISCSI_NP_THREAD_ACTIVE; 1232 1232 complete(&np->np_restart_comp); 1233 + } else if (np->np_thread_state == ISCSI_NP_THREAD_SHUTDOWN) { 1234 + spin_unlock_bh(&np->np_thread_lock); 1235 + goto exit; 1233 1236 } else { 1234 1237 np->np_thread_state = ISCSI_NP_THREAD_ACTIVE; 1235 1238 } ··· 1425 1422 } 1426 1423 1427 1424 out: 1428 - stop = kthread_should_stop(); 1429 - /* Wait for another socket.. */ 1430 - if (!stop) 1431 - return 1; 1425 + return 1; 1426 + 1432 1427 exit: 1433 1428 iscsi_stop_login_thread_timer(np); 1434 1429 spin_lock_bh(&np->np_thread_lock); ··· 1443 1442 1444 1443 allow_signal(SIGINT); 1445 1444 1446 - while (!kthread_should_stop()) { 1445 + while (1) { 1447 1446 ret = __iscsi_target_login_thread(np); 1448 1447 /* 1449 1448 * We break and exit here unless another sock_accept() call
+2
drivers/target/iscsi/iscsi_target_util.c
··· 1295 1295 login->login_failed = 1; 1296 1296 iscsit_collect_login_stats(conn, status_class, status_detail); 1297 1297 1298 + memset(&login->rsp[0], 0, ISCSI_HDR_LEN); 1299 + 1298 1300 hdr = (struct iscsi_login_rsp *)&login->rsp[0]; 1299 1301 hdr->opcode = ISCSI_OP_LOGIN_RSP; 1300 1302 hdr->status_class = status_class;
+1
drivers/target/loopback/tcm_loop.c
··· 239 239 return; 240 240 241 241 out_done: 242 + kmem_cache_free(tcm_loop_cmd_cache, tl_cmd); 242 243 sc->scsi_done(sc); 243 244 return; 244 245 }
+1
drivers/target/target_core_device.c
··· 616 616 dev->export_count--; 617 617 spin_unlock(&hba->device_lock); 618 618 619 + lun->lun_sep = NULL; 619 620 lun->lun_se_dev = NULL; 620 621 } 621 622
-4
include/linux/socket.h
··· 305 305 /* IPX options */ 306 306 #define IPX_TYPE 1 307 307 308 - extern int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, 309 - int offset, int len); 310 308 extern int csum_partial_copy_fromiovecend(unsigned char *kdata, 311 309 struct iovec *iov, 312 310 int offset, ··· 313 315 unsigned long nr_segs); 314 316 315 317 extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *address, int mode); 316 - extern int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata, 317 - int offset, int len); 318 318 extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr); 319 319 extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data); 320 320
+4 -1
include/linux/uio.h
··· 123 123 124 124 int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); 125 125 int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len); 126 - 126 + int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, 127 + int offset, int len); 128 + int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata, 129 + int offset, int len); 127 130 128 131 #endif
+55
lib/iovec.c
··· 51 51 return 0; 52 52 } 53 53 EXPORT_SYMBOL(memcpy_toiovec); 54 + 55 + /* 56 + * Copy kernel to iovec. Returns -EFAULT on error. 57 + */ 58 + 59 + int memcpy_toiovecend(const struct iovec *iov, unsigned char *kdata, 60 + int offset, int len) 61 + { 62 + int copy; 63 + for (; len > 0; ++iov) { 64 + /* Skip over the finished iovecs */ 65 + if (unlikely(offset >= iov->iov_len)) { 66 + offset -= iov->iov_len; 67 + continue; 68 + } 69 + copy = min_t(unsigned int, iov->iov_len - offset, len); 70 + if (copy_to_user(iov->iov_base + offset, kdata, copy)) 71 + return -EFAULT; 72 + offset = 0; 73 + kdata += copy; 74 + len -= copy; 75 + } 76 + 77 + return 0; 78 + } 79 + EXPORT_SYMBOL(memcpy_toiovecend); 80 + 81 + /* 82 + * Copy iovec to kernel. Returns -EFAULT on error. 83 + */ 84 + 85 + int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, 86 + int offset, int len) 87 + { 88 + /* Skip over the finished iovecs */ 89 + while (offset >= iov->iov_len) { 90 + offset -= iov->iov_len; 91 + iov++; 92 + } 93 + 94 + while (len > 0) { 95 + u8 __user *base = iov->iov_base + offset; 96 + int copy = min_t(unsigned int, len, iov->iov_len - offset); 97 + 98 + offset = 0; 99 + if (copy_from_user(kdata, base, copy)) 100 + return -EFAULT; 101 + len -= copy; 102 + kdata += copy; 103 + iov++; 104 + } 105 + 106 + return 0; 107 + } 108 + EXPORT_SYMBOL(memcpy_fromiovecend);
-55
net/core/iovec.c
··· 75 75 } 76 76 77 77 /* 78 - * Copy kernel to iovec. Returns -EFAULT on error. 79 - */ 80 - 81 - int memcpy_toiovecend(const struct iovec *iov, unsigned char *kdata, 82 - int offset, int len) 83 - { 84 - int copy; 85 - for (; len > 0; ++iov) { 86 - /* Skip over the finished iovecs */ 87 - if (unlikely(offset >= iov->iov_len)) { 88 - offset -= iov->iov_len; 89 - continue; 90 - } 91 - copy = min_t(unsigned int, iov->iov_len - offset, len); 92 - if (copy_to_user(iov->iov_base + offset, kdata, copy)) 93 - return -EFAULT; 94 - offset = 0; 95 - kdata += copy; 96 - len -= copy; 97 - } 98 - 99 - return 0; 100 - } 101 - EXPORT_SYMBOL(memcpy_toiovecend); 102 - 103 - /* 104 - * Copy iovec to kernel. Returns -EFAULT on error. 105 - */ 106 - 107 - int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, 108 - int offset, int len) 109 - { 110 - /* Skip over the finished iovecs */ 111 - while (offset >= iov->iov_len) { 112 - offset -= iov->iov_len; 113 - iov++; 114 - } 115 - 116 - while (len > 0) { 117 - u8 __user *base = iov->iov_base + offset; 118 - int copy = min_t(unsigned int, len, iov->iov_len - offset); 119 - 120 - offset = 0; 121 - if (copy_from_user(kdata, base, copy)) 122 - return -EFAULT; 123 - len -= copy; 124 - kdata += copy; 125 - iov++; 126 - } 127 - 128 - return 0; 129 - } 130 - EXPORT_SYMBOL(memcpy_fromiovecend); 131 - 132 - /* 133 78 * And now for the all-in-one: copy and checksum from a user iovec 134 79 * directly to a datagram 135 80 * Calls to csum_partial but the last must be in 32 bit chunks