Remix.run Logo
ninjin 3 days ago

I am somewhat cautious to comment as I know the author is way more experienced than I am and I fear that I may be missing something. However, let me try to accomplish the same with my elementary doas(1) knowledge.

Allowing mounting for a specific group is simple with doas.conf(5):

    permit :mountd cmd /sbin/mount
    permit :mountd cmd /sbin/umount
We can of course tighten it further as the author did:

    permit :mount-usb cmd /sbin/mount /dev/sdb1
    permit :umount-usb cmd /sbin/umount /media/usb
If you want to go more complex than specifying arguments, we could of course create a shell script and specify it instead of a binary.

Likewise, we can do something similar for a service account:

    permit :www-deployment as www-deployment cmd /var/www/bin/build /var/www/application
The key difference here would be that www-deployment can not delegate as easily to arbitrary users, as they would need to ask someone with root access to add additional users to the www-deployment group. But I am left wondering if this use case (if it is important enough) is not equally well served by specifying a location for non-root users to add permissions akin to what we see in doas.conf(5), but with the constraint that they of course can only allow other users to run commands with their privileges. Yes, it would "bloat" doas(1), but these code paths are not that long as long as you keep your scope constrained (doas(1) has a core of just over 500 lines and with environment handling and configuration format parsing we arrive a a final line count at just over 1,300).

At this point, the main advantage I see with capsudod is that you can more easily drop privileges and put in restrictions like pledge(2) before the binary is ever called upon by whatever user we have granted permissions. While with the doas(1) thinking above you have to run over plenty of code that could be exploited. Still, this feels like a rather minor relative improvement to what we already have.

Am I missing something in my ignorance? Lastly, let me also say that I am sure that sudo(8) has the ability to do the same things I proposed to do with doas(1) above, but I know the latter far better.

davexunit 3 days ago | parent | next [-]

The whole problem is mapping privilege to users and groups, so doas doesn't solve the issues explained in the article.

> The key difference here would be that www-deployment can not delegate as easily to arbitrary users, as they would need to ask someone with root access to add additional users to the www-deployment group. But I am left wondering if this use case (if it is important enough)...

Delegation is the killer feature of the object capability model. It's not just important enough, it's the most important. Keep in mind that the ACL model allows delegation, too, it's just unsafe. Users share credentials all the time. Capabilities allow delegation in a way that can be attenuated, revoked, and audited.

ninjin 3 days ago | parent [-]

Firstly, thank you for engaging and trying to enlighten me.

I do understand why capability delegation is useful and I am familiar with using Unix sockets to delegate the control of daemons using socket permissions, which feels similar to what we see here with capsudod (I have not read the code sadly, too much other code to read today).

However, I am still puzzled what the advantage of having a herd of capsudod instances running is to say my proposal of allowing users to set up their own doas.conf(5)s to delegate capabilities. Yes, we still need SUID and we will need to be darn sure 1,000 or so lines are properly secured, but it is attenuable, revocable, auditable, and feels (perhaps wrongly, because I have a bias towards text files describing the state of a system?) more natural to me than putting it all into the running state of a daemon.

Is there some other strength/weakness of these approaches that I am failing to see? I am no systems programmer, but I find topics like this interesting and dream of a day when I could be one.

davexunit 3 days ago | parent [-]

> However, I am still puzzled what the advantage of having a herd of capsudod instances running is to say my proposal of allowing users to set up their own doas.conf(5)s to delegate capabilities. Yes, we still need SUID and we will need to be darn sure 1,000 or so lines are properly secured, but it is attenuable, revocable, auditable, and feels (perhaps wrongly, because I have a bias towards text files describing the state of a system?) more natural to me than putting it all into the running state of a daemon.

I think two separate discussions are being mixed here. The above seems mostly concerned with the chosen interface of capsudo. Imperative vs. declarative is orthogonal to the discussion about object capabilities vs. ACLs.

srazkvt 3 days ago | parent | prev [-]

sure, but that doesn't change the fact that doas(1) is a suid binary. everything done would be done as root, from parsing the config file, checking the rights, and finally executing the command.

capsudo here would rely on singular unix sockets with file access rights, so in essence, it would indeed be similar to what you could do with doas, but the idea here is to seperate things. with doas, doas would check if you have the correct group or user to do the command, while with capsudo, the kernel would check it, and reject it if you don't have the right.