Gentoo Archives: gentoo-commits

From: Zac Medico <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: lib/portage/package/ebuild/, lib/_emerge/
Date: Sun, 01 Mar 2020 06:21:28
Message-Id: 1583042326.ec654122c0eb191c90ffb2c191403d342dbc361e.zmedico@gentoo
1 commit: ec654122c0eb191c90ffb2c191403d342dbc361e
2 Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
3 AuthorDate: Sun Mar 1 05:58:00 2020 +0000
4 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
5 CommitDate: Sun Mar 1 05:58:46 2020 +0000
6 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=ec654122
7
8 fetch: drop privileges early for NFS root_squash (bug 601252)
9
10 Drop privileges prior to fetch function calls, so that
11 all necessary operations can succeed when DISTDIR is
12 on NFS with root_squash enabled.
13
14 Bug: https://bugs.gentoo.org/601252
15 Signed-off-by: Zac Medico <zmedico <AT> gentoo.org>
16
17 lib/_emerge/EbuildFetcher.py | 12 +++++++++++-
18 lib/portage/package/ebuild/doebuild.py | 22 +++++++++++++++++-----
19 lib/portage/package/ebuild/fetch.py | 31 +++++++++++++++++++++++++++++++
20 3 files changed, 59 insertions(+), 6 deletions(-)
21
22 diff --git a/lib/_emerge/EbuildFetcher.py b/lib/_emerge/EbuildFetcher.py
23 index c9e03dc97..d315d4f02 100644
24 --- a/lib/_emerge/EbuildFetcher.py
25 +++ b/lib/_emerge/EbuildFetcher.py
26 @@ -12,7 +12,12 @@ from portage import _unicode_encode
27 from portage import _unicode_decode
28 from portage.checksum import _hash_filter
29 from portage.elog.messages import eerror
30 -from portage.package.ebuild.fetch import _check_distfile, fetch
31 +from portage.package.ebuild.fetch import (
32 + _check_distfile,
33 + _drop_privs_userfetch,
34 + _want_userfetch,
35 + fetch,
36 +)
37 from portage.util._async.AsyncTaskFuture import AsyncTaskFuture
38 from portage.util._async.ForkProcess import ForkProcess
39 from portage.util.futures.compat_coroutine import coroutine
40 @@ -239,6 +244,11 @@ class _EbuildFetcherProcess(ForkProcess):
41 portage.output.havecolor = self._settings.get('NOCOLOR') \
42 not in ('yes', 'true')
43
44 + # For userfetch, drop privileges for the entire fetch call, in
45 + # order to handle DISTDIR on NFS with root_squash for bug 601252.
46 + if _want_userfetch(self._settings):
47 + _drop_privs_userfetch(self._settings)
48 +
49 rval = 1
50 allow_missing = self._get_manifest().allow_missing or \
51 'digest' in self._settings.features
52
53 diff --git a/lib/portage/package/ebuild/doebuild.py b/lib/portage/package/ebuild/doebuild.py
54 index 92e9d755c..71e3a74ce 100644
55 --- a/lib/portage/package/ebuild/doebuild.py
56 +++ b/lib/portage/package/ebuild/doebuild.py
57 @@ -1,4 +1,4 @@
58 -# Copyright 2010-2019 Gentoo Authors
59 +# Copyright 2010-2020 Gentoo Authors
60 # Distributed under the terms of the GNU General Public License v2
61
62 from __future__ import unicode_literals
63 @@ -30,7 +30,7 @@ portage.proxy.lazyimport.lazyimport(globals(),
64 'portage.package.ebuild.config:check_config_instance',
65 'portage.package.ebuild.digestcheck:digestcheck',
66 'portage.package.ebuild.digestgen:digestgen',
67 - 'portage.package.ebuild.fetch:fetch',
68 + 'portage.package.ebuild.fetch:_drop_privs_userfetch,_want_userfetch,fetch',
69 'portage.package.ebuild.prepare_build_dirs:_prepare_fake_distdir',
70 'portage.package.ebuild._ipc.QueryCommand:QueryCommand',
71 'portage.dep._slot_operator:evaluate_slot_operator_equal_deps',
72 @@ -83,6 +83,7 @@ from portage.util.cpuinfo import get_cpu_count
73 from portage.util.lafilefixer import rewrite_lafile
74 from portage.util.compression_probe import _compressors
75 from portage.util.futures import asyncio
76 +from portage.util.futures.executor.fork import ForkExecutor
77 from portage.util.path import first_existing
78 from portage.util.socks5 import get_socks5_proxy
79 from portage.versions import _pkgsplit
80 @@ -1082,9 +1083,20 @@ def doebuild(myebuild, mydo, _unused=DeprecationWarning, settings=None, debug=0,
81 dist_digests = None
82 if mf is not None:
83 dist_digests = mf.getTypeDigests("DIST")
84 - if not fetch(fetchme, mysettings, listonly=listonly,
85 - fetchonly=fetchonly, allow_missing_digests=False,
86 - digests=dist_digests):
87 +
88 + def _fetch_subprocess(fetchme, mysettings, listonly, dist_digests):
89 + # For userfetch, drop privileges for the entire fetch call, in
90 + # order to handle DISTDIR on NFS with root_squash for bug 601252.
91 + if _want_userfetch(mysettings):
92 + _drop_privs_userfetch(mysettings)
93 +
94 + return fetch(fetchme, mysettings, listonly=listonly,
95 + fetchonly=fetchonly, allow_missing_digests=False,
96 + digests=dist_digests)
97 +
98 + loop = asyncio._safe_loop()
99 + if not loop.run_until_complete(loop.run_in_executor(ForkExecutor(loop=loop),
100 + _fetch_subprocess, fetchme, mysettings, listonly, dist_digests)):
101 # Since listonly mode is called by emerge --pretend in an
102 # asynchronous context, spawn_nofetch would trigger event loop
103 # recursion here, therefore delegate execution of pkg_nofetch
104
105 diff --git a/lib/portage/package/ebuild/fetch.py b/lib/portage/package/ebuild/fetch.py
106 index 06118b1a6..f7984130f 100644
107 --- a/lib/portage/package/ebuild/fetch.py
108 +++ b/lib/portage/package/ebuild/fetch.py
109 @@ -69,6 +69,37 @@ _userpriv_spawn_kwargs = (
110 def _hide_url_passwd(url):
111 return re.sub(r'//(.+):.+@(.+)', r'//\1:*password*@\2', url)
112
113 +
114 +def _want_userfetch(settings):
115 + """
116 + Check if it's desirable to drop privileges for userfetch.
117 +
118 + @param settings: portage config
119 + @type settings: portage.package.ebuild.config.config
120 + @return: True if desirable, False otherwise
121 + """
122 + return ('userfetch' in settings.features and
123 + portage.data.secpass >= 2 and os.getuid() == 0)
124 +
125 +
126 +def _drop_privs_userfetch(settings):
127 + """
128 + Drop privileges for userfetch, and update portage.data.secpass
129 + to correspond to the new privilege level.
130 + """
131 + spawn_kwargs = dict(_userpriv_spawn_kwargs)
132 + try:
133 + _ensure_distdir(settings, settings['DISTDIR'])
134 + except PortageException:
135 + if not os.path.isdir(settings['DISTDIR']):
136 + raise
137 + os.setgid(int(spawn_kwargs['gid']))
138 + os.setgroups(spawn_kwargs['groups'])
139 + os.setuid(int(spawn_kwargs['uid']))
140 + os.umask(spawn_kwargs['umask'])
141 + portage.data.secpass = 1
142 +
143 +
144 def _spawn_fetch(settings, args, **kwargs):
145 """
146 Spawn a process with appropriate settings for fetching, including