[newlib-cygwin/cygwin-acl] Fix up POSIX permission handling
Corinna Vinschen
corinna@sourceware.org
Tue Sep 1 20:24:00 GMT 2015
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=974123cddb8c1dbb51cf53f290e71c5adaa01cca
commit 974123cddb8c1dbb51cf53f290e71c5adaa01cca
Author: Corinna Vinschen <corinna@vinschen.de>
Date: Tue Sep 1 22:23:59 2015 +0200
Fix up POSIX permission handling
* fhandler_disk_file.cc (fhandler_disk_file::fchmod): Disable
deviation from POSIX 1003.1e in terms of GROUP_OBJ/CLASS_OBJ
permissions. Follow POSIX 1003.1e again. Keep old code in
for future reference.
* sec_acl.cc: Accommodate changes in ACE creation in leading
comment.
(set_posix_access): Fix user deny ACE creation. Split group
deny ACE creation into two steps, one to reflect CLASS_OBJ,
the other to reflect OTHER_OBJ.
Diff:
---
winsup/cygwin/fhandler_disk_file.cc | 10 +++++++
winsup/cygwin/sec_acl.cc | 54 ++++++++++++++++++++++++++++++-------
2 files changed, 55 insertions(+), 9 deletions(-)
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 204ba60..4885885 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -915,6 +915,7 @@ fhandler_disk_file::fchmod (mode_t mode)
/* Overwrite ACL permissions as required by POSIX 1003.1e
draft 17. */
aclp[0].a_perm = (mode >> 6) & S_IRWXO;
+#if 0
/* Deliberate deviation from POSIX 1003.1e here. We're not
writing CLASS_OBJ *or* GROUP_OBJ, but both. Otherwise we're
going to be in constant trouble with user expectations. */
@@ -923,6 +924,15 @@ fhandler_disk_file::fchmod (mode_t mode)
if (nentries > MIN_ACL_ENTRIES
&& (idx = searchace (aclp, nentries, CLASS_OBJ)) >= 0)
aclp[idx].a_perm = (mode >> 3) & S_IRWXO;
+#else
+ /* POSIXly correct: If CLASS_OBJ is present, chmod only modifies
+ CLASS_OBJ, not GROUP_OBJ. */
+ if (nentries > MIN_ACL_ENTRIES
+ && (idx = searchace (aclp, nentries, CLASS_OBJ)) >= 0)
+ aclp[idx].a_perm = (mode >> 3) & S_IRWXO;
+ else if ((idx = searchace (aclp, nentries, GROUP_OBJ)) >= 0)
+ aclp[idx].a_perm = (mode >> 3) & S_IRWXO;
+#endif
if ((idx = searchace (aclp, nentries, OTHER_OBJ)) >= 0)
aclp[idx].a_perm = mode & S_IRWXO;
if (pc.isdir ())
diff --git a/winsup/cygwin/sec_acl.cc b/winsup/cygwin/sec_acl.cc
index 82e9cb5..a84cd5e 100644
--- a/winsup/cygwin/sec_acl.cc
+++ b/winsup/cygwin/sec_acl.cc
@@ -37,25 +37,30 @@ details. */
or
USER_OBJ deny ACE == ~USER_OBJ & (GROUP_OBJ | OTHER_OBJ)
- - USER deny. If a user has different permissions from CLASS_OBJ, or if the
+ - USER deny. If a user has more permissions than CLASS_OBJ, or if the
user has less permissions than OTHER_OBJ, deny the excess permissions.
- USER deny ACE == (USER ^ CLASS_OBJ) | (~USER & OTHER_OBJ)
+ USER deny ACE == (USER & ~CLASS_OBJ) | (~USER & OTHER_OBJ)
- USER_OBJ allow ACE
- USER allow ACEs
- The POSIX permissions returned for a USER entry are the allow bits alone!
+ The POSIX permissions returned for a USER entry are the allow bits alone!
- GROUP{_OBJ} deny. If a group has more permissions than CLASS_OBJ,
or less permissions than OTHER_OBJ, deny the excess permissions.
- GROUP{_OBJ} deny ACEs == (GROUP & ~CLASS_OBJ) | (~GROUP & OTHER_OBJ)
+ GROUP{_OBJ} deny ACEs == (GROUP & ~CLASS_OBJ)
- GROUP_OBJ allow ACE
- GROUP allow ACEs
- The POSIX permissions returned for a GROUP entry are the allow bits alone!
+ The POSIX permissions returned for a GROUP entry are the allow bits alone!
+
+ - 2. GROUP{_OBJ} deny. If a group has less permissions than OTHER_OBJ,
+ deny the excess permissions.
+
+ 2. GROUP{_OBJ} deny ACEs == (~GROUP & OTHER_OBJ)
- OTHER_OBJ allow ACE
@@ -311,7 +316,9 @@ set_posix_access (mode_t attr, uid_t uid, gid_t gid,
check_types < CLASS_OBJ;
check_types <<= 2)
{
- /* Create deny ACEs for users, then groups. */
+ /* Create deny ACEs for users, then 1st run for groups. For groups,
+ only take CLASS_OBJ permissions into account. Class permissions
+ are handled in the 2nd deny loop below. */
for (start_idx = idx;
idx < nentries && aclbufp[idx].a_type & check_types;
++idx)
@@ -327,7 +334,7 @@ set_posix_access (mode_t attr, uid_t uid, gid_t gid,
if (aclbufp[idx].a_type & USER_OBJ)
deny = ~aclbufp[idx].a_perm & (class_obj | other_obj);
else if (aclbufp[idx].a_type & USER)
- deny = (aclbufp[idx].a_perm ^ class_obj)
+ deny = (aclbufp[idx].a_perm & ~class_obj)
| (~aclbufp[idx].a_perm & other_obj);
/* Accommodate Windows: Only generate deny masks for SYSTEM
and the Administrators group in terms of the execute bit,
@@ -337,8 +344,7 @@ set_posix_access (mode_t attr, uid_t uid, gid_t gid,
|| aclsid[idx] == well_known_admins_sid))
deny = aclbufp[idx].a_perm & ~(class_obj | S_IROTH | S_IWOTH);
else
- deny = (aclbufp[idx].a_perm & ~class_obj)
- | (~aclbufp[idx].a_perm & other_obj);
+ deny = (aclbufp[idx].a_perm & ~class_obj);
if (!deny)
continue;
access = 0;
@@ -391,6 +397,36 @@ set_posix_access (mode_t attr, uid_t uid, gid_t gid,
inherit))
return NULL;
}
+ /* 2nd deny loop: Create deny ACEs for groups when they have less
+ permissions than OTHER_OBJ. */
+ if (check_types == (GROUP_OBJ | GROUP))
+ for (idx = start_idx;
+ idx < nentries && aclbufp[idx].a_type & check_types;
+ ++idx)
+ {
+ if (aclbufp[idx].a_type & GROUP && aclsid[idx] == group)
+ continue;
+ /* Only generate deny masks for SYSTEM and the Administrators
+ group if they are the primary group. */
+ if (aclbufp[idx].a_type & GROUP
+ && (aclsid[idx] == well_known_system_sid
+ || aclsid[idx] == well_known_admins_sid))
+ deny = 0;
+ else
+ deny = (~aclbufp[idx].a_perm & other_obj);
+ if (!deny)
+ continue;
+ access = 0;
+ if (deny & S_IROTH)
+ access |= FILE_DENY_READ;
+ if (deny & S_IWOTH)
+ access |= FILE_DENY_WRITE;
+ if (deny & S_IXOTH)
+ access |= FILE_DENY_EXEC;
+ if (!add_access_denied_ace (acl, access, aclsid[idx], acl_len,
+ inherit))
+ return NULL;
+ }
}
/* For ptys if the admins group isn't in the ACL, add an ACE to make
sure the group has WRITE_DAC and WRITE_OWNER perms. */
More information about the Cygwin-cvs
mailing list