My most recent mini-adventure with sudo was on the Steam Deck; with OS updates, everything (or at least most?) of what's outside of your home directory is replaced. (In fact, you have to manually opt into being able to write to those directories at all, e.g. to use the system package manager instead of flatpak, by running `sudo steamos-readonly disable`). There are a couple sudo settings I change from the defaults, and because `/etc/sudoers and `/etc/sudoers.d/` (as in the entire directory) were restored to the base versions, my custom settings don't get preserved when updates occur. However, I was surprised to find out that using `visudo` to try to update the settings wasn't actually causing the settings I changed to take effect, which I eventually tracked down to some extra configs getting shipped by the base system in `/etc/sudoers.d`. I looked up what the precedence rules are for sudo rules, and apparently the rule is that anything in `/etc/sudoers.d/` will override `/etc/sudoers`, and the files in `/etc/sudoers.d/` are evaluated in lexigraphical order.
That's how I got where I am today, with a file called `zzz` that I copy into `/etc/sudoers.d/` every time there's a system update.
Whenever I think about writing a central privileged daemon to grant capabilities to other processes, I'm puzzled by the choice to remove the old version of CAP_SETPCAP in 2.6.24: "grant or remove new capabilities to/from an existing running process" - sadly it still exists but means something else in newer kernels with filesystem capabilities.
(In a sense, not having this capability in processes running as root is theatre anyway: you have /dev/kmem access so could just edit the kernel data structures. It's just doing so cleanly that is no longer possible.)
Being able to briefly escalate my editor to have the capabilities to write /etc/wibble.conf when I started editing it as a non-privileged user, then take away the capability again would be more convenient that always needing to run the editor as root. (So convenient, in fact, that people fake this with little editor helpers that do the equivalent of 'really tee FILE-TO-WRITE >/dev/null', but that's an ugly hack.)
If you squint hard enough, this is really a pretty similar idea to Polkit [0] but with a much simpler communication layer.
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.
You don't need to elevate privileges if you give things the right privileges from the start.
Sudo is just a hack to avoid setting up proper capabilities / permissions in the first place.
Every time somebody wants to do something in Linux and they mention Objects, I turn around and go the other way.
These people still do not understand why that userspace became so powerful and so useful.
I also think that's the "solution", which is to craft a new optional userspace experience that leaves traditional unix strings and pipes alone. It's not for me, but I'm sure many would like it. I mean, look at PowerShell on Linux :/
That's functionally equivalent to using sudo but only allowing a certain shell script that's a wrapper for what needs to be done by a given user (to avoid the whole syntax mess). But somehow with more boilerplate.
It's nice to see other people writing about the capability transfer feature of Unix domain sockets. File paths are not object capabilities, but file descriptors are. Using a privileged daemon on top of an ambient authority system like Linux seems to be a good way to retrofit object capabilities onto the operating systems we already use. This is the same approach we took in Goblins[0] for our Unix domain socket netlayer for the OCapN[1] protocol.
[0] https://spritely.institute/news/spritely-goblins-v0-16-0-rel...
[1] https://ocapn.org