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>
This commit is contained in:
Corinna Vinschen 2015-04-15 17:20:14 +02:00
parent c7bd0c3778
commit 5d31049e66
2 changed files with 80 additions and 20 deletions

View File

@ -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> 2015-04-14 Corinna Vinschen <corinna@vinschen.de>
* sec_acl.cc (get_posix_access): Don't use GROUP_OBJ access to fix up * sec_acl.cc (get_posix_access): Don't use GROUP_OBJ access to fix up

View File

@ -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; mode_t class_obj = 0, other_obj, group_obj, deny;
DWORD access; DWORD access;
int idx, start_idx, class_idx, tmp_idx; int idx, start_idx, class_idx, tmp_idx;
bool owner_eq_group;
bool dev_saw_admins = false; bool dev_saw_admins = false;
/* Initialize local security descriptor. */ /* 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); __seterrno_from_nt_status (status);
return NULL; return NULL;
} }
owner_eq_group = RtlEqualSid (owner, group);
/* No POSIX ACL? Use attr to generate one from scratch. */ /* No POSIX ACL? Use attr to generate one from scratch. */
if (!aclbufp) 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. */ /* Collect SIDs of all entries in aclbufp. */
aclsid = (cygpsid *) tp.w_get (); aclsid = (cygpsid *) tp.w_get ();
for (idx = 0; idx < nentries; ++idx) for (idx = 0; idx < nentries; ++idx)
switch (aclbufp[idx].a_type & ~ACL_DEFAULT) switch (aclbufp[idx].a_type)
{ {
case USER_OBJ: case USER_OBJ:
aclsid[idx] = (aclbufp[idx].a_type & ACL_DEFAULT) aclsid[idx] = owner;
? (PSID) well_known_creator_owner_sid : owner; break;
case DEF_USER_OBJ:
aclsid[idx] = well_known_creator_owner_sid;
break; break;
case USER: case USER:
case DEF_USER:
aclsid[idx] = sidfromuid (aclbufp[idx].a_id, &cldap); aclsid[idx] = sidfromuid (aclbufp[idx].a_id, &cldap);
break; break;
case GROUP_OBJ: case GROUP_OBJ:
aclsid[idx] = (aclbufp[idx].a_type & ACL_DEFAULT && !(attr & S_ISGID)) aclsid[idx] = group;
? (PSID) well_known_creator_group_sid : group; break;
case DEF_GROUP_OBJ:
aclsid[idx] = !(attr & S_ISGID) ? (PSID) well_known_creator_group_sid
: group;
break; break;
case GROUP: case GROUP:
case DEF_GROUP:
aclsid[idx] = sidfromgid (aclbufp[idx].a_id, &cldap); aclsid[idx] = sidfromgid (aclbufp[idx].a_id, &cldap);
break; break;
case CLASS_OBJ: case CLASS_OBJ:
case DEF_CLASS_OBJ:
aclsid[idx] = well_known_null_sid; aclsid[idx] = well_known_null_sid;
break; break;
case OTHER_OBJ: case OTHER_OBJ:
case DEF_OTHER_OBJ:
aclsid[idx] = well_known_world_sid; aclsid[idx] = well_known_world_sid;
break; 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); tmp_idx = searchace (aclbufp, nentries, def | OTHER_OBJ);
other_obj = aclbufp[tmp_idx].a_perm; 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 /* ... class_obj. Create Cygwin ACE. Only the S_ISGID attribute gets
inherited. */ inherited. */
access = CYG_ACE_ISBITS_TO_WIN (def ? attr & S_ISGID : attr); access = CYG_ACE_ISBITS_TO_WIN (def ? attr & S_ISGID : attr);
@ -514,11 +530,13 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
cygpsid ace_sid; cygpsid ace_sid;
int pos, type, id, idx; int pos, type, id, idx;
bool owner_eq_group;
bool just_created = false; bool just_created = false;
bool new_style = false; bool new_style = false;
bool saw_user_obj = false; bool saw_user_obj = false;
bool saw_group_obj = false; bool saw_group_obj = false;
bool saw_other_obj = false; bool saw_other_obj = false;
bool saw_def_user_obj = false;
bool saw_def_group_obj = false; bool saw_def_group_obj = false;
bool has_class_perm = false; bool has_class_perm = false;
bool has_def_class_perm = false; bool has_def_class_perm = false;
@ -585,6 +603,8 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
attr = *attr_ret & S_IFMT; attr = *attr_ret & S_IFMT;
just_created = *attr_ret & S_JUSTCREATED; 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. */ /* Create and initialize local aclent_t array. */
lacl = (aclent_t *) tp.c_get (); lacl = (aclent_t *) tp.c_get ();
@ -690,6 +710,7 @@ get_posix_access (PSECURITY_DESCRIPTOR psd,
type = DEF_USER_OBJ; type = DEF_USER_OBJ;
types_def |= type; types_def |= type;
id = ILLEGAL_GID; id = ILLEGAL_GID;
saw_def_user_obj = true;
} }
else if (ace_sid == well_known_creator_group_sid) 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); id = ace_sid.get_id (TRUE, &type, &cldap);
if (!type) if (!type)
continue; 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 /* If the SGID attribute is set on a just created file or dir, the
the desired primary group of the new object. */ first group in the ACL is the desired primary group of the new
if (just_created && new_style && attr & S_ISGID object. Alternatively, the first repetition of the owner SID is
&& !saw_group_obj && type == GROUP) 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; type = GROUP_OBJ;
lacl[1].a_id = gid = id; lacl[1].a_id = gid = id;
} owner_eq_group = true;
} }
if (!(ace->Header.AceFlags & INHERIT_ONLY || type & ACL_DEFAULT)) if (!(ace->Header.AceFlags & INHERIT_ONLY || type & ACL_DEFAULT))
{ {
if (type == USER_OBJ) if (type == USER_OBJ)
{ {
/* If we get a second entry for the owner, it's an additional /* If we get a second entry for the owner SID, it's either a
USER entry. This can happen when chown'ing a file. */ 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) if (saw_user_obj)
{
if (owner_eq_group && !saw_group_obj)
{
type = GROUP_OBJ;
saw_group_obj = true;
}
else
type = USER; type = USER;
if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) }
else if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
saw_user_obj = true; saw_user_obj = true;
} }
else if (type == GROUP_OBJ) 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 ((ace->Header.AceFlags & SUB_CONTAINERS_AND_OBJECTS_INHERIT))
{ {
if (type == USER_OBJ) if (type == USER_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; type = USER;
else if (type == GROUP_OBJ) }
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 /* If the SGID bit is set, the inheritable entry for the
primary group is, in fact, the DEF_GROUP_OBJ entry, 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 & DENY_RWX))
lacl[idx].a_perm |= lacl[2].a_perm & S_IRWXO; 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 /* Construct POSIX permission bits. Fortunately we know exactly where
to fetch the affecting bits from, at least as long as the array to fetch the affecting bits from, at least as long as the array
hasn't been sorted. */ hasn't been sorted. */