1 |
commit: df5b88d8407030f394b8d505988a7f6bb4be723e |
2 |
Author: Anthony G. Basile <blueness <AT> gentoo <DOT> org> |
3 |
AuthorDate: Thu Dec 27 01:58:33 2012 +0000 |
4 |
Commit: Anthony G. Basile <blueness <AT> gentoo <DOT> org> |
5 |
CommitDate: Thu Dec 27 01:58:40 2012 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/elfix.git;a=commit;h=df5b88d8 |
7 |
|
8 |
misc/alt-revdep-pax: use class LinkMap |
9 |
|
10 |
--- |
11 |
.gitignore | 1 + |
12 |
misc/alt-revdep-pax | 1001 ++++++++++++++++++++++----------------------------- |
13 |
2 files changed, 431 insertions(+), 571 deletions(-) |
14 |
|
15 |
diff --git a/.gitignore b/.gitignore |
16 |
index 9648131..f438112 100644 |
17 |
--- a/.gitignore |
18 |
+++ b/.gitignore |
19 |
@@ -33,3 +33,4 @@ dummy |
20 |
revdepbin |
21 |
# |
22 |
scripts/build |
23 |
+misc/__pycache__ |
24 |
|
25 |
diff --git a/misc/alt-revdep-pax b/misc/alt-revdep-pax |
26 |
index 69086af..be51bf9 100755 |
27 |
--- a/misc/alt-revdep-pax |
28 |
+++ b/misc/alt-revdep-pax |
29 |
@@ -1,20 +1,20 @@ |
30 |
#!/usr/bin/env python |
31 |
# |
32 |
-# alt-revdep-pax: this file is part of the elfix package |
33 |
-# Copyright (C) 2011 Anthony G. Basile |
34 |
+# alt-revdep-pax: this file is part of the elfix package |
35 |
+# Copyright (C) 2011 Anthony G. Basile |
36 |
# |
37 |
-# This program is free software: you can redistribute it and/or modify |
38 |
-# it under the terms of the GNU General Public License as published by |
39 |
-# the Free Software Foundation, either version 3 of the License, or |
40 |
-# (at your option) any later version. |
41 |
+# This program is free software: you can redistribute it and/or modify |
42 |
+# it under the terms of the GNU General Public License as published by |
43 |
+# the Free Software Foundation, either version 3 of the License, or |
44 |
+# (at your option) any later version. |
45 |
# |
46 |
-# This program is distributed in the hope that it will be useful, |
47 |
-# but WITHOUT ANY WARRANTY; without even the implied warranty of |
48 |
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
49 |
-# GNU General Public License for more details. |
50 |
+# This program is distributed in the hope that it will be useful, |
51 |
+# but WITHOUT ANY WARRANTY; without even the implied warranty of |
52 |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
53 |
+# GNU General Public License for more details. |
54 |
# |
55 |
-# You should have received a copy of the GNU General Public License |
56 |
-# along with this program. If not, see <http://www.gnu.org/licenses/>. |
57 |
+# You should have received a copy of the GNU General Public License |
58 |
+# along with this program. If not, see <http://www.gnu.org/licenses/>. |
59 |
# |
60 |
|
61 |
# |
62 |
@@ -29,590 +29,449 @@ |
63 |
import getopt |
64 |
import os |
65 |
import sys |
66 |
-import re |
67 |
import pax |
68 |
-import portage |
69 |
|
70 |
+from link_map import LinkMap |
71 |
|
72 |
-""" python2/3 compat input """ |
73 |
def get_input(prompt): |
74 |
- if sys.hexversion > 0x03000000: |
75 |
- return input(prompt) |
76 |
- else: |
77 |
- return raw_input(prompt) |
78 |
- |
79 |
- |
80 |
-""" |
81 |
-Return object_needed dictionary which has structure |
82 |
- |
83 |
- { full_path_to_ELF_object : [ soname1, soname2, ... ], ... } |
84 |
- |
85 |
-Here the sonames were obtained from the ELF object by scanelf -nm |
86 |
-(like readelf -d) during emerge. |
87 |
-""" |
88 |
-def get_object_needed(): |
89 |
- |
90 |
- vardb = portage.db[portage.root]["vartree"].dbapi |
91 |
- |
92 |
- object_needed = {} |
93 |
- |
94 |
- for pkg in vardb.cpv_all(): |
95 |
- needs = vardb.aux_get(pkg, ['NEEDED.ELF.2'])[0].strip() |
96 |
- if not needs: #skip empty lines |
97 |
- continue |
98 |
- lines = re.split('\n', needs) |
99 |
- for line in lines: |
100 |
- link = re.split(';', line) |
101 |
- elf = link[1] |
102 |
- sonames = re.split(',', link[4]) |
103 |
- object_needed[elf] = sonames |
104 |
- |
105 |
- return object_needed |
106 |
- |
107 |
- |
108 |
-""" |
109 |
-Return library2soname dictionary which has structure |
110 |
- |
111 |
- { full_path_to_library : soname, ... } |
112 |
- |
113 |
-and its inverse which has structure |
114 |
- |
115 |
- { soname : full_path_to_library, ... } |
116 |
-""" |
117 |
-def get_libraries(): |
118 |
- |
119 |
- vardb = portage.db[portage.root]["vartree"].dbapi |
120 |
- |
121 |
- library2soname = {} |
122 |
- soname2library = {} |
123 |
- |
124 |
- for pkg in vardb.cpv_all(): |
125 |
- needs = vardb.aux_get(pkg, ['NEEDED.ELF.2'])[0].strip() |
126 |
- if not needs: #skip empty lines |
127 |
- continue |
128 |
- lines = re.split('\n', needs) |
129 |
- for line in lines: |
130 |
- link = re.split(';', line) |
131 |
- elf = link[1] |
132 |
- soname = link[2] |
133 |
- if soname: #no soname => executable |
134 |
- library2soname[elf] = soname |
135 |
- soname2library[soname] = elf |
136 |
- |
137 |
- return ( library2soname, soname2library ) |
138 |
- |
139 |
- |
140 |
-""" |
141 |
-Return get_soname_needed dictionary which has structure: |
142 |
- |
143 |
- { soname : [ soname1, soname2, ... ], .... } |
144 |
- |
145 |
-Here the soname1, soname2,... were obtained from soname's corresponding |
146 |
-ELF object by scanelf -n during emerge. |
147 |
-""" |
148 |
-def get_soname_needed( object_needed, library2soname ): |
149 |
- |
150 |
- soname_needed = {} |
151 |
- |
152 |
- for elf in object_needed: |
153 |
- try: |
154 |
- soname = library2soname[elf] |
155 |
- soname_needed[soname] = object_needed[elf] |
156 |
- except KeyError: |
157 |
- continue # no soname, its probably an executable |
158 |
- |
159 |
- return soname_needed |
160 |
- |
161 |
-""" |
162 |
-Run through the entire chain of obj -> sonameX -> sonameY ... -> sonameZ chain. |
163 |
-We do this by continuously expanding the list value of the dictionary key elf |
164 |
-entry until there are no new soname's found. |
165 |
-""" |
166 |
-def expand_linkings( object_needed, soname2library ): |
167 |
- |
168 |
- for elf in object_needed: |
169 |
- while True: |
170 |
- found_new_soname = False |
171 |
- for s in object_needed[elf]: # For all the next links ... |
172 |
- try: |
173 |
- for sf in object_needed[soname2library[s]]: # ... go one step ahead in the chain |
174 |
- if sf in object_needed[elf]: # ... skip it if we already included it |
175 |
- continue |
176 |
- if not sf in soname2library: # ... skip if its a vdso |
177 |
- continue |
178 |
- # This appends to the object_needed |
179 |
- # and soname_needed lists. No copy |
180 |
- # was done so its the same lists in |
181 |
- # memory for both, and its modified |
182 |
- # for both. |
183 |
- object_needed[elf].append(sf) # ... otherwise collapse it back into |
184 |
- found_new_soname = True # first node of the chain. |
185 |
- |
186 |
- except KeyError: # Not all nodes in the chain have a next node |
187 |
- continue |
188 |
- |
189 |
- if not found_new_soname: # We're done, that last iteration found |
190 |
- break # no new nodes |
191 |
- |
192 |
- |
193 |
- |
194 |
- |
195 |
-def get_object_linkings(): |
196 |
- |
197 |
- object_needed = get_object_needed() |
198 |
- ( library2soname, soname2library ) = get_libraries() |
199 |
- soname_needed = get_soname_needed( object_needed, library2soname ) |
200 |
- expand_linkings( object_needed, soname2library ) |
201 |
- return ( object_needed, soname2library ) |
202 |
- |
203 |
- |
204 |
-def print_problems( elfs_without_flags, sonames_without_flags, sonames_missing_library): |
205 |
- |
206 |
- elfs_without_flags = set(elfs_without_flags) |
207 |
- print('\n**** ELF objections without any PAX flags ****\n') |
208 |
- for m in elfs_without_flags: |
209 |
- print('\t%s' % m) |
210 |
- |
211 |
- sonames_without_flags = set(sonames_without_flags) |
212 |
- print('\n**** SONAMEs with library files without PAX flags ****\n') |
213 |
- for m in sonames_without_flags: |
214 |
- print('\t%s' % m) |
215 |
- |
216 |
- sonames_missing_library = set(sonames_missing_library) |
217 |
- print('\n**** SONAMES without any library files ****\n') |
218 |
- for m in sonames_missing_library: |
219 |
- print('\t%s' % m) |
220 |
- |
221 |
- |
222 |
-def print_object_linkings( object_linkings, soname2library, verbose ): |
223 |
- |
224 |
- elfs_without_flags = [] |
225 |
- sonames_without_flags = [] |
226 |
- sonames_missing_library = [] |
227 |
- |
228 |
- for elf in object_linkings: |
229 |
- try: |
230 |
- ( elf_str_flags, elf_bin_flags ) = pax.getflags(elf) |
231 |
- sv = '%s ( %s )\n' % ( elf, elf_str_flags ) |
232 |
- s = sv |
233 |
- except pax.PaxError: |
234 |
- elfs_without_flags.append(elf) |
235 |
- continue |
236 |
- |
237 |
- count = 0 |
238 |
- for soname in object_linkings[elf]: |
239 |
- try: |
240 |
- library = soname2library[soname] |
241 |
- ( library_str_flags, library_bin_flags ) = pax.getflags(library) |
242 |
- sv = '%s\n\t%s\t%s ( %s )' % ( sv, soname, library, library_str_flags ) |
243 |
- if elf_str_flags != library_str_flags: |
244 |
- s = '%s\n\t%s\t%s ( %s )' % ( s, soname, library, library_str_flags ) |
245 |
- count = count + 1 |
246 |
- except KeyError: |
247 |
- sonames_missing_library.append(soname) |
248 |
- except pax.PaxError: |
249 |
- sonames_without_flags.append(soname) |
250 |
- |
251 |
- |
252 |
- if verbose: |
253 |
- print('%s\n' % sv) |
254 |
- if count == 0: |
255 |
- print('\tNo mismatches\n\n') |
256 |
- else: |
257 |
- print('\tMismatches\n\n') |
258 |
- else: |
259 |
- if count != 0: |
260 |
- print('%s\n\n' % s) |
261 |
- |
262 |
- print_problems( elfs_without_flags, sonames_without_flags, sonames_missing_library) |
263 |
- |
264 |
+ """ python2/3 compat input """ |
265 |
+ if sys.hexversion > 0x03000000: |
266 |
+ return input(prompt) |
267 |
+ else: |
268 |
+ return raw_input(prompt) |
269 |
+ |
270 |
+ |
271 |
+def print_problems(elfs_without_flags, sonames_without_flags, sonames_missing_library): |
272 |
+ elfs_without_flags = set(elfs_without_flags) |
273 |
+ print('\n**** ELF objections without any PAX flags ****') |
274 |
+ for m in elfs_without_flags: |
275 |
+ print('\t%s' % m) |
276 |
+ sonames_without_flags = set(sonames_without_flags) |
277 |
+ print('\n**** SONAMEs with library files without PAX flags ****') |
278 |
+ for m in sonames_without_flags: |
279 |
+ print('\t%s' % m) |
280 |
+ sonames_missing_library = set(sonames_missing_library) |
281 |
+ print('\n**** SONAMES without any library files ****') |
282 |
+ for m in sonames_missing_library: |
283 |
+ print('\t%s' % m) |
284 |
|
285 |
|
286 |
def run_forward(verbose): |
287 |
- |
288 |
- ( object_linkings, soname2library ) = get_object_linkings() |
289 |
- print_object_linkings( object_linkings, soname2library, verbose) |
290 |
- |
291 |
- |
292 |
- |
293 |
- |
294 |
-def get_object_reverse_linkings( object_linkings ): |
295 |
- |
296 |
- object_reverse_linkings = {} |
297 |
- |
298 |
- for elf in object_linkings: |
299 |
- for soname in object_linkings[elf]: |
300 |
- object_reverse_linkings.setdefault(soname,[]).append(elf) |
301 |
- |
302 |
- return object_reverse_linkings |
303 |
- |
304 |
- |
305 |
-def print_object_reverse_linkings( object_reverse_linkings, soname2library, verbose, executable_only): |
306 |
- |
307 |
- shell_path = path = os.getenv('PATH').split(':') |
308 |
- |
309 |
- elfs_without_flags = [] |
310 |
- sonames_without_flags = [] |
311 |
- sonames_missing_library = [] |
312 |
- |
313 |
- for soname in object_reverse_linkings: |
314 |
- try: |
315 |
- library = soname2library[soname] |
316 |
- ( library_str_flags, library_bin_flags ) = pax.getflags(library) |
317 |
- sv = '%s\t%s ( %s )\n' % ( soname, library, library_str_flags ) |
318 |
- s = sv |
319 |
- except KeyError: |
320 |
- sonames_missing_library.append(soname) |
321 |
- except pax.PaxError: |
322 |
- sonames_without_flags.append(soname) |
323 |
- |
324 |
- count = 0 |
325 |
- for elf in object_reverse_linkings[soname]: |
326 |
- try: |
327 |
- ( elf_str_flags, elf_bin_flags ) = pax.getflags(elf) |
328 |
- if executable_only: |
329 |
- if os.path.dirname(elf) in shell_path: |
330 |
- sv = '%s\n\t%s ( %s )' % ( sv, elf, elf_str_flags ) |
331 |
- if library_str_flags != elf_str_flags: |
332 |
- s = '%s\n\t%s ( %s )' % ( s, elf, elf_str_flags ) |
333 |
- count = count + 1 |
334 |
- else: |
335 |
- sv = '%s\n\t%s ( %s )' % ( sv, elf, elf_str_flags ) |
336 |
- if library_str_flags != elf_str_flags: |
337 |
- s = '%s\n\t%s ( %s )' % ( s, elf, elf_str_flags ) |
338 |
- count = count + 1 |
339 |
- except pax.PaxError: |
340 |
- elfs_without_flags.append(elf) |
341 |
- |
342 |
- if verbose: |
343 |
- print('%s\n' % sv) |
344 |
- if count == 0: |
345 |
- print('\tNo mismatches\n\n') |
346 |
- else: |
347 |
- print('\tMismatches\n\n') |
348 |
- else: |
349 |
- if count != 0: |
350 |
- print('%s\n\n' % s) |
351 |
- |
352 |
- print_problems( elfs_without_flags, sonames_without_flags, sonames_missing_library) |
353 |
+ (object_linkings, object_reverse_linkings, library2soname, soname2library) = LinkMap().get_maps() |
354 |
+ |
355 |
+ elfs_without_flags = [] |
356 |
+ sonames_without_flags = [] |
357 |
+ sonames_missing_library = [] |
358 |
+ |
359 |
+ for abi in object_linkings: |
360 |
+ for elf in object_linkings[abi]: |
361 |
+ try: |
362 |
+ (elf_str_flags, elf_bin_flags) = pax.getflags(elf) |
363 |
+ sv = '%s :%s ( %s )' % (elf, abi, elf_str_flags) |
364 |
+ s = sv |
365 |
+ except pax.PaxError: |
366 |
+ elfs_without_flags.append(elf) |
367 |
+ continue |
368 |
+ |
369 |
+ count = 0 |
370 |
+ for soname in object_linkings[abi][elf]: |
371 |
+ try: |
372 |
+ library = soname2library[(soname,abi)] |
373 |
+ (library_str_flags, library_bin_flags) = pax.getflags(library) |
374 |
+ sv = '%s\n\t%s\t%s ( %s )' % (sv, soname, library, library_str_flags) |
375 |
+ if elf_str_flags != library_str_flags: |
376 |
+ s = '%s\n\t%s\t%s ( %s )' % (s, soname, library, library_str_flags) |
377 |
+ count = count + 1 |
378 |
+ except KeyError: |
379 |
+ sonames_missing_library.append(soname) |
380 |
+ except pax.PaxError: |
381 |
+ sonames_without_flags.append(soname) |
382 |
+ |
383 |
+ if verbose: |
384 |
+ print('%s\n' % sv) |
385 |
+ if count == 0: |
386 |
+ print('\tNo mismatches\n\n') |
387 |
+ else: |
388 |
+ print('\tMismatches\n\n') |
389 |
+ else: |
390 |
+ if count != 0: |
391 |
+ print('%s\n\n' % s) |
392 |
+ |
393 |
+ if verbose: |
394 |
+ print_problems(elfs_without_flags, sonames_without_flags, sonames_missing_library) |
395 |
|
396 |
|
397 |
def run_reverse(verbose, executable_only): |
398 |
- ( object_linkings, soname2library ) = get_object_linkings() |
399 |
- object_reverse_linkings = get_object_reverse_linkings( object_linkings ) |
400 |
- print_object_reverse_linkings( object_reverse_linkings, soname2library, verbose, executable_only) |
401 |
- |
402 |
- |
403 |
+ (object_linkings, object_reverse_linkings, library2soname, soname2library) = LinkMap().get_maps() |
404 |
+ |
405 |
+ shell_path = path = os.getenv('PATH').split(':') |
406 |
+ |
407 |
+ elfs_without_flags = [] |
408 |
+ sonames_without_flags = [] |
409 |
+ sonames_missing_library = [] |
410 |
+ |
411 |
+ for abi in object_reverse_linkings: |
412 |
+ for soname in object_reverse_linkings[abi]: |
413 |
+ try: |
414 |
+ library = soname2library[(soname,abi)] |
415 |
+ (library_str_flags, library_bin_flags) = pax.getflags(library) |
416 |
+ sv = '%s\t%s :%s ( %s )' % (soname, library, abi, library_str_flags) |
417 |
+ s = sv |
418 |
+ except KeyError: |
419 |
+ sonames_missing_library.append(soname) |
420 |
+ except pax.PaxError: |
421 |
+ sonames_without_flags.append(soname) |
422 |
+ |
423 |
+ count = 0 |
424 |
+ for elf in object_reverse_linkings[abi][soname]: |
425 |
+ try: |
426 |
+ (elf_str_flags, elf_bin_flags) = pax.getflags(elf) |
427 |
+ if executable_only: |
428 |
+ if os.path.dirname(elf) in shell_path: |
429 |
+ sv = '%s\n\t%s ( %s )' % (sv, elf, elf_str_flags) |
430 |
+ if library_str_flags != elf_str_flags: |
431 |
+ s = '%s\n\t%s ( %s )' % (s, elf, elf_str_flags) |
432 |
+ count = count + 1 |
433 |
+ else: |
434 |
+ sv = '%s\n\t%s ( %s )' % (sv, elf, elf_str_flags) |
435 |
+ if library_str_flags != elf_str_flags: |
436 |
+ s = '%s\n\t%s ( %s )' % (s, elf, elf_str_flags) |
437 |
+ count = count + 1 |
438 |
+ except pax.PaxError: |
439 |
+ elfs_without_flags.append(elf) |
440 |
+ |
441 |
+ if verbose: |
442 |
+ print('%s\n' % sv) |
443 |
+ if count == 0: |
444 |
+ print('\tNo mismatches\n\n') |
445 |
+ else: |
446 |
+ print('\tMismatches\n\n') |
447 |
+ else: |
448 |
+ if count != 0: |
449 |
+ print('%s\n\n' % s) |
450 |
+ |
451 |
+ if verbose: |
452 |
+ print_problems( elfs_without_flags, sonames_without_flags, sonames_missing_library) |
453 |
|
454 |
|
455 |
def migrate_flags(importer, exporter_str_flags, exporter_bin_flags): |
456 |
- # We implement the following logic for setting the pax flags |
457 |
- # on the target elf object, the IMPORTER, given that the flags |
458 |
- # from the elf object we want it to match to, the EXPORTER. |
459 |
- # |
460 |
- # EXPORTER IMPORTER RESULT |
461 |
- # On On On |
462 |
- # On Off On + Warn |
463 |
- # On - On |
464 |
- # Off On On + Warn |
465 |
- # Off Off Off |
466 |
- # Off - Off |
467 |
- # - On On |
468 |
- # - Off Off |
469 |
- # - - - |
470 |
- |
471 |
- #See /usr/include/elf.h for these values |
472 |
- pf_flags = { |
473 |
- 'P':1<<4, 'p':1<<5, |
474 |
- 'S':1<<6, 's':1<<7, |
475 |
- 'M':1<<8, 'm':1<<9, |
476 |
- 'X':1<<10, 'x':1<<11, |
477 |
- 'E':1<<12, 'e':1<<13, |
478 |
- 'R':1<<14, 'r':1<<15 |
479 |
- } |
480 |
- |
481 |
- ( importer_str_flags, importer_bin_flags ) = pax.getflags(importer) |
482 |
- |
483 |
- # Start with the exporter's flags |
484 |
- result_bin_flags = exporter_bin_flags |
485 |
- |
486 |
- for i in range(len(importer_str_flags)): |
487 |
- |
488 |
- # The exporter's flag contradicts the importer's flag, so do nothing |
489 |
- if (exporter_str_flags[i].isupper() and importer_str_flags[i].islower()) or \ |
490 |
- (exporter_str_flags[i].islower() and importer_str_flags[i].isupper()): |
491 |
- |
492 |
- # Revert the exporter's flag, use the importer's flag and warn |
493 |
- result_bin_flags = result_bin_flags ^ pf_flags[exporter_str_flags[i]] |
494 |
- result_bin_flags = result_bin_flags | pf_flags[importer_str_flags[i]] |
495 |
- print('\t\tWarning: %s has %s, refusing to set to %s' % ( |
496 |
- importer, importer_str_flags[i], exporter_str_flags[i] )), |
497 |
- |
498 |
- # The exporter's flags is off, so use the importer's flag |
499 |
- if (exporter_str_flags[i] == '-' and importer_str_flags[i] != '-'): |
500 |
- result_bin_flags = result_bin_flags | pf_flags[importer_str_flags[i]] |
501 |
- |
502 |
- pax.setbinflags(importer, result_bin_flags) |
503 |
+ # We implement the following logic for setting the pax flags |
504 |
+ # on the target elf object, the IMPORTER, given that the flags |
505 |
+ # from the elf object we want it to match to, the EXPORTER. |
506 |
+ # |
507 |
+ # EXPORTER IMPORTER RESULT |
508 |
+ # On On On |
509 |
+ # On Off On + Warn |
510 |
+ # On - On |
511 |
+ # Off On On + Warn |
512 |
+ # Off Off Off |
513 |
+ # Off - Off |
514 |
+ # - On On |
515 |
+ # - Off Off |
516 |
+ # - - - |
517 |
+ |
518 |
+ #See /usr/include/elf.h for these values |
519 |
+ pf_flags = { |
520 |
+ 'P':1<<4, 'p':1<<5, |
521 |
+ 'S':1<<6, 's':1<<7, |
522 |
+ 'M':1<<8, 'm':1<<9, |
523 |
+ 'X':1<<10, 'x':1<<11, |
524 |
+ 'E':1<<12, 'e':1<<13, |
525 |
+ 'R':1<<14, 'r':1<<15 |
526 |
+ } |
527 |
+ |
528 |
+ (importer_str_flags, importer_bin_flags) = pax.getflags(importer) |
529 |
+ |
530 |
+ # Start with the exporter's flags |
531 |
+ result_bin_flags = exporter_bin_flags |
532 |
+ |
533 |
+ for i in range(len(importer_str_flags)): |
534 |
+ |
535 |
+ # The exporter's flag contradicts the importer's flag, so do nothing |
536 |
+ if (exporter_str_flags[i].isupper() and importer_str_flags[i].islower()) or \ |
537 |
+ (exporter_str_flags[i].islower() and importer_str_flags[i].isupper()): |
538 |
+ |
539 |
+ # Revert the exporter's flag, use the importer's flag and warn |
540 |
+ result_bin_flags = result_bin_flags ^ pf_flags[exporter_str_flags[i]] |
541 |
+ result_bin_flags = result_bin_flags | pf_flags[importer_str_flags[i]] |
542 |
+ print('\t\tWarning: %s has %s, refusing to set to %s' % ( |
543 |
+ importer, importer_str_flags[i], exporter_str_flags[i] )), |
544 |
+ |
545 |
+ # The exporter's flags is off, so use the importer's flag |
546 |
+ if (exporter_str_flags[i] == '-' and importer_str_flags[i] != '-'): |
547 |
+ result_bin_flags = result_bin_flags | pf_flags[importer_str_flags[i]] |
548 |
+ |
549 |
+ pax.setbinflags(importer, result_bin_flags) |
550 |
|
551 |
|
552 |
def run_elf(elf, verbose, mark, allyes): |
553 |
+ if not os.path.exists(elf): |
554 |
+ print('%s\tNo such OBJECT' % elf) |
555 |
+ return |
556 |
+ |
557 |
+ try: |
558 |
+ (elf_str_flags, elf_bin_flags) = pax.getflags(elf) |
559 |
+ print('%s (%s)\n' % (elf, elf_str_flags)) |
560 |
+ except pax.PaxError: |
561 |
+ print('%s: No PAX flags found\n' % elf) |
562 |
+ return |
563 |
+ |
564 |
+ (object_linkings, object_reverse_linkings, library2soname, soname2library) = LinkMap().get_maps() |
565 |
+ |
566 |
+ mismatched_libraries = [] |
567 |
+ |
568 |
+ for abi in object_linkings: |
569 |
+ if not elf in object_linkings[abi]: # There may be no elf for that abi |
570 |
+ continue |
571 |
+ for soname in object_linkings[abi][elf]: |
572 |
+ try: |
573 |
+ library = soname2library[(soname,abi)] |
574 |
+ (library_str_flags, library_bin_flags) = pax.getflags(library) |
575 |
+ if verbose: |
576 |
+ print('\t%s\t%s :%s ( %s )' % (soname, library, abi, library_str_flags)) |
577 |
+ if elf_str_flags != library_str_flags: |
578 |
+ mismatched_libraries.append(library) |
579 |
+ if not verbose: |
580 |
+ print('\t%s\t%s :%s ( %s )' % (soname, library, abi, library_str_flags)) |
581 |
+ except pax.PaxError: |
582 |
+ print('%s :%s: file for soname not found' % (soname,abi)) |
583 |
+ |
584 |
+ if len(mismatched_libraries) == 0: |
585 |
+ if not verbose: |
586 |
+ print('\tNo mismatches\n') |
587 |
+ else: |
588 |
+ print('\n'), |
589 |
+ if mark: |
590 |
+ print('\tWill mark libraries with %s\n' % elf_str_flags) |
591 |
+ for library in mismatched_libraries: |
592 |
+ do_marking = False |
593 |
+ while True: |
594 |
+ if allyes: |
595 |
+ ans = 'y' |
596 |
+ else: |
597 |
+ ans = get_input('\tSet flags for %s :%s (y/n): ' % (library,abi)) |
598 |
+ if ans == 'y': |
599 |
+ do_marking = True |
600 |
+ break |
601 |
+ elif ans == 'n': |
602 |
+ do_marking = False |
603 |
+ break |
604 |
+ else: |
605 |
+ print('\t\tPlease enter y or n') |
606 |
+ |
607 |
+ if do_marking: |
608 |
+ try: |
609 |
+ migrate_flags(library, elf_str_flags, elf_bin_flags) |
610 |
+ except pax.PaxError: |
611 |
+ print('\n\tCould not set PAX flags on %s, text maybe busy' % (library,abi)) |
612 |
+ |
613 |
+ try: |
614 |
+ (library_str_flags, library_bin_flags) = pax.getflags(library) |
615 |
+ print('\n\t\t%s ( %s )\n' % (library, library_str_flags)) |
616 |
+ except pax.PaxError: |
617 |
+ print('\n\t\t%s: Could not read PAX flags') |
618 |
|
619 |
- if not os.path.exists(elf): |
620 |
- print('%s\tNo such OBJECT' % elf) |
621 |
- return |
622 |
- |
623 |
- try: |
624 |
- (elf_str_flags, elf_bin_flags) = pax.getflags(elf) |
625 |
- print('%s (%s)\n' % (elf, elf_str_flags)) |
626 |
- except pax.PaxError: |
627 |
- print('%s: No PAX flags found\n' % elf) |
628 |
- return |
629 |
- |
630 |
- (object_linkings, soname2library) = get_object_linkings() |
631 |
- |
632 |
- mismatched_libraries = [] |
633 |
- |
634 |
- for soname in object_linkings[elf]: |
635 |
- try: |
636 |
- library = soname2library[soname] |
637 |
- ( library_str_flags, library_bin_flags ) = pax.getflags(library) |
638 |
- if verbose: |
639 |
- print('\t%s\t%s ( %s )' % ( soname, library, library_str_flags )) |
640 |
- if elf_str_flags != library_str_flags: |
641 |
- mismatched_libraries.append(library) |
642 |
- if not verbose: |
643 |
- print('\t%s\t%s ( %s )' % ( soname, library, library_str_flags )) |
644 |
- except pax.PaxError: |
645 |
- print('%s: file for soname not found' % soname) |
646 |
- |
647 |
- if len(mismatched_libraries) == 0: |
648 |
- if not verbose: |
649 |
- print('\tNo mismatches\n') |
650 |
- else: |
651 |
- print('\n'), |
652 |
- if mark: |
653 |
- print('\tWill mark libraries with %s\n' % elf_str_flags) |
654 |
- for library in mismatched_libraries: |
655 |
- do_marking = False |
656 |
- while True: |
657 |
- if allyes: |
658 |
- ans = 'y' |
659 |
- else: |
660 |
- ans = get_input('\tSet flags for %s (y/n): ' % library) |
661 |
- if ans == 'y': |
662 |
- do_marking = True |
663 |
- break |
664 |
- elif ans == 'n': |
665 |
- do_marking = False |
666 |
- break |
667 |
- else: |
668 |
- print('\t\tPlease enter y or n') |
669 |
- |
670 |
- if do_marking: |
671 |
- try: |
672 |
- migrate_flags(library, elf_str_flags, elf_bin_flags) |
673 |
- except pax.PaxError: |
674 |
- print('\n\tCould not set PAX flags on %s, text maybe busy' % library) |
675 |
- |
676 |
- try: |
677 |
- ( library_str_flags, library_bin_flags ) = pax.getflags(library) |
678 |
- print('\n\t\t%s ( %s )\n' % ( library, library_str_flags )) |
679 |
- except pax.PaxError: |
680 |
- print('\n\t\t%s: Could not read PAX flags') |
681 |
- |
682 |
- |
683 |
-def invert_so2library_mappings( so2library_mappings ): |
684 |
- library2soname_mappings = {} |
685 |
- for soname, library in so2library_mappings.items(): |
686 |
- library2soname_mappings[library] = soname |
687 |
- return library2soname_mappings |
688 |
- |
689 |
-#XXXXXXXXXXXXXXXXX |
690 |
|
691 |
def run_soname(name, verbose, use_soname, mark, allyes, executable_only): |
692 |
- shell_path = path = os.getenv('PATH').split(':') |
693 |
- |
694 |
- ( forward_linkings, so2library_mappings ) = get_object_linkings() |
695 |
- reverse_linkings = invert_linkings( forward_linkings ) |
696 |
- |
697 |
- if use_soname: |
698 |
- soname = name |
699 |
- else: |
700 |
- library2soname_mappings = invert_so2library_mappings(so2library_mappings) |
701 |
- try: |
702 |
- soname = library2soname_mappings[name] |
703 |
- except KeyError: |
704 |
- print('%s\tNo such LIBRARY' % name) |
705 |
- return |
706 |
- |
707 |
- try: |
708 |
- linkings = reverse_linkings[soname] |
709 |
- except KeyError: |
710 |
- print('%s\tNo such SONAME' % soname) |
711 |
- return |
712 |
- |
713 |
- library = so2library_mappings[soname] |
714 |
- |
715 |
- ( library_str_flags, library_bin_flags ) = pax.getflags(library) |
716 |
- print('%s\t%s (%s)\n' % ( soname, library, library_str_flags )) |
717 |
- |
718 |
- mismatched_binaries = [] |
719 |
- for binary in linkings: |
720 |
- try: |
721 |
- ( binary_str_flags, binary_bin_flags ) = pax.getflags(binary) |
722 |
- if verbose: |
723 |
- if executable_only: |
724 |
- if os.path.dirname(binary) in shell_path: |
725 |
- print('\t%s ( %s )' % ( binary, binary_str_flags )) |
726 |
- else: |
727 |
- print('\t%s ( %s )' % ( binary, binary_str_flags )) |
728 |
- if library_str_flags != binary_str_flags: |
729 |
- if executable_only: |
730 |
- if os.path.dirname(binary) in shell_path: |
731 |
- mismatched_binaries.append(binary) |
732 |
- if not verbose: |
733 |
- print('\t%s ( %s )' % ( binary, binary_str_flags )) |
734 |
- else: |
735 |
- mismatched_binaries.append(binary) |
736 |
- if not verbose: |
737 |
- print('\t%s ( %s )' % ( binary, binary_str_flags )) |
738 |
- except pax.PaxError: |
739 |
- print('cannot obtain pax flags for %s' % binary) |
740 |
- |
741 |
- if len(mismatched_binaries) == 0: |
742 |
- if not verbose: |
743 |
- print('\tNo mismatches\n') |
744 |
- else: |
745 |
- print('\n'), |
746 |
- if mark: |
747 |
- print('\tWill mark binaries with %s\n' % library_str_flags) |
748 |
- for binary in mismatched_binaries: |
749 |
- if executable_only: |
750 |
- if not os.path.dirname(binary) in shell_path: |
751 |
- continue |
752 |
- do_marking = False |
753 |
- while True: |
754 |
- if allyes: |
755 |
- ans = 'y' |
756 |
- else: |
757 |
- ans = get_input('\tSet flags for %s (y/n): ' % binary) |
758 |
- if ans == 'y': |
759 |
- do_marking = True |
760 |
- break |
761 |
- elif ans == 'n': |
762 |
- do_marking = False |
763 |
- break |
764 |
- else: |
765 |
- print('\t\tPlease enter y or n') |
766 |
- if do_marking: |
767 |
- try: |
768 |
- migrate_flags(binary, library_str_flags, library_bin_flags) |
769 |
- except pax.PaxError: |
770 |
- print('\n\tCould not set pax flags on %s, file is probably busy' % binary) |
771 |
- print('\tShut down all processes that use it and try again') |
772 |
- ( binary_str_flags, binary_bin_flags ) = pax.getflags(binary) |
773 |
- print('\n\t\t%s ( %s )\n' % ( binary, binary_str_flags )) |
774 |
+ shell_path = path = os.getenv('PATH').split(':') |
775 |
+ |
776 |
+ (object_linkings, object_reverse_linkings, library2soname, soname2library) = LinkMap().get_maps() |
777 |
+ |
778 |
+ if use_soname: |
779 |
+ soname = name |
780 |
+ abi_list = object_reverse_linkings.keys() |
781 |
+ for abi in abi_list: |
782 |
+ # There must be at least on abi with that soname |
783 |
+ if soname in object_reverse_linkings[abi]: |
784 |
+ break |
785 |
+ else: |
786 |
+ print('%s\tNo such SONAME' % soname) |
787 |
+ return |
788 |
+ else: |
789 |
+ try: |
790 |
+ (soname, abi) = library2soname[name] |
791 |
+ abi_list = [abi] |
792 |
+ except KeyError: |
793 |
+ print('%s\tNo such LIBRARY' % name) |
794 |
+ return |
795 |
+ |
796 |
+ |
797 |
+ mismatched_elfs = [] |
798 |
+ |
799 |
+ for abi in abi_list: |
800 |
+ # An soname can belong to one or more abis |
801 |
+ if not soname in object_reverse_linkings[abi]: |
802 |
+ continue |
803 |
+ |
804 |
+ library = soname2library[(soname,abi)] |
805 |
+ (library_str_flags, library_bin_flags) = pax.getflags(library) |
806 |
+ print('%s\t%s :%s (%s)\n' % (soname, library, ", ".join(abi_list), library_str_flags)) |
807 |
+ |
808 |
+ for elf in object_reverse_linkings[abi][soname]: |
809 |
+ try: |
810 |
+ (elf_str_flags, elf_bin_flags ) = pax.getflags(elf) |
811 |
+ if verbose: |
812 |
+ if executable_only: |
813 |
+ if os.path.dirname(elf) in shell_path: |
814 |
+ print('\t%s ( %s )' % (elf, elf_str_flags )) |
815 |
+ else: |
816 |
+ print('\t%s ( %s )' % ( elf, elf_str_flags )) |
817 |
+ if library_str_flags != elf_str_flags: |
818 |
+ if executable_only: |
819 |
+ if os.path.dirname(elf) in shell_path: |
820 |
+ mismatched_elfs.append(elf) |
821 |
+ if not verbose: |
822 |
+ print('\t%s ( %s )' % (elf, elf_str_flags )) |
823 |
+ else: |
824 |
+ mismatched_elfs.append(elf) |
825 |
+ if not verbose: |
826 |
+ print('\t%s ( %s )' % (elf, elf_str_flags )) |
827 |
+ except pax.PaxError: |
828 |
+ # If you can't get the pax flags, then its automatically mismatched |
829 |
+ if executable_only: |
830 |
+ if os.path.dirname(elf) in shell_path: |
831 |
+ mismatched_elfs.append(elf) |
832 |
+ if not verbose: |
833 |
+ print('\t%s ( %s )' % (elf, '****' )) |
834 |
+ else: |
835 |
+ mismatched_elfs.append(elf) |
836 |
+ if not verbose: |
837 |
+ print('\t%s ( %s )' % (elf, '****' )) |
838 |
+ |
839 |
+ if len(mismatched_elfs) == 0: |
840 |
+ if not verbose: |
841 |
+ print('\tNo mismatches\n') |
842 |
+ else: |
843 |
+ print('\n'), |
844 |
+ if mark: |
845 |
+ print('\tWill mark elf with %s\n' % library_str_flags) |
846 |
+ for elf in mismatched_elfs: |
847 |
+ if executable_only: |
848 |
+ if not os.path.dirname(elf) in shell_path: |
849 |
+ continue |
850 |
+ do_marking = False |
851 |
+ while True: |
852 |
+ if allyes: |
853 |
+ ans = 'y' |
854 |
+ else: |
855 |
+ ans = get_input('\tSet flags for %s (y/n): ' % elf) |
856 |
+ if ans == 'y': |
857 |
+ do_marking = True |
858 |
+ break |
859 |
+ elif ans == 'n': |
860 |
+ do_marking = False |
861 |
+ break |
862 |
+ else: |
863 |
+ print('\t\tPlease enter y or n') |
864 |
+ if do_marking: |
865 |
+ try: |
866 |
+ migrate_flags(elf, library_str_flags, library_bin_flags) |
867 |
+ except pax.PaxError: |
868 |
+ print('\n\tCould not set pax flags on %s, file is probably busy' % elf) |
869 |
+ print('\tShut down all processes that use it and try again') |
870 |
+ (elf_str_flags, elf_bin_flags) = pax.getflags(elf) |
871 |
+ print('\n\t\t%s ( %s )\n' % (elf, elf_str_flags )) |
872 |
|
873 |
|
874 |
def run_usage(): |
875 |
- print('Package Name : elfix') |
876 |
- print('Bug Reports : http://bugs.gentoo.org/') |
877 |
- print('Program Name : revdep-pax') |
878 |
- print('Description : Get or set pax flags on an ELF object') |
879 |
- print('') |
880 |
- print('Usage : revdep-pax -f [-v] print out all forward mappings for all system binaries') |
881 |
- print(' : revdep-pax -r [-ve] print out all reverse mappings for all system sonames') |
882 |
- print(' : revdep-pax -b OBJECT [-myv] print all forward mappings only for OBJECT') |
883 |
- print(' : revdep-pax -s SONAME [-myve] print all reverse mappings only for SONAME') |
884 |
- print(' : revdep-pax -l LIBRARY [-myve] print all reverse mappings only for LIBRARY file') |
885 |
- print(' : revdep-pax [-h] print out this help') |
886 |
- print(' : -v verbose, otherwise just print mismatching objects') |
887 |
- print(' : -e only print out executables in shell $PATH') |
888 |
- print(' : -m don\'t just report, but mark the mismatching objects') |
889 |
- print(' : -y assume "yes" to all prompts for marking (USE CAREFULLY!)') |
890 |
- print('') |
891 |
+ print('Package Name : elfix') |
892 |
+ print('Bug Reports : http://bugs.gentoo.org/') |
893 |
+ print('Program Name : revdep-pax') |
894 |
+ print('Description : Get or set pax flags on an ELF object') |
895 |
+ print('') |
896 |
+ print('Usage : revdep-pax -f [-v] print out all forward mappings for all system ELF objects') |
897 |
+ print(' : revdep-pax -r [-ve] print out all reverse mappings for all system sonames') |
898 |
+ print(' : revdep-pax -b OBJECT [-myv] print all forward mappings only for OBJECT') |
899 |
+ print(' : revdep-pax -s SONAME [-myve] print all reverse mappings only for SONAME') |
900 |
+ print(' : revdep-pax -l LIBRARY [-myve] print all reverse mappings only for LIBRARY file') |
901 |
+ print(' : revdep-pax [-h] print out this help') |
902 |
+ print(' : -v verbose, otherwise just print mismatching objects') |
903 |
+ print(' : -e only print out executables in shell $PATH') |
904 |
+ print(' : -m don\'t just report, but mark the mismatching objects') |
905 |
+ print(' : -y assume "yes" to all prompts for marking (USE CAREFULLY!)') |
906 |
+ print('') |
907 |
|
908 |
|
909 |
def main(): |
910 |
- # Are we root? |
911 |
- uid = os.getuid() |
912 |
- if uid != 0: |
913 |
- print('This program must be run as root') |
914 |
- sys.exit(1) |
915 |
- |
916 |
- try: |
917 |
- opts, args = getopt.getopt(sys.argv[1:], 'hfrb:s:l:vemy') |
918 |
- except getopt.GetoptError as err: |
919 |
- print(str(err)) # will print something like 'option -a not recognized' |
920 |
- run_usage() |
921 |
- sys.exit(1) |
922 |
- |
923 |
- if len(opts) == 0: |
924 |
- run_usage() |
925 |
- sys.exit(1) |
926 |
- |
927 |
- do_usage = False |
928 |
- do_forward = False |
929 |
- do_reverse = False |
930 |
- |
931 |
- elf = None |
932 |
- soname = None |
933 |
- library = None |
934 |
- |
935 |
- verbose = False |
936 |
- executable_only = False |
937 |
- mark = False |
938 |
- allyes = False |
939 |
- |
940 |
- opt_count = 0 |
941 |
- |
942 |
- for o, a in opts: |
943 |
- if o == '-h': |
944 |
- do_usage = True |
945 |
- opt_count += 1 |
946 |
- elif o == '-f': |
947 |
- do_forward = True |
948 |
- opt_count += 1 |
949 |
- elif o == '-r': |
950 |
- do_reverse = True |
951 |
- opt_count += 1 |
952 |
- elif o == '-b': |
953 |
- elf = a |
954 |
- opt_count += 1 |
955 |
- elif o == '-s': |
956 |
- soname = a |
957 |
- opt_count += 1 |
958 |
- elif o == '-l': |
959 |
- library = a |
960 |
- opt_count += 1 |
961 |
- elif o == '-v': |
962 |
- verbose = True |
963 |
- elif o == '-e': |
964 |
- executable_only = True |
965 |
- elif o == '-m': |
966 |
- mark = True |
967 |
- elif o == '-y': |
968 |
- allyes = True |
969 |
- else: |
970 |
- print('Option included in getopt but not handled here!') |
971 |
- print('Please file a bug') |
972 |
- sys.exit(1) |
973 |
- |
974 |
- # Only allow one of -h, -f -r -b -s |
975 |
- if opt_count > 1 or do_usage: |
976 |
- run_usage() |
977 |
- elif do_forward: |
978 |
- run_forward(verbose) |
979 |
- elif do_reverse: |
980 |
- run_reverse(verbose, executable_only) |
981 |
- elif elf != None: |
982 |
- run_elf(elf, verbose, mark, allyes) |
983 |
- elif soname != None: |
984 |
- run_soname(soname, verbose, True, mark, allyes, executable_only) |
985 |
- elif library != None: |
986 |
- library = os.path.realpath(library) |
987 |
- run_soname(library, verbose, False, mark, allyes, executable_only) |
988 |
+ # Are we root? |
989 |
+ uid = os.getuid() |
990 |
+ if uid != 0: |
991 |
+ print('This program must be run as root') |
992 |
+ sys.exit(1) |
993 |
+ |
994 |
+ try: |
995 |
+ opts, args = getopt.getopt(sys.argv[1:], 'hfrb:s:l:vemy') |
996 |
+ except getopt.GetoptError as err: |
997 |
+ print(str(err)) # will print something like 'option -a not recognized' |
998 |
+ run_usage() |
999 |
+ sys.exit(1) |
1000 |
+ |
1001 |
+ if len(opts) == 0: |
1002 |
+ run_usage() |
1003 |
+ sys.exit(1) |
1004 |
+ |
1005 |
+ do_usage = False |
1006 |
+ do_forward = False |
1007 |
+ do_reverse = False |
1008 |
+ |
1009 |
+ elf = None |
1010 |
+ soname = None |
1011 |
+ library = None |
1012 |
+ |
1013 |
+ verbose = False |
1014 |
+ executable_only = False |
1015 |
+ mark = False |
1016 |
+ allyes = False |
1017 |
+ |
1018 |
+ opt_count = 0 |
1019 |
+ |
1020 |
+ for o, a in opts: |
1021 |
+ if o == '-h': |
1022 |
+ do_usage = True |
1023 |
+ opt_count += 1 |
1024 |
+ elif o == '-f': |
1025 |
+ do_forward = True |
1026 |
+ opt_count += 1 |
1027 |
+ elif o == '-r': |
1028 |
+ do_reverse = True |
1029 |
+ opt_count += 1 |
1030 |
+ elif o == '-b': |
1031 |
+ elf = a |
1032 |
+ opt_count += 1 |
1033 |
+ elif o == '-s': |
1034 |
+ soname = a |
1035 |
+ opt_count += 1 |
1036 |
+ elif o == '-l': |
1037 |
+ library = a |
1038 |
+ opt_count += 1 |
1039 |
+ elif o == '-v': |
1040 |
+ verbose = True |
1041 |
+ elif o == '-e': |
1042 |
+ executable_only = True |
1043 |
+ elif o == '-m': |
1044 |
+ mark = True |
1045 |
+ elif o == '-y': |
1046 |
+ allyes = True |
1047 |
+ else: |
1048 |
+ print('Option included in getopt but not handled here!') |
1049 |
+ print('Please file a bug') |
1050 |
+ sys.exit(1) |
1051 |
+ |
1052 |
+ # Only allow one of -h, -f -r -b -s |
1053 |
+ if opt_count > 1 or do_usage: |
1054 |
+ run_usage() |
1055 |
+ elif do_forward: |
1056 |
+ run_forward(verbose) |
1057 |
+ elif do_reverse: |
1058 |
+ run_reverse(verbose, executable_only) |
1059 |
+ elif elf != None: |
1060 |
+ run_elf(elf, verbose, mark, allyes) |
1061 |
+ elif soname != None: |
1062 |
+ run_soname(soname, verbose, True, mark, allyes, executable_only) |
1063 |
+ elif library != None: |
1064 |
+ library = os.path.realpath(library) |
1065 |
+ run_soname(library, verbose, False, mark, allyes, executable_only) |
1066 |
|
1067 |
|
1068 |
if __name__ == '__main__': |
1069 |
- main() |
1070 |
+ main() |