commit:     47ac5aff464d414bcaa2d04e9eeff06aceec868c
Author:     Mike Gilbert <floppym <AT> gentoo <DOT> org>
AuthorDate: Sat Sep 17 23:37:46 2022 +0000
Commit:     Mike Gilbert <floppym <AT> gentoo <DOT> org>
CommitDate: Sun Sep 18 18:33:19 2022 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=47ac5aff

Move pty setup from AbstractEbuildProcess to SpawnProcess

This ensures that bash is always executed with a controlling terminal,
which prevents it from triggering sandbox failures on startup.

When merging a package, the 'instprep' phase is executed by a
MergeProcess task. The MergeProcess class derives from SpawnProcess
directly (not through AbstractEbuildProcess).

The SpawnProcess class calls portage.process.spawn() to execute a task.
When pid-sandbox is enabled, this creates a new PID namespaces, and
starts pid-ns-init to act as PID 1 in the new namespace.

pid-ns-init calls setsid(), which creates a new session and
disconnects the process from its controlling terminal.

Later, it calls ioctl(sys.stdout, termios.TIOCSCTTY) to associate the
process with the terminal attached to stdout. This only works if stdout
is a tty (not a pipe).

If pid-ns-init fails to associate the process with a controlling
terminal, bash will fail to open /dev/tty on startup. As a fallback,
bash will attempt to dereference /proc/self/fd/0 (stdin), and opens the
resulting path with O_RDWR.

If the ebuild sets PROPERTIES="interactive", stdin will be inherited
from the parent emerge process, and may be attached to a terminal device
(/dev/tty1, etc). Attempting to open this device is likely to trigger a
sandbox failure.

Bug: https://bugs.gentoo.org/870310
Signed-off-by: Mike Gilbert <floppym <AT> gentoo.org>

 lib/_emerge/AbstractEbuildProcess.py | 8 --------
 lib/_emerge/SpawnProcess.py          | 7 ++++++-
 2 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/lib/_emerge/AbstractEbuildProcess.py 
b/lib/_emerge/AbstractEbuildProcess.py
index 6d89d40f0..8712b8ea1 100644
--- a/lib/_emerge/AbstractEbuildProcess.py
+++ b/lib/_emerge/AbstractEbuildProcess.py
@@ -18,7 +18,6 @@ from portage.package.ebuild._ipc.ExitCommand import 
ExitCommand
 from portage.package.ebuild._ipc.QueryCommand import QueryCommand
 from portage import os
 from portage.util.futures import asyncio
-from portage.util._pty import _create_pty_or_pipe
 from portage.util import apply_secpass_permissions
 
 portage.proxy.lazyimport.lazyimport(
@@ -336,13 +335,6 @@ class AbstractEbuildProcess(SpawnProcess):
 
         self._eerror(textwrap.wrap(msg, 72))
 
-    def _pipe(self, fd_pipes):
-        stdout_pipe = None
-        if not self.background:
-            stdout_pipe = fd_pipes.get(1)
-        got_pty, master_fd, slave_fd = 
_create_pty_or_pipe(copy_term_size=stdout_pipe)
-        return (master_fd, slave_fd)
-
     def _can_log(self, slave_fd):
         # With sesandbox, logging works through a pty but not through a
         # normal pipe. So, disable logging if ptys are broken.

diff --git a/lib/_emerge/SpawnProcess.py b/lib/_emerge/SpawnProcess.py
index c43b17c12..ed5724c91 100644
--- a/lib/_emerge/SpawnProcess.py
+++ b/lib/_emerge/SpawnProcess.py
@@ -16,6 +16,7 @@ from portage.output import EOutput
 from portage.util import writemsg_level
 from portage.util._async.BuildLogger import BuildLogger
 from portage.util._async.PipeLogger import PipeLogger
+from portage.util._pty import _create_pty_or_pipe
 from portage.util.futures import asyncio
 
 
@@ -217,7 +218,11 @@ class SpawnProcess(SubProcess):
         @type fd_pipes: dict
         @param fd_pipes: pipes from which to copy terminal size if desired.
         """
-        return os.pipe()
+        stdout_pipe = None
+        if not self.background:
+            stdout_pipe = fd_pipes.get(1)
+        got_pty, master_fd, slave_fd = 
_create_pty_or_pipe(copy_term_size=stdout_pipe)
+        return (master_fd, slave_fd)
 
     def _spawn(self, args, **kwargs):
         spawn_func = portage.process.spawn

Reply via email to