diff options
Diffstat (limited to 'winsup/cygwin/security.cc')
-rw-r--r-- | winsup/cygwin/security.cc | 77 |
1 files changed, 49 insertions, 28 deletions
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index 0a843c7a0..6a5b86b27 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -456,7 +456,7 @@ get_group_sidlist (const char *logonserver, cygsidlist &grp_list, if (usersid == well_known_system_sid) { grp_list += well_known_system_sid; - grp_list += well_known_admin_sid; + grp_list += well_known_admins_sid; } else { @@ -626,10 +626,10 @@ get_dacl (PACL acl, cygsid usersid, cygsidlist &grp_list) __seterrno (); return FALSE; } - if (grp_list.contains (well_known_admin_sid)) + if (grp_list.contains (well_known_admins_sid)) { if (!AddAccessAllowedAce(acl, ACL_REVISION, GENERIC_ALL, - well_known_admin_sid)) + well_known_admins_sid)) { __seterrno (); return FALSE; @@ -1162,15 +1162,24 @@ get_nt_attribute (const char *file, int *attribute, *flags |= S_IXOTH | ((!(*anti & S_IXGRP)) ? S_IXGRP : 0) | ((!(*anti & S_IXUSR)) ? S_IXUSR : 0); - /* Sticky bit for directories according to linux rules. */ - if (!(ace->Mask & FILE_DELETE_CHILD) - && S_ISDIR(*attribute) - && !(*anti & S_ISVTX)) - *flags |= S_ISVTX; } + if ((*attribute & S_IFDIR) && + (ace->Mask & (FILE_WRITE_DATA | FILE_EXECUTE | FILE_DELETE_CHILD)) + == (FILE_WRITE_DATA | FILE_EXECUTE)) + *flags |= S_ISVTX; + } + else if (ace_sid == well_known_null_sid) + { + /* Read SUID, SGID and VTX bits from NULL ACE. */ + if (ace->Mask & FILE_READ_DATA) + *flags |= S_ISVTX; + if (ace->Mask & FILE_WRITE_DATA) + *flags |= S_ISGID; + if (ace->Mask & FILE_APPEND_DATA) + *flags |= S_ISUID; } } - *attribute &= ~(S_IRWXU|S_IRWXG|S_IRWXO|S_ISVTX); + *attribute &= ~(S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX | S_ISGID | S_ISUID); *attribute |= allow; *attribute &= ~deny; syscall_printf ("file: %s %x, uid %d, gid %d", file, *attribute, uid, gid); @@ -1335,16 +1344,6 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, return NULL; } - /* - * VTX bit may only be set if executable for `other' is set. - * For correct handling under WinNT, FILE_DELETE_CHILD has to - * be (un)set in each ACE. - */ - if (!(attribute & S_IXOTH)) - attribute &= ~S_ISVTX; - if (!(attribute & S_IFDIR)) - attribute |= S_ISVTX; - /* From here fill ACL. */ size_t acl_len = sizeof (ACL); int ace_off = 0; @@ -1355,10 +1354,11 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, if (attribute & S_IRUSR) owner_allow |= FILE_GENERIC_READ; if (attribute & S_IWUSR) - owner_allow |= FILE_GENERIC_WRITE | DELETE; + owner_allow |= FILE_GENERIC_WRITE; if (attribute & S_IXUSR) owner_allow |= FILE_GENERIC_EXECUTE; - if (!(attribute & S_ISVTX)) + if ((attribute & (S_IFDIR | S_IWUSR | S_IXUSR)) + == (S_IFDIR | S_IWUSR | S_IXUSR)) owner_allow |= FILE_DELETE_CHILD; /* Construct allow attribute for group. */ @@ -1367,10 +1367,11 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, if (attribute & S_IRGRP) group_allow |= FILE_GENERIC_READ; if (attribute & S_IWGRP) - group_allow |= STANDARD_RIGHTS_WRITE | FILE_GENERIC_WRITE | DELETE; + group_allow |= STANDARD_RIGHTS_WRITE | FILE_GENERIC_WRITE; if (attribute & S_IXGRP) group_allow |= FILE_GENERIC_EXECUTE; - if (!(attribute & S_ISVTX)) + if ((attribute & (S_IFDIR | S_IWGRP | S_IXGRP)) + == (S_IFDIR | S_IWGRP | S_IXGRP)) group_allow |= FILE_DELETE_CHILD; /* Construct allow attribute for everyone. */ @@ -1379,12 +1380,26 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, if (attribute & S_IROTH) other_allow |= FILE_GENERIC_READ; if (attribute & S_IWOTH) - other_allow |= STANDARD_RIGHTS_WRITE | FILE_GENERIC_WRITE | DELETE; + other_allow |= STANDARD_RIGHTS_WRITE | FILE_GENERIC_WRITE; if (attribute & S_IXOTH) other_allow |= FILE_GENERIC_EXECUTE; - if (!(attribute & S_ISVTX)) + if ((attribute & (S_IFDIR | S_IWOTH | S_IXOTH)) + == (S_IFDIR | S_IWOTH | S_IXOTH) + && !(attribute & S_ISVTX)) other_allow |= FILE_DELETE_CHILD; + /* Construct SUID, SGID and VTX bits in NULL ACE. */ + DWORD null_allow = 0L; + if (attribute & (S_ISUID | S_ISGID | S_ISVTX)) + { + if (attribute & S_ISUID) + null_allow |= FILE_APPEND_DATA; + if (attribute & S_ISGID) + null_allow |= FILE_WRITE_DATA; + if (attribute & S_ISVTX) + null_allow |= FILE_READ_DATA; + } + /* Construct deny attributes for owner and group. */ DWORD owner_deny = 0; if (is_grp_member (uid, gid)) @@ -1420,7 +1435,7 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, if (owner_deny && !add_access_denied_ace (acl, ace_off++, owner_deny, owner_sid, acl_len, inherit)) - return NULL; + return NULL; /* Set allow ACE for owner. */ if (!add_access_allowed_ace (acl, ace_off++, owner_allow, owner_sid, acl_len, inherit)) @@ -1429,7 +1444,7 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, if (group_deny && !add_access_denied_ace (acl, ace_off++, group_deny, group_sid, acl_len, inherit)) - return NULL; + return NULL; /* Set allow ACE for group. */ if (!add_access_allowed_ace (acl, ace_off++, group_allow, group_sid, acl_len, inherit)) @@ -1439,6 +1454,11 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, if (!add_access_allowed_ace (acl, ace_off++, other_allow, well_known_world_sid, acl_len, inherit)) return NULL; + /* Set null ACE for special bits. */ + if (null_allow + && !add_access_allowed_ace (acl, ace_off++, null_allow, + well_known_null_sid, acl_len, inherit)) + return NULL; /* Get owner and group from current security descriptor. */ PSID cur_owner_sid = NULL; @@ -1463,7 +1483,8 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, || (owner_sid && ace_sid == owner_sid) || (cur_group_sid && ace_sid == cur_group_sid) || (group_sid && ace_sid == group_sid) - || (ace_sid == well_known_world_sid)) + || (ace_sid == well_known_world_sid) + || (ace_sid == well_known_null_sid)) continue; /* * Add unrelated ACCESS_DENIED_ACE to the beginning but |