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

cifs: fix a buffer leak in smb2_query_symlink

This leak was introduced in 91cb74f5142c14dd921ab2d064b7b128054f9fae and caused us
to leak one small buffer for every symlink query.

Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>

authored by

Ronnie Sahlberg and committed by
Steve French
9d874c36 c7c137b9

+39 -29
+4 -2
fs/cifs/link.c
··· 421 421 return -ENOMEM; 422 422 } 423 423 424 - rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL); 424 + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL, 425 + NULL); 425 426 if (rc) 426 427 goto qmf_out_open_fail; 427 428 ··· 479 478 oparms.fid = &fid; 480 479 oparms.reconnect = false; 481 480 482 - rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL); 481 + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, 482 + NULL); 483 483 if (rc) { 484 484 kfree(utf16_path); 485 485 return rc;
+2 -1
fs/cifs/smb2file.c
··· 64 64 if (oparms->tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING) 65 65 memcpy(smb2_oplock + 1, fid->lease_key, SMB2_LEASE_KEY_SIZE); 66 66 67 - rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data, NULL); 67 + rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data, NULL, 68 + NULL); 68 69 if (rc) 69 70 goto out; 70 71
+2 -1
fs/cifs/smb2inode.c
··· 71 71 oparms.fid = &fid; 72 72 oparms.reconnect = false; 73 73 74 - rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL); 74 + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, 75 + NULL); 75 76 if (rc) { 76 77 kfree(utf16_path); 77 78 return rc;
+28 -23
fs/cifs/smb2ops.c
··· 348 348 oparams.fid = pfid; 349 349 oparams.reconnect = false; 350 350 351 - rc = SMB2_open(xid, &oparams, &srch_path, &oplock, NULL, NULL); 351 + rc = SMB2_open(xid, &oparams, &srch_path, &oplock, NULL, NULL, NULL); 352 352 if (rc == 0) { 353 353 memcpy(tcon->prfid, pfid, sizeof(struct cifs_fid)); 354 354 tcon->valid_root_fid = true; ··· 375 375 oparms.reconnect = false; 376 376 377 377 if (no_cached_open) 378 - rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL); 378 + rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, 379 + NULL); 379 380 else 380 381 rc = open_shroot(xid, tcon, &fid); 381 382 ··· 414 413 oparms.fid = &fid; 415 414 oparms.reconnect = false; 416 415 417 - rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL); 416 + rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL); 418 417 if (rc) 419 418 return; 420 419 ··· 450 449 oparms.fid = &fid; 451 450 oparms.reconnect = false; 452 451 453 - rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL); 452 + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL); 454 453 if (rc) { 455 454 kfree(utf16_path); 456 455 return rc; ··· 599 598 oparms.fid = &fid; 600 599 oparms.reconnect = false; 601 600 602 - rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL); 601 + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL); 603 602 kfree(utf16_path); 604 603 if (rc) { 605 604 cifs_dbg(FYI, "open failed rc=%d\n", rc); ··· 678 677 oparms.fid = &fid; 679 678 oparms.reconnect = false; 680 679 681 - rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL); 680 + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL); 682 681 kfree(utf16_path); 683 682 if (rc) { 684 683 cifs_dbg(FYI, "open failed rc=%d\n", rc); ··· 1262 1261 oparms.fid = fid; 1263 1262 oparms.reconnect = false; 1264 1263 1265 - rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL); 1264 + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL); 1266 1265 kfree(utf16_path); 1267 1266 if (rc) { 1268 1267 cifs_dbg(FYI, "open dir failed rc=%d\n", rc); ··· 1362 1361 oparms.fid = &fid; 1363 1362 oparms.reconnect = false; 1364 1363 1365 - rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL); 1364 + rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL); 1366 1365 if (rc) 1367 1366 return rc; 1368 1367 buf->f_type = SMB2_MAGIC_NUMBER; ··· 1516 1515 struct cifs_open_parms oparms; 1517 1516 struct cifs_fid fid; 1518 1517 struct kvec err_iov = {NULL, 0}; 1519 - struct smb2_err_rsp *err_buf; 1518 + struct smb2_err_rsp *err_buf = NULL; 1519 + int resp_buftype; 1520 1520 struct smb2_symlink_err_rsp *symlink; 1521 1521 unsigned int sub_len; 1522 1522 unsigned int sub_offset; ··· 1537 1535 oparms.fid = &fid; 1538 1536 oparms.reconnect = false; 1539 1537 1540 - rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov); 1541 - 1538 + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov, 1539 + &resp_buftype); 1542 1540 if (!rc || !err_iov.iov_base) { 1543 - kfree(utf16_path); 1544 - return -ENOENT; 1541 + rc = -ENOENT; 1542 + goto querty_exit; 1545 1543 } 1546 1544 1547 1545 err_buf = err_iov.iov_base; 1548 1546 if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) || 1549 1547 err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE) { 1550 - kfree(utf16_path); 1551 - return -ENOENT; 1548 + rc = -ENOENT; 1549 + goto querty_exit; 1552 1550 } 1553 1551 1554 1552 /* open must fail on symlink - reset rc */ ··· 1560 1558 print_offset = le16_to_cpu(symlink->PrintNameOffset); 1561 1559 1562 1560 if (err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) { 1563 - kfree(utf16_path); 1564 - return -ENOENT; 1561 + rc = -ENOENT; 1562 + goto querty_exit; 1565 1563 } 1566 1564 1567 1565 if (err_iov.iov_len < 1568 1566 SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) { 1569 - kfree(utf16_path); 1570 - return -ENOENT; 1567 + rc = -ENOENT; 1568 + goto querty_exit; 1571 1569 } 1572 1570 1573 1571 *target_path = cifs_strndup_from_utf16( 1574 1572 (char *)symlink->PathBuffer + sub_offset, 1575 1573 sub_len, true, cifs_sb->local_nls); 1576 1574 if (!(*target_path)) { 1577 - kfree(utf16_path); 1578 - return -ENOMEM; 1575 + rc = -ENOMEM; 1576 + goto querty_exit; 1579 1577 } 1580 1578 convert_delimiter(*target_path, '/'); 1581 1579 cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path); 1580 + 1581 + querty_exit: 1582 + free_rsp_buf(resp_buftype, err_buf); 1582 1583 kfree(utf16_path); 1583 1584 return rc; 1584 1585 } ··· 1654 1649 oparms.fid = &fid; 1655 1650 oparms.reconnect = false; 1656 1651 1657 - rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL); 1652 + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL); 1658 1653 kfree(utf16_path); 1659 1654 if (!rc) { 1660 1655 rc = SMB2_query_acl(xid, tlink_tcon(tlink), fid.persistent_fid, ··· 1717 1712 oparms.fid = &fid; 1718 1713 oparms.reconnect = false; 1719 1714 1720 - rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL); 1715 + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL); 1721 1716 kfree(utf16_path); 1722 1717 if (!rc) { 1723 1718 rc = SMB2_set_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
+2 -1
fs/cifs/smb2pdu.c
··· 1889 1889 int 1890 1890 SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, 1891 1891 __u8 *oplock, struct smb2_file_all_info *buf, 1892 - struct kvec *err_iov) 1892 + struct kvec *err_iov, int *buftype) 1893 1893 { 1894 1894 struct smb2_create_req *req; 1895 1895 struct smb2_create_rsp *rsp; ··· 2052 2052 cifs_stats_fail_inc(tcon, SMB2_CREATE_HE); 2053 2053 if (err_iov && rsp) { 2054 2054 *err_iov = rsp_iov; 2055 + *buftype = resp_buftype; 2055 2056 resp_buftype = CIFS_NO_BUFFER; 2056 2057 rsp = NULL; 2057 2058 }
+1 -1
fs/cifs/smb2proto.h
··· 125 125 extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, 126 126 __le16 *path, __u8 *oplock, 127 127 struct smb2_file_all_info *buf, 128 - struct kvec *err_iov); 128 + struct kvec *err_iov, int *resp_buftype); 129 129 extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, 130 130 u64 persistent_fid, u64 volatile_fid, u32 opcode, 131 131 bool is_fsctl, char *in_data, u32 indatalen,