Commit e70e392f authored by Namjae Jeon's avatar Namjae Jeon
Browse files

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: default avatarNamjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent a9a27d4a
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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;
+18 −6
Original line number Diff line number Diff line
@@ -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 */