From patchwork Fri Jun 12 14:32:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve French X-Patchwork-Id: 1308267 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-cifs-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=MXwgkNbp; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49k3920D2Pz9sSJ for ; Sat, 13 Jun 2020 00:32:38 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726089AbgFLOcf (ORCPT ); Fri, 12 Jun 2020 10:32:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56420 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726085AbgFLOce (ORCPT ); Fri, 12 Jun 2020 10:32:34 -0400 Received: from mail-yb1-xb33.google.com (mail-yb1-xb33.google.com [IPv6:2607:f8b0:4864:20::b33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 69D91C03E96F for ; Fri, 12 Jun 2020 07:32:34 -0700 (PDT) Received: by mail-yb1-xb33.google.com with SMTP id s1so4998874ybo.7 for ; Fri, 12 Jun 2020 07:32:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=+v8kMlyzLcctrqMIZIZd+wLqMrTepx0zE7lLQxrB2uk=; b=MXwgkNbpTZXl8u7uN324cWh68Fqwkun+MAHZIUL0Pq4LliRRKo3VGh9ZFoV5us6Dd4 2yBYaauA8YcbJr958j3MVFvor5cIiP9l+WyZbp+V0/trp6zgnJ+KiqycDyE0v6ANqBlQ UVPjA3FrdmBTgP1LGcRowGlBk3cwMB3HUoot93e4s4KYUNt0qZz3K8D1E1I7C4iNLvi0 EOUTKjblK6la2Ogheihf87sTBkoFIeV3pwYBrHhWVsgwJ/xO53De0od8vrOMQ201Ray6 vvX0M+JxzC9S3C7nboGlQBqrC/zefEWfMI+YzhstuoRnnqU/z+wFmHmyUxnN5sFnXOD4 TRew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=+v8kMlyzLcctrqMIZIZd+wLqMrTepx0zE7lLQxrB2uk=; b=aKllPEYqWod2bJtF7aSaGbV16vgG+c57QOCw662KrhE2FKdz/h4HKTKn0hGLsn+dYo b6saLJKCAXharDWZUBFt6XyhH0lUaSvyWISQibnCTbiguGwY0JrCJoxRm+p/He+9Jc2t bBjCQKO9xgbUQq9ZHgBPJgpEs9O8Fsf8FAcvRZd6fwybO3nDjxv+AmWWn+I1paJyYr88 d+qnGjm5aOOb6lJmu/UFR13F+8OxAGKdDnVDhqsjHbCTiYZYSlU16elNZ2fDKI+JGHaE LcYfEqy8HxWU4Xf0zuPHBGSfdPCTaq3z4IFc9mGigW7U/MIAfeuzpge9Dw3fVEq7zaQv Jkog== X-Gm-Message-State: AOAM532mzYfMv9A79FBkarHKf9l/jsJjG5MF5zpc7TL9SAVJGzW8JW28 NsECUYJQx43fuih1WgbjRask7PJm3umBmBSlP+uvZzgfr0U= X-Google-Smtp-Source: ABdhPJw4gyGp/0MGIwsMjxRbNZjGawOGmVr6yomXS1ZBjstfJgEdxnsAj93S9ylf7b6oECDM8KwFAqX67MB5rCSOF94= X-Received: by 2002:a25:ca45:: with SMTP id a66mr22212359ybg.85.1591972352985; Fri, 12 Jun 2020 07:32:32 -0700 (PDT) MIME-Version: 1.0 From: Steve French Date: Fri, 12 Jun 2020 09:32:22 -0500 Message-ID: Subject: [PATCH] smb3: allow uid and gid owners to be set on create with idsfromsid mount option To: CIFS Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org 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. Reviewed-by: Pavel Shilovsky From 6f20e0678a720aa65b42b1c8fa777396c0a03657 Mon Sep 17 00:00:00 2001 From: Steve French Date: Fri, 12 Jun 2020 09:25:21 -0500 Subject: [PATCH] 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 --- fs/cifs/cifsacl.c | 22 +++++++++ fs/cifs/cifsacl.h | 15 ++++++ fs/cifs/cifsproto.h | 1 + fs/cifs/smb2pdu.c | 112 +++++++++++++++++++++++++++++++++++--------- 4 files changed, 129 insertions(+), 21 deletions(-) diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index ae421634aa42..63aaa363ed14 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -849,6 +849,28 @@ unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode) return ace_size; } +unsigned int setup_special_user_owner_ACE(struct cifs_ace *pntace) +{ + int i; + unsigned int ace_size = 28; + + pntace->type = ACCESS_ALLOWED_ACE_TYPE; + pntace->flags = 0x0; + pntace->access_req = cpu_to_le32(GENERIC_ALL); + pntace->sid.num_subauth = 3; + pntace->sid.revision = 1; + for (i = 0; i < NUM_AUTHS; i++) + pntace->sid.authority[i] = sid_unix_NFS_users.authority[i]; + + pntace->sid.sub_auth[0] = sid_unix_NFS_users.sub_auth[0]; + pntace->sid.sub_auth[1] = sid_unix_NFS_users.sub_auth[1]; + pntace->sid.sub_auth[2] = cpu_to_le32(current_fsgid().val); + + /* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */ + pntace->size = cpu_to_le16(ace_size); + return ace_size; +} + static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid) { diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h index 21d7dee98d01..17562ea00e18 100644 --- a/fs/cifs/cifsacl.h +++ b/fs/cifs/cifsacl.h @@ -176,6 +176,21 @@ struct smb3_acl { __le16 Sbz2; /* MBZ */ } __packed; +/* + * Used to store the special 'NFS SIDs' used to persist the POSIX uid and gid + * See See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx + */ +struct owner_sid { + u8 Revision; + u8 NumAuth; + u8 Authority[6]; + __le32 SubAuthorities[3]; +} __packed; + +struct owner_group_sids { + struct owner_sid owner; + struct owner_sid group; +} __packed; /* * Minimum security identifier can be one for system defined Users diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index b603da73f4f5..7a836ec0438e 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -222,6 +222,7 @@ extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, const char *, int); extern unsigned int setup_authusers_ACE(struct cifs_ace *pace); extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode); +extern unsigned int setup_special_user_owner_ACE(struct cifs_ace *pace); extern void dequeue_mid(struct mid_q_entry *mid, bool malformed); extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 3f5c3dd57c86..5e82bb4a0b9f 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -2317,28 +2317,73 @@ add_twarp_context(struct kvec *iov, unsigned int *num_iovec, __u64 timewarp) return 0; } +/* See See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx */ +static void setup_owner_group_sids(char *buf) +{ + struct owner_group_sids *sids = (struct owner_group_sids *)buf; + + /* Populate the user ownership fields S-1-5-88-1 */ + sids->owner.Revision = 1; + sids->owner.NumAuth = 3; + sids->owner.Authority[5] = 5; + sids->owner.SubAuthorities[0] = cpu_to_le32(88); + sids->owner.SubAuthorities[1] = cpu_to_le32(1); + sids->owner.SubAuthorities[2] = cpu_to_le32(current_fsuid().val); + + /* Populate the group ownership fields S-1-5-88-2 */ + sids->group.Revision = 1; + sids->group.NumAuth = 3; + sids->group.Authority[5] = 5; + sids->group.SubAuthorities[0] = cpu_to_le32(88); + sids->group.SubAuthorities[1] = cpu_to_le32(2); + sids->group.SubAuthorities[2] = cpu_to_le32(current_fsgid().val); +} + /* See MS-SMB2 2.2.13.2.2 and MS-DTYP 2.4.6 */ static struct crt_sd_ctxt * -create_sd_buf(umode_t mode, unsigned int *len) +create_sd_buf(umode_t mode, bool set_owner, unsigned int *len) { struct crt_sd_ctxt *buf; struct cifs_ace *pace; unsigned int sdlen, acelen; + unsigned int owner_offset = 0; + unsigned int group_offset = 0; + + *len = roundup(sizeof(struct crt_sd_ctxt) + (sizeof(struct cifs_ace) * 2), 8); + + if (set_owner) { + /* offset fields are from beginning of security descriptor not of create context */ + owner_offset = sizeof(struct smb3_acl) + (sizeof(struct cifs_ace) * 2); + + /* sizeof(struct owner_group_sids) is already multiple of 8 so no need to round */ + *len += sizeof(struct owner_group_sids); + } - *len = roundup(sizeof(struct crt_sd_ctxt) + sizeof(struct cifs_ace) * 2, - 8); buf = kzalloc(*len, GFP_KERNEL); if (buf == NULL) return buf; + if (set_owner) { + buf->sd.OffsetOwner = cpu_to_le32(owner_offset); + group_offset = owner_offset + sizeof(struct owner_sid); + buf->sd.OffsetGroup = cpu_to_le32(group_offset); + } else { + buf->sd.OffsetOwner = 0; + buf->sd.OffsetGroup = 0; + } + sdlen = sizeof(struct smb3_sd) + sizeof(struct smb3_acl) + 2 * sizeof(struct cifs_ace); + if (set_owner) { + sdlen += sizeof(struct owner_group_sids); + setup_owner_group_sids(owner_offset + sizeof(struct create_context) + 8 /* name */ + + (char *)buf); + } buf->ccontext.DataOffset = cpu_to_le16(offsetof (struct crt_sd_ctxt, sd)); buf->ccontext.DataLength = cpu_to_le32(sdlen); - buf->ccontext.NameOffset = cpu_to_le16(offsetof - (struct crt_sd_ctxt, Name)); + buf->ccontext.NameOffset = cpu_to_le16(offsetof(struct crt_sd_ctxt, Name)); buf->ccontext.NameLength = cpu_to_le16(4); /* SMB2_CREATE_SD_BUFFER_TOKEN is "SecD" */ buf->Name[0] = 'S'; @@ -2359,23 +2404,34 @@ create_sd_buf(umode_t mode, unsigned int *len) /* create one ACE to hold the mode embedded in reserved special SID */ pace = (struct cifs_ace *)(sizeof(struct crt_sd_ctxt) + (char *)buf); acelen = setup_special_mode_ACE(pace, (__u64)mode); + + if (set_owner) { + /* we do not need to reallocate buffer to add the two more ACEs. plenty of space */ + pace = (struct cifs_ace *)(acelen + (sizeof(struct crt_sd_ctxt) + (char *)buf)); + acelen += setup_special_user_owner_ACE(pace); + /* it does not appear necessary to add an ACE for the NFS group SID */ + buf->acl.AceCount = cpu_to_le16(3); + } else + buf->acl.AceCount = cpu_to_le16(2); + /* and one more ACE to allow access for authenticated users */ pace = (struct cifs_ace *)(acelen + (sizeof(struct crt_sd_ctxt) + (char *)buf)); acelen += setup_authusers_ACE(pace); + buf->acl.AclSize = cpu_to_le16(sizeof(struct cifs_acl) + acelen); - buf->acl.AceCount = cpu_to_le16(2); + return buf; } static int -add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode) +add_sd_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode, bool set_owner) { struct smb2_create_req *req = iov[0].iov_base; unsigned int num = *num_iovec; unsigned int len = 0; - iov[num].iov_base = create_sd_buf(mode, &len); + iov[num].iov_base = create_sd_buf(mode, set_owner, &len); if (iov[num].iov_base == NULL) return -ENOMEM; iov[num].iov_len = len; @@ -2764,21 +2820,35 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server, return rc; } - if ((oparms->disposition != FILE_OPEN) && - (oparms->cifs_sb) && - (oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) && - (oparms->mode != ACL_NO_MODE)) { - if (n_iov > 2) { - struct create_context *ccontext = - (struct create_context *)iov[n_iov-1].iov_base; - ccontext->Next = - cpu_to_le32(iov[n_iov-1].iov_len); + if ((oparms->disposition != FILE_OPEN) && (oparms->cifs_sb)) { + bool set_mode; + bool set_owner; + + if ((oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) && + (oparms->mode != ACL_NO_MODE)) + set_mode = true; + else { + set_mode = false; + oparms->mode = ACL_NO_MODE; } - cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode); - rc = add_sd_context(iov, &n_iov, oparms->mode); - if (rc) - return rc; + if (oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) + set_owner = true; + else + set_owner = false; + + if (set_owner | set_mode) { + if (n_iov > 2) { + struct create_context *ccontext = + (struct create_context *)iov[n_iov-1].iov_base; + ccontext->Next = cpu_to_le32(iov[n_iov-1].iov_len); + } + + cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode); + rc = add_sd_context(iov, &n_iov, oparms->mode, set_owner); + if (rc) + return rc; + } } if (n_iov > 2) { -- 2.25.1