On Tue, 16 Jan 2024 at 20:13:21 +0900, Simon Richter wrote: > On 1/16/24 03:55, Simon McVittie wrote: > > I would personally like to see *more* privilege separation across IPC > > boundaries rather than less, if that can reduce the total attack surface > > of the setuid/setcap executables in the trusted computing base. > > we might have a component that has no special capabilities, but it is > privileged by the trust relationship from other components, which may in > turn have capabilities
Yes, but in IPC, those other components need to have been explicitly written to trust it: they are less likely to be trusting it by mistake as a result of implementation details. For me, the key difference between doing this via IPC and doing this via setuid is that the defaults are different (rather like "fail safe" vs. "fail open"). In a typical IPC mechanism, everything that is not explicitly communicated is safe: of course a service at a trust boundary still needs to be careful with its handling of anything that it parsed out of an IPC message (for example a D-Bus message) from a less-trusted client, but at least it can assume that its environment variables and other assorted process parameters inherited from its parent (typically a service manager like systemd, or some other piece of system infrastructure like dbus-daemon) are something that it can trust. It is only the IPC itself, plus whatever "business logic" is based on information obtained from IPC, that needs to be hardened against malicious clients. It's still a difficult problem, but we can trace data flows and reason about it. In setuid/setcap, every inheritable process parameter that is not explicitly unshared/reset is inherited, so the setuid entry point has to assume that most aspects of its execution environment (notably environment variables) were crafted by an actively malicious parent process controlled by an attacker. Everyone[citation needed] knows that this is true for environment variables, and yet we regularly see CVEs involving environment variables and setuid; but in a modern Linux kernel, there is a very long list of inheritable process parameters which can affect program behaviour. To take a few random examples, without looking it up, I would be unable to tell you whether entering a setuid program resets the RLIMIT_STACK limit, the PR_SET_PDEATHSIG and PR_SET_CHILD_SUBREAPER parameters, the capability bounding set and the seccomp filter. Probably you know better than me and can say "well *obviously* the answer is...", but can we really be confident that the same is true for every author of setuid code? Any of those process parameters could conceivably break security-sensitive assumptions made in a setuid program. This is particularly problematic if the setuid/setcap program is linked to third-party shared libraries, which were typically not designed or audited to be safe for use in such a hostile environment. Depending on their API specification, it might not even be *possible* for shared libraries to be setuid-safe without breaking compatibility - for instance if they implement a protocol or API that involves environment variables, then they don't really have the option of refusing to read from the environment. Even in libraries like glibc that are actively maintained and *do* intend to be safe for use in a hostile environment, we see vulnerabilities like CVE-2023-4911 relatively regularly. smcv