summary refs log tree commit diff
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.gz
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 */