summaryrefslogtreecommitdiffstats
path: root/fs/ksmbd
diff options
context:
space:
mode:
authorNamjae Jeon <namjae.jeon@samsung.com>2021-07-13 10:12:41 +0200
committerNamjae Jeon <namjae.jeon@samsung.com>2021-07-13 10:22:47 +0200
commit78ad2c277af4cf503f985fd506fbb1f8576460f2 (patch)
tree0e5337a35842e3b52c8e93562bf5bc1fbe7c4f53 /fs/ksmbd
parentksmbd: remove unneeded check_context_err (diff)
downloadlinux-78ad2c277af4cf503f985fd506fbb1f8576460f2.tar.xz
linux-78ad2c277af4cf503f985fd506fbb1f8576460f2.zip
ksmbd: fix memory leak in ksmbd_vfs_get_sd_xattr()
Add free acl.sd_buf and n.data on error handling in ksmbd_vfs_get_sd_xattr(). Reported-by: Coverity Scan <scan-admin@coverity.com> Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com> Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/ksmbd')
-rw-r--r--fs/ksmbd/vfs.c101
1 files changed, 52 insertions, 49 deletions
diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c
index 88e947f69f47..612c52d7a01b 100644
--- a/fs/ksmbd/vfs.c
+++ b/fs/ksmbd/vfs.c
@@ -1498,63 +1498,66 @@ int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn,
{
int rc;
struct ndr n;
+ struct inode *inode = d_inode(dentry);
+ struct ndr acl_ndr = {0};
+ struct xattr_ntacl acl;
+ struct xattr_smb_acl *smb_acl = NULL, *def_smb_acl = NULL;
+ __u8 cmp_hash[XATTR_SD_HASH_SIZE] = {0};
rc = ksmbd_vfs_getxattr(user_ns, dentry, XATTR_NAME_SD, &n.data);
- if (rc > 0) {
- struct inode *inode = d_inode(dentry);
- struct ndr acl_ndr = {0};
- struct xattr_ntacl acl;
- struct xattr_smb_acl *smb_acl = NULL, *def_smb_acl = NULL;
- __u8 cmp_hash[XATTR_SD_HASH_SIZE] = {0};
-
- n.length = rc;
- rc = ndr_decode_v4_ntacl(&n, &acl);
- if (rc)
- return rc;
-
- smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode,
- ACL_TYPE_ACCESS);
- if (S_ISDIR(inode->i_mode))
- def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns,
- inode,
- ACL_TYPE_DEFAULT);
-
- rc = ndr_encode_posix_acl(&acl_ndr, user_ns, inode,
- smb_acl, def_smb_acl);
- if (rc) {
- pr_err("failed to encode ndr to posix acl\n");
- goto out;
- }
+ if (rc <= 0)
+ return rc;
- rc = ksmbd_gen_sd_hash(conn, acl_ndr.data, acl_ndr.offset,
- cmp_hash);
- if (rc) {
- pr_err("failed to generate hash for ndr acl\n");
- goto out;
- }
+ n.length = rc;
+ rc = ndr_decode_v4_ntacl(&n, &acl);
+ if (rc)
+ goto free_n_data;
- if (memcmp(cmp_hash, acl.posix_acl_hash, XATTR_SD_HASH_SIZE)) {
- pr_err("hash value diff\n");
- rc = -EINVAL;
- goto out;
- }
+ smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode,
+ ACL_TYPE_ACCESS);
+ if (S_ISDIR(inode->i_mode))
+ def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode,
+ ACL_TYPE_DEFAULT);
+
+ rc = ndr_encode_posix_acl(&acl_ndr, user_ns, inode, smb_acl,
+ def_smb_acl);
+ if (rc) {
+ pr_err("failed to encode ndr to posix acl\n");
+ goto out_free;
+ }
- *pntsd = acl.sd_buf;
- (*pntsd)->osidoffset =
- cpu_to_le32(le32_to_cpu((*pntsd)->osidoffset) - NDR_NTSD_OFFSETOF);
- (*pntsd)->gsidoffset =
- cpu_to_le32(le32_to_cpu((*pntsd)->gsidoffset) - NDR_NTSD_OFFSETOF);
- (*pntsd)->dacloffset =
- cpu_to_le32(le32_to_cpu((*pntsd)->dacloffset) - NDR_NTSD_OFFSETOF);
+ rc = ksmbd_gen_sd_hash(conn, acl_ndr.data, acl_ndr.offset, cmp_hash);
+ if (rc) {
+ pr_err("failed to generate hash for ndr acl\n");
+ goto out_free;
+ }
- rc = acl.sd_size;
-out:
- kfree(n.data);
- kfree(acl_ndr.data);
- kfree(smb_acl);
- kfree(def_smb_acl);
+ if (memcmp(cmp_hash, acl.posix_acl_hash, XATTR_SD_HASH_SIZE)) {
+ pr_err("hash value diff\n");
+ rc = -EINVAL;
+ goto out_free;
}
+ *pntsd = acl.sd_buf;
+ (*pntsd)->osidoffset = cpu_to_le32(le32_to_cpu((*pntsd)->osidoffset) -
+ NDR_NTSD_OFFSETOF);
+ (*pntsd)->gsidoffset = cpu_to_le32(le32_to_cpu((*pntsd)->gsidoffset) -
+ NDR_NTSD_OFFSETOF);
+ (*pntsd)->dacloffset = cpu_to_le32(le32_to_cpu((*pntsd)->dacloffset) -
+ NDR_NTSD_OFFSETOF);
+
+ rc = acl.sd_size;
+out_free:
+ kfree(acl_ndr.data);
+ kfree(smb_acl);
+ kfree(def_smb_acl);
+ if (rc < 0) {
+ kfree(acl.sd_buf);
+ *pntsd = NULL;
+ }
+
+free_n_data:
+ kfree(n.data);
return rc;
}