guix-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: /run/setuid-programs via the Shepherd?


From: Juliana Sims
Subject: Re: /run/setuid-programs via the Shepherd?
Date: Sat, 08 Jun 2024 02:58:26 -0400

Hi Felix,

You ask a really interesting question. I think run0 is a great step in the right direction, and I would welcome the Shepherd gaining similar abilities. I also think run0 is a stopgap and we can do much better. Let me try to explain.

As I've announced previously, I'm working on porting the Shepherd to the Goblins object-capability security (ocap/ocaps) library, and very similar thoughts have cropped up for me as well while doing this work. Rather than merely imitate a better sudo, though, I think it would be compelling to leverage the system layer to create a security barrier that allows ocap security at the process level. This is beyond the scope of my current work, so what follows are just some ponderings and not representative of my work on the Shepherd. As a big caveat, these thoughts haven't been peer reviewed, as it were, by people more familiar with ocap security at scale. I point that out because, as far as ocaps are concerned, nothing I'm proposing is a new idea, and I may be missing pieces of the puzzle.

First, let me define a few terms. A capability is a reference -- in the code sense -- to an object. An object is similar to an actor in the actor model but with some restrictions. What's most important is that these objects encapsulate state and the ability to operate on that state, and they can only manipulate external state through capabilities. An object may receive a capability in one of three ways: it may be created with a capability; it may be granted a capability by an object with a capability on it (A has a capability on B and C; A can grant B a capability on C); or it may create the capability itself. The latter mechanism is only able to create capabilities on the object itself or on objects upon which it has capabilities. In short, "if you don't have it, you can't use it." (As a critical corollary, if you *do* have it you *can* use it, so be careful about the capabilities you hand out.) The overall model is called "object-capability security" because its original name, "capability security," has been applied to several similar but distinct systems since it was first formulated, and the role of the object is the most important and defining feature of this specific model.

On to the actual idea. To summarize, in an ocap system, we invert the authority flow of sudo/run0. We can think of sudo as untrusted code claiming to act on behalf of a trustworthy user and thus being allowed to execute as trusted code. (This was built on top of Unix's original security model, knowing where every other person with access to the OS works, so its weaknesses are understandable.) run0, as I understand it from the thread you linked, improves on sudo significantly by making untrusted code ask trusted code to act on its behalf to perform some delimited action. This is much better, but still relies on the identity of some user who gave the code permission to act in this way. The ocap model is closer to run0 (run0 reminds me of an ocap pattern called a powerbox), but ocaps has a key difference. In an ocap system, rather than untrusted code asking trusted code to do some specific task, untrusted code is unable to do anything until trusted code gives it the *capability* (in both the colloquial and ocaps sense) to do so. That is, whereas with run0 and sudo, *untrusted* code tells *trusted* code *what* to do, with ocaps, *trusted* code tells *untrusted* code what it's *allowed* to do.

Before we can have meaningful ocap security, we must reduce or eliminate ambient authority. This isn't very hard anymore, thanks in large part to systemd and changes it encouraged in the Linux kernel, like cgroups. run0 significantly reduces ambient authority -- yay! Guix has facilities towards this end as well -- the least authority wrapper comes up frequently. The harder part is bootstrapping capability grants. If we endeavor to build ocap security on top of an access control list (ACL) system, we frequently need something like a powerbox at some point. But if the ACL system in question is Guix, and the powerbox in question is (inside) the Shepherd, we can go much further towards proper capability flows. We can take `guix system reconfigure' (or `guix home reconfigure' for user processes) as the root of our capability bootstrap process. For example, capabilities could be granted at object creation by passing them around in system configurations which are then instantiated by the Guix build daemon at reconfigure/build time. At runtime, the Shepherd, which would receive capabilities at build time as well, could spawn processes in "dead worlds" with only the capabilities they need. Outside of Guix, Shepherd configuration files would be the root of these flows.

You may immediately notice this idea is rough. There is a circular dependency in that we need all relevant capabilities for `system reconfigure'/Shepherd configuration if we want to make it the root of our trust tree. As I gestured to previously, ocaps are working against the underlying problems of ACLs. I don't have good answers here. Unless and until we have absolute control over our computing environment from the bottom up (did someone say "user freedom?"), we can only offer some subset of the security guarantees of object-capability security. Still, that subset is more ergonomic and powerful than ACLs can offer. Just imagine never needing to invoke sudo (or run0) because every program has precisely the authority it needs precisely when it needs it. Such a world is possible. With a Goblins-based Shepherd and the cooperation of Guix, we could get quite close to that world while still building on top of ACLs.

To be clear, there's still quite a lot of work left to do to make all the necessary pieces to begin building this vision. But work on those pieces is well under way.

To bring this email back to directly the topic you raise, a Shepherd run0 is complementary to a future ocaps-ification of the broader process environment; they support and reinforce each other. Furthermore, with ocaps, the Shepherd could grow beyond run0. I personally think this is the direction Guix and the Shepherd should go.

WDYT?

Best,
Juli





reply via email to

[Prev in Thread] Current Thread [Next in Thread]