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>
This commit is contained in:
parent
f19b3967fb
commit
78ad2c277a
103
fs/ksmbd/vfs.c
103
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};
|
||||
if (rc <= 0)
|
||||
return rc;
|
||||
|
||||
n.length = rc;
|
||||
rc = ndr_decode_v4_ntacl(&n, &acl);
|
||||
if (rc)
|
||||
return rc;
|
||||
n.length = rc;
|
||||
rc = ndr_decode_v4_ntacl(&n, &acl);
|
||||
if (rc)
|
||||
goto free_n_data;
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (memcmp(cmp_hash, acl.posix_acl_hash, XATTR_SD_HASH_SIZE)) {
|
||||
pr_err("hash value diff\n");
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*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:
|
||||
kfree(n.data);
|
||||
kfree(acl_ndr.data);
|
||||
kfree(smb_acl);
|
||||
kfree(def_smb_acl);
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user