summaryrefslogtreecommitdiffstats
path: root/fs/ksmbd
diff options
context:
space:
mode:
authorNamjae Jeon <namjae.jeon@samsung.com>2021-08-21 23:26:01 +0900
committerNamjae Jeon <namjae.jeon@samsung.com>2021-08-21 23:26:34 +0900
commite70e392fa768d46ca59f2f8c0e7374099c980622 (patch)
tree0cfee79dd3e560ca1399274fe8f72424f8809b8d /fs/ksmbd
parenta9a27d4ab3de2a6a81bad4b158c74a554d78e89b (diff)
downloadlinux-e70e392fa768d46ca59f2f8c0e7374099c980622.tar.bz2
ksmbd: fix permission check issue on chown and chmod
When commanding chmod and chown on cifs&ksmbd, ksmbd allows it without file permissions check. There is code to check it in settattr_prepare. Instead of setting the inode directly, update the mode and uid/gid through notify_change. 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/smb2pdu.c5
-rw-r--r--fs/ksmbd/smbacl.c24
2 files changed, 23 insertions, 6 deletions
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c
index 0131997c2177..d329ea49fa14 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -5861,10 +5861,15 @@ int smb2_set_info(struct ksmbd_work *work)
break;
case SMB2_O_INFO_SECURITY:
ksmbd_debug(SMB, "GOT SMB2_O_INFO_SECURITY\n");
+ if (ksmbd_override_fsids(work)) {
+ rc = -ENOMEM;
+ goto err_out;
+ }
rc = smb2_set_info_sec(fp,
le32_to_cpu(req->AdditionalInformation),
req->Buffer,
le32_to_cpu(req->BufferLength));
+ ksmbd_revert_fsids(work);
break;
default:
rc = -EOPNOTSUPP;
diff --git a/fs/ksmbd/smbacl.c b/fs/ksmbd/smbacl.c
index 20455d810523..5456e3ad943e 100644
--- a/fs/ksmbd/smbacl.c
+++ b/fs/ksmbd/smbacl.c
@@ -1300,6 +1300,7 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
struct smb_fattr fattr = {{0}};
struct inode *inode = d_inode(path->dentry);
struct user_namespace *user_ns = mnt_user_ns(path->mnt);
+ struct iattr newattrs;
fattr.cf_uid = INVALID_UID;
fattr.cf_gid = INVALID_GID;
@@ -1309,12 +1310,23 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
if (rc)
goto out;
- inode->i_mode = (inode->i_mode & ~0777) | (fattr.cf_mode & 0777);
- if (!uid_eq(fattr.cf_uid, INVALID_UID))
- inode->i_uid = fattr.cf_uid;
- if (!gid_eq(fattr.cf_gid, INVALID_GID))
- inode->i_gid = fattr.cf_gid;
- mark_inode_dirty(inode);
+ newattrs.ia_valid = ATTR_CTIME;
+ if (!uid_eq(fattr.cf_uid, INVALID_UID)) {
+ newattrs.ia_valid |= ATTR_UID;
+ newattrs.ia_uid = fattr.cf_uid;
+ }
+ if (!gid_eq(fattr.cf_gid, INVALID_GID)) {
+ newattrs.ia_valid |= ATTR_GID;
+ newattrs.ia_gid = fattr.cf_gid;
+ }
+ newattrs.ia_valid |= ATTR_MODE;
+ newattrs.ia_mode = (inode->i_mode & ~0777) | (fattr.cf_mode & 0777);
+
+ inode_lock(inode);
+ rc = notify_change(user_ns, path->dentry, &newattrs, NULL);
+ inode_unlock(inode);
+ if (rc)
+ goto out;
ksmbd_vfs_remove_acl_xattrs(user_ns, path->dentry);
/* Update posix acls */