Skip to content

Commit bef4315

Browse files
Paulo Alcantaragregkh
authored andcommitted
smb: client: fix OOB in SMB2_query_info_init()
commit 33eae65 upstream. A small CIFS buffer (448 bytes) isn't big enough to hold SMB2_QUERY_INFO request along with user's input data from CIFS_QUERY_INFO ioctl. That is, if the user passed an input buffer > 344 bytes, the client will memcpy() off the end of @req->Buffer in SMB2_query_info_init() thus causing the following KASAN splat: BUG: KASAN: slab-out-of-bounds in SMB2_query_info_init+0x242/0x250 [cifs] Write of size 1023 at addr ffff88801308c5a8 by task a.out/1240 CPU: 1 PID: 1240 Comm: a.out Not tainted 6.7.0-rc4 #5 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.2-3-gd478f380-rebuilt.opensuse.org 04/01/2014 Call Trace: <TASK> dump_stack_lvl+0x4a/0x80 print_report+0xcf/0x650 ? srso_alias_return_thunk+0x5/0xfbef5 ? srso_alias_return_thunk+0x5/0xfbef5 ? srso_alias_return_thunk+0x5/0xfbef5 ? __phys_addr+0x46/0x90 kasan_report+0xd8/0x110 ? SMB2_query_info_init+0x242/0x250 [cifs] ? SMB2_query_info_init+0x242/0x250 [cifs] kasan_check_range+0x105/0x1b0 __asan_memcpy+0x3c/0x60 SMB2_query_info_init+0x242/0x250 [cifs] ? __pfx_SMB2_query_info_init+0x10/0x10 [cifs] ? srso_alias_return_thunk+0x5/0xfbef5 ? smb_rqst_len+0xa6/0xc0 [cifs] smb2_ioctl_query_info+0x4f4/0x9a0 [cifs] ? __pfx_smb2_ioctl_query_info+0x10/0x10 [cifs] ? __pfx_cifsConvertToUTF16+0x10/0x10 [cifs] ? kasan_set_track+0x25/0x30 ? srso_alias_return_thunk+0x5/0xfbef5 ? __kasan_kmalloc+0x8f/0xa0 ? srso_alias_return_thunk+0x5/0xfbef5 ? cifs_strndup_to_utf16+0x12d/0x1a0 [cifs] ? __build_path_from_dentry_optional_prefix+0x19d/0x2d0 [cifs] ? __pfx_smb2_ioctl_query_info+0x10/0x10 [cifs] cifs_ioctl+0x11c7/0x1de0 [cifs] ? __pfx_cifs_ioctl+0x10/0x10 [cifs] ? srso_alias_return_thunk+0x5/0xfbef5 ? rcu_is_watching+0x23/0x50 ? srso_alias_return_thunk+0x5/0xfbef5 ? __rseq_handle_notify_resume+0x6cd/0x850 ? __pfx___schedule+0x10/0x10 ? blkcg_iostat_update+0x250/0x290 ? srso_alias_return_thunk+0x5/0xfbef5 ? ksys_write+0xe9/0x170 __x64_sys_ioctl+0xc9/0x100 do_syscall_64+0x47/0xf0 entry_SYSCALL_64_after_hwframe+0x6f/0x77 RIP: 0033:0x7f893dde49cf Code: 00 48 89 44 24 18 31 c0 48 8d 44 24 60 c7 04 24 10 00 00 00 48 89 44 24 08 48 8d 44 24 20 48 89 44 24 10 b8 10 00 00 00 0f 05 <89> c2 3d 00 f0 ff ff 77 18 48 8b 44 24 18 64 48 2b 04 25 28 00 00 RSP: 002b:00007ffc03ff4160 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 00007ffc03ff4378 RCX: 00007f893dde49cf RDX: 00007ffc03ff41d0 RSI: 00000000c018cf07 RDI: 0000000000000003 RBP: 00007ffc03ff4260 R08: 0000000000000410 R09: 0000000000000001 R10: 00007f893dce7300 R11: 0000000000000246 R12: 0000000000000000 R13: 00007ffc03ff4388 R14: 00007f893df15000 R15: 0000000000406de0 </TASK> Fix this by increasing size of SMB2_QUERY_INFO request buffers and validating input length to prevent other callers from overflowing @Req in SMB2_query_info_init() as well. Fixes: f5b05d6 ("cifs: add IOCTL for QUERY_INFO passthrough to userspace") Cc: [email protected] Reported-by: Robert Morris <[email protected]> Signed-off-by: Paulo Alcantara <[email protected]> Signed-off-by: Steve French <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 71fe685 commit bef4315

File tree

1 file changed

+22
-7
lines changed

1 file changed

+22
-7
lines changed

fs/smb/client/smb2pdu.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -372,10 +372,15 @@ static int __smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon,
372372
void **request_buf, unsigned int *total_len)
373373
{
374374
/* BB eventually switch this to SMB2 specific small buf size */
375-
if (smb2_command == SMB2_SET_INFO)
375+
switch (smb2_command) {
376+
case SMB2_SET_INFO:
377+
case SMB2_QUERY_INFO:
376378
*request_buf = cifs_buf_get();
377-
else
379+
break;
380+
default:
378381
*request_buf = cifs_small_buf_get();
382+
break;
383+
}
379384
if (*request_buf == NULL) {
380385
/* BB should we add a retry in here if not a writepage? */
381386
return -ENOMEM;
@@ -3523,8 +3528,13 @@ SMB2_query_info_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
35233528
struct smb2_query_info_req *req;
35243529
struct kvec *iov = rqst->rq_iov;
35253530
unsigned int total_len;
3531+
size_t len;
35263532
int rc;
35273533

3534+
if (unlikely(check_add_overflow(input_len, sizeof(*req), &len) ||
3535+
len > CIFSMaxBufSize))
3536+
return -EINVAL;
3537+
35283538
rc = smb2_plain_req_init(SMB2_QUERY_INFO, tcon, server,
35293539
(void **) &req, &total_len);
35303540
if (rc)
@@ -3546,15 +3556,15 @@ SMB2_query_info_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
35463556

35473557
iov[0].iov_base = (char *)req;
35483558
/* 1 for Buffer */
3549-
iov[0].iov_len = total_len - 1 + input_len;
3559+
iov[0].iov_len = len;
35503560
return 0;
35513561
}
35523562

35533563
void
35543564
SMB2_query_info_free(struct smb_rqst *rqst)
35553565
{
35563566
if (rqst && rqst->rq_iov)
3557-
cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
3567+
cifs_buf_release(rqst->rq_iov[0].iov_base); /* request */
35583568
}
35593569

35603570
static int
@@ -5439,6 +5449,11 @@ build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon,
54395449
return 0;
54405450
}
54415451

5452+
static inline void free_qfs_info_req(struct kvec *iov)
5453+
{
5454+
cifs_buf_release(iov->iov_base);
5455+
}
5456+
54425457
int
54435458
SMB311_posix_qfs_info(const unsigned int xid, struct cifs_tcon *tcon,
54445459
u64 persistent_fid, u64 volatile_fid, struct kstatfs *fsdata)
@@ -5470,7 +5485,7 @@ SMB311_posix_qfs_info(const unsigned int xid, struct cifs_tcon *tcon,
54705485

54715486
rc = cifs_send_recv(xid, ses, server,
54725487
&rqst, &resp_buftype, flags, &rsp_iov);
5473-
cifs_small_buf_release(iov.iov_base);
5488+
free_qfs_info_req(&iov);
54745489
if (rc) {
54755490
cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
54765491
goto posix_qfsinf_exit;
@@ -5521,7 +5536,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
55215536

55225537
rc = cifs_send_recv(xid, ses, server,
55235538
&rqst, &resp_buftype, flags, &rsp_iov);
5524-
cifs_small_buf_release(iov.iov_base);
5539+
free_qfs_info_req(&iov);
55255540
if (rc) {
55265541
cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
55275542
goto qfsinf_exit;
@@ -5588,7 +5603,7 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
55885603

55895604
rc = cifs_send_recv(xid, ses, server,
55905605
&rqst, &resp_buftype, flags, &rsp_iov);
5591-
cifs_small_buf_release(iov.iov_base);
5606+
free_qfs_info_req(&iov);
55925607
if (rc) {
55935608
cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
55945609
goto qfsattr_exit;

0 commit comments

Comments
 (0)