diff options
| -rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 2 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_auth.c | 14 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_login.c | 13 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_util.c | 2 | ||||
| -rw-r--r-- | drivers/target/loopback/tcm_loop.c | 1 | ||||
| -rw-r--r-- | drivers/target/target_core_device.c | 1 | ||||
| -rw-r--r-- | include/linux/socket.h | 4 | ||||
| -rw-r--r-- | include/linux/uio.h | 5 | ||||
| -rw-r--r-- | lib/iovec.c | 55 | ||||
| -rw-r--r-- | net/core/iovec.c | 55 |
10 files changed, 82 insertions, 70 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 5663f4d19d02..1f4c794f5fcc 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c | |||
| @@ -1309,7 +1309,7 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf, | |||
| 1309 | if (cmd->data_direction != DMA_TO_DEVICE) { | 1309 | if (cmd->data_direction != DMA_TO_DEVICE) { |
| 1310 | pr_err("Command ITT: 0x%08x received DataOUT for a" | 1310 | pr_err("Command ITT: 0x%08x received DataOUT for a" |
| 1311 | " NON-WRITE command.\n", cmd->init_task_tag); | 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 | se_cmd = &cmd->se_cmd; | 1314 | se_cmd = &cmd->se_cmd; |
| 1315 | iscsit_mod_dataout_timer(cmd); | 1315 | iscsit_mod_dataout_timer(cmd); |
diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c index 19b842c3e0b3..ab4915c0d933 100644 --- a/drivers/target/iscsi/iscsi_target_auth.c +++ b/drivers/target/iscsi/iscsi_target_auth.c | |||
| @@ -174,7 +174,6 @@ static int chap_server_compute_md5( | |||
| 174 | char *nr_out_ptr, | 174 | char *nr_out_ptr, |
| 175 | unsigned int *nr_out_len) | 175 | unsigned int *nr_out_len) |
| 176 | { | 176 | { |
| 177 | char *endptr; | ||
| 178 | unsigned long id; | 177 | unsigned long id; |
| 179 | unsigned char id_as_uchar; | 178 | unsigned char id_as_uchar; |
| 180 | unsigned char digest[MD5_SIGNATURE_SIZE]; | 179 | unsigned char digest[MD5_SIGNATURE_SIZE]; |
| @@ -320,9 +319,14 @@ static int chap_server_compute_md5( | |||
| 320 | } | 319 | } |
| 321 | 320 | ||
| 322 | if (type == HEX) | 321 | if (type == HEX) |
| 323 | id = simple_strtoul(&identifier[2], &endptr, 0); | 322 | ret = kstrtoul(&identifier[2], 0, &id); |
| 324 | else | 323 | else |
| 325 | id = simple_strtoul(identifier, &endptr, 0); | 324 | ret = kstrtoul(identifier, 0, &id); |
| 325 | |||
| 326 | if (ret < 0) { | ||
| 327 | pr_err("kstrtoul() failed for CHAP identifier: %d\n", ret); | ||
| 328 | goto out; | ||
| 329 | } | ||
| 326 | if (id > 255) { | 330 | if (id > 255) { |
| 327 | pr_err("chap identifier: %lu greater than 255\n", id); | 331 | pr_err("chap identifier: %lu greater than 255\n", id); |
| 328 | goto out; | 332 | goto out; |
| @@ -351,6 +355,10 @@ static int chap_server_compute_md5( | |||
| 351 | pr_err("Unable to convert incoming challenge\n"); | 355 | pr_err("Unable to convert incoming challenge\n"); |
| 352 | goto out; | 356 | goto out; |
| 353 | } | 357 | } |
| 358 | if (challenge_len > 1024) { | ||
| 359 | pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n"); | ||
| 360 | goto out; | ||
| 361 | } | ||
| 354 | /* | 362 | /* |
| 355 | * During mutual authentication, the CHAP_C generated by the | 363 | * During mutual authentication, the CHAP_C generated by the |
| 356 | * initiator must not match the original CHAP_C generated by | 364 | * initiator must not match the original CHAP_C generated by |
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index fecb69535a15..5e71ac609418 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c | |||
| @@ -1216,7 +1216,7 @@ old_sess_out: | |||
| 1216 | static int __iscsi_target_login_thread(struct iscsi_np *np) | 1216 | static int __iscsi_target_login_thread(struct iscsi_np *np) |
| 1217 | { | 1217 | { |
| 1218 | u8 *buffer, zero_tsih = 0; | 1218 | u8 *buffer, zero_tsih = 0; |
| 1219 | int ret = 0, rc, stop; | 1219 | int ret = 0, rc; |
| 1220 | struct iscsi_conn *conn = NULL; | 1220 | struct iscsi_conn *conn = NULL; |
| 1221 | struct iscsi_login *login; | 1221 | struct iscsi_login *login; |
| 1222 | struct iscsi_portal_group *tpg = NULL; | 1222 | struct iscsi_portal_group *tpg = NULL; |
| @@ -1230,6 +1230,9 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) | |||
| 1230 | if (np->np_thread_state == ISCSI_NP_THREAD_RESET) { | 1230 | if (np->np_thread_state == ISCSI_NP_THREAD_RESET) { |
| 1231 | np->np_thread_state = ISCSI_NP_THREAD_ACTIVE; | 1231 | np->np_thread_state = ISCSI_NP_THREAD_ACTIVE; |
| 1232 | complete(&np->np_restart_comp); | 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 | } else { | 1236 | } else { |
| 1234 | np->np_thread_state = ISCSI_NP_THREAD_ACTIVE; | 1237 | np->np_thread_state = ISCSI_NP_THREAD_ACTIVE; |
| 1235 | } | 1238 | } |
| @@ -1422,10 +1425,8 @@ old_sess_out: | |||
| 1422 | } | 1425 | } |
| 1423 | 1426 | ||
| 1424 | out: | 1427 | out: |
| 1425 | stop = kthread_should_stop(); | 1428 | return 1; |
| 1426 | /* Wait for another socket.. */ | 1429 | |
| 1427 | if (!stop) | ||
| 1428 | return 1; | ||
| 1429 | exit: | 1430 | exit: |
| 1430 | iscsi_stop_login_thread_timer(np); | 1431 | iscsi_stop_login_thread_timer(np); |
| 1431 | spin_lock_bh(&np->np_thread_lock); | 1432 | spin_lock_bh(&np->np_thread_lock); |
| @@ -1442,7 +1443,7 @@ int iscsi_target_login_thread(void *arg) | |||
| 1442 | 1443 | ||
| 1443 | allow_signal(SIGINT); | 1444 | allow_signal(SIGINT); |
| 1444 | 1445 | ||
| 1445 | while (!kthread_should_stop()) { | 1446 | while (1) { |
| 1446 | ret = __iscsi_target_login_thread(np); | 1447 | ret = __iscsi_target_login_thread(np); |
| 1447 | /* | 1448 | /* |
| 1448 | * We break and exit here unless another sock_accept() call | 1449 | * We break and exit here unless another sock_accept() call |
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 53e157cb8c54..fd90b28f1d94 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c | |||
| @@ -1295,6 +1295,8 @@ int iscsit_tx_login_rsp(struct iscsi_conn *conn, u8 status_class, u8 status_deta | |||
| 1295 | login->login_failed = 1; | 1295 | login->login_failed = 1; |
| 1296 | iscsit_collect_login_stats(conn, status_class, status_detail); | 1296 | iscsit_collect_login_stats(conn, status_class, status_detail); |
| 1297 | 1297 | ||
| 1298 | memset(&login->rsp[0], 0, ISCSI_HDR_LEN); | ||
| 1299 | |||
| 1298 | hdr = (struct iscsi_login_rsp *)&login->rsp[0]; | 1300 | hdr = (struct iscsi_login_rsp *)&login->rsp[0]; |
| 1299 | hdr->opcode = ISCSI_OP_LOGIN_RSP; | 1301 | hdr->opcode = ISCSI_OP_LOGIN_RSP; |
| 1300 | hdr->status_class = status_class; | 1302 | hdr->status_class = status_class; |
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index 6d2f37578b29..8c64b8776a96 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c | |||
| @@ -239,6 +239,7 @@ static void tcm_loop_submission_work(struct work_struct *work) | |||
| 239 | return; | 239 | return; |
| 240 | 240 | ||
| 241 | out_done: | 241 | out_done: |
| 242 | kmem_cache_free(tcm_loop_cmd_cache, tl_cmd); | ||
| 242 | sc->scsi_done(sc); | 243 | sc->scsi_done(sc); |
| 243 | return; | 244 | return; |
| 244 | } | 245 | } |
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 11d26fe65bfb..98da90167159 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c | |||
| @@ -616,6 +616,7 @@ void core_dev_unexport( | |||
| 616 | dev->export_count--; | 616 | dev->export_count--; |
| 617 | spin_unlock(&hba->device_lock); | 617 | spin_unlock(&hba->device_lock); |
| 618 | 618 | ||
| 619 | lun->lun_sep = NULL; | ||
| 619 | lun->lun_se_dev = NULL; | 620 | lun->lun_se_dev = NULL; |
| 620 | } | 621 | } |
| 621 | 622 | ||
diff --git a/include/linux/socket.h b/include/linux/socket.h index 8e98297f1388..ec538fc287a6 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h | |||
| @@ -305,8 +305,6 @@ struct ucred { | |||
| 305 | /* IPX options */ | 305 | /* IPX options */ |
| 306 | #define IPX_TYPE 1 | 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 | extern int csum_partial_copy_fromiovecend(unsigned char *kdata, | 308 | extern int csum_partial_copy_fromiovecend(unsigned char *kdata, |
| 311 | struct iovec *iov, | 309 | struct iovec *iov, |
| 312 | int offset, | 310 | int offset, |
| @@ -315,8 +313,6 @@ extern unsigned long iov_pages(const struct iovec *iov, int offset, | |||
| 315 | unsigned long nr_segs); | 313 | unsigned long nr_segs); |
| 316 | 314 | ||
| 317 | extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *address, int mode); | 315 | extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *address, int mode); |
| 318 | extern int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata, | ||
| 319 | int offset, int len); | ||
| 320 | extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr); | 316 | extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr); |
| 321 | extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data); | 317 | extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data); |
| 322 | 318 | ||
diff --git a/include/linux/uio.h b/include/linux/uio.h index d54985e0705e..09a7cffc224e 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h | |||
| @@ -123,6 +123,9 @@ static inline void iov_iter_reexpand(struct iov_iter *i, size_t count) | |||
| 123 | 123 | ||
| 124 | int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); | 124 | int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); |
| 125 | int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len); | 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 | #endif | 131 | #endif |
diff --git a/lib/iovec.c b/lib/iovec.c index 454baa88bf27..7a7c2da4cddf 100644 --- a/lib/iovec.c +++ b/lib/iovec.c | |||
| @@ -51,3 +51,58 @@ int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len) | |||
| 51 | return 0; | 51 | return 0; |
| 52 | } | 52 | } |
| 53 | EXPORT_SYMBOL(memcpy_toiovec); | 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); | ||
diff --git a/net/core/iovec.c b/net/core/iovec.c index b61869429f4c..827dd6beb49c 100644 --- a/net/core/iovec.c +++ b/net/core/iovec.c | |||
| @@ -75,61 +75,6 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a | |||
| 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 | * And now for the all-in-one: copy and checksum from a user iovec | 78 | * And now for the all-in-one: copy and checksum from a user iovec |
| 134 | * directly to a datagram | 79 | * directly to a datagram |
| 135 | * Calls to csum_partial but the last must be in 32 bit chunks | 80 | * Calls to csum_partial but the last must be in 32 bit chunks |
