Skip to content

Commit

Permalink
cifs: fix a buffer leak in smb2_query_symlink
Browse files Browse the repository at this point in the history
This leak was introduced in 91cb74f 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>
  • Loading branch information
Ronnie Sahlberg authored and Steve French committed Jun 8, 2018
1 parent c7c137b commit 9d874c3
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 29 deletions.
6 changes: 4 additions & 2 deletions fs/cifs/link.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,8 @@ smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
return -ENOMEM;
}

rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL);
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL,
NULL);
if (rc)
goto qmf_out_open_fail;

Expand Down Expand Up @@ -478,7 +479,8 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = &fid;
oparms.reconnect = false;

rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
NULL);
if (rc) {
kfree(utf16_path);
return rc;
Expand Down
3 changes: 2 additions & 1 deletion fs/cifs/smb2file.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
if (oparms->tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
memcpy(smb2_oplock + 1, fid->lease_key, SMB2_LEASE_KEY_SIZE);

rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data, NULL);
rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data, NULL,
NULL);
if (rc)
goto out;

Expand Down
3 changes: 2 additions & 1 deletion fs/cifs/smb2inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = &fid;
oparms.reconnect = false;

rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
NULL);
if (rc) {
kfree(utf16_path);
return rc;
Expand Down
51 changes: 28 additions & 23 deletions fs/cifs/smb2ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)
oparams.fid = pfid;
oparams.reconnect = false;

rc = SMB2_open(xid, &oparams, &srch_path, &oplock, NULL, NULL);
rc = SMB2_open(xid, &oparams, &srch_path, &oplock, NULL, NULL, NULL);
if (rc == 0) {
memcpy(tcon->prfid, pfid, sizeof(struct cifs_fid));
tcon->valid_root_fid = true;
Expand All @@ -375,7 +375,8 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
oparms.reconnect = false;

if (no_cached_open)
rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL,
NULL);
else
rc = open_shroot(xid, tcon, &fid);

Expand Down Expand Up @@ -413,7 +414,7 @@ smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
oparms.fid = &fid;
oparms.reconnect = false;

rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL);
if (rc)
return;

Expand Down Expand Up @@ -449,7 +450,7 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = &fid;
oparms.reconnect = false;

rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
if (rc) {
kfree(utf16_path);
return rc;
Expand Down Expand Up @@ -598,7 +599,7 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = &fid;
oparms.reconnect = false;

rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
kfree(utf16_path);
if (rc) {
cifs_dbg(FYI, "open failed rc=%d\n", rc);
Expand Down Expand Up @@ -677,7 +678,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = &fid;
oparms.reconnect = false;

rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
kfree(utf16_path);
if (rc) {
cifs_dbg(FYI, "open failed rc=%d\n", rc);
Expand Down Expand Up @@ -1261,7 +1262,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = fid;
oparms.reconnect = false;

rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
kfree(utf16_path);
if (rc) {
cifs_dbg(FYI, "open dir failed rc=%d\n", rc);
Expand Down Expand Up @@ -1361,7 +1362,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = &fid;
oparms.reconnect = false;

rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL);
if (rc)
return rc;
buf->f_type = SMB2_MAGIC_NUMBER;
Expand Down Expand Up @@ -1515,7 +1516,8 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
struct cifs_open_parms oparms;
struct cifs_fid fid;
struct kvec err_iov = {NULL, 0};
struct smb2_err_rsp *err_buf;
struct smb2_err_rsp *err_buf = NULL;
int resp_buftype;
struct smb2_symlink_err_rsp *symlink;
unsigned int sub_len;
unsigned int sub_offset;
Expand All @@ -1535,18 +1537,18 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = &fid;
oparms.reconnect = false;

rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov);

rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov,
&resp_buftype);
if (!rc || !err_iov.iov_base) {
kfree(utf16_path);
return -ENOENT;
rc = -ENOENT;
goto querty_exit;
}

err_buf = err_iov.iov_base;
if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE) {
kfree(utf16_path);
return -ENOENT;
rc = -ENOENT;
goto querty_exit;
}

/* open must fail on symlink - reset rc */
Expand All @@ -1558,25 +1560,28 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
print_offset = le16_to_cpu(symlink->PrintNameOffset);

if (err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
kfree(utf16_path);
return -ENOENT;
rc = -ENOENT;
goto querty_exit;
}

if (err_iov.iov_len <
SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
kfree(utf16_path);
return -ENOENT;
rc = -ENOENT;
goto querty_exit;
}

*target_path = cifs_strndup_from_utf16(
(char *)symlink->PathBuffer + sub_offset,
sub_len, true, cifs_sb->local_nls);
if (!(*target_path)) {
kfree(utf16_path);
return -ENOMEM;
rc = -ENOMEM;
goto querty_exit;
}
convert_delimiter(*target_path, '/');
cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);

querty_exit:
free_rsp_buf(resp_buftype, err_buf);
kfree(utf16_path);
return rc;
}
Expand Down Expand Up @@ -1649,7 +1654,7 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
oparms.fid = &fid;
oparms.reconnect = false;

rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
kfree(utf16_path);
if (!rc) {
rc = SMB2_query_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
Expand Down Expand Up @@ -1712,7 +1717,7 @@ set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
oparms.fid = &fid;
oparms.reconnect = false;

rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
kfree(utf16_path);
if (!rc) {
rc = SMB2_set_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
Expand Down
3 changes: 2 additions & 1 deletion fs/cifs/smb2pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1889,7 +1889,7 @@ alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
int
SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
__u8 *oplock, struct smb2_file_all_info *buf,
struct kvec *err_iov)
struct kvec *err_iov, int *buftype)
{
struct smb2_create_req *req;
struct smb2_create_rsp *rsp;
Expand Down Expand Up @@ -2052,6 +2052,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
if (err_iov && rsp) {
*err_iov = rsp_iov;
*buftype = resp_buftype;
resp_buftype = CIFS_NO_BUFFER;
rsp = NULL;
}
Expand Down
2 changes: 1 addition & 1 deletion fs/cifs/smb2proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon);
extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
__le16 *path, __u8 *oplock,
struct smb2_file_all_info *buf,
struct kvec *err_iov);
struct kvec *err_iov, int *resp_buftype);
extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, u32 opcode,
bool is_fsctl, char *in_data, u32 indatalen,
Expand Down

0 comments on commit 9d874c3

Please sign in to comment.