Subject: Re: [vserver] Sending signals to PID 1
From: Herbert Poetzl <herbert@13thfloor.at>
Date: Sat, 27 Jun 2020 16:39:40 +0200

On Sat, Jun 27, 2020 at 09:18:07PM +1200, Andrew Ruthven wrote:
> Hey,

Hello Andrew,

> I'm trying to build a NFSROOT for FAI [0] within a vserver
> guest, but when it install sysvinit-core the postinst tries 
> to send a USR1 signal to PID 1 which fails with no such PID.

> I'm using "sysv" as the init style for the vserver guest, 

With the sysv (default) init style and no special flags you
end up without a visible pid 1 task inside the guest.

You can use the info_init cflag to make pid 1 from the host
visible inside the guest, but depending on the kernel/patch
version this will either give EPERM or ESRCH when sending
signals to this process (for obvious reasons)

> is it possible to allow to send signals to PID 1, even if 
> they're ignored?

What happens when you send a signal to pid 1 in a Linux-VServer
guest ist this:

 - the context (xid) from the sending process is retrieved
 - the target (pid) is reverse mapped via vx_rmap_pid()
 - if a real process (rpid) was found, the normal signal
   deliver continues including any security checks

Now in recent kernels the vx_rmap_pid() will simply return
'0' for a lookup of pid 1 inside a guest which doesn't have
an init process and as a consequence, the kernel will return
ESRCH which userspace interprets correctly as 'No such PID'

Note that this is also the case for guests with a 'blend
through' init process (from the host) but this behaviour
could be easily changed.

If done so, the return value would be EPERM, as the guest
is (by default) not allowed to send signals to the host
init process (again for obvious reasons).

What you could do is to change the signal delivery mechanism
to skip over sending the signal and reporting success in
the special case where the target pid is 1 and the reverse
mapped pid is 0, which in turn would make it look like any
signals to pid 1 (init) were delivered as expected.

The relevant code can be found in kernel/signal.c and
a good start-point would be kill_pid_info().

Hope this helps,
Herbert

> Cheers,
> Andrew

> [0] https://fai-project.org
> -- 
> Andrew Ruthven, Wellington, New Zealand
> MIITP

> At work: andrew.ruthven@catalyst.net.nz
> At home: andrew@etc.gen.nz
> Cloud  : https://catalystcloud.nz
> GPG fpr: C603 FC4E 600F 1CEC D1C8  D97C 4B53 D931 E4D3 E863