Skip to content

Commit 975221e

Browse files
committed
smb3: allow uid and gid owners to be set on create with idsfromsid mount option
Currently idsfromsid mount option allows querying owner information from the special sids used to represent POSIX uids and gids but needed changes to populate the security descriptor context with the owner information when idsfromsid mount option was used. Signed-off-by: Steve French <[email protected]> Reviewed-by: Pavel Shilovsky <[email protected]>
1 parent e4bd7c4 commit 975221e

File tree

4 files changed

+129
-21
lines changed

4 files changed

+129
-21
lines changed

fs/cifs/cifsacl.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,28 @@ unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode)
849849
return ace_size;
850850
}
851851

852+
unsigned int setup_special_user_owner_ACE(struct cifs_ace *pntace)
853+
{
854+
int i;
855+
unsigned int ace_size = 28;
856+
857+
pntace->type = ACCESS_ALLOWED_ACE_TYPE;
858+
pntace->flags = 0x0;
859+
pntace->access_req = cpu_to_le32(GENERIC_ALL);
860+
pntace->sid.num_subauth = 3;
861+
pntace->sid.revision = 1;
862+
for (i = 0; i < NUM_AUTHS; i++)
863+
pntace->sid.authority[i] = sid_unix_NFS_users.authority[i];
864+
865+
pntace->sid.sub_auth[0] = sid_unix_NFS_users.sub_auth[0];
866+
pntace->sid.sub_auth[1] = sid_unix_NFS_users.sub_auth[1];
867+
pntace->sid.sub_auth[2] = cpu_to_le32(current_fsgid().val);
868+
869+
/* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
870+
pntace->size = cpu_to_le16(ace_size);
871+
return ace_size;
872+
}
873+
852874
static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
853875
struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid)
854876
{

fs/cifs/cifsacl.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,21 @@ struct smb3_acl {
176176
__le16 Sbz2; /* MBZ */
177177
} __packed;
178178

179+
/*
180+
* Used to store the special 'NFS SIDs' used to persist the POSIX uid and gid
181+
* See See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
182+
*/
183+
struct owner_sid {
184+
u8 Revision;
185+
u8 NumAuth;
186+
u8 Authority[6];
187+
__le32 SubAuthorities[3];
188+
} __packed;
189+
190+
struct owner_group_sids {
191+
struct owner_sid owner;
192+
struct owner_sid group;
193+
} __packed;
179194

180195
/*
181196
* Minimum security identifier can be one for system defined Users

fs/cifs/cifsproto.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
222222
const char *, int);
223223
extern unsigned int setup_authusers_ACE(struct cifs_ace *pace);
224224
extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode);
225+
extern unsigned int setup_special_user_owner_ACE(struct cifs_ace *pace);
225226

226227
extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
227228
extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,

fs/cifs/smb2pdu.c

Lines changed: 91 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2317,28 +2317,73 @@ add_twarp_context(struct kvec *iov, unsigned int *num_iovec, __u64 timewarp)
23172317
return 0;
23182318
}
23192319

2320+
/* See See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx */
2321+
static void setup_owner_group_sids(char *buf)
2322+
{
2323+
struct owner_group_sids *sids = (struct owner_group_sids *)buf;
2324+
2325+
/* Populate the user ownership fields S-1-5-88-1 */
2326+
sids->owner.Revision = 1;
2327+
sids->owner.NumAuth = 3;
2328+
sids->owner.Authority[5] = 5;
2329+
sids->owner.SubAuthorities[0] = cpu_to_le32(88);
2330+
sids->owner.SubAuthorities[1] = cpu_to_le32(1);
2331+
sids->owner.SubAuthorities[2] = cpu_to_le32(current_fsuid().val);
2332+
2333+
/* Populate the group ownership fields S-1-5-88-2 */
2334+
sids->group.Revision = 1;
2335+
sids->group.NumAuth = 3;
2336+
sids->group.Authority[5] = 5;
2337+
sids->group.SubAuthorities[0] = cpu_to_le32(88);
2338+
sids->group.SubAuthorities[1] = cpu_to_le32(2);
2339+
sids->group.SubAuthorities[2] = cpu_to_le32(current_fsgid().val);
2340+
}
2341+
23202342
/* See MS-SMB2 2.2.13.2.2 and MS-DTYP 2.4.6 */
23212343
static struct crt_sd_ctxt *
2322-
create_sd_buf(umode_t mode, unsigned int *len)
2344+
create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
23232345
{
23242346
struct crt_sd_ctxt *buf;
23252347
struct cifs_ace *pace;
23262348
unsigned int sdlen, acelen;
2349+
unsigned int owner_offset = 0;
2350+
unsigned int group_offset = 0;
2351+
2352+
*len = roundup(sizeof(struct crt_sd_ctxt) + (sizeof(struct cifs_ace) * 2), 8);
2353+
2354+
if (set_owner) {
2355+
/* offset fields are from beginning of security descriptor not of create context */
2356+
owner_offset = sizeof(struct smb3_acl) + (sizeof(struct cifs_ace) * 2);
2357+
2358+
/* sizeof(struct owner_group_sids) is already multiple of 8 so no need to round */
2359+
*len += sizeof(struct owner_group_sids);
2360+
}
23272361

2328-
*len = roundup(sizeof(struct crt_sd_ctxt) + sizeof(struct cifs_ace) * 2,
2329-
8);
23302362
buf = kzalloc(*len, GFP_KERNEL);
23312363
if (buf == NULL)
23322364
return buf;
23332365

2366+
if (set_owner) {
2367+
buf->sd.OffsetOwner = cpu_to_le32(owner_offset);
2368+
group_offset = owner_offset + sizeof(struct owner_sid);
2369+
buf->sd.OffsetGroup = cpu_to_le32(group_offset);
2370+
} else {
2371+
buf->sd.OffsetOwner = 0;
2372+
buf->sd.OffsetGroup = 0;
2373+
}
2374+
23342375
sdlen = sizeof(struct smb3_sd) + sizeof(struct smb3_acl) +
23352376
2 * sizeof(struct cifs_ace);
2377+
if (set_owner) {
2378+
sdlen += sizeof(struct owner_group_sids);
2379+
setup_owner_group_sids(owner_offset + sizeof(struct create_context) + 8 /* name */
2380+
+ (char *)buf);
2381+
}
23362382

23372383
buf->ccontext.DataOffset = cpu_to_le16(offsetof
23382384
(struct crt_sd_ctxt, sd));
23392385
buf->ccontext.DataLength = cpu_to_le32(sdlen);
2340-
buf->ccontext.NameOffset = cpu_to_le16(offsetof
2341-
(struct crt_sd_ctxt, Name));
2386+
buf->ccontext.NameOffset = cpu_to_le16(offsetof(struct crt_sd_ctxt, Name));
23422387
buf->ccontext.NameLength = cpu_to_le16(4);
23432388
/* SMB2_CREATE_SD_BUFFER_TOKEN is "SecD" */
23442389
buf->Name[0] = 'S';
@@ -2359,23 +2404,34 @@ create_sd_buf(umode_t mode, unsigned int *len)
23592404
/* create one ACE to hold the mode embedded in reserved special SID */
23602405
pace = (struct cifs_ace *)(sizeof(struct crt_sd_ctxt) + (char *)buf);
23612406
acelen = setup_special_mode_ACE(pace, (__u64)mode);
2407+
2408+
if (set_owner) {
2409+
/* we do not need to reallocate buffer to add the two more ACEs. plenty of space */
2410+
pace = (struct cifs_ace *)(acelen + (sizeof(struct crt_sd_ctxt) + (char *)buf));
2411+
acelen += setup_special_user_owner_ACE(pace);
2412+
/* it does not appear necessary to add an ACE for the NFS group SID */
2413+
buf->acl.AceCount = cpu_to_le16(3);
2414+
} else
2415+
buf->acl.AceCount = cpu_to_le16(2);
2416+
23622417
/* and one more ACE to allow access for authenticated users */
23632418
pace = (struct cifs_ace *)(acelen + (sizeof(struct crt_sd_ctxt) +
23642419
(char *)buf));
23652420
acelen += setup_authusers_ACE(pace);
2421+
23662422
buf->acl.AclSize = cpu_to_le16(sizeof(struct cifs_acl) + acelen);
2367-
buf->acl.AceCount = cpu_to_le16(2);
2423+
23682424
return buf;
23692425
}
23702426

23712427
static int
2372-
add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode)
2428+
add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode, bool set_owner)
23732429
{
23742430
struct smb2_create_req *req = iov[0].iov_base;
23752431
unsigned int num = *num_iovec;
23762432
unsigned int len = 0;
23772433

2378-
iov[num].iov_base = create_sd_buf(mode, &len);
2434+
iov[num].iov_base = create_sd_buf(mode, set_owner, &len);
23792435
if (iov[num].iov_base == NULL)
23802436
return -ENOMEM;
23812437
iov[num].iov_len = len;
@@ -2764,21 +2820,35 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
27642820
return rc;
27652821
}
27662822

2767-
if ((oparms->disposition != FILE_OPEN) &&
2768-
(oparms->cifs_sb) &&
2769-
(oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) &&
2770-
(oparms->mode != ACL_NO_MODE)) {
2771-
if (n_iov > 2) {
2772-
struct create_context *ccontext =
2773-
(struct create_context *)iov[n_iov-1].iov_base;
2774-
ccontext->Next =
2775-
cpu_to_le32(iov[n_iov-1].iov_len);
2823+
if ((oparms->disposition != FILE_OPEN) && (oparms->cifs_sb)) {
2824+
bool set_mode;
2825+
bool set_owner;
2826+
2827+
if ((oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) &&
2828+
(oparms->mode != ACL_NO_MODE))
2829+
set_mode = true;
2830+
else {
2831+
set_mode = false;
2832+
oparms->mode = ACL_NO_MODE;
27762833
}
27772834

2778-
cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode);
2779-
rc = add_sd_context(iov, &n_iov, oparms->mode);
2780-
if (rc)
2781-
return rc;
2835+
if (oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
2836+
set_owner = true;
2837+
else
2838+
set_owner = false;
2839+
2840+
if (set_owner | set_mode) {
2841+
if (n_iov > 2) {
2842+
struct create_context *ccontext =
2843+
(struct create_context *)iov[n_iov-1].iov_base;
2844+
ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len);
2845+
}
2846+
2847+
cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode);
2848+
rc = add_sd_context(iov, &n_iov, oparms->mode, set_owner);
2849+
if (rc)
2850+
return rc;
2851+
}
27822852
}
27832853

27842854
if (n_iov > 2) {

0 commit comments

Comments
 (0)