commit:     37e4dc5ae842afa03849a47b123345906fdd81a2
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Tue Jan 22 07:17:18 2019 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Wed Jan 23 04:47:25 2019 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=37e4dc5a

pid-sandbox: pid-ns-init setsid support (bug 675870)

Use setsid to isolate the parent process from signals sent
to the process group, and forward signals to the entire
process group with kill(0, signum).

Bug: https://bugs.gentoo.org/675870
Signed-off-by: Zac Medico <zmedico <AT> gentoo.org>

 bin/pid-ns-init | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/bin/pid-ns-init b/bin/pid-ns-init
index f9b8cc4f3..76ae8de75 100644
--- a/bin/pid-ns-init
+++ b/bin/pid-ns-init
@@ -33,8 +33,12 @@ KILL_SIGNALS = (
 )
 
 
-def forward_kill_signal(main_child_pid, signum, frame):
-       os.kill(main_child_pid, signum)
+def forward_kill_signal(pid, signum, frame):
+       if pid == 0:
+               # Avoid a signal feedback loop, since signals sent to the
+               # process group are also sent to the current process.
+               signal.signal(signum, signal.SIG_DFL)
+       os.kill(pid, signum)
 
 
 def main(argv):
@@ -47,6 +51,7 @@ def main(argv):
                # (forwarding signals to init and forwarding exit status to the 
parent
                # process).
                main_child_pid = int(argv[1])
+               setsid = False
                proc = None
        else:
                # The current process is init (pid 1) in a child pid namespace.
@@ -55,11 +60,16 @@ def main(argv):
                popen_kwargs = {}
                if sys.version_info.major > 2:
                        popen_kwargs['pass_fds'] = pass_fds
+               # Isolate parent process from process group SIGSTOP (bug 675870)
+               setsid = True
+               os.setsid()
                proc = subprocess.Popen(args, executable=binary,
                        preexec_fn=signal_disposition_preexec, **popen_kwargs)
                main_child_pid = proc.pid
 
-       sig_handler = functools.partial(forward_kill_signal, main_child_pid)
+       # If setsid has been called, use kill(0, signum) to
+       # forward signals to the entire process group.
+       sig_handler = functools.partial(forward_kill_signal, 0 if setsid else 
main_child_pid)
        for signum in KILL_SIGNALS:
                signal.signal(signum, sig_handler)
 

Reply via email to