aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar KOLANICH <kolan_n@mail.ru>2017-01-04 18:54:33 +0300
committerLibravatar KOLANICH <kolan_n@mail.ru>2017-01-04 20:33:17 +0300
commit80965e6a7f7ec62ba2c5385a320018adb5463c73 (patch)
tree2984dda1425170128a1068346512d5bd9048fde6
parent3 new Python scripts in contrib section (diff)
downloadfirejail-80965e6a7f7ec62ba2c5385a320018adb5463c73.tar.gz
firejail-80965e6a7f7ec62ba2c5385a320018adb5463c73.tar.zst
firejail-80965e6a7f7ec62ba2c5385a320018adb5463c73.zip
Improved fix_private-bin.py a bit: added commandline arguments, metainfo and breadth-first search
-rwxr-xr-xcontrib/fix_private-bin.py129
1 files changed, 109 insertions, 20 deletions
diff --git a/contrib/fix_private-bin.py b/contrib/fix_private-bin.py
index 705e46e46..270c758a2 100755
--- a/contrib/fix_private-bin.py
+++ b/contrib/fix_private-bin.py
@@ -1,15 +1,47 @@
1#!/usr/bin/python3 1#!/usr/bin/python3
2 2
3__author__ = "KOLANICH"
4__copyright__ = """This is free and unencumbered software released into the public domain.
5
6Anyone is free to copy, modify, publish, use, compile, sell, or
7distribute this software, either in source code form or as a compiled
8binary, for any purpose, commercial or non-commercial, and by any
9means.
10
11In jurisdictions that recognize copyright laws, the author or authors
12of this software dedicate any and all copyright interest in the
13software to the public domain. We make this dedication for the benefit
14of the public at large and to the detriment of our heirs and
15successors. We intend this dedication to be an overt act of
16relinquishment in perpetuity of all present and future rights to this
17software under copyright law.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25OTHER DEALINGS IN THE SOFTWARE.
26
27For more information, please refer to <http://unlicense.org/>"""
28__license__ = "Unlicense"
29
3import sys, os, glob, re 30import sys, os, glob, re
4 31
5privRx=re.compile("^(?:#\s*)?private-bin") 32privRx=re.compile("^(?:#\s*)?private-bin")
6 33
7def fixSymlinkedBins(files, replMap): 34def fixSymlinkedBins(files, replMap):
35 """
36 Used to add filenames to private-bin directives of files if the ones present are mentioned in replMap
37 replMap is a dict where key is the marker filename and value is the filename to add
38 """
39
8 rxs=dict() 40 rxs=dict()
9 for (old,new) in replMap.items(): 41 for (old,new) in replMap.items():
10 rxs[old]=re.compile("\\b"+old+"\\b") 42 rxs[old]=re.compile("\\b"+old+"\\b")
11 rxs[new]=re.compile("\\b"+new+"\\b") 43 rxs[new]=re.compile("\\b"+new+"\\b")
12 print(rxs) 44 #print(rxs)
13 45
14 for filename in files: 46 for filename in files:
15 lines=None 47 lines=None
@@ -28,9 +60,12 @@ def fixSymlinkedBins(files, replMap):
28 if shouldUpdate: 60 if shouldUpdate:
29 with open(filename,"w") as file: 61 with open(filename,"w") as file:
30 file.writelines(lines) 62 file.writelines(lines)
31 pass 63 pass
32 64
33def createListOfBinaries(files): 65def createSetOfBinaries(files):
66 """
67 Creates a set of binaries mentioned in private-bin directives of files.
68 """
34 s=set() 69 s=set()
35 for filename in files: 70 for filename in files:
36 lines=None 71 lines=None
@@ -44,25 +79,79 @@ def createListOfBinaries(files):
44 return s 79 return s
45 80
46def createSymlinkTable(binDirs, binariesSet): 81def createSymlinkTable(binDirs, binariesSet):
82 """
83 creates a dict of symlinked binaries in the system where a key is a symlink name and value is a symlinked binary.
84 binDirs are folders to look into for binaries symlinks
85 binariesSet is a set of binaries to be checked if they are actually a symlinks
86 """
47 m=dict() 87 m=dict()
48 for sh in binariesSet: 88 toProcess=binariesSet
49 for bD in binDirs: 89 while len(toProcess)!=0:
50 p=bD+os.path.sep+sh 90 additional=set()
51 if os.path.exists(p): 91 for sh in toProcess:
52 if os.path.islink(p): 92 for bD in binDirs:
53 m[sh]=os.readlink(p) 93 p=bD+os.path.sep+sh
54 else: 94 if os.path.exists(p):
55 pass 95 if os.path.islink(p):
56 break 96 m[sh]=os.readlink(p)
97 additional.add(m[sh].split(" ")[0])
98 else:
99 pass
100 break
101 toProcess=additional
57 return m 102 return m
58 103
104def doTheFixes(profilesPath, binDirs):
105 """
106 Fixes private-bin in .profiles for firejail. The pipeline is as follows:
107 discover files -> discover mentioned binaries ->
108 discover the ones which are symlinks ->
109 make a look-up table for fix ->
110 filter the ones can be fixed (we cannot fix the ones which are not in directories for binaries) ->
111 apply fix
112 """
113 files=glob.glob(profilesPath+os.path.sep+"*.profile")
114 bins=createSetOfBinaries(files)
115 #print("The binaries used are:")
116 #print(bins)
117 stbl=createSymlinkTable(binDirs,bins)
118 print("The replacement table is:")
119 print(stbl)
120 stbl={a[0]:a[1] for a in stbl.items() if a[0].find(os.path.sep) < 0 and a[1].find(os.path.sep)<0}
121 print("Filtered replacement table is:")
122 print(stbl)
123 fixSymlinkedBins(files,stbl)
124
125def printHelp():
126 print("python3 "+os.path.basename(__file__)+" <dir with .profile files>\nThe default dir is "+defaultProfilesPath+"\n"+doTheFixes.__doc__)
127
128def main():
129 """The main function. Parses the commandline args, shows messages and calles the function actually doing the work."""
130 print(repr(sys.argv))
131 defaultProfilesPath="../etc"
132 if len(sys.argv)>2 or (len(sys.argv)==2 and (sys.argv[1] == '-h' or sys.argv[1] == '--help') ):
133 printHelp()
134 exit(1)
135
136 profilesPath=None
137 if len(sys.argv)==2:
138 if os.path.isdir(sys.argv[1]):
139 profilesPath=os.path.abspath(sys.argv[1])
140 else:
141 if os.path.exists(sys.argv[1]):
142 print(sys.argv[1]+" is not a dir")
143 else:
144 print(sys.argv[1]+" does not exist")
145 printHelp()
146 exit(1)
147 else:
148 print("Using default profiles dir: " + defaultProfilesPath)
149 profilesPath=defaultProfilesPath
59 150
60sh="sh" 151 binDirs=["/bin","/usr/bin","/usr/sbin","/usr/local/bin","/usr/local/sbin"]
61binDirs=["/bin","/usr/bin","/usr/sbin","/usr/local/bin","/usr/local/sbin"] 152 print("Binaries dirs are:")
62profilesPath="." 153 print(binDirs)
63files=glob.glob(profilesPath+os.path.sep+"*.profile") 154 doTheFixes(profilesPath, binDirs)
64 155
65bins=createListOfBinaries(files) 156if __name__ == "__main__":
66stbl=createSymlinkTable(binDirs,bins) 157 main()
67print(stbl)
68fixSymlinkedBins(files,{a[0]:a[1] for a in stbl.items() if a[0].find("/") < 0 and a[1].find("/")<0})