Gentoo Archives: gentoo-commits

From: "Anthony G. Basile" <blueness@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/elfix:master commit in: /, misc/
Date: Thu, 27 Dec 2012 01:59:16
Message-Id: 1356573520.df5b88d8407030f394b8d505988a7f6bb4be723e.blueness@gentoo
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()