blob: 5e70b468a129cceac34781028a452972ec07029e [file] [log] [blame]
developer87287e92023-01-17 17:45:00 +08001diff -Naur a/feeds/packages/kernel/ksmbd/patches/03-multiple_vulnerabilities_fix.patch b/feeds/packages/kernel/ksmbd/patches/03-multiple_vulnerabilities_fix.patch
2--- a/feeds/packages/kernel/ksmbd/patches/03-multiple_vulnerabilities_fix.patch 1970-01-01 08:00:00.000000000 +0800
3+++ b/feeds/packages/kernel/ksmbd/patches/03-multiple_vulnerabilities_fix.patch 2023-01-17 17:31:25.943136641 +0800
4@@ -0,0 +1,430 @@
5+diff -Naur a/smb2misc.c b/smb2misc.c
6+--- a/smb2misc.c 2023-01-17 10:34:34.291983249 +0800
7++++ b/smb2misc.c 2023-01-17 15:17:16.924040490 +0800
8+@@ -91,11 +91,6 @@
9+ *off = 0;
10+ *len = 0;
11+
12+- /* error reqeusts do not have data area */
13+- if (hdr->Status && hdr->Status != STATUS_MORE_PROCESSING_REQUIRED &&
14+- (((struct smb2_err_rsp *)hdr)->StructureSize) == SMB2_ERROR_STRUCTURE_SIZE2_LE)
15+- return ret;
16+-
17+ /*
18+ * Following commands have data areas so we have to get the location
19+ * of the data buffer offset and data buffer length for the particular
20+@@ -137,8 +132,11 @@
21+ *len = le16_to_cpu(((struct smb2_read_req *)hdr)->ReadChannelInfoLength);
22+ break;
23+ case SMB2_WRITE:
24+- if (((struct smb2_write_req *)hdr)->DataOffset) {
25+- *off = le16_to_cpu(((struct smb2_write_req *)hdr)->DataOffset);
26++ if (((struct smb2_write_req *)hdr)->DataOffset ||
27++ ((struct smb2_write_req *)hdr)->Length) {
28++ *off = max_t(unsigned int,
29++ le16_to_cpu(((struct smb2_write_req *)hdr)->DataOffset),
30++ offsetof(struct smb2_write_req, Buffer));
31+ *len = le32_to_cpu(((struct smb2_write_req *)hdr)->Length);
32+ break;
33+ }
34+diff -Naur a/smb2pdu.c b/smb2pdu.c
35+--- a/smb2pdu.c 2023-01-17 10:37:20.251390488 +0800
36++++ b/smb2pdu.c 2023-01-17 17:25:58.076142662 +0800
37+@@ -540,9 +540,10 @@
38+ struct smb2_query_info_req *req;
39+
40+ req = smb2_get_msg(work->request_buf);
41+- if (req->InfoType == SMB2_O_INFO_FILE &&
42+- (req->FileInfoClass == FILE_FULL_EA_INFORMATION ||
43+- req->FileInfoClass == FILE_ALL_INFORMATION))
44++ if ((req->InfoType == SMB2_O_INFO_FILE &&
45++ (req->FileInfoClass == FILE_FULL_EA_INFORMATION ||
46++ req->FileInfoClass == FILE_ALL_INFORMATION)) ||
47++ req->InfoType == SMB2_O_INFO_SECURITY)
48+ sz = large_sz;
49+ }
50+
51+@@ -1146,12 +1147,16 @@
52+ status);
53+ rsp->hdr.Status = status;
54+ rc = -EINVAL;
55++ kfree(conn->preauth_info);
56++ conn->preauth_info = NULL;
57+ goto err_out;
58+ }
59+
60+ rc = init_smb3_11_server(conn);
61+ if (rc < 0) {
62+ rsp->hdr.Status = STATUS_INVALID_PARAMETER;
63++ kfree(conn->preauth_info);
64++ conn->preauth_info = NULL;
65+ goto err_out;
66+ }
67+
68+@@ -3004,7 +3009,7 @@
69+ goto err_out;
70+
71+ rc = build_sec_desc(user_ns,
72+- pntsd, NULL,
73++ pntsd, NULL, 0,
74+ OWNER_SECINFO |
75+ GROUP_SECINFO |
76+ DACL_SECINFO,
77+@@ -3861,6 +3866,15 @@
78+ return 0;
79+ }
80+
81++static int smb2_resp_buf_len(struct ksmbd_work *work, unsigned short hdr2_len)
82++{
83++ int free_len;
84++
85++ free_len = (int)(work->response_sz -
86++ (get_rfc1002_len(work->response_buf) + 4)) - hdr2_len;
87++ return free_len;
88++}
89++
90+ static int smb2_calc_max_out_buf_len(struct ksmbd_work *work,
91+ unsigned short hdr2_len,
92+ unsigned int out_buf_len)
93+@@ -3870,9 +3884,7 @@
94+ if (out_buf_len > work->conn->vals->max_trans_size)
95+ return -EINVAL;
96+
97+- free_len = (int)(work->response_sz -
98+- (get_rfc1002_len(work->response_buf) + 4)) -
99+- hdr2_len;
100++ free_len = smb2_resp_buf_len(work, hdr2_len);
101+ if (free_len < 0)
102+ return -EINVAL;
103+
104+@@ -5164,10 +5176,10 @@
105+ struct smb_ntsd *pntsd = (struct smb_ntsd *)rsp->Buffer, *ppntsd = NULL;
106+ struct smb_fattr fattr = {{0}};
107+ struct inode *inode;
108+- __u32 secdesclen;
109++ __u32 secdesclen = 0;
110+ unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;
111+ int addition_info = le32_to_cpu(req->AdditionalInformation);
112+- int rc;
113++ int rc = 0, ppntsd_size = 0;
114+
115+ if (addition_info & ~(OWNER_SECINFO | GROUP_SECINFO | DACL_SECINFO |
116+ PROTECTED_DACL_SECINFO |
117+@@ -5213,11 +5225,14 @@
118+
119+ if (test_share_config_flag(work->tcon->share_conf,
120+ KSMBD_SHARE_FLAG_ACL_XATTR))
121+- ksmbd_vfs_get_sd_xattr(work->conn, user_ns,
122+- fp->filp->f_path.dentry, &ppntsd);
123+-
124+- rc = build_sec_desc(user_ns, pntsd, ppntsd, addition_info,
125+- &secdesclen, &fattr);
126++ ppntsd_size = ksmbd_vfs_get_sd_xattr(work->conn, user_ns,
127++ fp->filp->f_path.dentry,
128++ &ppntsd);
129++
130++ /* Check if sd buffer size exceeds response buffer size */
131++ if (smb2_resp_buf_len(work, 8) > ppntsd_size)
132++ rc = build_sec_desc(user_ns, pntsd, ppntsd, ppntsd_size,
133++ addition_info, &secdesclen, &fattr);
134+ posix_acl_release(fattr.cf_acls);
135+ posix_acl_release(fattr.cf_dacls);
136+ kfree(ppntsd);
137+@@ -6580,14 +6595,12 @@
138+ writethrough = true;
139+
140+ if (is_rdma_channel == false) {
141+- if ((u64)le16_to_cpu(req->DataOffset) + length >
142+- get_rfc1002_len(work->request_buf)) {
143+- pr_err("invalid write data offset %u, smb_len %u\n",
144+- le16_to_cpu(req->DataOffset),
145+- get_rfc1002_len(work->request_buf));
146++ if (le16_to_cpu(req->DataOffset) <
147++ offsetof(struct smb2_write_req, Buffer)) {
148+ err = -EINVAL;
149+ goto out;
150+ }
151++
152+ data_buf = (char *)(((char *)&req->hdr.ProtocolId) +
153+ le16_to_cpu(req->DataOffset));
154+
155+diff -Naur a/smbacl.c b/smbacl.c
156+--- a/smbacl.c 2023-01-17 16:38:30.244282066 +0800
157++++ b/smbacl.c 2023-01-17 17:03:41.689373609 +0800
158+@@ -722,6 +722,7 @@
159+ static void set_ntacl_dacl(struct user_namespace *user_ns,
160+ struct smb_acl *pndacl,
161+ struct smb_acl *nt_dacl,
162++ unsigned int aces_size,
163+ const struct smb_sid *pownersid,
164+ const struct smb_sid *pgrpsid,
165+ struct smb_fattr *fattr)
166+@@ -735,9 +736,19 @@
167+ if (nt_num_aces) {
168+ ntace = (struct smb_ace *)((char *)nt_dacl + sizeof(struct smb_acl));
169+ for (i = 0; i < nt_num_aces; i++) {
170+- memcpy((char *)pndace + size, ntace, le16_to_cpu(ntace->size));
171+- size += le16_to_cpu(ntace->size);
172+- ntace = (struct smb_ace *)((char *)ntace + le16_to_cpu(ntace->size));
173++ unsigned short nt_ace_size;
174++
175++ if (offsetof(struct smb_ace, access_req) > aces_size)
176++ break;
177++
178++ nt_ace_size = le16_to_cpu(ntace->size);
179++ if (nt_ace_size > aces_size)
180++ break;
181++
182++ memcpy((char *)pndace + size, ntace, nt_ace_size);
183++ size += nt_ace_size;
184++ aces_size -= nt_ace_size;
185++ ntace = (struct smb_ace *)((char *)ntace + nt_ace_size);
186+ num_aces++;
187+ }
188+ }
189+@@ -910,7 +921,7 @@
190+ /* Convert permission bits from mode to equivalent CIFS ACL */
191+ int build_sec_desc(struct user_namespace *user_ns,
192+ struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd,
193+- int addition_info, __u32 *secdesclen,
194++ int ppntsd_size, int addition_info, __u32 *secdesclen,
195+ struct smb_fattr *fattr)
196+ {
197+ int rc = 0;
198+@@ -970,15 +981,25 @@
199+
200+ if (!ppntsd) {
201+ set_mode_dacl(user_ns, dacl_ptr, fattr);
202+- } else if (!ppntsd->dacloffset) {
203+- goto out;
204+ } else {
205+ struct smb_acl *ppdacl_ptr;
206++ unsigned int dacl_offset = le32_to_cpu(ppntsd->dacloffset);
207++ int ppdacl_size, ntacl_size = ppntsd_size - dacl_offset;
208++
209++ if (!dacl_offset ||
210++ (dacl_offset + sizeof(struct smb_acl) > ppntsd_size))
211++ goto out;
212++
213++ ppdacl_ptr = (struct smb_acl *)((char *)ppntsd + dacl_offset);
214++ ppdacl_size = le16_to_cpu(ppdacl_ptr->size);
215++ if (ppdacl_size > ntacl_size ||
216++ ppdacl_size < sizeof(struct smb_acl))
217++ goto out;
218+
219+- ppdacl_ptr = (struct smb_acl *)((char *)ppntsd +
220+- le32_to_cpu(ppntsd->dacloffset));
221+ set_ntacl_dacl(user_ns, dacl_ptr, ppdacl_ptr,
222+- nowner_sid_ptr, ngroup_sid_ptr, fattr);
223++ ntacl_size - sizeof(struct smb_acl),
224++ nowner_sid_ptr, ngroup_sid_ptr,
225++ fattr);
226+ }
227+ pntsd->dacloffset = cpu_to_le32(offset);
228+ offset += le16_to_cpu(dacl_ptr->size);
229+@@ -1012,24 +1033,31 @@
230+ struct smb_sid owner_sid, group_sid;
231+ struct dentry *parent = path->dentry->d_parent;
232+ struct user_namespace *user_ns = mnt_user_ns(path->mnt);
233+- int inherited_flags = 0, flags = 0, i, ace_cnt = 0, nt_size = 0;
234+- int rc = 0, num_aces, dacloffset, pntsd_type, acl_len;
235++ int inherited_flags = 0, flags = 0, i, ace_cnt = 0, nt_size = 0, pdacl_size;
236++ int rc = 0, num_aces, dacloffset, pntsd_type, pntsd_size, acl_len, aces_size;
237+ char *aces_base;
238+ bool is_dir = S_ISDIR(d_inode(path->dentry)->i_mode);
239+
240+- acl_len = ksmbd_vfs_get_sd_xattr(conn, user_ns,
241+- parent, &parent_pntsd);
242+- if (acl_len <= 0)
243++ pntsd_size = ksmbd_vfs_get_sd_xattr(conn, user_ns,
244++ parent, &parent_pntsd);
245++ if (pntsd_size <= 0)
246+ return -ENOENT;
247+ dacloffset = le32_to_cpu(parent_pntsd->dacloffset);
248+- if (!dacloffset) {
249++ if (!dacloffset || (dacloffset + sizeof(struct smb_acl) > pntsd_size)) {
250+ rc = -EINVAL;
251+ goto free_parent_pntsd;
252+ }
253+
254+ parent_pdacl = (struct smb_acl *)((char *)parent_pntsd + dacloffset);
255++ acl_len = pntsd_size - dacloffset;
256+ num_aces = le32_to_cpu(parent_pdacl->num_aces);
257+ pntsd_type = le16_to_cpu(parent_pntsd->type);
258++ pdacl_size = le16_to_cpu(parent_pdacl->size);
259++
260++ if (pdacl_size > acl_len || pdacl_size < sizeof(struct smb_acl)) {
261++ rc = -EINVAL;
262++ goto free_parent_pntsd;
263++ }
264+
265+ aces_base = kmalloc(sizeof(struct smb_ace) * num_aces * 2, GFP_KERNEL);
266+ if (!aces_base) {
267+@@ -1040,11 +1068,23 @@
268+ aces = (struct smb_ace *)aces_base;
269+ parent_aces = (struct smb_ace *)((char *)parent_pdacl +
270+ sizeof(struct smb_acl));
271++ aces_size = acl_len - sizeof(struct smb_acl);
272+
273+ if (pntsd_type & DACL_AUTO_INHERITED)
274+ inherited_flags = INHERITED_ACE;
275+
276+ for (i = 0; i < num_aces; i++) {
277++ int pace_size;
278++
279++ if (offsetof(struct smb_ace, access_req) > aces_size)
280++ break;
281++
282++ pace_size = le16_to_cpu(parent_aces->size);
283++ if (pace_size > aces_size)
284++ break;
285++
286++ aces_size -= pace_size;
287++
288+ flags = parent_aces->flags;
289+ if (!smb_inherit_flags(flags, is_dir))
290+ goto pass;
291+@@ -1089,8 +1129,7 @@
292+ aces = (struct smb_ace *)((char *)aces + le16_to_cpu(aces->size));
293+ ace_cnt++;
294+ pass:
295+- parent_aces =
296+- (struct smb_ace *)((char *)parent_aces + le16_to_cpu(parent_aces->size));
297++ parent_aces = (struct smb_ace *)((char *)parent_aces + pace_size);
298+ }
299+
300+ if (nt_size > 0) {
301+@@ -1185,7 +1224,7 @@
302+ struct smb_ntsd *pntsd = NULL;
303+ struct smb_acl *pdacl;
304+ struct posix_acl *posix_acls;
305+- int rc = 0, acl_size;
306++ int rc = 0, pntsd_size, acl_size, aces_size, pdacl_size, dacl_offset;
307+ struct smb_sid sid;
308+ int granted = le32_to_cpu(*pdaccess & ~FILE_MAXIMAL_ACCESS_LE);
309+ struct smb_ace *ace;
310+@@ -1194,37 +1233,33 @@
311+ struct smb_ace *others_ace = NULL;
312+ struct posix_acl_entry *pa_entry;
313+ unsigned int sid_type = SIDOWNER;
314+- char *end_of_acl;
315++ unsigned short ace_size;
316+
317+ ksmbd_debug(SMB, "check permission using windows acl\n");
318+- acl_size = ksmbd_vfs_get_sd_xattr(conn, user_ns,
319+- path->dentry, &pntsd);
320+- if (acl_size <= 0 || !pntsd || !pntsd->dacloffset) {
321+- kfree(pntsd);
322+- return 0;
323+- }
324++ pntsd_size = ksmbd_vfs_get_sd_xattr(conn, user_ns,
325++ path->dentry, &pntsd);
326++ if (pntsd_size <= 0 || !pntsd)
327++ goto err_out;
328++
329++ dacl_offset = le32_to_cpu(pntsd->dacloffset);
330++ if (!dacl_offset ||
331++ (dacl_offset + sizeof(struct smb_acl) > pntsd_size))
332++ goto err_out;
333+
334+ pdacl = (struct smb_acl *)((char *)pntsd + le32_to_cpu(pntsd->dacloffset));
335+- end_of_acl = ((char *)pntsd) + acl_size;
336+- if (end_of_acl <= (char *)pdacl) {
337+- kfree(pntsd);
338+- return 0;
339+- }
340++ acl_size = pntsd_size - dacl_offset;
341++ pdacl_size = le16_to_cpu(pdacl->size);
342+
343+- if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size) ||
344+- le16_to_cpu(pdacl->size) < sizeof(struct smb_acl)) {
345+- kfree(pntsd);
346+- return 0;
347+- }
348++ if (pdacl_size > acl_size || pdacl_size < sizeof(struct smb_acl))
349++ goto err_out;
350+
351+ if (!pdacl->num_aces) {
352+- if (!(le16_to_cpu(pdacl->size) - sizeof(struct smb_acl)) &&
353++ if (!(pdacl_size - sizeof(struct smb_acl)) &&
354+ *pdaccess & ~(FILE_READ_CONTROL_LE | FILE_WRITE_DAC_LE)) {
355+ rc = -EACCES;
356+ goto err_out;
357+ }
358+- kfree(pntsd);
359+- return 0;
360++ goto err_out;
361+ }
362+
363+ if (*pdaccess & FILE_MAXIMAL_ACCESS_LE) {
364+@@ -1232,11 +1267,16 @@
365+ DELETE;
366+
367+ ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
368++ aces_size = acl_size - sizeof(struct smb_acl);
369+ for (i = 0; i < le32_to_cpu(pdacl->num_aces); i++) {
370++ if (offsetof(struct smb_ace, access_req) > aces_size)
371++ break;
372++ ace_size = le16_to_cpu(ace->size);
373++ if (ace_size > aces_size)
374++ break;
375++ aces_size -= ace_size;
376+ granted |= le32_to_cpu(ace->access_req);
377+ ace = (struct smb_ace *)((char *)ace + le16_to_cpu(ace->size));
378+- if (end_of_acl < (char *)ace)
379+- goto err_out;
380+ }
381+
382+ if (!pdacl->num_aces)
383+@@ -1248,7 +1288,15 @@
384+ id_to_sid(uid, sid_type, &sid);
385+
386+ ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
387++ aces_size = acl_size - sizeof(struct smb_acl);
388+ for (i = 0; i < le32_to_cpu(pdacl->num_aces); i++) {
389++ if (offsetof(struct smb_ace, access_req) > aces_size)
390++ break;
391++ ace_size = le16_to_cpu(ace->size);
392++ if (ace_size > aces_size)
393++ break;
394++ aces_size -= ace_size;
395++
396+ if (!compare_sids(&sid, &ace->sid) ||
397+ !compare_sids(&sid_unix_NFS_mode, &ace->sid)) {
398+ found = 1;
399+@@ -1258,8 +1306,6 @@
400+ others_ace = ace;
401+
402+ ace = (struct smb_ace *)((char *)ace + le16_to_cpu(ace->size));
403+- if (end_of_acl < (char *)ace)
404+- goto err_out;
405+ }
406+
407+ if (*pdaccess & FILE_MAXIMAL_ACCESS_LE && found) {
408+diff -Naur a/smbacl.h b/smbacl.h
409+--- a/smbacl.h 2023-01-17 17:09:11.618949941 +0800
410++++ b/smbacl.h 2023-01-17 17:10:10.681651570 +0800
411+@@ -196,7 +196,7 @@
412+ int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,
413+ int acl_len, struct smb_fattr *fattr);
414+ int build_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,
415+- struct smb_ntsd *ppntsd, int addition_info,
416++ struct smb_ntsd *ppntsd, int ppntsd_size, int addition_info,
417+ __u32 *secdesclen, struct smb_fattr *fattr);
418+ int init_acl_state(struct posix_acl_state *state, int cnt);
419+ void free_acl_state(struct posix_acl_state *state);
420+diff -Naur a/vfs.c b/vfs.c
421+--- a/vfs.c 2023-01-17 17:10:33.910672093 +0800
422++++ b/vfs.c 2023-01-17 17:11:28.493111948 +0800
423+@@ -1708,6 +1708,11 @@
424+ }
425+
426+ *pntsd = acl.sd_buf;
427++ if (acl.sd_size < sizeof(struct smb_ntsd)) {
428++ pr_err("sd size is invalid\n");
429++ goto out_free;
430++ }
431++
432+ (*pntsd)->osidoffset = cpu_to_le32(le32_to_cpu((*pntsd)->osidoffset) -
433+ NDR_NTSD_OFFSETOF);
434+ (*pntsd)->gsidoffset = cpu_to_le32(le32_to_cpu((*pntsd)->gsidoffset) -