1 |
Author: zmedico |
2 |
Date: 2008-07-31 03:46:10 +0000 (Thu, 31 Jul 2008) |
3 |
New Revision: 11290 |
4 |
|
5 |
Modified: |
6 |
main/trunk/pym/portage/__init__.py |
7 |
Log: |
8 |
Fixes in portage.fetch() for bugs #233303 and #94133: |
9 |
|
10 |
* Totally skip $DISTDIR creation if the fetch_to_ro feature is enabled. |
11 |
* Don't touch $DISTDIR permissions unless unless usepriv and/or userfetch |
12 |
are enabled. |
13 |
* When usepriv and/or userfetch are enabled, test whether or not a process |
14 |
that has dropped privileges is able to create a file in the directory, |
15 |
and only adjust permissions if the test fails. |
16 |
|
17 |
* Completely |
18 |
|
19 |
|
20 |
Modified: main/trunk/pym/portage/__init__.py |
21 |
=================================================================== |
22 |
--- main/trunk/pym/portage/__init__.py 2008-07-31 00:59:31 UTC (rev 11289) |
23 |
+++ main/trunk/pym/portage/__init__.py 2008-07-31 03:46:10 UTC (rev 11290) |
24 |
@@ -3184,7 +3184,8 @@ |
25 |
con = con.replace(settings["PORTAGE_T"], settings["PORTAGE_FETCH_T"]) |
26 |
selinux.setexec(con) |
27 |
# bash is an allowed entrypoint, while most binaries are not |
28 |
- args = [BASH_BINARY, "-c", "exec \"$@\"", args[0]] + args |
29 |
+ if args[0] != BASH_BINARY: |
30 |
+ args = [BASH_BINARY, "-c", "exec \"$@\"", args[0]] + args |
31 |
|
32 |
rval = portage.process.spawn(args, |
33 |
env=dict(settings.iteritems()), **kwargs) |
34 |
@@ -3195,6 +3196,35 @@ |
35 |
|
36 |
return rval |
37 |
|
38 |
+_userpriv_test_write_file_cache = {} |
39 |
+_userpriv_test_write_cmd_script = "> %(file_path)s ; rval=$? ; " + \ |
40 |
+ "rm -f %(file_path)s ; exit $rval" |
41 |
+ |
42 |
+def _userpriv_test_write_file(settings, file_path): |
43 |
+ """ |
44 |
+ Drop privileges and try to open a file for writing. The file may or |
45 |
+ may not exist, and the parent directory is assumed to exist. The file |
46 |
+ is removed before returning. |
47 |
+ |
48 |
+ @param settings: A config instance which is passed to _spawn_fetch() |
49 |
+ @param file_path: A file path to open and write. |
50 |
+ @return: True if write succeeds, False otherwise. |
51 |
+ """ |
52 |
+ |
53 |
+ global _userpriv_test_write_file_cache, _userpriv_test_write_cmd_script |
54 |
+ rval = _userpriv_test_write_file_cache.get(file_path) |
55 |
+ if rval is not None: |
56 |
+ return rval |
57 |
+ |
58 |
+ args = [BASH_BINARY, "-c", _userpriv_test_write_cmd_script % \ |
59 |
+ {"file_path" : _shell_quote(file_path)}] |
60 |
+ |
61 |
+ returncode = _spawn_fetch(settings, args) |
62 |
+ |
63 |
+ rval = returncode == os.EX_OK |
64 |
+ _userpriv_test_write_file_cache[file_path] = rval |
65 |
+ return rval |
66 |
+ |
67 |
def _checksum_failure_temp_file(distdir, basename): |
68 |
""" |
69 |
First try to find a duplicate temp file with the same checksum and return |
70 |
@@ -3302,6 +3332,11 @@ |
71 |
|
72 |
features = mysettings.features |
73 |
restrict = mysettings.get("PORTAGE_RESTRICT","").split() |
74 |
+ |
75 |
+ from portage.data import secpass |
76 |
+ userfetch = secpass >= 2 and "userfetch" in features |
77 |
+ userpriv = secpass >= 2 and "userpriv" in features |
78 |
+ |
79 |
# 'nomirror' is bad/negative logic. You Restrict mirroring, not no-mirroring. |
80 |
if "mirror" in restrict or \ |
81 |
"nomirror" in restrict: |
82 |
@@ -3501,7 +3536,8 @@ |
83 |
if not mysettings.get(var_name, None): |
84 |
can_fetch = False |
85 |
|
86 |
- if can_fetch: |
87 |
+ if can_fetch and not fetch_to_ro: |
88 |
+ global _userpriv_test_write_file_cache |
89 |
dirmode = 02070 |
90 |
filemode = 060 |
91 |
modemask = 02 |
92 |
@@ -3519,7 +3555,17 @@ |
93 |
|
94 |
for x in distdir_dirs: |
95 |
mydir = os.path.join(mysettings["DISTDIR"], x) |
96 |
+ write_test_file = os.path.join( |
97 |
+ mydir, ".__portage_test_write__") |
98 |
+ |
99 |
+ if os.path.isdir(mydir): |
100 |
+ if not (userfetch or userpriv): |
101 |
+ continue |
102 |
+ if _userpriv_test_write_file(mysettings, write_test_file): |
103 |
+ continue |
104 |
+ |
105 |
if portage.util.ensure_dirs(mydir, gid=dir_gid, mode=dirmode, mask=modemask): |
106 |
+ _userpriv_test_write_file_cache.pop(write_test_file, None) |
107 |
writemsg("Adjusting permissions recursively: '%s'\n" % mydir, |
108 |
noiselevel=-1) |
109 |
def onerror(e): |