|
|
Subscribe / Log in / New account

Setuid inherits ulimit?

Setuid inherits ulimit?

Posted Aug 28, 2014 2:52 UTC (Thu) by zblaxell (subscriber, #26385)
In reply to: Setuid inherits ulimit? by epa
Parent article: The poisoned NUL byte, 2014 edition (Project Zero)

There is no safe value because a value that is appropriate for one workload is inappropriate for others. Consider a busy web app hosting server running user code through cgi-bin. Normally CGI scripts would have tight resource restrictions, but they may also have access to a setuid sendmail binary. If this "default ulimit" scheme is implemented, it could result in a DoS opportunity instead of a resource starvation attack--doubly so if the default ulimit values come from the sendmail developer instead of the app hosting admin.

ulimit values form a relatively small part of the total attack surface that a child setuid process exposes to its unprivileged parent. If you specify ulimits for setuid program correctness then you have to deal with real resource exhaustion, prctl settings, and cgroup limits too. Failure to deliver precisely the resources specified by ulimit values under this scheme would result in a possible attack vector, so the semantics of ulimit must be significantly altered in a very expensive and inflexible direction under this scheme.

It is theoretically possible to specify the execution environment completely, but that specification is huge on a modern Unix, and implementing it correctly is invasive.

On Unixish OSes it's easier to just not bother with setuid in the first place. Linux has authenticated local IPC to allow unprivileged processes to collaborate with privileged peers when they need a temporary privilege boost. This capability alone makes most setuid use cases redundant.


to post comments

Setuid inherits ulimit?

Posted Aug 28, 2014 11:02 UTC (Thu) by epa (subscriber, #39769) [Link] (6 responses)

I think you misunderstand my point. Perhaps I chose poor wording to call them 'safe' values for resource limits. I should have said 'standard' values. I quite agree that the appropriate limits vary by workload. Of course if the setuid program needs a higher limit then, being root, it can arrange to change the limit. The point is that the developer of the setuid program knows what to expect; you don't have the program developed and tested assuming some reasonable set of limits and then run with different limits. It always runs, by default, with the same standard limits the developer had in mind.

Would you ever want to run your setuid sendmail binary with lower resource limits? I see your point that resource restrictions are important, and you might want to apply them to child processes even if those children are setuid root. However, the premise of this discussion is that setuid programs can have bugs triggered by bumping against unexpected ulimit settings, so that running sendmail with lower limits might tickle a bug and end up causing an exploit. It's a matter of judgement in individual cases which is best.

I don't object to running setuid programs with funky ulimit settings, just as I don't object to running them with LD_PRELOAD plugins to muck around with the standard library. But I think that doing so should require an explicit and privileged step (so, for running sendmail, a suid root wrapper could set the lower ulimit values and then exec the sendmail binary). That is already the case for LD_PRELOAD, which is explicitly ignored for setuid binaries, and I think it should be the case for ulimit too.

You are right that there are many other bits of the execution environment to consider. That is not a reason to ignore this one particular bit. And you are also right that better alternatives exist for many cases where setuid binaries are used; but as long as setuid binaries continue to exist, they need to work in the safest and most predictable way possible.

Setuid inherits ulimit?

Posted Aug 28, 2014 12:18 UTC (Thu) by zblaxell (subscriber, #26385) [Link] (5 responses)

You still haven't provided a solution for the cgroups and real resource exhaustion cases, which have the same effect as the ulimit, but cannot be resolved by adding more privileged code to an already complex situation. In addition to all of the above, setuid programs have also been attacked through their inherited FDs (including working directory and TTY) and environment variables (including stuff you'd normally want to use from a privileged program, like TERM and TZ).

There are lots of surprising behavior differences that arise with setuid programs. This stuff has been analyzed to death for decades. Fast-forward to the end: you want the setuid program to behave exactly the same way as a program that was never setuid and never executed in the environment of an unprivileged parent in the first place, including--and especially--with respect to exploitable features of the execution environment that the privileged software developer might not be aware of. On Linux in particular, "features of the execution environment" is a rapidly changing and growing list.

It's much easier--and safer--to start a process from a safe, well-defined, and privileged environment than it is to get back there from an arbitrary starting point chosen with malicious intent.

My point is that we should put 'rootflags=nosuid' on the kernel command line, replace the handful of programs that break (e.g. sudo and mutt_dotlock) and never look back.

That setuid wrapper that sets up ulimits? Replace it with a server and a legacy-compatible client wrapper. setuid sendmail? Replace it with postfix. All those online tutorials that say 'sudo some-arbitrary-command'? Replace with 'ssh -XAt root@localhost some-arbitrary-command'. Need the child's working directory, stdin, or stdout, or just a safe way to open files as the unprivileged user? Pass file descriptors to the server process (we do have sendmsg(2) and fchdir(2) after all). And so on.

Setuid inherits ulimit?

Posted Aug 28, 2014 13:28 UTC (Thu) by epa (subscriber, #39769) [Link] (4 responses)

Here the program being attacked was pkexec which exists specifically to provide an authenticated way to execute a program as another user. (And that is a legitimate use case, as anyone who has worked on a support desk will attest.) While as you say, many examples of setuid programs can be replaced, not all can be.

Setuid inherits ulimit?

Posted Aug 28, 2014 13:59 UTC (Thu) by cortana (subscriber, #24596) [Link] (3 responses)

The replacement would be a service that runs programs, as requested via a client, as a particular user. A bit like ssh, but without the network/encryption overhead.

$ sudo find / -xdev  -perm /4000
/bin/fusermount
/bin/mount
/bin/ping6
/bin/ping
/bin/umount
/bin/su
/sbin/mount.nfs
/usr/bin/traceroute6.iputils
/usr/bin/chsh
/usr/bin/lppasswd
/usr/bin/sudoedit
/usr/bin/slock
/usr/bin/sudo
/usr/bin/gpasswd
/usr/bin/at
/usr/bin/X
/usr/bin/ksu
/usr/bin/nvidia-modprobe
/usr/bin/passwd
/usr/bin/staprun
/usr/bin/mtr
/usr/bin/chfn
/usr/bin/beep
/usr/bin/newgrp
/usr/bin/pkexec
/usr/lib/openssh/ssh-keysign
/usr/lib/pt_chown
/usr/lib/hadoop-yarn/bin/container-executor
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/chromium/chrome-sandbox
/usr/lib/hadoop-0.20-mapreduce/sbin/Linux-amd64-64/task-controller
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/virtualbox/VBoxHeadless
/usr/lib/virtualbox/VirtualBox
/usr/lib/virtualbox/VBoxNetDHCP
/usr/lib/virtualbox/VBoxSDL
/usr/lib/virtualbox/VBoxNetAdpCtl
/usr/lib/eject/dmcrypt-get-device
/usr/lib/x86_64-linux-gnu/spice-gtk/spice-client-glib-usb-acl-helper
/usr/sbin/uuidd
/usr/sbin/exim4
/usr/sbin/pppd
Some will be harder to replace with services than others.

Setuid inherits ulimit?

Posted Aug 28, 2014 14:01 UTC (Thu) by cortana (subscriber, #24596) [Link]

For the complete light show, try:

> find / -xdev -type f -perm /6000 -exec ls --color=auto -l {} +

Setuid inherits ulimit?

Posted Aug 28, 2014 18:31 UTC (Thu) by justincormack (subscriber, #70439) [Link]

Linux has had ping sockets for ages https://lwn.net/Articles/420799/ but distros still don't seem to be using them.

Setuid inherits ulimit?

Posted Aug 28, 2014 18:55 UTC (Thu) by zblaxell (subscriber, #26385) [Link]

Do any of those have to be setuid?

su, sudo, sudoedit, ksu, etc. can be replaced with a lightweight equivalent to 'ssh root@localhost' with various options. You can even reuse most of the exisitng sudo code unmodified (it just has to know that uid comes from SO_PEERCRED instead of geteuid()).

mtr, ping, traceroute6, etc. need a socket in raw mode. There are better ways that a process could get one, e.g. put permission bits on network interfaces in the kernel, so an admin can authorize any process to listen to the local WiFi interface without having completely unrelated root privileges. I gather OSX does something like this, so ping just works without setuid there.

Mail has long been available on Unix through a wide variety of servers that don't need setuid bits. Ditto user account management tools like chfn and passwd (NIS is well into decade #3, although a more lightweight replacement that isn't network-accessible and full of bugs might be a good idea).

User mounts and VM management tools are already available through dbus servers, so deprecate the legacy interfaces.

'at' and 'crontab' already communicate with a privileged server through an IPC (FIFO), so they're half done. Just implement the other half.

pkexec is...wrong. It already talks to a privileged server process for authentication, but it doesn't use that server process to provide the privileged process's execution environment. It's all right there, all it has to do is move some FD's around and fork()...*headdesk*


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds