Re: [RFC PATCH] Implement /proc/pid/kill

From: Aleksa Sarai
Date: Tue Oct 30 2018 - 16:45:22 EST


On 2018-10-30, Daniel Colascione <dancol@xxxxxxxxxx> wrote:
> >> Add a simple proc-based kill interface. To use /proc/pid/kill, just
> >> write the signal number in base-10 ASCII to the kill file of the
> >> process to be killed: for example, 'echo 9 > /proc/$$/kill'.
> >>
> >> Semantically, /proc/pid/kill works like kill(2), except that the
> >> process ID comes from the proc filesystem context instead of from an
> >> explicit system call parameter. This way, it's possible to avoid races
> >> between inspecting some aspect of a process and that process's PID
> >> being reused for some other process.
> >
> > (Aside from any UX concerns other folks might have.)
> >
> > I think it would be a good idea to (at least temporarily) restrict this
> > so that only processes that are in the same PID namespace as the /proc
> > being resolved through may use this interface. Otherwise you might have
> > cases where partial container breakouts can start sending signals to
> > PIDs they wouldn't normally be able to address.
>
> That's a good idea.

(Oh and I wonder how this interacts with SELinux/AppArmor signal
mediation.)

> > (Unfortunately
> > there are lots of things that make it a bit difficult to use /proc/$pid
> > exclusively for introspection of a process -- especially in the context
> > of containers.)
>
> Tons of things already break without a working /proc. What do you have in mind?

Heh, if only that was the only blocker. :P

The basic problem is that currently container runtimes either depend on
some non-transient on-disk state (which becomes invalid on machine
reboots or dead processes and so on), or on long-running processes that
keep file descriptors required for administration of a container alive
(think O_PATH to /dev/pts/ptmx to avoid malicious container filesystem
attacks). Usually both.

What would be really useful would be having some way of "hiding away" a
mount namespace (of the pid1 of the container) that has all of the
information and bind-mounts-to-file-descriptors that are necessary for
administration. If the container's pid1 dies all of the transient state
has disappeared automatically -- because the stashed mount namespace has
died. In addition, if this was done the way I'm thinking with (and this
is the contentious bit) hierarchical mount namespaces you could make it
so that the pid1 could not manipulate its current mount namespace to
confuse the administrative process. You would also then create an
intermediate user namespace to help with several race conditions (that
have caused security bugs like CVE-2016-9962) we've seen when joining
containers.

Unfortunately this all depends on hierarchical mount namespaces (and
note that this would just be that NS_GET_PARENT gives you the mount
namespace that it was created in -- I'm not suggesting we redesign peers
or anything like that). This makes it basically a non-starter.

But if, on top of this ground-work, we then referenced containers
entirely via an fd to /proc/$pid then you could also avoid PID reuse
races (as well as being able to find out implicitly whether a container
has died thanks to the error semantics of /proc/$pid). And that's the
way I would suggest doing it (if we had these other things in place).

--
Aleksa Sarai
Senior Software Engineer (Containers)
SUSE Linux GmbH
<https://www.cyphar.com/>

Attachment: signature.asc
Description: PGP signature