Skip to content

Commit 2c87d6a

Browse files
longlimsftsmfrench
authored andcommitted
cifs: Allocate memory for all iovs in smb2_ioctl
An IOCTL uses up to 2 iovs. The 1st iov is the command itself, the 2nd iov is optional data for that command. The 1st iov is always allocated on the heap but the 2nd iov may point to a variable on the stack. This will trigger an error when passing the 2nd iov for RDMA I/O. Fix this by allocating a buffer for the 2nd iov. Signed-off-by: Long Li <[email protected]> Signed-off-by: Steve French <[email protected]> Reviewed-by: Pavel Shilovsky <[email protected]> Reviewed-by: Ronnie sahlberg <[email protected]>
1 parent 3b24911 commit 2c87d6a

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

fs/cifs/smb2pdu.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2538,11 +2538,25 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst,
25382538
struct kvec *iov = rqst->rq_iov;
25392539
unsigned int total_len;
25402540
int rc;
2541+
char *in_data_buf;
25412542

25422543
rc = smb2_plain_req_init(SMB2_IOCTL, tcon, (void **) &req, &total_len);
25432544
if (rc)
25442545
return rc;
25452546

2547+
if (indatalen) {
2548+
/*
2549+
* indatalen is usually small at a couple of bytes max, so
2550+
* just allocate through generic pool
2551+
*/
2552+
in_data_buf = kmalloc(indatalen, GFP_NOFS);
2553+
if (!in_data_buf) {
2554+
cifs_small_buf_release(req);
2555+
return -ENOMEM;
2556+
}
2557+
memcpy(in_data_buf, in_data, indatalen);
2558+
}
2559+
25462560
req->CtlCode = cpu_to_le32(opcode);
25472561
req->PersistentFileId = persistent_fid;
25482562
req->VolatileFileId = volatile_fid;
@@ -2563,7 +2577,7 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst,
25632577
cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer));
25642578
rqst->rq_nvec = 2;
25652579
iov[0].iov_len = total_len - 1;
2566-
iov[1].iov_base = in_data;
2580+
iov[1].iov_base = in_data_buf;
25672581
iov[1].iov_len = indatalen;
25682582
} else {
25692583
rqst->rq_nvec = 1;
@@ -2605,8 +2619,11 @@ SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst,
26052619
void
26062620
SMB2_ioctl_free(struct smb_rqst *rqst)
26072621
{
2608-
if (rqst && rqst->rq_iov)
2622+
if (rqst && rqst->rq_iov) {
26092623
cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
2624+
if (rqst->rq_iov[1].iov_len)
2625+
kfree(rqst->rq_iov[1].iov_base);
2626+
}
26102627
}
26112628

26122629

0 commit comments

Comments
 (0)