Skip to content

Commit eb477e0

Browse files
committed
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
2 parents 3e7b256 + 81a9c5e commit eb477e0

File tree

10 files changed

+82
-70
lines changed

10 files changed

+82
-70
lines changed

drivers/target/iscsi/iscsi_target.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1309,7 +1309,7 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
13091309
if (cmd->data_direction != DMA_TO_DEVICE) {
13101310
pr_err("Command ITT: 0x%08x received DataOUT for a"
13111311
" 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);
13131313
}
13141314
se_cmd = &cmd->se_cmd;
13151315
iscsit_mod_dataout_timer(cmd);

drivers/target/iscsi/iscsi_target_auth.c

+11-3
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,6 @@ static int chap_server_compute_md5(
174174
char *nr_out_ptr,
175175
unsigned int *nr_out_len)
176176
{
177-
char *endptr;
178177
unsigned long id;
179178
unsigned char id_as_uchar;
180179
unsigned char digest[MD5_SIGNATURE_SIZE];
@@ -320,9 +319,14 @@ static int chap_server_compute_md5(
320319
}
321320

322321
if (type == HEX)
323-
id = simple_strtoul(&identifier[2], &endptr, 0);
322+
ret = kstrtoul(&identifier[2], 0, &id);
324323
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+
}
326330
if (id > 255) {
327331
pr_err("chap identifier: %lu greater than 255\n", id);
328332
goto out;
@@ -351,6 +355,10 @@ static int chap_server_compute_md5(
351355
pr_err("Unable to convert incoming challenge\n");
352356
goto out;
353357
}
358+
if (challenge_len > 1024) {
359+
pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n");
360+
goto out;
361+
}
354362
/*
355363
* During mutual authentication, the CHAP_C generated by the
356364
* initiator must not match the original CHAP_C generated by

drivers/target/iscsi/iscsi_target_login.c

+7-6
Original file line numberDiff line numberDiff line change
@@ -1216,7 +1216,7 @@ void iscsi_target_login_sess_out(struct iscsi_conn *conn,
12161216
static int __iscsi_target_login_thread(struct iscsi_np *np)
12171217
{
12181218
u8 *buffer, zero_tsih = 0;
1219-
int ret = 0, rc, stop;
1219+
int ret = 0, rc;
12201220
struct iscsi_conn *conn = NULL;
12211221
struct iscsi_login *login;
12221222
struct iscsi_portal_group *tpg = NULL;
@@ -1230,6 +1230,9 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
12301230
if (np->np_thread_state == ISCSI_NP_THREAD_RESET) {
12311231
np->np_thread_state = ISCSI_NP_THREAD_ACTIVE;
12321232
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;
12331236
} else {
12341237
np->np_thread_state = ISCSI_NP_THREAD_ACTIVE;
12351238
}
@@ -1422,10 +1425,8 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
14221425
}
14231426

14241427
out:
1425-
stop = kthread_should_stop();
1426-
/* Wait for another socket.. */
1427-
if (!stop)
1428-
return 1;
1428+
return 1;
1429+
14291430
exit:
14301431
iscsi_stop_login_thread_timer(np);
14311432
spin_lock_bh(&np->np_thread_lock);
@@ -1442,7 +1443,7 @@ int iscsi_target_login_thread(void *arg)
14421443

14431444
allow_signal(SIGINT);
14441445

1445-
while (!kthread_should_stop()) {
1446+
while (1) {
14461447
ret = __iscsi_target_login_thread(np);
14471448
/*
14481449
* We break and exit here unless another sock_accept() call

drivers/target/iscsi/iscsi_target_util.c

+2
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,8 @@ int iscsit_tx_login_rsp(struct iscsi_conn *conn, u8 status_class, u8 status_deta
12951295
login->login_failed = 1;
12961296
iscsit_collect_login_stats(conn, status_class, status_detail);
12971297

1298+
memset(&login->rsp[0], 0, ISCSI_HDR_LEN);
1299+
12981300
hdr = (struct iscsi_login_rsp *)&login->rsp[0];
12991301
hdr->opcode = ISCSI_OP_LOGIN_RSP;
13001302
hdr->status_class = status_class;

drivers/target/loopback/tcm_loop.c

+1
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ static void tcm_loop_submission_work(struct work_struct *work)
239239
return;
240240

241241
out_done:
242+
kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
242243
sc->scsi_done(sc);
243244
return;
244245
}

drivers/target/target_core_device.c

+1
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,7 @@ void core_dev_unexport(
616616
dev->export_count--;
617617
spin_unlock(&hba->device_lock);
618618

619+
lun->lun_sep = NULL;
619620
lun->lun_se_dev = NULL;
620621
}
621622

include/linux/socket.h

-4
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,6 @@ struct ucred {
305305
/* IPX options */
306306
#define IPX_TYPE 1
307307

308-
extern int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov,
309-
int offset, int len);
310308
extern int csum_partial_copy_fromiovecend(unsigned char *kdata,
311309
struct iovec *iov,
312310
int offset,
@@ -315,8 +313,6 @@ extern unsigned long iov_pages(const struct iovec *iov, int offset,
315313
unsigned long nr_segs);
316314

317315
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);
320316
extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr);
321317
extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
322318

include/linux/uio.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ static inline void iov_iter_reexpand(struct iov_iter *i, size_t count)
123123

124124
int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
125125
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);
127130

128131
#endif

lib/iovec.c

+55
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,58 @@ int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
5151
return 0;
5252
}
5353
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);

net/core/iovec.c

-55
Original file line numberDiff line numberDiff line change
@@ -74,61 +74,6 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a
7474
return err;
7575
}
7676

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-
13277
/*
13378
* And now for the all-in-one: copy and checksum from a user iovec
13479
* directly to a datagram

0 commit comments

Comments
 (0)