Skip to content

Commit

Permalink
cifs: allow chmod to set mode bits using special sid
Browse files Browse the repository at this point in the history
    When mounting with "modefromsid" set mode bits (chmod) by
    adding ACE with special SID (S-1-5-88-3-<mode>) to the ACL.
    Subsequent patch will fix setting default mode on file
    create and mkdir.

    See See e.g.
        https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/hh509017(v=ws.10)

Signed-off-by: Steve French <stfrench@microsoft.com>
  • Loading branch information
Steve French committed Sep 16, 2019
1 parent e2f8fbf commit 2244217
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 7 deletions.
42 changes: 37 additions & 5 deletions fs/cifs/cifsacl.c
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,


static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
struct cifs_sid *pgrpsid, __u64 nmode)
struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid)
{
u16 size = 0;
struct cifs_acl *pnndacl;
Expand All @@ -820,8 +820,33 @@ static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
&sid_everyone, nmode, S_IRWXO);

/* TBD: Move this ACE to the top of ACE list instead of bottom */
if (modefromsid) {
struct cifs_ace *pntace =
(struct cifs_ace *)((char *)pnndacl + size);
int i;

pntace->type = ACCESS_DENIED;
pntace->flags = 0x0;
pntace->sid.num_subauth = 3;
pntace->sid.revision = 1;
/* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4) */
pntace->size = cpu_to_le16(28);
size += 28;
for (i = 0; i < NUM_AUTHS; i++)
pntace->sid.authority[i] =
sid_unix_NFS_mode.authority[i];
pntace->sid.sub_auth[0] = sid_unix_NFS_mode.sub_auth[0];
pntace->sid.sub_auth[1] = sid_unix_NFS_mode.sub_auth[1];
pntace->sid.sub_auth[2] = cpu_to_le32(nmode & 07777);

pndacl->num_aces = cpu_to_le32(4);
size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
&sid_unix_NFS_mode, nmode, S_IRWXO);
} else
pndacl->num_aces = cpu_to_le32(3);

pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
pndacl->num_aces = cpu_to_le32(3);

return 0;
}
Expand Down Expand Up @@ -921,7 +946,8 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb,

/* Convert permission bits from mode to equivalent CIFS ACL */
static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
__u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid, int *aclflag)
__u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid,
bool mode_from_sid, int *aclflag)
{
int rc = 0;
__u32 dacloffset;
Expand All @@ -946,7 +972,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
ndacl_ptr->num_aces = 0;

rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
nmode);
nmode, mode_from_sid);
sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
/* copy sec desc control portion & owner and group sids */
copy_sec_desc(pntsd, pnntsd, sidsoffset);
Expand Down Expand Up @@ -1196,6 +1222,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
struct smb_version_operations *ops;
bool mode_from_sid;

if (IS_ERR(tlink))
return PTR_ERR(tlink);
Expand Down Expand Up @@ -1233,8 +1260,13 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
return -ENOMEM;
}

if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)
mode_from_sid = true;
else
mode_from_sid = false;

rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
&aclflag);
mode_from_sid, &aclflag);

cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);

Expand Down
6 changes: 4 additions & 2 deletions fs/cifs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2489,7 +2489,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
if (attrs->ia_valid & ATTR_GID)
gid = attrs->ia_gid;

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)) {
if (uid_valid(uid) || gid_valid(gid)) {
rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
uid, gid);
Expand All @@ -2510,7 +2511,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
if (attrs->ia_valid & ATTR_MODE) {
mode = attrs->ia_mode;
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)) {
rc = id_mode_to_cifs_acl(inode, full_path, mode,
INVALID_UID, INVALID_GID);
if (rc) {
Expand Down

0 comments on commit 2244217

Please sign in to comment.