diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 2ff511b98..1f7a23e5b 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,16 @@ +2014-08-28 Corinna Vinschen + + * fhandler.cc (fhandler_base::facl): Drop CLASS_OBJ entry. + * fhandler_disk_file.cc (fhandler_disk_file::facl): Ditto in noacl case. + * sec_acl.cc (getacl): Compute useful fake CLASS_OBJ and DEF_CLASS_OBJ + permission bits based on how these values are generated on Linux. + Add commants to explain what the code is doing. + * security.cc (get_attribute_from_acl): Compute group permission based + on the actual primary group permissions and all secondary user and group + ACCESS_ALLOWED_ACEs to emulate Linux' behaviour more closely. + (check_access): Fix typos im comment. + * include/cygwin/acl.h (MIN_ACL_ENTRIES): Redefine as 3. + 2014-08-28 Corinna Vinschen * fhandler_disk_file.cc (fhandler_disk_file::fstatvfs): Try the diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index c64fc33b1..8444d4abc 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -1737,9 +1737,6 @@ fhandler_base::facl (int cmd, int nentries, aclent_t *aclbufp) aclbufp[2].a_type = OTHER_OBJ; aclbufp[2].a_id = ILLEGAL_GID; aclbufp[2].a_perm = S_IROTH | S_IWOTH; - aclbufp[3].a_type = CLASS_OBJ; - aclbufp[3].a_id = ILLEGAL_GID; - aclbufp[3].a_perm = S_IRWXU | S_IRWXG | S_IRWXO; res = MIN_ACL_ENTRIES; } break; diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index a2ed1cfd1..2d1468bb4 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -1045,9 +1045,6 @@ cant_access_acl: aclbufp[2].a_type = OTHER_OBJ; aclbufp[2].a_id = ILLEGAL_GID; aclbufp[2].a_perm = st.st_mode & S_IRWXO; - aclbufp[3].a_type = CLASS_OBJ; - aclbufp[3].a_id = ILLEGAL_GID; - aclbufp[3].a_perm = S_IRWXU | S_IRWXG | S_IRWXO; res = MIN_ACL_ENTRIES; } } diff --git a/winsup/cygwin/include/cygwin/acl.h b/winsup/cygwin/include/cygwin/acl.h index 9a62e325e..8fa5a65a5 100644 --- a/winsup/cygwin/include/cygwin/acl.h +++ b/winsup/cygwin/include/cygwin/acl.h @@ -1,6 +1,6 @@ /* cygwin/acl.h header file for Cygwin. - Copyright 1999, 2000, 2001, 2002, 2010 Red Hat, Inc. + Copyright 1999, 2000, 2001, 2002, 2010, 2014 Red Hat, Inc. Written by C. Vinschen. This file is part of Cygwin. @@ -25,7 +25,7 @@ extern "C" { #define GETACL (0x1) #define GETACLCNT (0x2) -#define MIN_ACL_ENTRIES (4) // minimal acl entries from GETACLCNT +#define MIN_ACL_ENTRIES (3) // minimal acl entries from GETACLCNT #define MAX_ACL_ENTRIES (256) // max entries of each type // Return values of aclcheck(3) in case of error */ diff --git a/winsup/cygwin/sec_acl.cc b/winsup/cygwin/sec_acl.cc index ec5876099..4acb5c37f 100644 --- a/winsup/cygwin/sec_acl.cc +++ b/winsup/cygwin/sec_acl.cc @@ -309,9 +309,6 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp) lacl[1].a_id = gid; lacl[2].a_type = OTHER_OBJ; lacl[2].a_id = ILLEGAL_GID; - lacl[3].a_type = CLASS_OBJ; - lacl[3].a_id = ILLEGAL_GID; - lacl[3].a_perm = S_IROTH | S_IWOTH | S_IXOTH; PACL acl; BOOLEAN acl_exists; @@ -324,9 +321,11 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp) } int pos, i, types_def = 0; + int pgrp_pos = 1, def_pgrp_pos = -1; + mode_t class_perm = 0, def_class_perm = 0; if (!acl_exists || !acl) - for (pos = 0; pos < 3; ++pos) /* Don't change CLASS_OBJ entry */ + for (pos = 0; pos < 3; ++pos) lacl[pos].a_perm = S_IROTH | S_IWOTH | S_IXOTH; else { @@ -358,13 +357,13 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp) } else if (ace_sid == well_known_creator_group_sid) { - type = GROUP_OBJ | ACL_DEFAULT; + type = DEF_GROUP_OBJ; types_def |= type; id = ILLEGAL_GID; } else if (ace_sid == well_known_creator_owner_sid) { - type = USER_OBJ | ACL_DEFAULT; + type = DEF_USER_OBJ; types_def |= type; id = ILLEGAL_GID; } @@ -376,7 +375,12 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp) if (!(ace->Header.AceFlags & INHERIT_ONLY_ACE || type & ACL_DEFAULT)) { if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0) - getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType); + { + getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType); + /* Fix up CLASS_OBJ value. */ + if (type == USER || type == GROUP) + class_perm |= lacl[pos].a_perm; + } } if ((ace->Header.AceFlags & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE)) @@ -389,13 +393,31 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp) type |= ACL_DEFAULT; types_def |= type; if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0) - getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType); + { + getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType); + /* Fix up DEF_CLASS_OBJ value. */ + if (type == DEF_USER || type == DEF_GROUP) + def_class_perm |= lacl[pos].a_perm; + /* And note the position of the DEF_GROUP_OBJ entry. */ + else if (type == DEF_GROUP_OBJ) + def_pgrp_pos = pos; + } } } + /* If secondary user and group entries exist in the ACL, fake a matching + CLASS_OBJ entry. The CLASS_OBJ permissions are the or'ed permissions + of the primary group permissions and all secondary user and group + permissions. */ + if (class_perm && (pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) >= 0) + { + lacl[pos].a_type = CLASS_OBJ; + lacl[pos].a_id = ILLEGAL_GID; + lacl[pos].a_perm = class_perm | lacl[pgrp_pos].a_perm; + } + /* Ensure that the default acl contains at least + DEF_(USER|GROUP|OTHER)_OBJ entries. */ if (types_def && (pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) >= 0) { - /* Ensure that the default acl contains at - least DEF_(USER|GROUP|OTHER)_OBJ entries. */ if (!(types_def & USER_OBJ)) { lacl[pos].a_type = DEF_USER_OBJ; @@ -408,6 +430,8 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp) lacl[pos].a_type = DEF_GROUP_OBJ; lacl[pos].a_id = gid; lacl[pos].a_perm = lacl[1].a_perm; + /* Note the position of the DEF_GROUP_OBJ entry. */ + def_pgrp_pos = pos; pos++; } if (!(types_def & OTHER_OBJ) && pos < MAX_ACL_ENTRIES) @@ -417,13 +441,18 @@ getacl (HANDLE handle, path_conv &pc, int nentries, aclent_t *aclbufp) lacl[pos].a_perm = lacl[2].a_perm; pos++; } - /* Include DEF_CLASS_OBJ if any named default ace exists. */ - if ((types_def & (USER|GROUP)) && pos < MAX_ACL_ENTRIES) - { - lacl[pos].a_type = DEF_CLASS_OBJ; - lacl[pos].a_id = ILLEGAL_GID; - lacl[pos].a_perm = S_IROTH | S_IWOTH | S_IXOTH; - } + } + /* If secondary user default and group default entries exist in the ACL, + fake a matching DEF_CLASS_OBJ entry. The DEF_CLASS_OBJ permissions are + the or'ed permissions of the primary group default permissions and all + secondary user and group default permissions. */ + if (def_class_perm && (pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) >= 0) + { + lacl[pos].a_type = DEF_CLASS_OBJ; + lacl[pos].a_id = ILLEGAL_GID; + lacl[pos].a_perm = def_class_perm; + if (def_pgrp_pos >= 0) + lacl[pos].a_perm |= lacl[def_pgrp_pos].a_perm; } } if ((pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) < 0) diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index af89a5238..4c46e05d9 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -314,6 +314,21 @@ get_attribute_from_acl (mode_t *attribute, PACL acl, PSID owner_sid, *flags |= ((!(*anti & S_IXGRP)) ? S_IXGRP : 0) | ((grp_member && !(*anti & S_IXUSR)) ? S_IXUSR : 0); } + else if (flags == &allow) + { + /* Simplified computation of additional group permissions based on + the CLASS_OBJ value. CLASS_OBJ represents the or'ed value of + the primary group permissions and all secondary user and group + permissions. FIXME: This only takes ACCESS_ALLOWED_ACEs into + account. The computation with additional ACCESS_DENIED_ACE + handling is much more complicated. */ + if (ace->Mask & FILE_READ_BITS) + *flags |= S_IRGRP; + if (ace->Mask & FILE_WRITE_BITS) + *flags |= S_IWGRP; + if (ace->Mask & FILE_EXEC_BITS) + *flags |= S_IXGRP; + } } *attribute &= ~(S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX | S_ISGID | S_ISUID); if (owner_sid && group_sid && RtlEqualSid (owner_sid, group_sid) @@ -1049,8 +1064,8 @@ check_access (security_descriptor &sd, GENERIC_MAPPING &mapping, /* Samba override. Check security descriptor for Samba UNIX user and group accounts and check if we have an RFC 2307 mapping to a Windows account. - Create a new security descriptor with all of the UNIX acocunts with - valid mapping replaced with their WIndows counterpart. */ + Create a new security descriptor with all of the UNIX accounts with + valid mapping replaced with their Windows counterpart. */ static void convert_samba_sd (security_descriptor &sd_ret) {