Commit 0f22053e authored by Shyam Prasad N's avatar Shyam Prasad N Committed by Steve French

cifs: Fix unix perm bits to cifsacl conversion for "other" bits.

With the "cifsacl" mount option, the mode bits set on the file/dir
is converted to corresponding ACEs in DACL. However, only the
ALLOWED ACEs were being set for "owner" and "group" SIDs. Since
owner is a subset of group, and group is a subset of
everyone/world SID, in order to properly emulate unix perm groups,
we need to add DENIED ACEs. If we don't do that, "owner" and "group"
SIDs could get more access rights than they should. Which is what
was happening. This fixes it.

We try to keep the "preferred" order of ACEs, i.e. DENYs followed
by ALLOWs. However, for a small subset of cases we cannot
maintain the preferred order. In that case, we'll end up with the
DENY ACE for group after the ALLOW for the owner.

If owner SID == group SID, use the more restrictive
among the two perm bits and convert them to ACEs.

Also, for reverse mapping, i.e. to convert ACL to unix perm bits,
for the "others" bits, we needed to add the masked bits of the
owner and group masks to others mask.

Updated version of patch fixes a problem noted by the kernel
test robot.
Reported-by: default avatarkernel test robot <lkp@intel.com>
Signed-off-by: default avatarShyam Prasad N <sprasad@microsoft.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent bc7c4129
This diff is collapsed.
...@@ -215,8 +215,8 @@ extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, ...@@ -215,8 +215,8 @@ extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
struct cifs_fattr *fattr, struct inode *inode, struct cifs_fattr *fattr, struct inode *inode,
bool get_mode_from_special_sid, bool get_mode_from_special_sid,
const char *path, const struct cifs_fid *pfid); const char *path, const struct cifs_fid *pfid);
extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64, extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
kuid_t, kgid_t); kuid_t uid, kgid_t gid);
extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *,
const char *, u32 *); const char *, u32 *);
extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *, extern struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *,
......
...@@ -2813,7 +2813,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) ...@@ -2813,7 +2813,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) || if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) { (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
if (uid_valid(uid) || gid_valid(gid)) { if (uid_valid(uid) || gid_valid(gid)) {
rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64, mode = NO_CHANGE_64;
rc = id_mode_to_cifs_acl(inode, full_path, &mode,
uid, gid); uid, gid);
if (rc) { if (rc) {
cifs_dbg(FYI, "%s: Setting id failed with error: %d\n", cifs_dbg(FYI, "%s: Setting id failed with error: %d\n",
...@@ -2834,13 +2835,20 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) ...@@ -2834,13 +2835,20 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
rc = 0; rc = 0;
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) || if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) { (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
rc = id_mode_to_cifs_acl(inode, full_path, mode, rc = id_mode_to_cifs_acl(inode, full_path, &mode,
INVALID_UID, INVALID_GID); INVALID_UID, INVALID_GID);
if (rc) { if (rc) {
cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n", cifs_dbg(FYI, "%s: Setting ACL failed with error: %d\n",
__func__, rc); __func__, rc);
goto cifs_setattr_exit; goto cifs_setattr_exit;
} }
/*
* In case of CIFS_MOUNT_CIFS_ACL, we cannot support all modes.
* Pick up the actual mode bits that were set.
*/
if (mode != attrs->ia_mode)
attrs->ia_mode = mode;
} else } else
if (((mode & S_IWUGO) == 0) && if (((mode & S_IWUGO) == 0) &&
(cifsInode->cifsAttrs & ATTR_READONLY) == 0) { (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment