aboutsummaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorLibravatar KOLANICH <KOLANICH@users.noreply.github.com>2020-02-07 22:06:34 +0000
committerLibravatar GitHub <noreply@github.com>2020-02-07 22:06:34 +0000
commit91cefc6a469652af4c110a8fa3f258d775969fc8 (patch)
treea401cf70b7a58898485897796a9cfb212445db2f /contrib
parentFixing the bug in 189772034b211578aca59540d7277f45da4f45d2 breaking meld (diff)
downloadfirejail-91cefc6a469652af4c110a8fa3f258d775969fc8.tar.gz
firejail-91cefc6a469652af4c110a8fa3f258d775969fc8.tar.zst
firejail-91cefc6a469652af4c110a8fa3f258d775969fc8.zip
Fixed formatting (autopep8 + black + manual postprocessing). (#3208)
Added typing. Replaced os.path with pathlib. Made it work. Fixes in .gitignore.
Diffstat (limited to 'contrib')
-rwxr-xr-xcontrib/fix_private-bin.py164
1 files changed, 95 insertions, 69 deletions
diff --git a/contrib/fix_private-bin.py b/contrib/fix_private-bin.py
index c6c6f908d..668d68ff2 100755
--- a/contrib/fix_private-bin.py
+++ b/contrib/fix_private-bin.py
@@ -1,5 +1,4 @@
1#!/usr/bin/python3 1#!/usr/bin/python3
2
3__author__ = "KOLANICH" 2__author__ = "KOLANICH"
4__copyright__ = """This is free and unencumbered software released into the public domain. 3__copyright__ = """This is free and unencumbered software released into the public domain.
5 4
@@ -27,122 +26,149 @@ OTHER DEALINGS IN THE SOFTWARE.
27For more information, please refer to <https://unlicense.org/>""" 26For more information, please refer to <https://unlicense.org/>"""
28__license__ = "Unlicense" 27__license__ = "Unlicense"
29 28
30import sys, os, glob, re 29import typing
30import sys, os, re
31from collections import OrderedDict
32from pathlib import Path
33from shutil import which
31 34
32privRx = re.compile("^(?:#\s*)?private-bin") 35privRx = re.compile(r"^(#\s*)?(private-bin)(\s+)(.+)$")
33 36
34 37
35def fixSymlinkedBins(files, replMap): 38def fixSymlinkedBins(files: typing.List[Path], replMap: typing.Dict[str, str]) -> None:
39 """
40 Used to add filenames to private-bin directives of files if the ones present are mentioned in replMap
41 replMap is a dict where key is the marker filename and value is the filename to add
36 """ 42 """
37 Used to add filenames to private-bin directives of files if the ones present are mentioned in replMap
38 replMap is a dict where key is the marker filename and value is the filename to add
39 """
40
41 rxs = dict()
42 for (old, new) in replMap.items():
43 rxs[old] = re.compile("\\b" + old + "\\b")
44 rxs[new] = re.compile("\\b" + new + "\\b")
45 #print(rxs)
46 43
47 for filename in files: 44 for filename in files:
48 lines = None 45 lines = filename.read_text(encoding="utf-8").split("\n")
49 with open(filename, "r") as file:
50 lines = file.readlines()
51 46
52 shouldUpdate = False 47 shouldUpdate = False
53 for (i, line) in enumerate(lines): 48 for (i, line) in enumerate(lines):
54 if privRx.search(line): 49 m = privRx.match(line)
50 if m:
51 lineUpdated = False
52 mBins = OrderedDict((sb, sb) for sb in (b.strip() for b in m.group(4).split(",")))
53
55 for (old, new) in replMap.items(): 54 for (old, new) in replMap.items():
56 if rxs[old].search(line) and not rxs[new].search(line): 55 if old in mBins:
57 lines[i] = rxs[old].sub(old + "," + new, line) 56 #print(old, "->", new)
58 shouldUpdate = True 57 if new not in mBins:
59 print(lines[i]) 58 mBins[old] = old + "," + new
59 lineUpdated = True
60
61 if lineUpdated:
62 comment = m.group(1)
63 if comment is None:
64 comment = ""
65 lines[i] = comment + m.group(2) + m.group(3) + ",".join(mBins.values())
66 shouldUpdate = True
60 67
61 if shouldUpdate: 68 if shouldUpdate:
62 with open(filename, "w") as file: 69 filename.write_text("\n".join(lines), encoding="utf-8")
63 file.writelines(lines)
64 70
65 71
66def createSetOfBinaries(files): 72def createSetOfBinaries(files: typing.List[Path]) -> typing.Set[str]:
73 """
74 Creates a set of binaries mentioned in private-bin directives of files.
67 """ 75 """
68 Creates a set of binaries mentioned in private-bin directives of files.
69 """
70 s = set() 76 s = set()
71 for filename in files: 77 for filename in files:
72 with open(filename, "r") as file: 78 with open(filename, "r") as file:
73 for line in file: 79 for line in file:
74 if privRx.search(line): 80 m = privRx.match(line)
75 bins = line.split(",") 81 if m:
76 bins[0] = bins[0].split(" ")[-1] 82 bins = m.group(4).split(",")
77 bins = [n.strip() for n in bins] 83 bins = [n.strip() for n in bins]
78 s = s | set(bins) 84 s = s | set(bins)
79 return s 85 return s
80 86
87def getExecutableNameFromLink(p: Path) -> str:
88 return os.readlink(str(p)).split(" ")[0]
89
90
91forbiddenExecutables= ["firejail"]
92
93def populateForbiddenExecutables():
94 forbiddenSymlinks = []
95 for e in forbiddenExecutables:
96 r = which(e)
97 if r is not None:
98 yield r
99
100forbiddenSymlinks = set(populateForbiddenExecutables())
81 101
82def createSymlinkTable(binDirs, binariesSet): 102
103def createSymlinkTable(binDirs: typing.Iterable[Path], binariesSet: typing.Set[str]) -> typing.Mapping[str, str]:
104 """
105 creates a dict of symlinked binaries in the system where a key is a symlink name and value is a symlinked binary.
106 binDirs are folders to look into for binaries symlinks
107 binariesSet is a set of binaries to be checked if they are actually a symlinks
83 """ 108 """
84 creates a dict of symlinked binaries in the system where a key is a symlink name and value is a symlinked binary.
85 binDirs are folders to look into for binaries symlinks
86 binariesSet is a set of binaries to be checked if they are actually a symlinks
87 """
88 m = dict() 109 m = dict()
89 toProcess = binariesSet 110 toProcess = binariesSet
90 while len(toProcess) != 0: 111 while len(toProcess) != 0:
91 additional = set() 112 additional = set()
92 for sh in toProcess: 113 for binName in toProcess:
93 for bD in binDirs: 114 for binaryDir in binDirs:
94 p = bD + os.path.sep + sh 115 p = binaryDir / binName
95 if os.path.exists(p): 116 if p.is_symlink():
96 if os.path.islink(p): 117 res = []
97 m[sh] = os.readlink(p) 118 nm = getExecutableNameFromLink(p)
98 additional.add(m[sh].split(" ")[0]) 119 if nm in forbiddenSymlinks:
99 else: 120 continue
100 pass 121 m[binName] = nm
122 additional.add(nm)
101 break 123 break
124
102 toProcess = additional 125 toProcess = additional
103 return m 126 return m
104 127
105 128
106def doTheFixes(profilesPath, binDirs): 129def doTheFixes(profilesPath: Path, binDirs: typing.Iterable[Path]) -> None:
107 """ 130 """
108 Fixes private-bin in .profiles for firejail. The pipeline is as follows: 131 Fixes private-bin in .profiles for firejail. The pipeline is as follows:
109 discover files -> discover mentioned binaries -> 132 discover files -> discover mentioned binaries ->
110 discover the ones which are symlinks -> 133 discover the ones which are symlinks ->
111 make a look-up table for fix -> 134 make a look-up table for fix ->
112 filter the ones can be fixed (we cannot fix the ones which are not in directories for binaries) -> 135 filter the ones can be fixed (we cannot fix the ones which are not in directories for binaries) ->
113 apply fix 136 apply fix
114 """ 137 """
115 files = glob.glob(profilesPath + os.path.sep + "*.profile") 138 files = list(profilesPath.glob("**/*.profile"))
116 bins = createSetOfBinaries(files) 139 bins = createSetOfBinaries(files)
117 #print("The binaries used are:") 140 #print("The binaries used are:")
118 #print(bins) 141 #print(bins)
119 stbl = createSymlinkTable(binDirs, bins) 142 stbl = createSymlinkTable(binDirs, bins)
120 print("The replacement table is:") 143 print("The replacement table is:")
121 print(stbl) 144 print(stbl)
122 stbl = { 145 for k, v in tuple(stbl.items()):
123 a[0]: a[1] 146 if k.find(os.path.sep) < 0 and v.find(os.path.sep) < 0:
124 for a in stbl.items() 147 pass
125 if a[0].find(os.path.sep) < 0 and a[1].find(os.path.sep) < 0 148 else:
126 } 149 del stbl[k]
150
127 print("Filtered replacement table is:") 151 print("Filtered replacement table is:")
128 print(stbl) 152 print(stbl)
129 fixSymlinkedBins(files, stbl) 153 fixSymlinkedBins(files, stbl)
130 154
131 155
156thisDir = Path(__file__).absolute().parent
157defaultProfilesPath = (thisDir.parent / "etc")
158
159
132def printHelp(): 160def printHelp():
133 print("python3 " + os.path.basename(__file__) + 161 print("python3 " + str(thisDir) +
134 " <dir with .profile files>\nThe default dir is " + 162 " <dir with .profile files>\nThe default dir is " +
135 defaultProfilesPath + "\n" + doTheFixes.__doc__) 163 str(defaultProfilesPath) + "\n" + doTheFixes.__doc__)
136 164
137 165
138def main(): 166def main() -> None:
139 """The main function. Parses the commandline args, shows messages and calles the function actually doing the work.""" 167 """The main function. Parses the commandline args, shows messages and calles the function actually doing the work."""
140 print(repr(sys.argv))
141 defaultProfilesPath = "../etc"
142 if len(sys.argv) > 2 or (len(sys.argv) == 2 and 168 if len(sys.argv) > 2 or (len(sys.argv) == 2 and
143 (sys.argv[1] == '-h' or sys.argv[1] == '--help')): 169 (sys.argv[1] == "-h" or sys.argv[1] == "--help")):
144 printHelp() 170 printHelp()
145 exit(1) 171 sys.exit(1)
146 172
147 profilesPath = None 173 profilesPath = None
148 if len(sys.argv) == 2: 174 if len(sys.argv) == 2:
@@ -154,14 +180,14 @@ def main():
154 else: 180 else:
155 print(sys.argv[1] + " does not exist") 181 print(sys.argv[1] + " does not exist")
156 printHelp() 182 printHelp()
157 exit(1) 183 sys.exit(1)
158 else: 184 else:
159 print("Using default profiles dir: " + defaultProfilesPath) 185 print("Using default profiles dir: ", defaultProfilesPath)
160 profilesPath = defaultProfilesPath 186 profilesPath = defaultProfilesPath
161 187
162 binDirs = [ 188 binDirs = ("/bin", "/usr/bin", "/usr/bin", "/usr/sbin", "/usr/local/bin", "/usr/local/sbin")
163 "/bin", "/usr/bin", "/usr/sbin", "/usr/local/bin", "/usr/local/sbin" 189 binDirs = type(binDirs)(Path(p) for p in binDirs)
164 ] 190
165 print("Binaries dirs are:") 191 print("Binaries dirs are:")
166 print(binDirs) 192 print(binDirs)
167 doTheFixes(profilesPath, binDirs) 193 doTheFixes(profilesPath, binDirs)