developer | e7af5f9 | 2023-01-17 17:45:00 +0800 | [diff] [blame] | 1 | diff -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) - |