From: Arfrever Frehtes Taifersar Arahesis <arfre...@apache.org>

Drop permissions only for subprocess of pid-ns-init but not pid-ns-init
itself. With FEATURES="pid-sandbox userpriv", pid-ns-init should be
run with unchanged permissions (usually UID=0, GID=0).

Bug: https://bugs.gentoo.org/675868
Signed-off-by: Arfrever Frehtes Taifersar Arahesis <arfre...@apache.org>
Signed-off-by: Zac Medico <zmed...@gentoo.org>
---
 bin/pid-ns-init        | 49 ++++++++++++++++++++++++++----------------
 lib/portage/process.py | 12 +++++++++--
 2 files changed, 40 insertions(+), 21 deletions(-)

diff --git a/bin/pid-ns-init b/bin/pid-ns-init
index f9b8cc4f3..486fd13da 100644
--- a/bin/pid-ns-init
+++ b/bin/pid-ns-init
@@ -11,21 +11,6 @@ import subprocess
 import sys
 
 
-if sys.version_info.major < 3 or platform.python_implementation() != 'CPython':
-       def signal_disposition_preexec():
-               for signum in (
-                       signal.SIGHUP,
-                       signal.SIGINT,
-                       signal.SIGPIPE,
-                       signal.SIGQUIT,
-                       signal.SIGTERM,
-                       ):
-                       signal.signal(signum, signal.SIG_DFL)
-else:
-       # CPython >= 3 subprocess.Popen handles this internally.
-       signal_disposition_preexec = None
-
-
 KILL_SIGNALS = (
        signal.SIGINT,
        signal.SIGTERM,
@@ -37,9 +22,31 @@ def forward_kill_signal(main_child_pid, signum, frame):
        os.kill(main_child_pid, signum)
 
 
+def preexec_fn(uid, gid, groups, umask):
+       if gid is not None:
+               os.setgid(gid)
+       if groups is not None:
+               os.setgroups(groups)
+       if uid is not None:
+               os.setuid(uid)
+       if umask is not None:
+               os.umask(umask)
+
+       # CPython >= 3 subprocess.Popen handles this internally.
+       if sys.version_info.major < 3 or platform.python_implementation() != 
'CPython':
+               for signum in (
+                       signal.SIGHUP,
+                       signal.SIGINT,
+                       signal.SIGPIPE,
+                       signal.SIGQUIT,
+                       signal.SIGTERM,
+                       ):
+                       signal.signal(signum, signal.SIG_DFL)
+
+
 def main(argv):
        if len(argv) < 2:
-               return 'Usage: {} <main-child-pid> or <pass_fds> <binary> 
<argv0> [arg]..'.format(argv[0])
+               return 'Usage: {} <main-child-pid> or <uid> <gid> <groups> 
<umask> <pass_fds> <binary> <argv0> [arg]..'.format(argv[0])
 
        if len(argv) == 2:
                # The child process is init (pid 1) in a child pid namespace, 
and
@@ -50,13 +57,17 @@ def main(argv):
                proc = None
        else:
                # The current process is init (pid 1) in a child pid namespace.
-               pass_fds, binary, args = tuple(int(fd) for fd in 
argv[1].split(',')), argv[2], argv[3:]
+               uid, gid, groups, umask, pass_fds, binary, args = argv[1], 
argv[2], argv[3], argv[4], tuple(int(fd) for fd in argv[5].split(',')), 
argv[6], argv[7:]
+               uid = int(uid) if uid else None
+               gid = int(gid) if gid else None
+               groups = tuple(int(group) for group in groups.split(',')) if 
groups else None
+               umask = int(umask) if umask else None
 
                popen_kwargs = {}
+               popen_kwargs['preexec_fn'] = functools.partial(preexec_fn, uid, 
gid, groups, umask)
                if sys.version_info.major > 2:
                        popen_kwargs['pass_fds'] = pass_fds
-               proc = subprocess.Popen(args, executable=binary,
-                       preexec_fn=signal_disposition_preexec, **popen_kwargs)
+               proc = subprocess.Popen(args, executable=binary, **popen_kwargs)
                main_child_pid = proc.pid
 
        sig_handler = functools.partial(forward_kill_signal, main_child_pid)
diff --git a/lib/portage/process.py b/lib/portage/process.py
index dd3d58ddc..0dba55de3 100644
--- a/lib/portage/process.py
+++ b/lib/portage/process.py
@@ -1,5 +1,5 @@
 # portage.py -- core Portage functionality
-# Copyright 1998-2018 Gentoo Authors
+# Copyright 1998-2019 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 
@@ -467,7 +467,7 @@ def _exec(binary, mycommand, opt_name, fd_pipes,
        @param gid: Group ID to run the process under
        @type gid: Integer
        @param groups: Groups the Process should be in.
-       @type groups: Integer
+       @type groups: List
        @param uid: User ID to run the process under
        @type uid: Integer
        @param umask: an int representing a unix umask (see man chmod for umask 
details)
@@ -571,8 +571,16 @@ def _exec(binary, mycommand, opt_name, fd_pipes,
                                                                        
portage._python_interpreter,
                                                                        
os.path.join(portage._bin_path,
                                                                                
'pid-ns-init'),
+                                                                       
_unicode_encode('' if uid is None else str(uid)),
+                                                                       
_unicode_encode('' if gid is None else str(gid)),
+                                                                       
_unicode_encode('' if groups is None else ','.join(str(group) for group in 
groups)),
+                                                                       
_unicode_encode('' if umask is None else str(umask)),
                                                                        
_unicode_encode(','.join(str(fd) for fd in fd_pipes)),
                                                                        binary] 
+ myargs
+                                                               uid = None
+                                                               gid = None
+                                                               groups = None
+                                                               umask = None
                                                        else:
                                                                # Execute a 
supervisor process which will forward
                                                                # signals to 
init and forward exit status to the
-- 
2.18.1


Reply via email to