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

Reply via email to