|
|
Log in / Subscribe / Register

Sticky groups in the shadows

By Jonathan Corbet
May 14, 2021
Group membership is normally used to grant access to some resource; examples might include using groups to control access to a shared directory, a printer, or the ability to use tools like sudo. It is possible, though, to use group membership to deny access to a resource instead, and some administrators make use of that feature. But groups only work as a negative credential if the user cannot shed them at will. Occasionally, some way to escape a group has turned up, resulting in vulnerabilities on systems where they are used to block access; despite fixes in the past, it turns out that there is still a potential problem with groups and user namespaces; this patch set from Giuseppe Scrivano seeks to mitigate it through the creation of "shadow" groups.

There are two ways to prevent access to a file based on group membership. One of those is to simply set the group owner of the file to the group that is to be denied, then set the permissions to disallow group access. Members of the chosen group will be denied access to the file, even if the world permissions would otherwise allow that access. The alternative is to use access control lists to explicitly deny access to the intended group or groups. Once again, any process in any of the designated groups will not be allowed access.

By way of a refresher, it's worth remembering that Linux has two separate concepts of group membership. The "primary group" or "effective group ID" is the group that will be attached to new files in the absence of other constraints. This was once the only group associated with a process in Unix systems, and is set with setgid(). The "supplementary" groups are a newer addition that allow a process to belong to multiple groups simultaneously; the list of supplementary groups can be changed with setgroups(). Negative access-control decisions are usually (but not necessarily) based on supplementary group membership.

The "negative groups" access-control technique will prove porous, though, if processes are allowed to shed group membership at will. Both setgid() and setgroups() are privileged operations so, in normal circumstances, group membership is not under the control of the process involved. At least, that is true until user namespaces enter the picture.

Back in 2014, a problem with user namespaces and groups came to light. Any user can create a user namespace and run as root within that namespace; as a result, actions that are blocked outside of the namespace (setgroups(), for example) become possible inside. User namespaces thus made it easy for a user to evade being hampered by membership in the wrong group; all that was needed was to create a namespace, then call setgroups() to drop membership of that group inside the namespace. User namespaces were designed to not confer any extra privilege outside of the namespace, but the removal of a credential was not originally seen as raising privilege.

The solution adopted at the time was to add a control file (called setgroups) to each process's /proc directory. Writing "deny" to that file will disable setgroups() to all processes within the user namespace containing the target process — and to all descendant user namespaces as well — while writing allow will enable setgroups(). This action must be performed before setting the group-ID map for the namespace, otherwise writing the group-ID map will enable setgroups(). This policy was chosen for ease of verification; there is exactly one place where setgroups() can be enabled for a namespace. If setgroups() is explicitly disabled, it will remain that way for the life of the namespace; there is no way to enable it again.

This fix solved the problem, but at a cost: setgroups() exists for a reason, and there are legitimate workloads that would like to make use of it. Denying setgroups() will keep processes from escaping unwanted groups within a namespace, but it also prevents any other change of supplementary groups.

To remedy this issue, Scrivano's patch set adds another possible value, "shadow", for the setgroups file. Writing shadow has the same effect as writing allowed, in that the setgroups() system call will be allowed inside the namespace, but there is a difference. When the setgroups file is written, the kernel will make a copy of the target process's supplementary groups at that time and store it with the namespace. Whenever setgroups() is called, this list of "shadow" groups will be appended to the groups provided by the caller, essentially requesting continued membership in all of those groups.

In other words, the "shadow" mode makes the initial set of supplementary groups sticky. Suitably privileged processes within the namespace can use setgroups() to add new groups; they can also remove groups that were not part of the initial set. But the supplementary groups that the namespace was created with will always be there, even though the process can no longer see them — getgroups() will not list the groups that have not been explicitly requested with a setgroups() call.

This particular patch has been around for a while; in the past, its complexity has not seemed to be justified by the benefits it brings. A recent user request for this feature has brought this work back to light, though. Whether it will clear the bar this time remains to be seen, but it seems likely that there will always be users who want to have both the ability to use negative group protections and to change group memberships within user namespaces.

Index entries for this article
KernelNamespaces/User namespaces
KernelNegative groups


to post comments

Split group membership into two bits

Posted May 14, 2021 16:45 UTC (Fri) by epa (subscriber, #39769) [Link]

Since group membership can be a negative credential, instead of storing a single bit of information "is the user a member of this group?" there should be two separate bits stored:

A. Does the user have the privileges associated with being a member of this group?
B. Does the user have the privileges associated with *not* being a member of this group?

Removing yourself entirely from a group, as at present, means setting bit A to zero but setting bit B to 1, possibly giving yourself more privileges. So it has to be restricted. But if you had a system call that just unset one or both of the bits, it could be a pure dropping of privilege and available in any context.

Sticky groups in the shadows

Posted May 14, 2021 18:12 UTC (Fri) by josh (subscriber, #17465) [Link] (1 responses)

It'd be nice if the "shadow" groups *only* participated in permission denial, not permission granting. In particular, that way processes inside a namespace that drop permissions do indeed lose those permissions, they just still have the shadow groups around for the purposes of processing negative permissions for that group.

Sticky groups in the shadows

Posted May 22, 2021 19:21 UTC (Sat) by riking (subscriber, #95706) [Link]

Yes, this is what I imagined was going on. If one does not take care to only perform this operation on colluding processes (set to only negative groups, write "shadow", restore normal/positive groups), odd behavior will certainly result.

Denying access w/ groups

Posted May 14, 2021 18:45 UTC (Fri) by clugstj (subscriber, #4020) [Link] (19 responses)

Can anyone provide an example where using a group to deny access is simpler to maintain than doing it the normal way (using a group to grant access)?

Denying access w/ groups

Posted May 14, 2021 19:12 UTC (Fri) by Wol (subscriber, #4433) [Link] (17 responses)

Simple. John is in a project that needs access to shared resources.

Jane doesn't want John to have access to her resources within that shared group.

As I understand the linux (and windows) access system, trying to lock John out of Jane's files is a nightmare.

(Which is why Pr1mos - "if the user is named the groups are ignored" - makes that so simple ...)

Cheers,
Wol

Denying access w/ groups

Posted May 14, 2021 19:30 UTC (Fri) by clugstj (subscriber, #4020) [Link] (1 responses)

If Jane wants to limit access to her files, she needs to be in her own group and give access to only those that she want to have access. Using group membership to deny access at the same time as others are using group membership to grant access is a recipe for confusion.

Denying access w/ groups

Posted May 14, 2021 19:53 UTC (Fri) by Wol (subscriber, #4433) [Link]

Thing is, does Jane have the ability to grant and deny access to her files ...

Especially if they're in a project folder and not her private home area.

Cheers,
Wol

Denying access w/ groups

Posted May 14, 2021 20:25 UTC (Fri) by pwfxq (subscriber, #84695) [Link] (12 responses)

> Which is why Pr1mos - "if the user is named the groups are ignored" - makes that so simple

It took me a moment to work out what you were saying: The more explicit the setting, the higher its precedence. This is method is used in all sorts of places.

Denying access w/ groups

Posted May 14, 2021 20:36 UTC (Fri) by Wol (subscriber, #4433) [Link] (11 responses)

The "problem" with linux and windows is that, as far as I can make out, user and group permissions add up. So if you give explicit permissions to someone and you don't know what groups they are in, what they've actually got may bear no resemblance to what you've given them.

Whereas if the name trumps the groups, then group permissions become irrelevant.

And what if the administrator uses group permissions to lock them out of your files, but you want them to have access? It's a problem all round ...

Cheers,
Wol

Denying access w/ groups

Posted May 14, 2021 21:03 UTC (Fri) by bfields (subscriber, #19510) [Link] (4 responses)

I'm not sure what you're saying, but it sounds incorrect.

If you're the owner of the file (or, in the case of posix ACLs, if you're explicitly named in the user list), then those permissions do determine your access.

But, I may misunderstand what you're saying. Have you tested the actual linux behavior?

Denying access w/ groups

Posted May 16, 2021 9:58 UTC (Sun) by Wol (subscriber, #4433) [Link] (3 responses)

I haven't used acls on windows or linux. But reading up on them, as far as I can tell, user and group acls are added together. Otherwise deny acls wouldn't make sense ...

Cheers,
Wol

Denying access w/ groups

Posted May 17, 2021 6:39 UTC (Mon) by jem (subscriber, #24231) [Link] (1 responses)

File permissions in Unix work like this: If you are the owner of the file, the "user" permissions are checked, and nothing else. If you are not the file owner, but one of the group IDs of the process matches the owning group of the file, the group permissions determine access, and nothing else. Only if the above user ID and group ID checks fall through, the "other" permissions are checked. Traditional Unix file permissions are not added together.

POSIX ACLs work in the same way, except now, for the sake of checking access, a file can have more than one owner, each with potentially different combinations of "rwx". In the same way, a file can have more than one group owner, each with different permissions.

With POSIX ACLs, if the user ID of the process matches any of the file owners, then the user permissions determine the access, and nothing else. If there is no user ID match, then the process group IDs are checked: if any of the group IDs of the process matches any of the ACL group owners, then the group permissions determine the access. If a positive match is found, access is granted, else it is denied. As with non-ACL permissions, if there is no owner or group owner match, the "other" permissions are checked.

POSIX ACLs are further complicated by a "mask" entry, which was added for backwards compatibility; I won't go into that here. POSIX ACLs do not have "deny" entries.

Denying access w/ groups

Posted May 20, 2021 19:41 UTC (Thu) by foom (subscriber, #14868) [Link]

If you have a file with permissions:
Owner someuser: rwx
Group somegroup: ---
Others: r--

If you're 'someuser', you have read/write/execute access. If you're in somegroup, you have no access. If you're not either, you have read access.

So, if user2 is normally a member of 'somegroup', but can somehow drop that group membership, they'll gain access to this file, which they shouldn't be able to read.

In practice, this isn't usually a problem, because almost nobody ever intentionally sets up permissions like this. But it's possible.

Denying access w/ groups

Posted May 22, 2021 19:29 UTC (Sat) by riking (subscriber, #95706) [Link]

Discord's ACLs are the model everyone should be striving for. https://discord.com/developers/docs/topics/permissions#pe...

1. Ambient positive access for @everyone is applied
2. Ambient positive access for your groups is applied
3. Resource deny rules for @everyone are applied
4. Resource allow rules for @everyone are applied
5. Resource deny rules for your groups are applied
6. Resource allow rules for your groups are applied
7. Resource deny rules for your user are applied
8. Resource allow rules for your user are applied

Steps 3+4, 5+6, and 7+8 are represented as bitmask pairs. `permissions = (permissions &~ rule.deny) | rule.allow;`
(Steps 1 and 2 don't need a deny value, because they're applying onto a blank slate.)

Denying access w/ groups

Posted May 15, 2021 0:42 UTC (Sat) by NYKevin (subscriber, #129325) [Link] (5 responses)

> The "problem" with linux and windows is that, as far as I can make out, user and group permissions add up. So if you give explicit permissions to someone and you don't know what groups they are in, what they've actually got may bear no resemblance to what you've given them.

I'm fairly certain Linux doesn't work that way, as others have said.

> Whereas if the name trumps the groups, then group permissions become irrelevant.

No, because with traditional Unix owner/group/world permissions bits, you can only name one person, and that person has to be the owner (i.e. they have the right to edit the permissions), which effectively means that the owner's permissions are "just to prevent mistakes" rather than a meaningful security barrier. So for actual security, you just have the group permissions and the "world" (everybody else) permissions. While it might be uncommon for the world permissions to be more permissive than the group permissions, it's not *that* weird or complicated to reason about.

You can do more elaborate stuff with POSIX ACLs, natch, but not everybody wants to dig out the man page on how those actually work. Sometimes, a negative group file mode is easier to understand and reason about.

> And what if the administrator uses group permissions to lock them out of your files, but you want them to have access?

Then the two of you can shout at each other in meatspace until one of you gets hoarse. Ultimately, the kernel provides the primitives which it provides, and it's the administrator's responsibility to use those primitives wisely.

Denying access w/ groups

Posted May 17, 2021 8:22 UTC (Mon) by ibukanov (subscriber, #3942) [Link] (4 responses)

One can be the owner of a file on Linux and still has no ability to access it or change it in any way if one does not have the executable permission for the parent folder.

Denying access w/ groups

Posted May 17, 2021 8:54 UTC (Mon) by anselm (subscriber, #2796) [Link] (2 responses)

Which is why as an unprivileged user you can't use chown to donate files to other users. (Otherwise, Alice could annoy Bob if Bob has a 10-gig quota for files, by creating a 10-gig file in her own – protected – home directory and then making it over to Bob. It counts towards Bob's quota but Bob has no way to get at or remove the file.)

Denying access w/ groups

Posted May 17, 2021 10:05 UTC (Mon) by jem (subscriber, #24231) [Link] (1 responses)

Alice could also annoy Bob by finding a large file in Bob's unprotected home directory and making a link to it in her own directory.

Denying access w/ groups

Posted May 18, 2021 17:57 UTC (Tue) by BenHutchings (subscriber, #37955) [Link]

Which is one reason to enable the fs.protected_hardlinks sysctl.

Denying access w/ groups

Posted May 17, 2021 21:20 UTC (Mon) by NYKevin (subscriber, #129325) [Link]

If you lack execute permissions to any component of the path, then the permissions on the file are not a security boundary (because you can't even get that far to begin with, or if you can, then you must already be the superuser anyway). Therefore, the owner permissions are never a security boundary, just as I said.

Denying access w/ groups

Posted May 15, 2021 0:25 UTC (Sat) by rgmoore (✭ supporter ✭, #75) [Link]

As I understand the linux (and windows) access system, trying to lock John out of Jane's files is a nightmare.

It's actually not that hard under Windows. It has "deny" permissions, and they take precedence over "allow" permissions. So Jane just has to tell Windows to deny John access, and he's locked out unless he's an administrator and can ignore everything.

Denying access w/ groups

Posted May 15, 2021 14:54 UTC (Sat) by ibukanov (subscriber, #3942) [Link]

It is possible to solve Jane’s problem in a rather straightforward way. Crate a group that can can access the shared resources, then grant read and execute privilege to a folder to that group with no access to others then give read/write access to everybody to a sub folder there. That will be the shared area. Then Jane can restrict the access as usual.

Denying access w/ groups

Posted May 14, 2021 20:27 UTC (Fri) by rav (guest, #89256) [Link]

On a shared-user system at my university, all users are in a 'users' group, and the webserver is not in the 'users' group. Since you're not privileged, you can't assign your public_html directory to the webserver's uid/gid, but you *can* set it to be not group-readable for the 'users' group, thus in effect allowing the webserver to serve the files but disallowing your colleagues from snooping around.

Just make named permission TRUMP everything else

Posted May 14, 2021 19:05 UTC (Fri) by Wol (subscriber, #4433) [Link]

Negative permissions are just are nightmare all round.

Pr1mos was

If the user is named, THAT'S WHAT THEY GET
If they're not named, but in named groups, permissions are added.
If neither they or their groups are named, they get the default (which defaults to deny)

Nice and simple, easy to understand, and no worries about the administrator changing group permissions and accidentally granting permissions the file owner didn't want.

Cheers,
Wol

Sticky groups in the shadows

Posted May 15, 2021 18:05 UTC (Sat) by maximoburrito (guest, #144651) [Link] (1 responses)

Is there a reason we don't just have negative groups, groups that are defined by the users NOT in them?

thegroup; -fred, -george

Everyone but frec and george are in the group.

Sticky groups in the shadows

Posted May 15, 2021 19:41 UTC (Sat) by NYKevin (subscriber, #129325) [Link]

So, firstly, we need to clarify what we mean by "[supplementary] group." A (supplementary) group is:

1. One element of a per-process (or per-thread) attribute, manipulated by getgroups(2) and setgroups(2), and inherited across fork and exec.
2. A set of users who have a group in sense (1) automatically attached to their login shell at startup, along with some extra metadata such as a name.

You are (I think) proposing a modification to groups in sense (2), such that a group can be made to attach to every user except for (e.g.) "fred and george." But the process of attaching supplementary groups to users is (I *think*) entirely done in userspace by either login(1) or one of its friends. So from the kernel's perspective, groups in sense (2) are Somebody Else's Problem, and there is no reasonable way for the kernel to translate a use of subtractive group permissions into an inverted group membership. Instead, they would have to remove subtractive group permissions and tell everyone "go develop a new feature in userspace to replace the kernelspace feature we just killed"; that would be quite obnoxious and obviously contrary to the kernel's normal backwards compatibility promises.

Sticky groups in the shadows

Posted May 16, 2021 23:35 UTC (Sun) by Paf (subscriber, #91811) [Link] (2 responses)

When I worked as a windows sysadmin, we had a rule on deny permissions:
Don’t. They are a road to massive confusion and misunderstanding.

In our experience in corporate environments, requests for them were almost always the result of bad planning or confused organizational structures.

I understand they can be useful technically, but gosh they are terrible organizationally. Weird, magic exceptions, and an overlay atop normal permissions to boot. “Everyone except Steve” or “everyone except Accounting”, etc.

Sticky groups in the shadows

Posted May 17, 2021 20:26 UTC (Mon) by NYKevin (subscriber, #129325) [Link] (1 responses)

In my experience, deny is most commonly used for Compliance Reasons™ - i.e. "Our lawyers told us we have to be absolutely certain that group X cannot access thing Y, no matter what." While it may be annoying, it does mean that the pointy-haired boss can't accidentally violate a legal requirement just by telling IT "We need access to thing Y because I said so." In this respect, it functions like a rudimentary form of mandatory access control.

In practice, thing Y is often some form of PII, particularly medical or payments information, but occasionally it will be a trade secret, privileged legal document, or other such materials. As a side note, getting these deny ACLs removed or narrowed is often a rather involved bureaucratic process, but that's a business requirement, not a technical limitation.

Sticky groups in the shadows

Posted May 19, 2021 2:12 UTC (Wed) by Paf (subscriber, #91811) [Link]

Ah, that makes sense - I had not run across that specific use case.

My experience of them was people driving themselves to madness rather than being willing to think through their organizational and permission structures.


Copyright © 2021, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds