History

Merge tag '6.4-rc5-smb3-server-fixes' of git://git.samba.org/ksmbd

Pull smb server fixes from Steve French: "Five smb3 server fixes, all also for stable: - Fix four slab out of bounds warnings: improve checks for protocol id, and for small packet length, and for create context parsing, and for negotiate context parsing - Fix for incorrect dereferencing POSIX ACLs" * tag '6.4-rc5-smb3-server-fixes' of git://git.samba.org/ksmbd: ksmbd: validate smb request protocol id ksmbd: check the validation of pdu_size in ksmbd_conn_handler_loop ksmbd: fix posix_acls and acls dereferencing possible ERR_PTR() ksmbd: fix out-of-bound read in parse_lease_state() ksmbd: fix out-of-bound read in deassemble_neg_contexts()

Linus Torvalds committed 3 years ago

Commit 65d7ca52 parents 022ce88 1c1bcf26 files · +62 −56Browse files

Unified · Split

6 files
  1. fs/smb/server/connection.c +15 −2
  2. fs/smb/server/oplock.c +24 −42
  3. fs/smb/server/smb2pdu.c +6 −7
  4. fs/smb/server/smb_common.c +13 −1
  5. fs/smb/server/smbacl.c +2 −2
  6. fs/smb/server/vfs.c +2 −2
fs/smb/server/connection.c+15−2
@@ -294,6 +294,9 @@ bool ksmbd_conn_alive(struct ksmbd_conn *conn) · 293 unmodified lines
294 return true;294 return true;
295}295}
296 296
297#define SMB1_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb_hdr))
298#define SMB2_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb2_hdr) + 4)
299
297/**300/**
298 * ksmbd_conn_handler_loop() - session thread to listen on new smb requests301 * ksmbd_conn_handler_loop() - session thread to listen on new smb requests
299 * @p: connection instance302 * @p: connection instance
@@ -350,6 +353,9 @@ int ksmbd_conn_handler_loop(void *p) · 50 unmodified lines
350 if (pdu_size > MAX_STREAM_PROT_LEN)353 if (pdu_size > MAX_STREAM_PROT_LEN)
351 break;354 break;
352 355
356 if (pdu_size < SMB1_MIN_SUPPORTED_HEADER_SIZE)
357 break;
358
353 /* 4 for rfc1002 length field */359 /* 4 for rfc1002 length field */
354 /* 1 for implied bcc[0] */360 /* 1 for implied bcc[0] */
355 size = pdu_size + 4 + 1;361 size = pdu_size + 4 + 1;
@@ -358,8 +364,6 @@ int ksmbd_conn_handler_loop(void *p) · 2 unmodified lines
358 break;364 break;
359 365
360 memcpy(conn->request_buf, hdr_buf, sizeof(hdr_buf));366 memcpy(conn->request_buf, hdr_buf, sizeof(hdr_buf));
361 if (!ksmbd_smb_request(conn))
362 break;
363 367
364 /*368 /*
365 * We already read 4 bytes to find out PDU size, now369 * We already read 4 bytes to find out PDU size, now
@@ -377,6 +381,15 @@ int ksmbd_conn_handler_loop(void *p) · 11 unmodified lines
377 continue;381 continue;
378 }382 }
379 383
384 if (!ksmbd_smb_request(conn))
385 break;
386
387 if (((struct smb2_hdr *)smb2_get_msg(conn->request_buf))->ProtocolId ==
388 SMB2_PROTO_NUMBER) {
389 if (pdu_size < SMB2_MIN_SUPPORTED_HEADER_SIZE)
390 break;
391 }
392
380 if (!default_conn_ops.process_fn) {393 if (!default_conn_ops.process_fn) {
381 pr_err("No connection request callback\n");394 pr_err("No connection request callback\n");
382 break;395 break;
fs/smb/server/oplock.c+24−42
@@ -1415,56 +1415,38 @@ void create_lease_buf(u8 *rbuf, struct lease *lease) · 1414 unmodified lines
1415 */1415 */
1416struct lease_ctx_info *parse_lease_state(void *open_req)1416struct lease_ctx_info *parse_lease_state(void *open_req)
1417{1417{
1418 char *data_offset;
1419 struct create_context *cc;1418 struct create_context *cc;
1420 unsigned int next = 0;
1421 char *name;
1422 bool found = false;
1423 struct smb2_create_req *req = (struct smb2_create_req *)open_req;1419 struct smb2_create_req *req = (struct smb2_create_req *)open_req;
1424 struct lease_ctx_info *lreq = kzalloc(sizeof(struct lease_ctx_info),1420 struct lease_ctx_info *lreq;
1425 GFP_KERNEL);1421
1422 cc = smb2_find_context_vals(req, SMB2_CREATE_REQUEST_LEASE, 4);
1423 if (IS_ERR_OR_NULL(cc))
1424 return NULL;
1425
1426 lreq = kzalloc(sizeof(struct lease_ctx_info), GFP_KERNEL);
1426 if (!lreq)1427 if (!lreq)
1427 return NULL;1428 return NULL;
1428 1429
1429 data_offset = (char *)req + le32_to_cpu(req->CreateContextsOffset);1430 if (sizeof(struct lease_context_v2) == le32_to_cpu(cc->DataLength)) {
1430 cc = (struct create_context *)data_offset;1431 struct create_lease_v2 *lc = (struct create_lease_v2 *)cc;
1431 do {
1432 cc = (struct create_context *)((char *)cc + next);
1433 name = le16_to_cpu(cc->NameOffset) + (char *)cc;
1434 if (le16_to_cpu(cc->NameLength) != 4 ||
1435 strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4)) {
1436 next = le32_to_cpu(cc->Next);
1437 continue;
1438 }
1439 found = true;
1440 break;
1441 } while (next != 0);
1442 1432
1443 if (found) {1433 memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
1444 if (sizeof(struct lease_context_v2) == le32_to_cpu(cc->DataLength)) {1434 lreq->req_state = lc->lcontext.LeaseState;
1445 struct create_lease_v2 *lc = (struct create_lease_v2 *)cc;1435 lreq->flags = lc->lcontext.LeaseFlags;
1446 1436 lreq->duration = lc->lcontext.LeaseDuration;
1447 memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);1437 memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,
1448 lreq->req_state = lc->lcontext.LeaseState;1438 SMB2_LEASE_KEY_SIZE);
1449 lreq->flags = lc->lcontext.LeaseFlags;1439 lreq->version = 2;
1450 lreq->duration = lc->lcontext.LeaseDuration;1440 } else {
1451 memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,1441 struct create_lease *lc = (struct create_lease *)cc;
1452 SMB2_LEASE_KEY_SIZE);
1453 lreq->version = 2;
1454 } else {
1455 struct create_lease *lc = (struct create_lease *)cc;
1456 1442
1457 memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);1443 memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
1458 lreq->req_state = lc->lcontext.LeaseState;1444 lreq->req_state = lc->lcontext.LeaseState;
1459 lreq->flags = lc->lcontext.LeaseFlags;1445 lreq->flags = lc->lcontext.LeaseFlags;
1460 lreq->duration = lc->lcontext.LeaseDuration;1446 lreq->duration = lc->lcontext.LeaseDuration;
1461 lreq->version = 1;1447 lreq->version = 1;
1462 }
1463 return lreq;
1464 }1448 }
1465 1449 return lreq;
1466 kfree(lreq);
1467 return NULL;
1468}1450}
1469 1451
1470/**1452/**
fs/smb/server/smb2pdu.c+6−7
@@ -963,13 +963,13 @@ static void decode_sign_cap_ctxt(struct ksmbd_conn *conn, · 962 unmodified lines
963 963
964static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,964static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
965 struct smb2_negotiate_req *req,965 struct smb2_negotiate_req *req,
966 int len_of_smb)966 unsigned int len_of_smb)
967{967{
968 /* +4 is to account for the RFC1001 len field */968 /* +4 is to account for the RFC1001 len field */
969 struct smb2_neg_context *pctx = (struct smb2_neg_context *)req;969 struct smb2_neg_context *pctx = (struct smb2_neg_context *)req;
970 int i = 0, len_of_ctxts;970 int i = 0, len_of_ctxts;
971 int offset = le32_to_cpu(req->NegotiateContextOffset);971 unsigned int offset = le32_to_cpu(req->NegotiateContextOffset);
972 int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount);972 unsigned int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount);
973 __le32 status = STATUS_INVALID_PARAMETER;973 __le32 status = STATUS_INVALID_PARAMETER;
974 974
975 ksmbd_debug(SMB, "decoding %d negotiate contexts\n", neg_ctxt_cnt);975 ksmbd_debug(SMB, "decoding %d negotiate contexts\n", neg_ctxt_cnt);
@@ -983,7 +983,7 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn, · 7 unmodified lines
983 while (i++ < neg_ctxt_cnt) {983 while (i++ < neg_ctxt_cnt) {
984 int clen, ctxt_len;984 int clen, ctxt_len;
985 985
986 if (len_of_ctxts < sizeof(struct smb2_neg_context))986 if (len_of_ctxts < (int)sizeof(struct smb2_neg_context))
987 break;987 break;
988 988
989 pctx = (struct smb2_neg_context *)((char *)pctx + offset);989 pctx = (struct smb2_neg_context *)((char *)pctx + offset);
@@ -1038,9 +1038,8 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn, · 48 unmodified lines
1038 }1038 }
1039 1039
1040 /* offsets must be 8 byte aligned */1040 /* offsets must be 8 byte aligned */
1041 clen = (clen + 7) & ~0x7;1041 offset = (ctxt_len + 7) & ~0x7;
1042 offset = clen + sizeof(struct smb2_neg_context);1042 len_of_ctxts -= offset;
1043 len_of_ctxts -= clen + sizeof(struct smb2_neg_context);
1044 }1043 }
1045 return status;1044 return status;
1046}1045}
fs/smb/server/smb_common.c+13−1
@@ -158,7 +158,19 @@ int ksmbd_verify_smb_message(struct ksmbd_work *work) · 157 unmodified lines
158 */158 */
159bool ksmbd_smb_request(struct ksmbd_conn *conn)159bool ksmbd_smb_request(struct ksmbd_conn *conn)
160{160{
161 return conn->request_buf[0] == 0;161 __le32 *proto = (__le32 *)smb2_get_msg(conn->request_buf);
162
163 if (*proto == SMB2_COMPRESSION_TRANSFORM_ID) {
164 pr_err_ratelimited("smb2 compression not support yet");
165 return false;
166 }
167
168 if (*proto != SMB1_PROTO_NUMBER &&
169 *proto != SMB2_PROTO_NUMBER &&
170 *proto != SMB2_TRANSFORM_PROTO_NUM)
171 return false;
172
173 return true;
162}174}
163 175
164static bool supported_protocol(int idx)176static bool supported_protocol(int idx)
fs/smb/server/smbacl.c+2−2
@@ -1290,7 +1290,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path, · 1289 unmodified lines
1290 1290
1291 if (IS_ENABLED(CONFIG_FS_POSIX_ACL)) {1291 if (IS_ENABLED(CONFIG_FS_POSIX_ACL)) {
1292 posix_acls = get_inode_acl(d_inode(path->dentry), ACL_TYPE_ACCESS);1292 posix_acls = get_inode_acl(d_inode(path->dentry), ACL_TYPE_ACCESS);
1293 if (posix_acls && !found) {1293 if (!IS_ERR_OR_NULL(posix_acls) && !found) {
1294 unsigned int id = -1;1294 unsigned int id = -1;
1295 1295
1296 pa_entry = posix_acls->a_entries;1296 pa_entry = posix_acls->a_entries;
@@ -1314,7 +1314,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path, · 17 unmodified lines
1314 }1314 }
1315 }1315 }
1316 }1316 }
1317 if (posix_acls)1317 if (!IS_ERR_OR_NULL(posix_acls))
1318 posix_acl_release(posix_acls);1318 posix_acl_release(posix_acls);
1319 }1319 }
1320 1320
fs/smb/server/vfs.c+2−2
@@ -1321,7 +1321,7 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct mnt_idmap *id · 1320 unmodified lines
1321 return NULL;1321 return NULL;
1322 1322
1323 posix_acls = get_inode_acl(inode, acl_type);1323 posix_acls = get_inode_acl(inode, acl_type);
1324 if (!posix_acls)1324 if (IS_ERR_OR_NULL(posix_acls))
1325 return NULL;1325 return NULL;
1326 1326
1327 smb_acl = kzalloc(sizeof(struct xattr_smb_acl) +1327 smb_acl = kzalloc(sizeof(struct xattr_smb_acl) +
@@ -1830,7 +1830,7 @@ int ksmbd_vfs_inherit_posix_acl(struct mnt_idmap *idmap, · 502 unmodified lines
1830 return -EOPNOTSUPP;1830 return -EOPNOTSUPP;
1831 1831
1832 acls = get_inode_acl(parent_inode, ACL_TYPE_DEFAULT);1832 acls = get_inode_acl(parent_inode, ACL_TYPE_DEFAULT);
1833 if (!acls)1833 if (IS_ERR_OR_NULL(acls))
1834 return -ENOENT;1834 return -ENOENT;
1835 pace = acls->a_entries;1835 pace = acls->a_entries;
1836 1836

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t