Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'v7.1-rc3-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

- Fix for two ACL issues (security fix to validate dacloffset better
and chmod fix)

- Fix out of bounds reads (in check_wsl_eas and smb2_check_msg for
symlinks)

- Two Kerberos fixes including an important one when AES-256 encryption
chosen

- Fix open_cached_dir problem when directory leases disabled

* tag 'v7.1-rc3-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
smb: client: validate dacloffset before building DACL pointers
smb/client: fix out-of-bounds read in smb2_compound_op()
smb/client: fix out-of-bounds read in symlink_data()
smb: client: Zero-pad short GSS session keys per MS-SMB2
smb: client: Use FullSessionKey for AES-256 encryption key derivation
smb: client: use kzalloc to zero-initialize security descriptor buffer
cifs: abort open_cached_dir if we don't request leases

+96 -24
+8
fs/smb/client/cached_dir.c
··· 286 286 &rqst[0], &oplock, &oparms, utf16_path); 287 287 if (rc) 288 288 goto oshr_free; 289 + 290 + if (oplock != SMB2_OPLOCK_LEVEL_II) { 291 + rc = -EINVAL; 292 + cifs_dbg(FYI, "%s: Oplock level %d not suitable for cached directory\n", 293 + __func__, oplock); 294 + goto oshr_free; 295 + } 296 + 289 297 smb2_set_next_command(tcon, &rqst[0]); 290 298 291 299 memset(&qi_iov, 0, sizeof(qi_iov));
+33 -4
fs/smb/client/cifsacl.c
··· 1264 1264 return 0; 1265 1265 } 1266 1266 1267 + static bool dacl_offset_valid(unsigned int acl_len, __u32 dacloffset) 1268 + { 1269 + if (acl_len < sizeof(struct smb_acl)) 1270 + return false; 1271 + 1272 + if (dacloffset < sizeof(struct smb_ntsd)) 1273 + return false; 1274 + 1275 + return dacloffset <= acl_len - sizeof(struct smb_acl); 1276 + } 1277 + 1267 1278 1268 1279 /* Convert CIFS ACL to POSIX form */ 1269 1280 static int parse_sec_desc(struct cifs_sb_info *cifs_sb, ··· 1295 1284 group_sid_ptr = (struct smb_sid *)((char *)pntsd + 1296 1285 le32_to_cpu(pntsd->gsidoffset)); 1297 1286 dacloffset = le32_to_cpu(pntsd->dacloffset); 1298 - dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset); 1299 1287 cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n", 1300 1288 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset), 1301 1289 le32_to_cpu(pntsd->gsidoffset), ··· 1325 1315 return rc; 1326 1316 } 1327 1317 1328 - if (dacloffset) 1318 + if (dacloffset) { 1319 + if (!dacl_offset_valid(acl_len, dacloffset)) { 1320 + cifs_dbg(VFS, "Server returned illegal DACL offset\n"); 1321 + return -EINVAL; 1322 + } 1323 + 1324 + dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset); 1329 1325 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, 1330 1326 group_sid_ptr, fattr, get_mode_from_special_sid); 1331 - else 1327 + } else { 1332 1328 cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */ 1329 + } 1333 1330 1334 1331 return rc; 1335 1332 } ··· 1359 1342 1360 1343 dacloffset = le32_to_cpu(pntsd->dacloffset); 1361 1344 if (dacloffset) { 1345 + if (!dacl_offset_valid(secdesclen, dacloffset)) { 1346 + cifs_dbg(VFS, "Server returned illegal DACL offset\n"); 1347 + return -EINVAL; 1348 + } 1349 + 1362 1350 dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset); 1363 1351 rc = validate_dacl(dacl_ptr, end_of_acl); 1364 1352 if (rc) ··· 1732 1710 nsecdesclen = sizeof(struct smb_ntsd) + (sizeof(struct smb_sid) * 2); 1733 1711 dacloffset = le32_to_cpu(pntsd->dacloffset); 1734 1712 if (dacloffset) { 1713 + if (!dacl_offset_valid(secdesclen, dacloffset)) { 1714 + cifs_dbg(VFS, "Server returned illegal DACL offset\n"); 1715 + rc = -EINVAL; 1716 + goto id_mode_to_cifs_acl_exit; 1717 + } 1718 + 1735 1719 dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset); 1736 1720 rc = validate_dacl(dacl_ptr, (char *)pntsd + secdesclen); 1737 1721 if (rc) { ··· 1760 1732 * descriptor parameters, and security descriptor itself 1761 1733 */ 1762 1734 nsecdesclen = max_t(u32, nsecdesclen, DEFAULT_SEC_DESC_LEN); 1763 - pnntsd = kmalloc(nsecdesclen, GFP_KERNEL); 1735 + pnntsd = kzalloc(nsecdesclen, GFP_KERNEL); 1764 1736 if (!pnntsd) { 1765 1737 kfree(pntsd); 1766 1738 cifs_put_tlink(tlink); ··· 1780 1752 rc = ops->set_acl(pnntsd, nsecdesclen, inode, path, aclflag); 1781 1753 cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc); 1782 1754 } 1755 + id_mode_to_cifs_acl_exit: 1783 1756 cifs_put_tlink(tlink); 1784 1757 1785 1758 kfree(pnntsd);
+1 -1
fs/smb/client/ioctl.c
··· 296 296 break; 297 297 case SMB2_ENCRYPTION_AES256_CCM: 298 298 case SMB2_ENCRYPTION_AES256_GCM: 299 - out.session_key_length = CIFS_SESS_KEY_SIZE; 299 + out.session_key_length = ses->auth_key.len; 300 300 out.server_in_key_length = out.server_out_key_length = SMB3_GCM256_CRYPTKEY_SIZE; 301 301 break; 302 302 default:
+8 -4
fs/smb/client/smb2inode.c
··· 111 111 u32 outlen, next; 112 112 u16 vlen; 113 113 u8 nlen; 114 - u8 *end; 114 + u8 *ea_end, *iov_end; 115 115 116 116 outlen = le32_to_cpu(rsp->OutputBufferLength); 117 117 if (outlen < SMB2_WSL_MIN_QUERY_EA_RESP_SIZE || ··· 120 120 121 121 ea = (void *)((u8 *)rsp_iov->iov_base + 122 122 le16_to_cpu(rsp->OutputBufferOffset)); 123 - end = (u8 *)rsp_iov->iov_base + rsp_iov->iov_len; 123 + ea_end = (u8 *)ea + outlen; 124 + iov_end = (u8 *)rsp_iov->iov_base + rsp_iov->iov_len; 125 + if (ea_end > iov_end) 126 + return -EINVAL; 127 + 124 128 for (;;) { 125 - if ((u8 *)ea > end - sizeof(*ea)) 129 + if ((u8 *)ea > ea_end - sizeof(*ea)) 126 130 return -EINVAL; 127 131 128 132 nlen = ea->ea_name_length; 129 133 vlen = le16_to_cpu(ea->ea_value_length); 130 134 if (nlen != SMB2_WSL_XATTR_NAME_LEN || 131 - (u8 *)ea->ea_data + nlen + 1 + vlen > end) 135 + (u8 *)ea->ea_data + nlen + 1 + vlen > ea_end) 132 136 return -EINVAL; 133 137 134 138 switch (vlen) {
+2 -1
fs/smb/client/smb2misc.c
··· 241 241 if (len != calc_len) { 242 242 /* create failed on symlink */ 243 243 if (command == SMB2_CREATE_HE && 244 - shdr->Status == STATUS_STOPPED_ON_SYMLINK) 244 + shdr->Status == STATUS_STOPPED_ON_SYMLINK && 245 + len > calc_len) 245 246 return 0; 246 247 /* Windows 7 server returns 24 bytes more */ 247 248 if (calc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE)
+18 -5
fs/smb/client/smb2pdu.c
··· 1713 1713 is_binding = (ses->ses_status == SES_GOOD); 1714 1714 spin_unlock(&ses->ses_lock); 1715 1715 1716 + /* 1717 + * Per MS-SMB2 3.2.5.3, Session.SessionKey is the first 16 bytes of the 1718 + * GSS cryptographic key, right-padded with zero bytes if shorter. 1719 + * Allocate at least SMB2_NTLMV2_SESSKEY_SIZE bytes (zeroed) so the KDF 1720 + * input buffer is always valid for HMAC-SHA256 even with deprecated 1721 + * Kerberos enctypes that return a short session key. 1722 + */ 1723 + if (unlikely(msg->sesskey_len < SMB2_NTLMV2_SESSKEY_SIZE)) 1724 + cifs_dbg(VFS, 1725 + "short GSS session key (%u bytes); zero-padding per MS-SMB2 3.2.5.3\n", 1726 + msg->sesskey_len); 1727 + 1716 1728 kfree_sensitive(ses->auth_key.response); 1717 - ses->auth_key.response = kmemdup(msg->data, 1718 - msg->sesskey_len, 1719 - GFP_KERNEL); 1729 + ses->auth_key.len = max_t(unsigned int, msg->sesskey_len, 1730 + SMB2_NTLMV2_SESSKEY_SIZE); 1731 + ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL); 1720 1732 if (!ses->auth_key.response) { 1721 1733 cifs_dbg(VFS, "%s: can't allocate (%u bytes) memory\n", 1722 - __func__, msg->sesskey_len); 1734 + __func__, ses->auth_key.len); 1735 + ses->auth_key.len = 0; 1723 1736 rc = -ENOMEM; 1724 1737 goto out_put_spnego_key; 1725 1738 } 1726 - ses->auth_key.len = msg->sesskey_len; 1739 + memcpy(ses->auth_key.response, msg->data, msg->sesskey_len); 1727 1740 1728 1741 sess_data->iov[1].iov_base = msg->data + msg->sesskey_len; 1729 1742 sess_data->iov[1].iov_len = msg->secblob_len;
+26 -9
fs/smb/client/smb2transport.c
··· 251 251 } 252 252 253 253 static void generate_key(struct cifs_ses *ses, struct kvec label, 254 - struct kvec context, __u8 *key, unsigned int key_size) 254 + struct kvec context, __u8 *key, unsigned int key_size, 255 + unsigned int full_key_size) 255 256 { 256 257 unsigned char zero = 0x0; 257 258 __u8 i[4] = {0, 0, 0, 1}; ··· 266 265 memset(key, 0x0, key_size); 267 266 268 267 hmac_sha256_init_usingrawkey(&hmac_ctx, ses->auth_key.response, 269 - SMB2_NTLMV2_SESSKEY_SIZE); 268 + full_key_size); 270 269 hmac_sha256_update(&hmac_ctx, i, 4); 271 270 hmac_sha256_update(&hmac_ctx, label.iov_base, label.iov_len); 272 271 hmac_sha256_update(&hmac_ctx, &zero, 1); ··· 299 298 struct TCP_Server_Info *server, 300 299 const struct derivation_triplet *ptriplet) 301 300 { 301 + unsigned int full_key_size = SMB2_NTLMV2_SESSKEY_SIZE; 302 302 bool is_binding = false; 303 303 int chan_index = 0; 304 304 ··· 332 330 if (is_binding) { 333 331 generate_key(ses, ptriplet->signing.label, 334 332 ptriplet->signing.context, 335 - ses->chans[chan_index].signkey, 336 - SMB3_SIGN_KEY_SIZE); 333 + ses->chans[chan_index].signkey, SMB3_SIGN_KEY_SIZE, 334 + SMB2_NTLMV2_SESSKEY_SIZE); 337 335 } else { 338 336 generate_key(ses, ptriplet->signing.label, 339 - ptriplet->signing.context, 340 - ses->smb3signingkey, SMB3_SIGN_KEY_SIZE); 337 + ptriplet->signing.context, ses->smb3signingkey, 338 + SMB3_SIGN_KEY_SIZE, SMB2_NTLMV2_SESSKEY_SIZE); 339 + 340 + /* 341 + * Per MS-SMB2 3.2.5.3.1, signing key always uses Session.SessionKey 342 + * (first 16 bytes). Encryption/decryption keys use 343 + * Session.FullSessionKey when dialect is 3.1.1 and cipher is 344 + * AES-256-CCM or AES-256-GCM, otherwise Session.SessionKey. 345 + */ 346 + 347 + if (server->dialect == SMB311_PROT_ID && 348 + (server->cipher_type == SMB2_ENCRYPTION_AES256_CCM || 349 + server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) 350 + full_key_size = ses->auth_key.len; 341 351 342 352 /* safe to access primary channel, since it will never go away */ 343 353 spin_lock(&ses->chan_lock); ··· 359 345 360 346 generate_key(ses, ptriplet->encryption.label, 361 347 ptriplet->encryption.context, 362 - ses->smb3encryptionkey, SMB3_ENC_DEC_KEY_SIZE); 348 + ses->smb3encryptionkey, SMB3_ENC_DEC_KEY_SIZE, 349 + full_key_size); 350 + 363 351 generate_key(ses, ptriplet->decryption.label, 364 352 ptriplet->decryption.context, 365 - ses->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE); 353 + ses->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE, 354 + full_key_size); 366 355 } 367 356 368 357 #ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS ··· 378 361 &ses->Suid); 379 362 cifs_dbg(VFS, "Cipher type %d\n", server->cipher_type); 380 363 cifs_dbg(VFS, "Session Key %*ph\n", 381 - SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response); 364 + (int)ses->auth_key.len, ses->auth_key.response); 382 365 cifs_dbg(VFS, "Signing Key %*ph\n", 383 366 SMB3_SIGN_KEY_SIZE, ses->smb3signingkey); 384 367 if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||