On 1/13/19 8:57 PM, Brian Dolbec wrote:
> On Sun, 13 Jan 2019 16:27:21 -0800
> Zac Medico <zmed...@gentoo.org> wrote:
> 
>> Execute pid-ns-init as the first fork after unshare, as
>> required for it to have pid 1 and become the default reaper
>> of orphaned descendant processes. In _exec, exec a separate
>> pid-ns-init process to behave as a supervisor which will
>> forward signals to init and forward exit status to the parent
>> process.
>>
>> Fixes: a75d5546e3a4 ("Introduce a tiny init replacement for inside
>> pid namespace") Bug: https://bugs.gentoo.org/670484
>> ---
>>  bin/pid-ns-init        | 44
>> ++++++++++++++++++++++++++++++++++++++---- lib/portage/process.py |
>> 26 ++++++++++++++++++------- 2 files changed, 59 insertions(+), 11
>> deletions(-)
>>
>> diff --git a/bin/pid-ns-init b/bin/pid-ns-init
>> index 843257b70..3792eeaa4 100644
>> --- a/bin/pid-ns-init
>> +++ b/bin/pid-ns-init
>> @@ -1,23 +1,59 @@
>>  #!/usr/bin/env python
>> -# Copyright 2018 Gentoo Authors
>> +# Copyright 2018-2019 Gentoo Authors
>>  # Distributed under the terms of the GNU General Public License v2
>>  
>> +import functools
>>  import os
>> +import signal
>>  import sys
>>  
>>  
>> +KILL_SIGNALS = (
>> +    signal.SIGINT,
>> +    signal.SIGTERM,
>> +    signal.SIGHUP,
>> +)
>> +
>> +def forward_kill_signal(main_child_pid, signum, frame):
>> +    os.kill(main_child_pid, signum)
>> +
>> +
>>  def main(argv):
>>      if len(argv) < 2:
>> -            return 'Usage: {} <main-child-pid>'.format(argv[0])
>> -    main_child_pid = int(argv[1])
>> +            return 'Usage: {} <main-child-pid> or <binary>
>> argv0..'.format(argv[0]) +
>> +    if len(argv) == 2:
>> +            # The child process is init (pid 1) in a child pid
>> namespace, and
>> +            # the current process supervises from within the
>> global pid namespace
>> +            # (forwarding signals to init and forwarding exit
>> status to the parent
>> +            # process).
>> +            main_child_pid = int(argv[1])
>> +    else:
>> +            # The current process is init (pid 1) in a child pid
>> namespace.
>> +            binary = argv[1]
>> +            args = argv[2:]
>> +
>> +            main_child_pid = os.fork()
>> +            if main_child_pid == 0:
>> +                    os.execv(binary, args)
>> +
>> +    sig_handler = functools.partial(forward_kill_signal,
>> main_child_pid)
>> +    for signum in KILL_SIGNALS:
>> +            signal.signal(signum, sig_handler)
>>  
>>      # wait for child processes
>>      while True:
>> -            pid, status = os.wait()
>> +            try:
>> +                    pid, status = os.wait()
>> +            except OSError as e:
>> +                    if e.errno == errno.EINTR:
>> +                            continue
>> +                    raise
>>              if pid == main_child_pid:
>>                      if os.WIFEXITED(status):
>>                              return os.WEXITSTATUS(status)
>>                      elif os.WIFSIGNALED(status):
>> +                            signal.signal(os.WTERMSIG(status),
>> signal.SIG_DFL) os.kill(os.getpid(), os.WTERMSIG(status))
>>                      # go to the unreachable place
>>                      break
>> diff --git a/lib/portage/process.py b/lib/portage/process.py
>> index 7103b6b31..3e07f806c 100644
>> --- a/lib/portage/process.py
>> +++ b/lib/portage/process.py
>> @@ -564,15 +564,27 @@ def _exec(binary, mycommand, opt_name, fd_pipes,
>>                                                      noiselevel=-1)
>>                                      else:
>>                                              if unshare_pid:
>> -                                                    # pid
>> namespace requires us to become init
>> -                                                    fork_ret =
>> os.fork()
>> -                                                    if
>> fork_ret != 0:
>> -
>> os.execv(portage._python_interpreter, [
>> +
>> main_child_pid = os.fork()
>> +                                                    if
>> main_child_pid == 0:
>> +                                                            #
>> pid namespace requires us to become init
>> +
>> binary, myargs = portage._python_interpreter, [
>> +
>> portage._python_interpreter,
>> +
>> os.path.join(portage._bin_path,
>> +                                                                            
>>         'pid-ns-init')]
>> + [binary] + myargs
>> +                                                    else:
>> +                                                            #
>> Execute a supervisor process which will forward
>> +                                                            #
>> signals to init and forward exit status to the
>> +                                                            #
>> parent process. The supervisor process runs in
>> +                                                            #
>> the global pid namespace, so skip /proc remount
>> +                                                            #
>> and other setup that's intended only for the
>> +                                                            #
>> init process.
>> +
>> binary, myargs = portage._python_interpreter,
>> [ portage._python_interpreter, os.path.join(portage._bin_path,
>> -                                                                            
>> 'pid-ns-init'),
>> -                                                                    '%s'
>> % fork_ret,
>> -                                                                    ])
>> +                                                                    
>> 'pid-ns-init'),
>> str(main_child_pid)] +
>> +
>> os.execve(binary, myargs, env) +
>>                                              if unshare_mount:
>>                                                      # mark the
>> whole filesystem as slave to avoid # mounts escaping the namespace
> 
> Looks fine,

Thanks, merged:

https://gitweb.gentoo.org/proj/portage.git/commit/?id=fb406579b1d13c1ba23b28e0bb794c22878a58c0

> but I defer to floppym, mgorny since this affects systemd

I not experiencing any problems with systemd here. We've got this patch
to solve the systemd pkg_postinst thing:

https://gitweb.gentoo.org/proj/portage.git/commit/?id=bbfc36befdeed60f29c17d80d7766fd0da402d61
-- 
Thanks,
Zac

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to