diff options
author | Namjae Jeon <linkinjeon@kernel.org> | 2022-08-02 07:28:51 +0900 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2022-08-04 09:51:38 -0500 |
commit | 8f0541186e9ad1b62accc9519cc2b7a7240272a7 (patch) | |
tree | 8caec6f470b7d64be7883f31817dfb7e04a75e38 /fs/ksmbd/smb2pdu.c | |
parent | 824d4f64c20093275f72fc8101394d75ff6a249e (diff) | |
download | linux-8f0541186e9ad1b62accc9519cc2b7a7240272a7.tar.bz2 |
ksmbd: fix heap-based overflow in set_ntacl_dacl()
The testcase use SMB2_SET_INFO_HE command to set a malformed file attribute
under the label `security.NTACL`. SMB2_QUERY_INFO_HE command in testcase
trigger the following overflow.
[ 4712.003781] ==================================================================
[ 4712.003790] BUG: KASAN: slab-out-of-bounds in build_sec_desc+0x842/0x1dd0 [ksmbd]
[ 4712.003807] Write of size 1060 at addr ffff88801e34c068 by task kworker/0:0/4190
[ 4712.003813] CPU: 0 PID: 4190 Comm: kworker/0:0 Not tainted 5.19.0-rc5 #1
[ 4712.003850] Workqueue: ksmbd-io handle_ksmbd_work [ksmbd]
[ 4712.003867] Call Trace:
[ 4712.003870] <TASK>
[ 4712.003873] dump_stack_lvl+0x49/0x5f
[ 4712.003935] print_report.cold+0x5e/0x5cf
[ 4712.003972] ? ksmbd_vfs_get_sd_xattr+0x16d/0x500 [ksmbd]
[ 4712.003984] ? cmp_map_id+0x200/0x200
[ 4712.003988] ? build_sec_desc+0x842/0x1dd0 [ksmbd]
[ 4712.004000] kasan_report+0xaa/0x120
[ 4712.004045] ? build_sec_desc+0x842/0x1dd0 [ksmbd]
[ 4712.004056] kasan_check_range+0x100/0x1e0
[ 4712.004060] memcpy+0x3c/0x60
[ 4712.004064] build_sec_desc+0x842/0x1dd0 [ksmbd]
[ 4712.004076] ? parse_sec_desc+0x580/0x580 [ksmbd]
[ 4712.004088] ? ksmbd_acls_fattr+0x281/0x410 [ksmbd]
[ 4712.004099] smb2_query_info+0xa8f/0x6110 [ksmbd]
[ 4712.004111] ? psi_group_change+0x856/0xd70
[ 4712.004148] ? update_load_avg+0x1c3/0x1af0
[ 4712.004152] ? asym_cpu_capacity_scan+0x5d0/0x5d0
[ 4712.004157] ? xas_load+0x23/0x300
[ 4712.004162] ? smb2_query_dir+0x1530/0x1530 [ksmbd]
[ 4712.004173] ? _raw_spin_lock_bh+0xe0/0xe0
[ 4712.004179] handle_ksmbd_work+0x30e/0x1020 [ksmbd]
[ 4712.004192] process_one_work+0x778/0x11c0
[ 4712.004227] ? _raw_spin_lock_irq+0x8e/0xe0
[ 4712.004231] worker_thread+0x544/0x1180
[ 4712.004234] ? __cpuidle_text_end+0x4/0x4
[ 4712.004239] kthread+0x282/0x320
[ 4712.004243] ? process_one_work+0x11c0/0x11c0
[ 4712.004246] ? kthread_complete_and_exit+0x30/0x30
[ 4712.004282] ret_from_fork+0x1f/0x30
This patch add the buffer validation for security descriptor that is
stored by malformed SMB2_SET_INFO_HE command. and allocate large
response buffer about SMB2_O_INFO_SECURITY file info class.
Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
Cc: stable@vger.kernel.org
Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-17771
Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/ksmbd/smb2pdu.c')
-rw-r--r-- | fs/ksmbd/smb2pdu.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 5943cb17a9b0..9751cc92c111 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -535,9 +535,10 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work) struct smb2_query_info_req *req; req = smb2_get_msg(work->request_buf); - if (req->InfoType == SMB2_O_INFO_FILE && - (req->FileInfoClass == FILE_FULL_EA_INFORMATION || - req->FileInfoClass == FILE_ALL_INFORMATION)) + if ((req->InfoType == SMB2_O_INFO_FILE && + (req->FileInfoClass == FILE_FULL_EA_INFORMATION || + req->FileInfoClass == FILE_ALL_INFORMATION)) || + req->InfoType == SMB2_O_INFO_SECURITY) sz = large_sz; } @@ -2988,7 +2989,7 @@ int smb2_open(struct ksmbd_work *work) goto err_out; rc = build_sec_desc(user_ns, - pntsd, NULL, + pntsd, NULL, 0, OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO, @@ -3833,6 +3834,15 @@ static int verify_info_level(int info_level) return 0; } +static int smb2_resp_buf_len(struct ksmbd_work *work, unsigned short hdr2_len) +{ + int free_len; + + free_len = (int)(work->response_sz - + (get_rfc1002_len(work->response_buf) + 4)) - hdr2_len; + return free_len; +} + static int smb2_calc_max_out_buf_len(struct ksmbd_work *work, unsigned short hdr2_len, unsigned int out_buf_len) @@ -3842,9 +3852,7 @@ static int smb2_calc_max_out_buf_len(struct ksmbd_work *work, if (out_buf_len > work->conn->vals->max_trans_size) return -EINVAL; - free_len = (int)(work->response_sz - - (get_rfc1002_len(work->response_buf) + 4)) - - hdr2_len; + free_len = smb2_resp_buf_len(work, hdr2_len); if (free_len < 0) return -EINVAL; @@ -5107,10 +5115,10 @@ static int smb2_get_info_sec(struct ksmbd_work *work, struct smb_ntsd *pntsd = (struct smb_ntsd *)rsp->Buffer, *ppntsd = NULL; struct smb_fattr fattr = {{0}}; struct inode *inode; - __u32 secdesclen; + __u32 secdesclen = 0; unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID; int addition_info = le32_to_cpu(req->AdditionalInformation); - int rc; + int rc = 0, ppntsd_size = 0; if (addition_info & ~(OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO | PROTECTED_DACL_SECINFO | @@ -5156,11 +5164,14 @@ static int smb2_get_info_sec(struct ksmbd_work *work, if (test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_ACL_XATTR)) - ksmbd_vfs_get_sd_xattr(work->conn, user_ns, - fp->filp->f_path.dentry, &ppntsd); - - rc = build_sec_desc(user_ns, pntsd, ppntsd, addition_info, - &secdesclen, &fattr); + ppntsd_size = ksmbd_vfs_get_sd_xattr(work->conn, user_ns, + fp->filp->f_path.dentry, + &ppntsd); + + /* Check if sd buffer size exceeds response buffer size */ + if (smb2_resp_buf_len(work, 8) > ppntsd_size) + rc = build_sec_desc(user_ns, pntsd, ppntsd, ppntsd_size, + addition_info, &secdesclen, &fattr); posix_acl_release(fattr.cf_acls); posix_acl_release(fattr.cf_dacls); kfree(ppntsd); |