Merge tag '5.15-rc3-ksmbd-fixes' of git://git.samba.org/ksmbd

Pull ksmbd server fixes from Steve French:
"Eleven fixes for the ksmbd kernel server, mostly security related:

- an important fix for disabling weak NTLMv1 authentication

- seven security (improved buffer overflow checks) fixes

- fix for wrong infolevel struct used in some getattr/setattr paths

- two small documentation fixes"

* tag '5.15-rc3-ksmbd-fixes' of git://git.samba.org/ksmbd:
ksmbd: missing check for NULL in convert_to_nt_pathname()
ksmbd: fix transform header validation
ksmbd: add buffer validation for SMB2_CREATE_CONTEXT
ksmbd: add validation in smb2 negotiate
ksmbd: add request buffer validation in smb2_set_info
ksmbd: use correct basic info level in set_file_basic_info()
ksmbd: remove NTLMv1 authentication
ksmbd: fix documentation for 2 functions
MAINTAINERS: rename cifs_common to smbfs_common in cifs and ksmbd entry
ksmbd: fix invalid request buffer access in compound
ksmbd: remove RFC1002 check in smb2 request

+295 -343
+2 -2
MAINTAINERS
··· 4657 4657 T: git git://git.samba.org/sfrench/cifs-2.6.git 4658 4658 F: Documentation/admin-guide/cifs/ 4659 4659 F: fs/cifs/ 4660 - F: fs/cifs_common/ 4660 + F: fs/smbfs_common/ 4661 4661 4662 4662 COMPACTPCI HOTPLUG CORE 4663 4663 M: Scott Murray <scott@spiteful.org> ··· 10195 10195 L: linux-cifs@vger.kernel.org 10196 10196 S: Maintained 10197 10197 T: git git://git.samba.org/ksmbd.git 10198 - F: fs/cifs_common/ 10199 10198 F: fs/ksmbd/ 10199 + F: fs/smbfs_common/ 10200 10200 10201 10201 KERNEL UNIT TESTING FRAMEWORK (KUnit) 10202 10202 M: Brendan Higgins <brendanhiggins@google.com>
-205
fs/ksmbd/auth.c
··· 68 68 memcpy(buf, NEGOTIATE_GSS_HEADER, AUTH_GSS_LENGTH); 69 69 } 70 70 71 - static void 72 - str_to_key(unsigned char *str, unsigned char *key) 73 - { 74 - int i; 75 - 76 - key[0] = str[0] >> 1; 77 - key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2); 78 - key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3); 79 - key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4); 80 - key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5); 81 - key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6); 82 - key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7); 83 - key[7] = str[6] & 0x7F; 84 - for (i = 0; i < 8; i++) 85 - key[i] = (key[i] << 1); 86 - } 87 - 88 - static int 89 - smbhash(unsigned char *out, const unsigned char *in, unsigned char *key) 90 - { 91 - unsigned char key2[8]; 92 - struct des_ctx ctx; 93 - 94 - if (fips_enabled) { 95 - ksmbd_debug(AUTH, "FIPS compliance enabled: DES not permitted\n"); 96 - return -ENOENT; 97 - } 98 - 99 - str_to_key(key, key2); 100 - des_expand_key(&ctx, key2, DES_KEY_SIZE); 101 - des_encrypt(&ctx, out, in); 102 - memzero_explicit(&ctx, sizeof(ctx)); 103 - return 0; 104 - } 105 - 106 - static int ksmbd_enc_p24(unsigned char *p21, const unsigned char *c8, unsigned char *p24) 107 - { 108 - int rc; 109 - 110 - rc = smbhash(p24, c8, p21); 111 - if (rc) 112 - return rc; 113 - rc = smbhash(p24 + 8, c8, p21 + 7); 114 - if (rc) 115 - return rc; 116 - return smbhash(p24 + 16, c8, p21 + 14); 117 - } 118 - 119 - /* produce a md4 message digest from data of length n bytes */ 120 - static int ksmbd_enc_md4(unsigned char *md4_hash, unsigned char *link_str, 121 - int link_len) 122 - { 123 - int rc; 124 - struct ksmbd_crypto_ctx *ctx; 125 - 126 - ctx = ksmbd_crypto_ctx_find_md4(); 127 - if (!ctx) { 128 - ksmbd_debug(AUTH, "Crypto md4 allocation error\n"); 129 - return -ENOMEM; 130 - } 131 - 132 - rc = crypto_shash_init(CRYPTO_MD4(ctx)); 133 - if (rc) { 134 - ksmbd_debug(AUTH, "Could not init md4 shash\n"); 135 - goto out; 136 - } 137 - 138 - rc = crypto_shash_update(CRYPTO_MD4(ctx), link_str, link_len); 139 - if (rc) { 140 - ksmbd_debug(AUTH, "Could not update with link_str\n"); 141 - goto out; 142 - } 143 - 144 - rc = crypto_shash_final(CRYPTO_MD4(ctx), md4_hash); 145 - if (rc) 146 - ksmbd_debug(AUTH, "Could not generate md4 hash\n"); 147 - out: 148 - ksmbd_release_crypto_ctx(ctx); 149 - return rc; 150 - } 151 - 152 - static int ksmbd_enc_update_sess_key(unsigned char *md5_hash, char *nonce, 153 - char *server_challenge, int len) 154 - { 155 - int rc; 156 - struct ksmbd_crypto_ctx *ctx; 157 - 158 - ctx = ksmbd_crypto_ctx_find_md5(); 159 - if (!ctx) { 160 - ksmbd_debug(AUTH, "Crypto md5 allocation error\n"); 161 - return -ENOMEM; 162 - } 163 - 164 - rc = crypto_shash_init(CRYPTO_MD5(ctx)); 165 - if (rc) { 166 - ksmbd_debug(AUTH, "Could not init md5 shash\n"); 167 - goto out; 168 - } 169 - 170 - rc = crypto_shash_update(CRYPTO_MD5(ctx), server_challenge, len); 171 - if (rc) { 172 - ksmbd_debug(AUTH, "Could not update with challenge\n"); 173 - goto out; 174 - } 175 - 176 - rc = crypto_shash_update(CRYPTO_MD5(ctx), nonce, len); 177 - if (rc) { 178 - ksmbd_debug(AUTH, "Could not update with nonce\n"); 179 - goto out; 180 - } 181 - 182 - rc = crypto_shash_final(CRYPTO_MD5(ctx), md5_hash); 183 - if (rc) 184 - ksmbd_debug(AUTH, "Could not generate md5 hash\n"); 185 - out: 186 - ksmbd_release_crypto_ctx(ctx); 187 - return rc; 188 - } 189 - 190 71 /** 191 72 * ksmbd_gen_sess_key() - function to generate session key 192 73 * @sess: session of connection ··· 206 325 } 207 326 208 327 /** 209 - * ksmbd_auth_ntlm() - NTLM authentication handler 210 - * @sess: session of connection 211 - * @pw_buf: NTLM challenge response 212 - * @passkey: user password 213 - * 214 - * Return: 0 on success, error number on error 215 - */ 216 - int ksmbd_auth_ntlm(struct ksmbd_session *sess, char *pw_buf) 217 - { 218 - int rc; 219 - unsigned char p21[21]; 220 - char key[CIFS_AUTH_RESP_SIZE]; 221 - 222 - memset(p21, '\0', 21); 223 - memcpy(p21, user_passkey(sess->user), CIFS_NTHASH_SIZE); 224 - rc = ksmbd_enc_p24(p21, sess->ntlmssp.cryptkey, key); 225 - if (rc) { 226 - pr_err("password processing failed\n"); 227 - return rc; 228 - } 229 - 230 - ksmbd_enc_md4(sess->sess_key, user_passkey(sess->user), 231 - CIFS_SMB1_SESSKEY_SIZE); 232 - memcpy(sess->sess_key + CIFS_SMB1_SESSKEY_SIZE, key, 233 - CIFS_AUTH_RESP_SIZE); 234 - sess->sequence_number = 1; 235 - 236 - if (strncmp(pw_buf, key, CIFS_AUTH_RESP_SIZE) != 0) { 237 - ksmbd_debug(AUTH, "ntlmv1 authentication failed\n"); 238 - return -EINVAL; 239 - } 240 - 241 - ksmbd_debug(AUTH, "ntlmv1 authentication pass\n"); 242 - return 0; 243 - } 244 - 245 - /** 246 328 * ksmbd_auth_ntlmv2() - NTLMv2 authentication handler 247 329 * @sess: session of connection 248 330 * @ntlmv2: NTLMv2 challenge response ··· 286 442 } 287 443 288 444 /** 289 - * __ksmbd_auth_ntlmv2() - NTLM2(extended security) authentication handler 290 - * @sess: session of connection 291 - * @client_nonce: client nonce from LM response. 292 - * @ntlm_resp: ntlm response data from client. 293 - * 294 - * Return: 0 on success, error number on error 295 - */ 296 - static int __ksmbd_auth_ntlmv2(struct ksmbd_session *sess, char *client_nonce, 297 - char *ntlm_resp) 298 - { 299 - char sess_key[CIFS_SMB1_SESSKEY_SIZE] = {0}; 300 - int rc; 301 - unsigned char p21[21]; 302 - char key[CIFS_AUTH_RESP_SIZE]; 303 - 304 - rc = ksmbd_enc_update_sess_key(sess_key, 305 - client_nonce, 306 - (char *)sess->ntlmssp.cryptkey, 8); 307 - if (rc) { 308 - pr_err("password processing failed\n"); 309 - goto out; 310 - } 311 - 312 - memset(p21, '\0', 21); 313 - memcpy(p21, user_passkey(sess->user), CIFS_NTHASH_SIZE); 314 - rc = ksmbd_enc_p24(p21, sess_key, key); 315 - if (rc) { 316 - pr_err("password processing failed\n"); 317 - goto out; 318 - } 319 - 320 - if (memcmp(ntlm_resp, key, CIFS_AUTH_RESP_SIZE) != 0) 321 - rc = -EINVAL; 322 - out: 323 - return rc; 324 - } 325 - 326 - /** 327 445 * ksmbd_decode_ntlmssp_auth_blob() - helper function to construct 328 446 * authenticate blob 329 447 * @authblob: authenticate blob source pointer ··· 317 511 lm_off = le32_to_cpu(authblob->LmChallengeResponse.BufferOffset); 318 512 nt_off = le32_to_cpu(authblob->NtChallengeResponse.BufferOffset); 319 513 nt_len = le16_to_cpu(authblob->NtChallengeResponse.Length); 320 - 321 - /* process NTLM authentication */ 322 - if (nt_len == CIFS_AUTH_RESP_SIZE) { 323 - if (le32_to_cpu(authblob->NegotiateFlags) & 324 - NTLMSSP_NEGOTIATE_EXTENDED_SEC) 325 - return __ksmbd_auth_ntlmv2(sess, (char *)authblob + 326 - lm_off, (char *)authblob + nt_off); 327 - else 328 - return ksmbd_auth_ntlm(sess, (char *)authblob + 329 - nt_off); 330 - } 331 514 332 515 /* TODO : use domain name that imported from configuration file */ 333 516 domain_name = smb_strndup_from_utf16((const char *)authblob +
-16
fs/ksmbd/crypto_ctx.c
··· 81 81 case CRYPTO_SHASH_SHA512: 82 82 tfm = crypto_alloc_shash("sha512", 0, 0); 83 83 break; 84 - case CRYPTO_SHASH_MD4: 85 - tfm = crypto_alloc_shash("md4", 0, 0); 86 - break; 87 - case CRYPTO_SHASH_MD5: 88 - tfm = crypto_alloc_shash("md5", 0, 0); 89 - break; 90 84 default: 91 85 return NULL; 92 86 } ··· 206 212 struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void) 207 213 { 208 214 return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA512); 209 - } 210 - 211 - struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md4(void) 212 - { 213 - return ____crypto_shash_ctx_find(CRYPTO_SHASH_MD4); 214 - } 215 - 216 - struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md5(void) 217 - { 218 - return ____crypto_shash_ctx_find(CRYPTO_SHASH_MD5); 219 215 } 220 216 221 217 static struct ksmbd_crypto_ctx *____crypto_aead_ctx_find(int id)
-8
fs/ksmbd/crypto_ctx.h
··· 15 15 CRYPTO_SHASH_CMACAES, 16 16 CRYPTO_SHASH_SHA256, 17 17 CRYPTO_SHASH_SHA512, 18 - CRYPTO_SHASH_MD4, 19 - CRYPTO_SHASH_MD5, 20 18 CRYPTO_SHASH_MAX, 21 19 }; 22 20 ··· 41 43 #define CRYPTO_CMACAES(c) ((c)->desc[CRYPTO_SHASH_CMACAES]) 42 44 #define CRYPTO_SHA256(c) ((c)->desc[CRYPTO_SHASH_SHA256]) 43 45 #define CRYPTO_SHA512(c) ((c)->desc[CRYPTO_SHASH_SHA512]) 44 - #define CRYPTO_MD4(c) ((c)->desc[CRYPTO_SHASH_MD4]) 45 - #define CRYPTO_MD5(c) ((c)->desc[CRYPTO_SHASH_MD5]) 46 46 47 47 #define CRYPTO_HMACMD5_TFM(c) ((c)->desc[CRYPTO_SHASH_HMACMD5]->tfm) 48 48 #define CRYPTO_HMACSHA256_TFM(c)\ ··· 48 52 #define CRYPTO_CMACAES_TFM(c) ((c)->desc[CRYPTO_SHASH_CMACAES]->tfm) 49 53 #define CRYPTO_SHA256_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA256]->tfm) 50 54 #define CRYPTO_SHA512_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA512]->tfm) 51 - #define CRYPTO_MD4_TFM(c) ((c)->desc[CRYPTO_SHASH_MD4]->tfm) 52 - #define CRYPTO_MD5_TFM(c) ((c)->desc[CRYPTO_SHASH_MD5]->tfm) 53 55 54 56 #define CRYPTO_GCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_GCM]) 55 57 #define CRYPTO_CCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_CCM]) ··· 58 64 struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void); 59 65 struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void); 60 66 struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha256(void); 61 - struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md4(void); 62 - struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md5(void); 63 67 struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void); 64 68 struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void); 65 69 void ksmbd_crypto_destroy(void);
+7 -10
fs/ksmbd/misc.c
··· 162 162 { 163 163 char *ab_pathname; 164 164 165 - if (strlen(filename) == 0) { 166 - ab_pathname = kmalloc(2, GFP_KERNEL); 167 - ab_pathname[0] = '\\'; 168 - ab_pathname[1] = '\0'; 169 - } else { 170 - ab_pathname = kstrdup(filename, GFP_KERNEL); 171 - if (!ab_pathname) 172 - return NULL; 165 + if (strlen(filename) == 0) 166 + filename = "\\"; 173 167 174 - ksmbd_conv_path_to_windows(ab_pathname); 175 - } 168 + ab_pathname = kstrdup(filename, GFP_KERNEL); 169 + if (!ab_pathname) 170 + return NULL; 171 + 172 + ksmbd_conv_path_to_windows(ab_pathname); 176 173 return ab_pathname; 177 174 } 178 175
+31 -10
fs/ksmbd/oplock.c
··· 1451 1451 */ 1452 1452 struct create_context *smb2_find_context_vals(void *open_req, const char *tag) 1453 1453 { 1454 - char *data_offset; 1455 1454 struct create_context *cc; 1456 1455 unsigned int next = 0; 1457 1456 char *name; 1458 1457 struct smb2_create_req *req = (struct smb2_create_req *)open_req; 1458 + unsigned int remain_len, name_off, name_len, value_off, value_len, 1459 + cc_len; 1459 1460 1460 - data_offset = (char *)req + 4 + le32_to_cpu(req->CreateContextsOffset); 1461 - cc = (struct create_context *)data_offset; 1461 + /* 1462 + * CreateContextsOffset and CreateContextsLength are guaranteed to 1463 + * be valid because of ksmbd_smb2_check_message(). 1464 + */ 1465 + cc = (struct create_context *)((char *)req + 4 + 1466 + le32_to_cpu(req->CreateContextsOffset)); 1467 + remain_len = le32_to_cpu(req->CreateContextsLength); 1462 1468 do { 1463 - int val; 1464 - 1465 1469 cc = (struct create_context *)((char *)cc + next); 1466 - name = le16_to_cpu(cc->NameOffset) + (char *)cc; 1467 - val = le16_to_cpu(cc->NameLength); 1468 - if (val < 4) 1470 + if (remain_len < offsetof(struct create_context, Buffer)) 1469 1471 return ERR_PTR(-EINVAL); 1470 1472 1471 - if (memcmp(name, tag, val) == 0) 1472 - return cc; 1473 1473 next = le32_to_cpu(cc->Next); 1474 + name_off = le16_to_cpu(cc->NameOffset); 1475 + name_len = le16_to_cpu(cc->NameLength); 1476 + value_off = le16_to_cpu(cc->DataOffset); 1477 + value_len = le32_to_cpu(cc->DataLength); 1478 + cc_len = next ? next : remain_len; 1479 + 1480 + if ((next & 0x7) != 0 || 1481 + next > remain_len || 1482 + name_off != offsetof(struct create_context, Buffer) || 1483 + name_len < 4 || 1484 + name_off + name_len > cc_len || 1485 + (value_off & 0x7) != 0 || 1486 + (value_off && (value_off < name_off + name_len)) || 1487 + ((u64)value_off + value_len > cc_len)) 1488 + return ERR_PTR(-EINVAL); 1489 + 1490 + name = (char *)cc + name_off; 1491 + if (memcmp(name, tag, name_len) == 0) 1492 + return cc; 1493 + 1494 + remain_len -= next; 1474 1495 } while (next != 0); 1475 1496 1476 1497 return NULL;
+197 -61
fs/ksmbd/smb2pdu.c
··· 459 459 bool is_chained_smb2_message(struct ksmbd_work *work) 460 460 { 461 461 struct smb2_hdr *hdr = work->request_buf; 462 - unsigned int len; 462 + unsigned int len, next_cmd; 463 463 464 464 if (hdr->ProtocolId != SMB2_PROTO_NUMBER) 465 465 return false; 466 466 467 467 hdr = ksmbd_req_buf_next(work); 468 - if (le32_to_cpu(hdr->NextCommand) > 0) { 468 + next_cmd = le32_to_cpu(hdr->NextCommand); 469 + if (next_cmd > 0) { 470 + if ((u64)work->next_smb2_rcv_hdr_off + next_cmd + 471 + __SMB2_HEADER_STRUCTURE_SIZE > 472 + get_rfc1002_len(work->request_buf)) { 473 + pr_err("next command(%u) offset exceeds smb msg size\n", 474 + next_cmd); 475 + return false; 476 + } 477 + 469 478 ksmbd_debug(SMB, "got SMB2 chained command\n"); 470 479 init_chained_smb2_rsp(work); 471 480 return true; ··· 1067 1058 struct smb2_negotiate_req *req = work->request_buf; 1068 1059 struct smb2_negotiate_rsp *rsp = work->response_buf; 1069 1060 int rc = 0; 1061 + unsigned int smb2_buf_len, smb2_neg_size; 1070 1062 __le32 status; 1071 1063 1072 1064 ksmbd_debug(SMB, "Received negotiate request\n"); ··· 1083 1073 rsp->hdr.Status = STATUS_INVALID_PARAMETER; 1084 1074 rc = -EINVAL; 1085 1075 goto err_out; 1076 + } 1077 + 1078 + smb2_buf_len = get_rfc1002_len(work->request_buf); 1079 + smb2_neg_size = offsetof(struct smb2_negotiate_req, Dialects) - 4; 1080 + if (smb2_neg_size > smb2_buf_len) { 1081 + rsp->hdr.Status = STATUS_INVALID_PARAMETER; 1082 + rc = -EINVAL; 1083 + goto err_out; 1084 + } 1085 + 1086 + if (conn->dialect == SMB311_PROT_ID) { 1087 + unsigned int nego_ctxt_off = le32_to_cpu(req->NegotiateContextOffset); 1088 + 1089 + if (smb2_buf_len < nego_ctxt_off) { 1090 + rsp->hdr.Status = STATUS_INVALID_PARAMETER; 1091 + rc = -EINVAL; 1092 + goto err_out; 1093 + } 1094 + 1095 + if (smb2_neg_size > nego_ctxt_off) { 1096 + rsp->hdr.Status = STATUS_INVALID_PARAMETER; 1097 + rc = -EINVAL; 1098 + goto err_out; 1099 + } 1100 + 1101 + if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) > 1102 + nego_ctxt_off) { 1103 + rsp->hdr.Status = STATUS_INVALID_PARAMETER; 1104 + rc = -EINVAL; 1105 + goto err_out; 1106 + } 1107 + } else { 1108 + if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) > 1109 + smb2_buf_len) { 1110 + rsp->hdr.Status = STATUS_INVALID_PARAMETER; 1111 + rc = -EINVAL; 1112 + goto err_out; 1113 + } 1086 1114 } 1087 1115 1088 1116 conn->cli_cap = le32_to_cpu(req->Capabilities); ··· 2141 2093 * smb2_set_ea() - handler for setting extended attributes using set 2142 2094 * info command 2143 2095 * @eabuf: set info command buffer 2096 + * @buf_len: set info command buffer length 2144 2097 * @path: dentry path for get ea 2145 2098 * 2146 2099 * Return: 0 on success, otherwise error 2147 2100 */ 2148 - static int smb2_set_ea(struct smb2_ea_info *eabuf, struct path *path) 2101 + static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len, 2102 + struct path *path) 2149 2103 { 2150 2104 struct user_namespace *user_ns = mnt_user_ns(path->mnt); 2151 2105 char *attr_name = NULL, *value; 2152 2106 int rc = 0; 2153 - int next = 0; 2107 + unsigned int next = 0; 2108 + 2109 + if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength + 2110 + le16_to_cpu(eabuf->EaValueLength)) 2111 + return -EINVAL; 2154 2112 2155 2113 attr_name = kmalloc(XATTR_NAME_MAX + 1, GFP_KERNEL); 2156 2114 if (!attr_name) ··· 2221 2167 2222 2168 next: 2223 2169 next = le32_to_cpu(eabuf->NextEntryOffset); 2170 + if (next == 0 || buf_len < next) 2171 + break; 2172 + buf_len -= next; 2224 2173 eabuf = (struct smb2_ea_info *)((char *)eabuf + next); 2174 + if (next < (u32)eabuf->EaNameLength + le16_to_cpu(eabuf->EaValueLength)) 2175 + break; 2176 + 2225 2177 } while (next != 0); 2226 2178 2227 2179 kfree(attr_name); ··· 2427 2367 ksmbd_debug(SMB, 2428 2368 "Set ACLs using SMB2_CREATE_SD_BUFFER context\n"); 2429 2369 sd_buf = (struct create_sd_buf_req *)context; 2370 + if (le16_to_cpu(context->DataOffset) + 2371 + le32_to_cpu(context->DataLength) < 2372 + sizeof(struct create_sd_buf_req)) 2373 + return -EINVAL; 2430 2374 return set_info_sec(work->conn, work->tcon, path, &sd_buf->ntsd, 2431 2375 le32_to_cpu(sd_buf->ccontext.DataLength), true); 2432 2376 } ··· 2625 2561 goto err_out1; 2626 2562 } else if (context) { 2627 2563 ea_buf = (struct create_ea_buf_req *)context; 2564 + if (le16_to_cpu(context->DataOffset) + 2565 + le32_to_cpu(context->DataLength) < 2566 + sizeof(struct create_ea_buf_req)) { 2567 + rc = -EINVAL; 2568 + goto err_out1; 2569 + } 2628 2570 if (req->CreateOptions & FILE_NO_EA_KNOWLEDGE_LE) { 2629 2571 rsp->hdr.Status = STATUS_ACCESS_DENIED; 2630 2572 rc = -EACCES; ··· 2669 2599 } else if (context) { 2670 2600 struct create_posix *posix = 2671 2601 (struct create_posix *)context; 2602 + if (le16_to_cpu(context->DataOffset) + 2603 + le32_to_cpu(context->DataLength) < 2604 + sizeof(struct create_posix)) { 2605 + rc = -EINVAL; 2606 + goto err_out1; 2607 + } 2672 2608 ksmbd_debug(SMB, "get posix context\n"); 2673 2609 2674 2610 posix_mode = le32_to_cpu(posix->Mode); ··· 2824 2748 created = true; 2825 2749 user_ns = mnt_user_ns(path.mnt); 2826 2750 if (ea_buf) { 2827 - rc = smb2_set_ea(&ea_buf->ea, &path); 2751 + if (le32_to_cpu(ea_buf->ccontext.DataLength) < 2752 + sizeof(struct smb2_ea_info)) { 2753 + rc = -EINVAL; 2754 + goto err_out; 2755 + } 2756 + 2757 + rc = smb2_set_ea(&ea_buf->ea, 2758 + le32_to_cpu(ea_buf->ccontext.DataLength), 2759 + &path); 2828 2760 if (rc == -EOPNOTSUPP) 2829 2761 rc = 0; 2830 2762 else if (rc) ··· 3065 2981 rc = PTR_ERR(az_req); 3066 2982 goto err_out; 3067 2983 } else if (az_req) { 3068 - loff_t alloc_size = le64_to_cpu(az_req->AllocationSize); 2984 + loff_t alloc_size; 3069 2985 int err; 3070 2986 2987 + if (le16_to_cpu(az_req->ccontext.DataOffset) + 2988 + le32_to_cpu(az_req->ccontext.DataLength) < 2989 + sizeof(struct create_alloc_size_req)) { 2990 + rc = -EINVAL; 2991 + goto err_out; 2992 + } 2993 + alloc_size = le64_to_cpu(az_req->AllocationSize); 3071 2994 ksmbd_debug(SMB, 3072 2995 "request smb2 create allocate size : %llu\n", 3073 2996 alloc_size); ··· 4243 4152 static int get_file_basic_info(struct smb2_query_info_rsp *rsp, 4244 4153 struct ksmbd_file *fp, void *rsp_org) 4245 4154 { 4246 - struct smb2_file_all_info *basic_info; 4155 + struct smb2_file_basic_info *basic_info; 4247 4156 struct kstat stat; 4248 4157 u64 time; 4249 4158 ··· 4253 4162 return -EACCES; 4254 4163 } 4255 4164 4256 - basic_info = (struct smb2_file_all_info *)rsp->Buffer; 4165 + basic_info = (struct smb2_file_basic_info *)rsp->Buffer; 4257 4166 generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp), 4258 4167 &stat); 4259 4168 basic_info->CreationTime = cpu_to_le64(fp->create_time); ··· 4266 4175 basic_info->Attributes = fp->f_ci->m_fattr; 4267 4176 basic_info->Pad1 = 0; 4268 4177 rsp->OutputBufferLength = 4269 - cpu_to_le32(offsetof(struct smb2_file_all_info, AllocationSize)); 4270 - inc_rfc1001_len(rsp_org, offsetof(struct smb2_file_all_info, 4271 - AllocationSize)); 4178 + cpu_to_le32(sizeof(struct smb2_file_basic_info)); 4179 + inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_basic_info)); 4272 4180 return 0; 4273 4181 } 4274 4182 ··· 5423 5333 static int smb2_create_link(struct ksmbd_work *work, 5424 5334 struct ksmbd_share_config *share, 5425 5335 struct smb2_file_link_info *file_info, 5426 - struct file *filp, 5336 + unsigned int buf_len, struct file *filp, 5427 5337 struct nls_table *local_nls) 5428 5338 { 5429 5339 char *link_name = NULL, *target_name = NULL, *pathname = NULL; 5430 5340 struct path path; 5431 5341 bool file_present = true; 5432 5342 int rc; 5343 + 5344 + if (buf_len < (u64)sizeof(struct smb2_file_link_info) + 5345 + le32_to_cpu(file_info->FileNameLength)) 5346 + return -EINVAL; 5433 5347 5434 5348 ksmbd_debug(SMB, "setting FILE_LINK_INFORMATION\n"); 5435 5349 pathname = kmalloc(PATH_MAX, GFP_KERNEL); ··· 5494 5400 return rc; 5495 5401 } 5496 5402 5497 - static int set_file_basic_info(struct ksmbd_file *fp, char *buf, 5403 + static int set_file_basic_info(struct ksmbd_file *fp, 5404 + struct smb2_file_basic_info *file_info, 5498 5405 struct ksmbd_share_config *share) 5499 5406 { 5500 - struct smb2_file_all_info *file_info; 5501 5407 struct iattr attrs; 5502 5408 struct timespec64 ctime; 5503 5409 struct file *filp; ··· 5508 5414 if (!(fp->daccess & FILE_WRITE_ATTRIBUTES_LE)) 5509 5415 return -EACCES; 5510 5416 5511 - file_info = (struct smb2_file_all_info *)buf; 5512 5417 attrs.ia_valid = 0; 5513 5418 filp = fp->filp; 5514 5419 inode = file_inode(filp); ··· 5584 5491 } 5585 5492 5586 5493 static int set_file_allocation_info(struct ksmbd_work *work, 5587 - struct ksmbd_file *fp, char *buf) 5494 + struct ksmbd_file *fp, 5495 + struct smb2_file_alloc_info *file_alloc_info) 5588 5496 { 5589 5497 /* 5590 5498 * TODO : It's working fine only when store dos attributes ··· 5593 5499 * properly with any smb.conf option 5594 5500 */ 5595 5501 5596 - struct smb2_file_alloc_info *file_alloc_info; 5597 5502 loff_t alloc_blks; 5598 5503 struct inode *inode; 5599 5504 int rc; ··· 5600 5507 if (!(fp->daccess & FILE_WRITE_DATA_LE)) 5601 5508 return -EACCES; 5602 5509 5603 - file_alloc_info = (struct smb2_file_alloc_info *)buf; 5604 5510 alloc_blks = (le64_to_cpu(file_alloc_info->AllocationSize) + 511) >> 9; 5605 5511 inode = file_inode(fp->filp); 5606 5512 ··· 5635 5543 } 5636 5544 5637 5545 static int set_end_of_file_info(struct ksmbd_work *work, struct ksmbd_file *fp, 5638 - char *buf) 5546 + struct smb2_file_eof_info *file_eof_info) 5639 5547 { 5640 - struct smb2_file_eof_info *file_eof_info; 5641 5548 loff_t newsize; 5642 5549 struct inode *inode; 5643 5550 int rc; ··· 5644 5553 if (!(fp->daccess & FILE_WRITE_DATA_LE)) 5645 5554 return -EACCES; 5646 5555 5647 - file_eof_info = (struct smb2_file_eof_info *)buf; 5648 5556 newsize = le64_to_cpu(file_eof_info->EndOfFile); 5649 5557 inode = file_inode(fp->filp); 5650 5558 ··· 5670 5580 } 5671 5581 5672 5582 static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp, 5673 - char *buf) 5583 + struct smb2_file_rename_info *rename_info, 5584 + unsigned int buf_len) 5674 5585 { 5675 5586 struct user_namespace *user_ns; 5676 5587 struct ksmbd_file *parent_fp; ··· 5683 5592 pr_err("no right to delete : 0x%x\n", fp->daccess); 5684 5593 return -EACCES; 5685 5594 } 5595 + 5596 + if (buf_len < (u64)sizeof(struct smb2_file_rename_info) + 5597 + le32_to_cpu(rename_info->FileNameLength)) 5598 + return -EINVAL; 5686 5599 5687 5600 user_ns = file_mnt_user_ns(fp->filp); 5688 5601 if (ksmbd_stream_fd(fp)) ··· 5710 5615 } 5711 5616 } 5712 5617 next: 5713 - return smb2_rename(work, fp, user_ns, 5714 - (struct smb2_file_rename_info *)buf, 5618 + return smb2_rename(work, fp, user_ns, rename_info, 5715 5619 work->sess->conn->local_nls); 5716 5620 } 5717 5621 5718 - static int set_file_disposition_info(struct ksmbd_file *fp, char *buf) 5622 + static int set_file_disposition_info(struct ksmbd_file *fp, 5623 + struct smb2_file_disposition_info *file_info) 5719 5624 { 5720 - struct smb2_file_disposition_info *file_info; 5721 5625 struct inode *inode; 5722 5626 5723 5627 if (!(fp->daccess & FILE_DELETE_LE)) { ··· 5725 5631 } 5726 5632 5727 5633 inode = file_inode(fp->filp); 5728 - file_info = (struct smb2_file_disposition_info *)buf; 5729 5634 if (file_info->DeletePending) { 5730 5635 if (S_ISDIR(inode->i_mode) && 5731 5636 ksmbd_vfs_empty_dir(fp) == -ENOTEMPTY) ··· 5736 5643 return 0; 5737 5644 } 5738 5645 5739 - static int set_file_position_info(struct ksmbd_file *fp, char *buf) 5646 + static int set_file_position_info(struct ksmbd_file *fp, 5647 + struct smb2_file_pos_info *file_info) 5740 5648 { 5741 - struct smb2_file_pos_info *file_info; 5742 5649 loff_t current_byte_offset; 5743 5650 unsigned long sector_size; 5744 5651 struct inode *inode; 5745 5652 5746 5653 inode = file_inode(fp->filp); 5747 - file_info = (struct smb2_file_pos_info *)buf; 5748 5654 current_byte_offset = le64_to_cpu(file_info->CurrentByteOffset); 5749 5655 sector_size = inode->i_sb->s_blocksize; 5750 5656 ··· 5759 5667 return 0; 5760 5668 } 5761 5669 5762 - static int set_file_mode_info(struct ksmbd_file *fp, char *buf) 5670 + static int set_file_mode_info(struct ksmbd_file *fp, 5671 + struct smb2_file_mode_info *file_info) 5763 5672 { 5764 - struct smb2_file_mode_info *file_info; 5765 5673 __le32 mode; 5766 5674 5767 - file_info = (struct smb2_file_mode_info *)buf; 5768 5675 mode = file_info->Mode; 5769 5676 5770 5677 if ((mode & ~FILE_MODE_INFO_MASK) || ··· 5793 5702 * TODO: need to implement an error handling for STATUS_INFO_LENGTH_MISMATCH 5794 5703 */ 5795 5704 static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, 5796 - int info_class, char *buf, 5705 + struct smb2_set_info_req *req, 5797 5706 struct ksmbd_share_config *share) 5798 5707 { 5799 - switch (info_class) { 5708 + unsigned int buf_len = le32_to_cpu(req->BufferLength); 5709 + 5710 + switch (req->FileInfoClass) { 5800 5711 case FILE_BASIC_INFORMATION: 5801 - return set_file_basic_info(fp, buf, share); 5712 + { 5713 + if (buf_len < sizeof(struct smb2_file_basic_info)) 5714 + return -EINVAL; 5802 5715 5716 + return set_file_basic_info(fp, (struct smb2_file_basic_info *)req->Buffer, share); 5717 + } 5803 5718 case FILE_ALLOCATION_INFORMATION: 5804 - return set_file_allocation_info(work, fp, buf); 5719 + { 5720 + if (buf_len < sizeof(struct smb2_file_alloc_info)) 5721 + return -EINVAL; 5805 5722 5723 + return set_file_allocation_info(work, fp, 5724 + (struct smb2_file_alloc_info *)req->Buffer); 5725 + } 5806 5726 case FILE_END_OF_FILE_INFORMATION: 5807 - return set_end_of_file_info(work, fp, buf); 5727 + { 5728 + if (buf_len < sizeof(struct smb2_file_eof_info)) 5729 + return -EINVAL; 5808 5730 5731 + return set_end_of_file_info(work, fp, 5732 + (struct smb2_file_eof_info *)req->Buffer); 5733 + } 5809 5734 case FILE_RENAME_INFORMATION: 5735 + { 5810 5736 if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { 5811 5737 ksmbd_debug(SMB, 5812 5738 "User does not have write permission\n"); 5813 5739 return -EACCES; 5814 5740 } 5815 - return set_rename_info(work, fp, buf); 5816 5741 5742 + if (buf_len < sizeof(struct smb2_file_rename_info)) 5743 + return -EINVAL; 5744 + 5745 + return set_rename_info(work, fp, 5746 + (struct smb2_file_rename_info *)req->Buffer, 5747 + buf_len); 5748 + } 5817 5749 case FILE_LINK_INFORMATION: 5818 - return smb2_create_link(work, work->tcon->share_conf, 5819 - (struct smb2_file_link_info *)buf, fp->filp, 5820 - work->sess->conn->local_nls); 5750 + { 5751 + if (buf_len < sizeof(struct smb2_file_link_info)) 5752 + return -EINVAL; 5821 5753 5754 + return smb2_create_link(work, work->tcon->share_conf, 5755 + (struct smb2_file_link_info *)req->Buffer, 5756 + buf_len, fp->filp, 5757 + work->sess->conn->local_nls); 5758 + } 5822 5759 case FILE_DISPOSITION_INFORMATION: 5760 + { 5823 5761 if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { 5824 5762 ksmbd_debug(SMB, 5825 5763 "User does not have write permission\n"); 5826 5764 return -EACCES; 5827 5765 } 5828 - return set_file_disposition_info(fp, buf); 5829 5766 5767 + if (buf_len < sizeof(struct smb2_file_disposition_info)) 5768 + return -EINVAL; 5769 + 5770 + return set_file_disposition_info(fp, 5771 + (struct smb2_file_disposition_info *)req->Buffer); 5772 + } 5830 5773 case FILE_FULL_EA_INFORMATION: 5831 5774 { 5832 5775 if (!(fp->daccess & FILE_WRITE_EA_LE)) { ··· 5869 5744 return -EACCES; 5870 5745 } 5871 5746 5872 - return smb2_set_ea((struct smb2_ea_info *)buf, 5873 - &fp->filp->f_path); 5874 - } 5747 + if (buf_len < sizeof(struct smb2_ea_info)) 5748 + return -EINVAL; 5875 5749 5750 + return smb2_set_ea((struct smb2_ea_info *)req->Buffer, 5751 + buf_len, &fp->filp->f_path); 5752 + } 5876 5753 case FILE_POSITION_INFORMATION: 5877 - return set_file_position_info(fp, buf); 5754 + { 5755 + if (buf_len < sizeof(struct smb2_file_pos_info)) 5756 + return -EINVAL; 5878 5757 5758 + return set_file_position_info(fp, (struct smb2_file_pos_info *)req->Buffer); 5759 + } 5879 5760 case FILE_MODE_INFORMATION: 5880 - return set_file_mode_info(fp, buf); 5761 + { 5762 + if (buf_len < sizeof(struct smb2_file_mode_info)) 5763 + return -EINVAL; 5764 + 5765 + return set_file_mode_info(fp, (struct smb2_file_mode_info *)req->Buffer); 5766 + } 5881 5767 } 5882 5768 5883 - pr_err("Unimplemented Fileinfoclass :%d\n", info_class); 5769 + pr_err("Unimplemented Fileinfoclass :%d\n", req->FileInfoClass); 5884 5770 return -EOPNOTSUPP; 5885 5771 } 5886 5772 ··· 5952 5816 switch (req->InfoType) { 5953 5817 case SMB2_O_INFO_FILE: 5954 5818 ksmbd_debug(SMB, "GOT SMB2_O_INFO_FILE\n"); 5955 - rc = smb2_set_info_file(work, fp, req->FileInfoClass, 5956 - req->Buffer, work->tcon->share_conf); 5819 + rc = smb2_set_info_file(work, fp, req, work->tcon->share_conf); 5957 5820 break; 5958 5821 case SMB2_O_INFO_SECURITY: 5959 5822 ksmbd_debug(SMB, "GOT SMB2_O_INFO_SECURITY\n"); ··· 8306 8171 8307 8172 WORK_BUFFERS(work, req, rsp); 8308 8173 8309 - if (le16_to_cpu(req->Command) == SMB2_NEGOTIATE_HE) 8174 + if (le16_to_cpu(req->Command) == SMB2_NEGOTIATE_HE && 8175 + conn->preauth_info) 8310 8176 ksmbd_gen_preauth_integrity_hash(conn, (char *)rsp, 8311 8177 conn->preauth_info->Preauth_HashValue); 8312 8178 ··· 8414 8278 unsigned int buf_data_size = pdu_length + 4 - 8415 8279 sizeof(struct smb2_transform_hdr); 8416 8280 struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf; 8417 - unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize); 8418 8281 int rc = 0; 8419 - 8420 - sess = ksmbd_session_lookup_all(conn, le64_to_cpu(tr_hdr->SessionId)); 8421 - if (!sess) { 8422 - pr_err("invalid session id(%llx) in transform header\n", 8423 - le64_to_cpu(tr_hdr->SessionId)); 8424 - return -ECONNABORTED; 8425 - } 8426 8282 8427 8283 if (pdu_length + 4 < 8428 8284 sizeof(struct smb2_transform_hdr) + sizeof(struct smb2_hdr)) { ··· 8423 8295 return -ECONNABORTED; 8424 8296 } 8425 8297 8426 - if (pdu_length + 4 < orig_len + sizeof(struct smb2_transform_hdr)) { 8298 + if (pdu_length + 4 < 8299 + le32_to_cpu(tr_hdr->OriginalMessageSize) + sizeof(struct smb2_transform_hdr)) { 8427 8300 pr_err("Transform message is broken\n"); 8301 + return -ECONNABORTED; 8302 + } 8303 + 8304 + sess = ksmbd_session_lookup_all(conn, le64_to_cpu(tr_hdr->SessionId)); 8305 + if (!sess) { 8306 + pr_err("invalid session id(%llx) in transform header\n", 8307 + le64_to_cpu(tr_hdr->SessionId)); 8428 8308 return -ECONNABORTED; 8429 8309 } 8430 8310
+9
fs/ksmbd/smb2pdu.h
··· 1464 1464 char FileName[1]; 1465 1465 } __packed; /* level 18 Query */ 1466 1466 1467 + struct smb2_file_basic_info { /* data block encoding of response to level 18 */ 1468 + __le64 CreationTime; /* Beginning of FILE_BASIC_INFO equivalent */ 1469 + __le64 LastAccessTime; 1470 + __le64 LastWriteTime; 1471 + __le64 ChangeTime; 1472 + __le32 Attributes; 1473 + __u32 Pad1; /* End of FILE_BASIC_INFO_INFO equivalent */ 1474 + } __packed; 1475 + 1467 1476 struct smb2_file_alt_name_info { 1468 1477 __le32 FileNameLength; 1469 1478 char FileName[0];
+28 -19
fs/ksmbd/smb_common.c
··· 155 155 */ 156 156 bool ksmbd_smb_request(struct ksmbd_conn *conn) 157 157 { 158 - int type = *(char *)conn->request_buf; 159 - 160 - switch (type) { 161 - case RFC1002_SESSION_MESSAGE: 162 - /* Regular SMB request */ 163 - return true; 164 - case RFC1002_SESSION_KEEP_ALIVE: 165 - ksmbd_debug(SMB, "RFC 1002 session keep alive\n"); 166 - break; 167 - default: 168 - ksmbd_debug(SMB, "RFC 1002 unknown request type 0x%x\n", type); 169 - } 170 - 171 - return false; 158 + return conn->request_buf[0] == 0; 172 159 } 173 160 174 161 static bool supported_protocol(int idx) ··· 169 182 idx <= server_conf.max_protocol); 170 183 } 171 184 172 - static char *next_dialect(char *dialect, int *next_off) 185 + static char *next_dialect(char *dialect, int *next_off, int bcount) 173 186 { 174 187 dialect = dialect + *next_off; 175 - *next_off = strlen(dialect); 188 + *next_off = strnlen(dialect, bcount); 189 + if (dialect[*next_off] != '\0') 190 + return NULL; 176 191 return dialect; 177 192 } 178 193 ··· 189 200 dialect = cli_dialects; 190 201 bcount = le16_to_cpu(byte_count); 191 202 do { 192 - dialect = next_dialect(dialect, &next); 203 + dialect = next_dialect(dialect, &next, bcount); 204 + if (!dialect) 205 + break; 193 206 ksmbd_debug(SMB, "client requested dialect %s\n", 194 207 dialect); 195 208 if (!strcmp(dialect, smb1_protos[i].name)) { ··· 239 248 240 249 static int ksmbd_negotiate_smb_dialect(void *buf) 241 250 { 242 - __le32 proto; 251 + int smb_buf_length = get_rfc1002_len(buf); 252 + __le32 proto = ((struct smb2_hdr *)buf)->ProtocolId; 243 253 244 - proto = ((struct smb2_hdr *)buf)->ProtocolId; 245 254 if (proto == SMB2_PROTO_NUMBER) { 246 255 struct smb2_negotiate_req *req; 256 + int smb2_neg_size = 257 + offsetof(struct smb2_negotiate_req, Dialects) - 4; 247 258 248 259 req = (struct smb2_negotiate_req *)buf; 260 + if (smb2_neg_size > smb_buf_length) 261 + goto err_out; 262 + 263 + if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) > 264 + smb_buf_length) 265 + goto err_out; 266 + 249 267 return ksmbd_lookup_dialect_by_id(req->Dialects, 250 268 req->DialectCount); 251 269 } ··· 264 264 struct smb_negotiate_req *req; 265 265 266 266 req = (struct smb_negotiate_req *)buf; 267 + if (le16_to_cpu(req->ByteCount) < 2) 268 + goto err_out; 269 + 270 + if (offsetof(struct smb_negotiate_req, DialectsArray) - 4 + 271 + le16_to_cpu(req->ByteCount) > smb_buf_length) { 272 + goto err_out; 273 + } 274 + 267 275 return ksmbd_lookup_dialect_by_name(req->DialectsArray, 268 276 req->ByteCount); 269 277 } 270 278 279 + err_out: 271 280 return BAD_PROT_ID; 272 281 } 273 282
-8
fs/ksmbd/smb_common.h
··· 48 48 #define CIFS_DEFAULT_IOSIZE (64 * 1024) 49 49 #define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */ 50 50 51 - /* RFC 1002 session packet types */ 52 - #define RFC1002_SESSION_MESSAGE 0x00 53 - #define RFC1002_SESSION_REQUEST 0x81 54 - #define RFC1002_POSITIVE_SESSION_RESPONSE 0x82 55 - #define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83 56 - #define RFC1002_RETARGET_SESSION_RESPONSE 0x84 57 - #define RFC1002_SESSION_KEEP_ALIVE 0x85 58 - 59 51 /* Responses when opening a file. */ 60 52 #define F_SUPERSEDED 0 61 53 #define F_OPENED 1
+19 -2
fs/ksmbd/smbacl.c
··· 380 380 { 381 381 int i, ret; 382 382 int num_aces = 0; 383 - int acl_size; 383 + unsigned int acl_size; 384 384 char *acl_base; 385 385 struct smb_ace **ppace; 386 386 struct posix_acl_entry *cf_pace, *cf_pdace; ··· 392 392 return; 393 393 394 394 /* validate that we do not go past end of acl */ 395 - if (end_of_acl <= (char *)pdacl || 395 + if (end_of_acl < (char *)pdacl + sizeof(struct smb_acl) || 396 396 end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) { 397 397 pr_err("ACL too small to parse DACL\n"); 398 398 return; ··· 431 431 * user/group/other have no permissions 432 432 */ 433 433 for (i = 0; i < num_aces; ++i) { 434 + if (end_of_acl - acl_base < acl_size) 435 + break; 436 + 434 437 ppace[i] = (struct smb_ace *)(acl_base + acl_size); 435 438 acl_base = (char *)ppace[i]; 439 + acl_size = offsetof(struct smb_ace, sid) + 440 + offsetof(struct smb_sid, sub_auth); 441 + 442 + if (end_of_acl - acl_base < acl_size || 443 + ppace[i]->sid.num_subauth > SID_MAX_SUB_AUTHORITIES || 444 + (end_of_acl - acl_base < 445 + acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth) || 446 + (le16_to_cpu(ppace[i]->size) < 447 + acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth)) 448 + break; 449 + 436 450 acl_size = le16_to_cpu(ppace[i]->size); 437 451 ppace[i]->access_req = 438 452 smb_map_generic_desired_access(ppace[i]->access_req); ··· 820 806 821 807 if (!pntsd) 822 808 return -EIO; 809 + 810 + if (acl_len < sizeof(struct smb_ntsd)) 811 + return -EINVAL; 823 812 824 813 owner_sid_ptr = (struct smb_sid *)((char *)pntsd + 825 814 le32_to_cpu(pntsd->osidoffset));
+2 -2
fs/ksmbd/transport_tcp.c
··· 215 215 * ksmbd_kthread_fn() - listen to new SMB connections and callback server 216 216 * @p: arguments to forker thread 217 217 * 218 - * Return: Returns a task_struct or ERR_PTR 218 + * Return: 0 on success, error number otherwise 219 219 */ 220 220 static int ksmbd_kthread_fn(void *p) 221 221 { ··· 387 387 /** 388 388 * create_socket - create socket for ksmbd/0 389 389 * 390 - * Return: Returns a task_struct or ERR_PTR 390 + * Return: 0 on success, error number otherwise 391 391 */ 392 392 static int create_socket(struct interface *iface) 393 393 {