From c25d86eb4ee0e2214e71259bca4998a67ce7c227 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Wed, 17 Jan 2007 23:01:09 +0000 Subject: For bug #162404, spawn tee outside the sesandbox domain so that it reads from a pipe between two domains. (trunk r5689:5691) svn path=/main/branches/2.1.2/; revision=5692 --- pym/portage.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/pym/portage.py b/pym/portage.py index 13014ef6..53eac070 100644 --- a/pym/portage.py +++ b/pym/portage.py @@ -2164,6 +2164,29 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, **keyw env=mysettings.environ() keywords["opt_name"]="[%s]" % mysettings["PF"] + # The default policy for the sesandbox domain only allows entry (via exec) + # from shells and from binaries that belong to portage (the number of entry + # points is minimized). The "tee" binary is not among the allowed entry + # points, so it is spawned outside of the sesandbox domain and reads from a + # pipe between two domains. + logfile = keywords.get("logfile") + mypids = [] + pw = None + if logfile: + del keywords["logfile"] + fd_pipes = keywords.get("fd_pipes") + if fd_pipes is None: + fd_pipes = {0:0, 1:1, 2:2} + elif 1 not in fd_pipes or 2 not in fd_pipes: + raise ValueError(fd_pipes) + pr, pw = os.pipe() + mypids.extend(portage_exec.spawn(('tee', '-i', '-a', logfile), + returnpid=True, fd_pipes={0:pr, 1:fd_pipes[1], 2:fd_pipes[2]})) + os.close(pr) + fd_pipes[1] = pw + fd_pipes[2] = pw + keywords["fd_pipes"] = fd_pipes + features = mysettings.features # XXX: Negative RESTRICT word droppriv=(droppriv and ("userpriv" in features) and not \ @@ -2189,12 +2212,33 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, **keyw con = con.replace(mysettings["PORTAGE_T"], mysettings["PORTAGE_SANDBOX_T"]) selinux.setexec(con) - retval = spawn_func(mystring, env=env, **keywords) - - if sesandbox: - selinux.setexec(None) - - return retval + returnpid = keywords.get("returnpid") + keywords["returnpid"] = True + try: + mypids.extend(spawn_func(mystring, env=env, **keywords)) + finally: + if pw: + os.close(pw) + if sesandbox: + selinux.setexec(None) + + if returnpid: + return mypids + + while mypids: + pid = mypids.pop(0) + retval = os.waitpid(pid, 0)[1] + portage_exec.spawned_pids.remove(pid) + if retval != os.EX_OK: + for pid in mypids: + if os.waitpid(pid, os.WNOHANG) == (0,0): + os.kill(pid, signal.SIGTERM) + os.waitpid(pid, 0) + portage_exec.spawned_pids.remove(pid) + if retval & 0xff: + return (retval & 0xff) << 8 + return retval >> 8 + return os.EX_OK def fetch(myuris, mysettings, listonly=0, fetchonly=0, locks_in_subdir=".locks",use_locks=1, try_mirrors=1): "fetch files. Will use digest file if available." -- cgit v1.2.3-18-g5258