1 |
From: Arfrever Frehtes Taifersar Arahesis <Arfrever@××××××.Org> |
2 |
|
3 |
Drop permissions only for subprocess of pid-ns-init but not pid-ns-init |
4 |
itself. With FEATURES="pid-sandbox userpriv", pid-ns-init should be |
5 |
run with unchanged permissions (usually UID=0, GID=0). |
6 |
|
7 |
Bug: https://bugs.gentoo.org/675868 |
8 |
Signed-off-by: Arfrever Frehtes Taifersar Arahesis <Arfrever@××××××.Org> |
9 |
Signed-off-by: Zac Medico <zmedico@g.o> |
10 |
--- |
11 |
bin/pid-ns-init | 49 ++++++++++++++++++++++++++---------------- |
12 |
lib/portage/process.py | 12 +++++++++-- |
13 |
2 files changed, 40 insertions(+), 21 deletions(-) |
14 |
|
15 |
diff --git a/bin/pid-ns-init b/bin/pid-ns-init |
16 |
index f9b8cc4f3..486fd13da 100644 |
17 |
--- a/bin/pid-ns-init |
18 |
+++ b/bin/pid-ns-init |
19 |
@@ -11,21 +11,6 @@ import subprocess |
20 |
import sys |
21 |
|
22 |
|
23 |
-if sys.version_info.major < 3 or platform.python_implementation() != 'CPython': |
24 |
- def signal_disposition_preexec(): |
25 |
- for signum in ( |
26 |
- signal.SIGHUP, |
27 |
- signal.SIGINT, |
28 |
- signal.SIGPIPE, |
29 |
- signal.SIGQUIT, |
30 |
- signal.SIGTERM, |
31 |
- ): |
32 |
- signal.signal(signum, signal.SIG_DFL) |
33 |
-else: |
34 |
- # CPython >= 3 subprocess.Popen handles this internally. |
35 |
- signal_disposition_preexec = None |
36 |
- |
37 |
- |
38 |
KILL_SIGNALS = ( |
39 |
signal.SIGINT, |
40 |
signal.SIGTERM, |
41 |
@@ -37,9 +22,31 @@ def forward_kill_signal(main_child_pid, signum, frame): |
42 |
os.kill(main_child_pid, signum) |
43 |
|
44 |
|
45 |
+def preexec_fn(uid, gid, groups, umask): |
46 |
+ if gid is not None: |
47 |
+ os.setgid(gid) |
48 |
+ if groups is not None: |
49 |
+ os.setgroups(groups) |
50 |
+ if uid is not None: |
51 |
+ os.setuid(uid) |
52 |
+ if umask is not None: |
53 |
+ os.umask(umask) |
54 |
+ |
55 |
+ # CPython >= 3 subprocess.Popen handles this internally. |
56 |
+ if sys.version_info.major < 3 or platform.python_implementation() != 'CPython': |
57 |
+ for signum in ( |
58 |
+ signal.SIGHUP, |
59 |
+ signal.SIGINT, |
60 |
+ signal.SIGPIPE, |
61 |
+ signal.SIGQUIT, |
62 |
+ signal.SIGTERM, |
63 |
+ ): |
64 |
+ signal.signal(signum, signal.SIG_DFL) |
65 |
+ |
66 |
+ |
67 |
def main(argv): |
68 |
if len(argv) < 2: |
69 |
- return 'Usage: {} <main-child-pid> or <pass_fds> <binary> <argv0> [arg]..'.format(argv[0]) |
70 |
+ return 'Usage: {} <main-child-pid> or <uid> <gid> <groups> <umask> <pass_fds> <binary> <argv0> [arg]..'.format(argv[0]) |
71 |
|
72 |
if len(argv) == 2: |
73 |
# The child process is init (pid 1) in a child pid namespace, and |
74 |
@@ -50,13 +57,17 @@ def main(argv): |
75 |
proc = None |
76 |
else: |
77 |
# The current process is init (pid 1) in a child pid namespace. |
78 |
- pass_fds, binary, args = tuple(int(fd) for fd in argv[1].split(',')), argv[2], argv[3:] |
79 |
+ 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:] |
80 |
+ uid = int(uid) if uid else None |
81 |
+ gid = int(gid) if gid else None |
82 |
+ groups = tuple(int(group) for group in groups.split(',')) if groups else None |
83 |
+ umask = int(umask) if umask else None |
84 |
|
85 |
popen_kwargs = {} |
86 |
+ popen_kwargs['preexec_fn'] = functools.partial(preexec_fn, uid, gid, groups, umask) |
87 |
if sys.version_info.major > 2: |
88 |
popen_kwargs['pass_fds'] = pass_fds |
89 |
- proc = subprocess.Popen(args, executable=binary, |
90 |
- preexec_fn=signal_disposition_preexec, **popen_kwargs) |
91 |
+ proc = subprocess.Popen(args, executable=binary, **popen_kwargs) |
92 |
main_child_pid = proc.pid |
93 |
|
94 |
sig_handler = functools.partial(forward_kill_signal, main_child_pid) |
95 |
diff --git a/lib/portage/process.py b/lib/portage/process.py |
96 |
index dd3d58ddc..0dba55de3 100644 |
97 |
--- a/lib/portage/process.py |
98 |
+++ b/lib/portage/process.py |
99 |
@@ -1,5 +1,5 @@ |
100 |
# portage.py -- core Portage functionality |
101 |
-# Copyright 1998-2018 Gentoo Authors |
102 |
+# Copyright 1998-2019 Gentoo Authors |
103 |
# Distributed under the terms of the GNU General Public License v2 |
104 |
|
105 |
|
106 |
@@ -467,7 +467,7 @@ def _exec(binary, mycommand, opt_name, fd_pipes, |
107 |
@param gid: Group ID to run the process under |
108 |
@type gid: Integer |
109 |
@param groups: Groups the Process should be in. |
110 |
- @type groups: Integer |
111 |
+ @type groups: List |
112 |
@param uid: User ID to run the process under |
113 |
@type uid: Integer |
114 |
@param umask: an int representing a unix umask (see man chmod for umask details) |
115 |
@@ -571,8 +571,16 @@ def _exec(binary, mycommand, opt_name, fd_pipes, |
116 |
portage._python_interpreter, |
117 |
os.path.join(portage._bin_path, |
118 |
'pid-ns-init'), |
119 |
+ _unicode_encode('' if uid is None else str(uid)), |
120 |
+ _unicode_encode('' if gid is None else str(gid)), |
121 |
+ _unicode_encode('' if groups is None else ','.join(str(group) for group in groups)), |
122 |
+ _unicode_encode('' if umask is None else str(umask)), |
123 |
_unicode_encode(','.join(str(fd) for fd in fd_pipes)), |
124 |
binary] + myargs |
125 |
+ uid = None |
126 |
+ gid = None |
127 |
+ groups = None |
128 |
+ umask = None |
129 |
else: |
130 |
# Execute a supervisor process which will forward |
131 |
# signals to init and forward exit status to the |
132 |
-- |
133 |
2.18.1 |