[newlib-cygwin] Handle files with owner == group.

Corinna Vinschen corinna@sourceware.org
Wed Apr 15 15:20:00 GMT 2015


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=5d31049e662805f2e43364f1980b8d84999c71c9

commit 5d31049e662805f2e43364f1980b8d84999c71c9
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Wed Apr 15 17:20:14 2015 +0200

    Handle files with owner == group.
    
    	* sec_acl.cc (set_posix_access): Handle files with owner == group.
    	Rephrase switch statement checking against unfiltered a_type value.
    	(get_posix_access): Handle files with owner == group.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/ChangeLog  |  6 ++++
 winsup/cygwin/sec_acl.cc | 94 +++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 80 insertions(+), 20 deletions(-)

diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 47a4b1a..9adade0 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,9 @@
+2015-04-15  Corinna Vinschen  <corinna@vinschen.de>
+
+	* sec_acl.cc (set_posix_access): Handle files with owner == group.
+	Rephrase switch statement checking against unfiltered a_type value.
+	(get_posix_access): Handle files with owner == group.
+
 2015-04-14  Corinna Vinschen  <corinna@vinschen.de>
 
 	* sec_acl.cc (get_posix_access): Don't use GROUP_OBJ access to fix up
diff --git a/winsup/cygwin/sec_acl.cc b/winsup/cygwin/sec_acl.cc
index e7c8de6..a8ffbf0 100644
--- a/winsup/cygwin/sec_acl.cc
+++ b/winsup/cygwin/sec_acl.cc
@@ -141,6 +141,7 @@ set_posix_access (mode_t attr, uid_t uid, gid_t gid,
   mode_t class_obj = 0, other_obj, group_obj, deny;
   DWORD access;
   int idx, start_idx, class_idx, tmp_idx;
+  bool owner_eq_group;
   bool dev_saw_admins = false;
 
   /* Initialize local security descriptor. */
@@ -165,6 +166,7 @@ set_posix_access (mode_t attr, uid_t uid, gid_t gid,
       __seterrno_from_nt_status (status);
       return NULL;
     }
+  owner_eq_group = RtlEqualSid (owner, group);
 
   /* No POSIX ACL?  Use attr to generate one from scratch. */
   if (!aclbufp)
@@ -198,26 +200,35 @@ set_posix_access (mode_t attr, uid_t uid, gid_t gid,
   /* Collect SIDs of all entries in aclbufp. */
   aclsid = (cygpsid *) tp.w_get ();
   for (idx = 0; idx < nentries; ++idx)
-    switch (aclbufp[idx].a_type & ~ACL_DEFAULT)
+    switch (aclbufp[idx].a_type)
       {
       case USER_OBJ:
-	aclsid[idx] = (aclbufp[idx].a_type & ACL_DEFAULT)
-		      ? (PSID) well_known_creator_owner_sid : owner;
+	aclsid[idx] = owner;
+	break;
+      case DEF_USER_OBJ:
+	aclsid[idx] = well_known_creator_owner_sid;
 	break;
       case USER:
+      case DEF_USER:
 	aclsid[idx] = sidfromuid (aclbufp[idx].a_id, &cldap);
 	break;
       case GROUP_OBJ:
-	aclsid[idx] = (aclbufp[idx].a_type & ACL_DEFAULT && !(attr & S_ISGID))
-		      ? (PSID) well_known_creator_group_sid : group;
+	aclsid[idx] = group;
+	break;
+      case DEF_GROUP_OBJ:
+	aclsid[idx] = !(attr & S_ISGID) ? (PSID) well_known_creator_group_sid
+					: group;
 	break;
       case GROUP:
+      case DEF_GROUP:
 	aclsid[idx] = sidfromgid (aclbufp[idx].a_id, &cldap);
 	break;
       case CLASS_OBJ:
+      case DEF_CLASS_OBJ:
 	aclsid[idx] = well_known_null_sid;
 	break;
       case OTHER_OBJ:
+      case DEF_OTHER_OBJ:
 	aclsid[idx] = well_known_world_sid;
 	break;
       }
@@ -256,6 +267,11 @@ set_posix_access (mode_t attr, uid_t uid, gid_t gid,
       tmp_idx = searchace (aclbufp, nentries, def | OTHER_OBJ);
       other_obj = aclbufp[tmp_idx].a_perm;
 
+      /* Do we potentially chmod a file with owner SID == group SID?  If so,
+	 make sure the owner perms are always >= group perms. */
+      if (!def && owner_eq_group)
+	  aclbufp[0].a_perm |= group_obj;
+
       /* ... class_obj.  Create Cygwin ACE.  Only the S_ISGID attribute gets
 	 inherited. */
       access = CYG_ACE_ISBITS_TO_WIN (def ? attr & S_ISGID : attr);
@@ -514,11 +530,13 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
   cygpsid ace_sid;
   int pos, type, id, idx;
 
+  bool owner_eq_group;
   bool just_created = false;
   bool new_style = false;
   bool saw_user_obj = false;
   bool saw_group_obj = false;
   bool saw_other_obj = false;
+  bool saw_def_user_obj = false;
   bool saw_def_group_obj = false;
   bool has_class_perm = false;
   bool has_def_class_perm = false;
@@ -585,6 +603,8 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
       attr = *attr_ret & S_IFMT;
       just_created = *attr_ret & S_JUSTCREATED;
     }
+  /* Remember the fact that owner and group are the same account. */
+  owner_eq_group = owner_sid == group_sid;
 
   /* Create and initialize local aclent_t array. */
   lacl = (aclent_t *) tp.c_get ();
@@ -690,6 +710,7 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
 	  type = DEF_USER_OBJ;
 	  types_def |= type;
 	  id = ILLEGAL_GID;
+	  saw_def_user_obj = true;
 	}
       else if (ace_sid == well_known_creator_group_sid)
 	{
@@ -703,25 +724,38 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
 	  id = ace_sid.get_id (TRUE, &type, &cldap);
 	  if (!type)
 	    continue;
-	  /* If the SGID attribute is set on a new-style Cygwin ACL on
-	     a just created file or dir, the first group in the ACL is
-	     the desired primary group of the new object. */
-	  if (just_created && new_style && attr & S_ISGID
-	      && !saw_group_obj && type == GROUP)
-	    {
-	      type = GROUP_OBJ;
-	      lacl[1].a_id = gid = id;
-	    }
+	}
+      /* If the SGID attribute is set on a just created file or dir, the
+         first group in the ACL is the desired primary group of the new
+	 object.  Alternatively, the first repetition of the owner SID is
+	 the desired primary group, and we mark the object as owner_eq_group
+	 object. */
+      if (just_created && attr & S_ISGID && !saw_group_obj
+	  && (type == GROUP || (type == USER_OBJ && saw_user_obj)))
+	{
+	  type = GROUP_OBJ;
+	  lacl[1].a_id = gid = id;
+	  owner_eq_group = true;
 	}
       if (!(ace->Header.AceFlags & INHERIT_ONLY || type & ACL_DEFAULT))
 	{
 	  if (type == USER_OBJ)
 	    {
-	      /* If we get a second entry for the owner, it's an additional
-		 USER entry.  This can happen when chown'ing a file. */
+	      /* If we get a second entry for the owner SID, it's either a
+		 GROUP_OBJ entry for the same SID, if owner SID == group SID,
+		 or it's an additional USER entry.  The latter can happen
+		 when chown'ing a file. */
 	      if (saw_user_obj)
-		type = USER;
-	      if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
+		{
+		  if (owner_eq_group && !saw_group_obj)
+		    {
+		      type = GROUP_OBJ;
+		      saw_group_obj = true;
+		    }
+		  else
+		    type = USER;
+		}
+	      else if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
 		saw_user_obj = true;
 	    }
 	  else if (type == GROUP_OBJ)
@@ -755,8 +789,23 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
       if ((ace->Header.AceFlags & SUB_CONTAINERS_AND_OBJECTS_INHERIT))
 	{
 	  if (type == USER_OBJ)
-	    type = USER;
-	  else if (type == GROUP_OBJ)
+	    {
+	      /* As above: If we get a second entry for the owner SID, it's
+		 a GROUP_OBJ entry for the same SID if owner SID == group SID,
+		 but this time only if the S_ISGID bit is set. Otherwise it's
+		 an additional USER entry. */
+	      if (saw_def_user_obj)
+		{
+		  if (owner_eq_group && !saw_def_group_obj && attr & S_ISGID)
+		    type = GROUP_OBJ;	/* This needs post-processing in the
+					   following GROUP_OBJ handling... */
+		  else
+		    type = USER;
+		}
+	      else if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
+		saw_def_user_obj = true;
+	    }
+	  if (type == GROUP_OBJ)
 	    {
 	      /* If the SGID bit is set, the inheritable entry for the
 		 primary group is, in fact, the DEF_GROUP_OBJ entry,
@@ -897,6 +946,11 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
 		 && !(lacl[idx].a_perm & DENY_RWX))
 	  lacl[idx].a_perm |= lacl[2].a_perm & S_IRWXO;
       }
+  /* If owner SID == group SID (Microsoft Accounts) merge group perms into
+     user perms but leave group perms intact.  That's a fake, but it allows
+     to keep track of the POSIX group perms without much effort. */
+  if (owner_eq_group)
+    lacl[0].a_perm |= lacl[1].a_perm;
   /* Construct POSIX permission bits.  Fortunately we know exactly where
      to fetch the affecting bits from, at least as long as the array
      hasn't been sorted. */



More information about the Cygwin-cvs mailing list