Hacker News new | ask | show | jobs
by hpb42 959 days ago
One of those left out features is `sudoedit` or `sudo -e`. I use this a lot when editing files in /etc or any file that my user does not have permissions. The flag first copies the file to a temporary location with permissions for my user to edit, then opens my text editor (defined via $SUDO_EDITOR env var) as _my user_, without any sudo permissions. After I close the editor, the file is copied back with the original permissions only if there were any changes.

The cool thing is running the editor via my user, which loads my user's configuration/plugins, instead of the root user's.

6 comments

> One of those left out features

They indicate that many omittted features are by design, but this particular one is implied to be planned:

> Some functionality is not yet supported; in particular sudoedit

This would be a great use case for a capability security model. Essentially what you really want is the sudo command to acquire a temporary capability token to edit that specific file. Then run your editor and pass it the capability. (And revoke the capability when the editor process closes).

It’s a pity this isn’t more straight forward to implement on Linux.

Are there no overwrite/seek bugs in Unix that could be exploited in that case? It seems to me like only using sudo for a cp command would reduce the attack surface.
I’d certainly hope not. A capability based security system in an OS is only secure if it doesn’t have bugs. Just like most security-critical software.

However, I’m not sure that Linux is capable of masquerading as a general purpose capability based operating system. I think it’s missing a bunch of APIs.

> Essentially what you really want is the sudo command to acquire a temporary capability token to edit that specific file.

This should be doable with an XDG portal model, right?

It's doable by opening the file in a privileged process (sudo) and passing the file descriptor to a non-privileged process.

Maybe one could make a sudoedit that opens a file in sudo process and then spawns a non-privileged editor process which inherits the file descriptor and is given the /dev/fd/ path on the command line, so it stays none the wiser about the whole process.

Sounds like a bit of recipe for accidentally handing access to an unintended privileged fd through inheritance (ignoring the /dev/fd one) such that a compromised unprivileged SUDO_EDITOR value gives you sudo access. Maybe not likely, but I’d really be hesitant about any feature that relies on implicit fd inheritance…
Another option could be to open a UNIX socket in the privileged sudo process, spawn an unprivileged child process 'shim' that connects to that socket, and then the sudo process can pass the file descriptor over the socket. Since the child shim is 'clean', it should have nothing more than stdin/out/err open, plus now this passed FD. Then the shim can spawn the target program and allow it to inherit just the passed FD.

I think the larger issue is that I doubt many (if any?) editors allow opening a file via an inherited file descriptor! I guess some will read stdin (the shim could close stdin and then dup2() it into its place), but then there's no way to save the file back when finished.

Close all other fds between fork and exec then (you can look at the code of base::LaunchProcess in Chromium for an example). It’s a minuscule amount of code to audit compared to XDG portals. And it’s backwards-compatible with decades of unix programs.

For a more complicated solution: spawn a zygote process early with a unix socket which you’ll use to send the fd later. Zygote at start drops provileges. When it receives the fd, it closes the socket and execs the editor.

I’m not saying it’s not possible to do correctly. But do you not agree that the first is hard to correctly (can overlook an fd) while the latter is a lot of complexity?

There is the CLOEXEC flag which is the intended way to manage this but it’s not the default and you have to be diligent about setting it which again carries its own set of challenges.

What you’d really want is CLOEXEC implicitly on all fds and having to explicitly opt in for fd inheritance.

So now any program that's running as your user, even your browser, can edit any file you edit with sudo. It just has to watch for your editor to quit and win a race with sudo to modify the file before sudo reads it.
It sounds like 90% of "sudoedit" can be done without elevated permissions, assuming your user can read the file.
In Vim:

:w !sudo tee %

Which I map to :w!!

Of course, if you’re not using Vim, you’re doing it wrong :)

It is a little less useful if the file is not readable by your user, and once you authenticate anything within your vim can also silently run other sudo commands since on most distros sudo remembers the autnentication for a while.

Now that I think of it, not sure how sudoedit behaves wrt this cached auth.

I think you can use the sudo -k flag to clear the cached auth
I usully use "sudo -E EDITOR_OF_MY_CHOICE"
Many editors can execute shell commands, so this isn't the same at all.
That makes your editor run as root, which is a bad idea for many reasons (aside from security, any mistake now has the potential mess with the whole system).