FAILED: patch "[PATCH] ksmbd: fix heap-based overflow in set_ntacl_dacl()" failed to apply to 5.15-stable tree
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 8f0541186e9ad1b62accc9519cc2b7a7240272a7 Mon Sep 17 00:00:00 2001
From: Namjae Jeon <[email protected]>
Date: Tue, 2 Aug 2022 07:28:51 +0900
Subject: [PATCH] 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.
fs/ksmbd/smb2pdu.c +25 -14
@@ -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);
fs/ksmbd/smbacl.c +88 -42
238 lines not on this page · raw message
fs/ksmbd/smbacl.h +1 -1
@@ -193,7 +193,7 @@ struct posix_acl_state {int parse_sec_desc (struct user_namespace *user_ns,struct smb_ntsd *pntsd,int acl_len,struct smb_fattr *fattr);int build_sec_desc (struct user_namespace *user_ns,struct smb_ntsd *pntsd, -struct smb_ntsd *ppntsd,int addition_info, +struct smb_ntsd *ppntsd,int ppntsd_size,int addition_info,__u32 *secdesclen,struct smb_fattr *fattr);int init_acl_state (struct posix_acl_state *state,int cnt);void free_acl_state (struct posix_acl_state *state);
fs/ksmbd/vfs.c +5 -0
@@ -1539,6 +1539,11 @@ int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, } *pntsd = acl.sd_buf; +if (acl.sd_size <sizeof (struct smb_ntsd )) { +pr_err ("sd size is invalid\n" ); + goto out_free; + } + (*pntsd)->osidoffset =cpu_to_le32 (le32_to_cpu ((*pntsd)->osidoffset) -NDR_NTSD_OFFSETOF ); (*pntsd)->gsidoffset = cpu_to_le32(le32_to_cpu((*pntsd)->gsidoffset) -