mirror of
https://github.com/netblue30/firejail.git
synced 2026-05-15 14:16:14 -06:00
Various python cleanups -- note fix_private-bin.py is (still) broken
This commit is contained in:
parent
7c903b45c2
commit
a179c7dc91
5 changed files with 184 additions and 152 deletions
|
|
@ -29,80 +29,84 @@ __license__ = "Unlicense"
|
|||
|
||||
import sys, os, glob, re
|
||||
|
||||
privRx=re.compile("^(?:#\s*)?private-bin")
|
||||
privRx = re.compile("^(?:#\s*)?private-bin")
|
||||
|
||||
|
||||
def fixSymlinkedBins(files, replMap):
|
||||
"""
|
||||
"""
|
||||
Used to add filenames to private-bin directives of files if the ones present are mentioned in replMap
|
||||
replMap is a dict where key is the marker filename and value is the filename to add
|
||||
"""
|
||||
|
||||
rxs=dict()
|
||||
for (old,new) in replMap.items():
|
||||
rxs[old]=re.compile("\\b"+old+"\\b")
|
||||
rxs[new]=re.compile("\\b"+new+"\\b")
|
||||
#print(rxs)
|
||||
rxs = dict()
|
||||
for (old, new) in replMap.items():
|
||||
rxs[old] = re.compile("\\b" + old + "\\b")
|
||||
rxs[new] = re.compile("\\b" + new + "\\b")
|
||||
#print(rxs)
|
||||
|
||||
for filename in files:
|
||||
lines=None
|
||||
with open(filename,"r") as file:
|
||||
lines=file.readlines()
|
||||
for filename in files:
|
||||
lines = None
|
||||
with open(filename, "r") as file:
|
||||
lines = file.readlines()
|
||||
|
||||
shouldUpdate=False
|
||||
for (i,line) in enumerate(lines):
|
||||
if privRx.search(line):
|
||||
for (old,new) in replMap.items():
|
||||
if rxs[old].search(line) and not rxs[new].search(line):
|
||||
lines[i]=rxs[old].sub(old+","+new, line)
|
||||
shouldUpdate=True
|
||||
print(lines[i])
|
||||
shouldUpdate = False
|
||||
for (i, line) in enumerate(lines):
|
||||
if privRx.search(line):
|
||||
for (old, new) in replMap.items():
|
||||
if rxs[old].search(line) and not rxs[new].search(line):
|
||||
lines[i] = rxs[old].sub(old + "," + new, line)
|
||||
shouldUpdate = True
|
||||
print(lines[i])
|
||||
|
||||
if shouldUpdate:
|
||||
with open(filename, "w") as file:
|
||||
file.writelines(lines)
|
||||
pass
|
||||
|
||||
if shouldUpdate:
|
||||
with open(filename,"w") as file:
|
||||
file.writelines(lines)
|
||||
pass
|
||||
|
||||
def createSetOfBinaries(files):
|
||||
"""
|
||||
"""
|
||||
Creates a set of binaries mentioned in private-bin directives of files.
|
||||
"""
|
||||
s=set()
|
||||
for filename in files:
|
||||
lines=None
|
||||
with open(filename,"r") as file:
|
||||
for line in file:
|
||||
if privRx.search(line):
|
||||
bins=line.split(",")
|
||||
bins[0]=bins[0].split(" ")[-1]
|
||||
bins = [n.strip() for n in bins]
|
||||
s=s|set(bins)
|
||||
return s
|
||||
s = set()
|
||||
for filename in files:
|
||||
lines = None
|
||||
with open(filename, "r") as file:
|
||||
for line in file:
|
||||
if privRx.search(line):
|
||||
bins = line.split(",")
|
||||
bins[0] = bins[0].split(" ")[-1]
|
||||
bins = [n.strip() for n in bins]
|
||||
s = s | set(bins)
|
||||
return s
|
||||
|
||||
|
||||
def createSymlinkTable(binDirs, binariesSet):
|
||||
"""
|
||||
"""
|
||||
creates a dict of symlinked binaries in the system where a key is a symlink name and value is a symlinked binary.
|
||||
binDirs are folders to look into for binaries symlinks
|
||||
binariesSet is a set of binaries to be checked if they are actually a symlinks
|
||||
"""
|
||||
m=dict()
|
||||
toProcess=binariesSet
|
||||
while len(toProcess)!=0:
|
||||
additional=set()
|
||||
for sh in toProcess:
|
||||
for bD in binDirs:
|
||||
p=bD+os.path.sep+sh
|
||||
if os.path.exists(p):
|
||||
if os.path.islink(p):
|
||||
m[sh]=os.readlink(p)
|
||||
additional.add(m[sh].split(" ")[0])
|
||||
else:
|
||||
pass
|
||||
break
|
||||
toProcess=additional
|
||||
return m
|
||||
m = dict()
|
||||
toProcess = binariesSet
|
||||
while len(toProcess) != 0:
|
||||
additional = set()
|
||||
for sh in toProcess:
|
||||
for bD in binDirs:
|
||||
p = bD + os.path.sep + sh
|
||||
if os.path.exists(p):
|
||||
if os.path.islink(p):
|
||||
m[sh] = os.readlink(p)
|
||||
additional.add(m[sh].split(" ")[0])
|
||||
else:
|
||||
pass
|
||||
break
|
||||
toProcess = additional
|
||||
return m
|
||||
|
||||
|
||||
def doTheFixes(profilesPath, binDirs):
|
||||
"""
|
||||
"""
|
||||
Fixes private-bin in .profiles for firejail. The pipeline is as follows:
|
||||
discover files -> discover mentioned binaries ->
|
||||
discover the ones which are symlinks ->
|
||||
|
|
@ -110,48 +114,60 @@ def doTheFixes(profilesPath, binDirs):
|
|||
filter the ones can be fixed (we cannot fix the ones which are not in directories for binaries) ->
|
||||
apply fix
|
||||
"""
|
||||
files=glob.glob(profilesPath+os.path.sep+"*.profile")
|
||||
bins=createSetOfBinaries(files)
|
||||
#print("The binaries used are:")
|
||||
#print(bins)
|
||||
stbl=createSymlinkTable(binDirs,bins)
|
||||
print("The replacement table is:")
|
||||
print(stbl)
|
||||
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}
|
||||
print("Filtered replacement table is:")
|
||||
print(stbl)
|
||||
fixSymlinkedBins(files,stbl)
|
||||
files = glob.glob(profilesPath + os.path.sep + "*.profile")
|
||||
bins = createSetOfBinaries(files)
|
||||
#print("The binaries used are:")
|
||||
#print(bins)
|
||||
stbl = createSymlinkTable(binDirs, bins)
|
||||
print("The replacement table is:")
|
||||
print(stbl)
|
||||
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
|
||||
}
|
||||
print("Filtered replacement table is:")
|
||||
print(stbl)
|
||||
fixSymlinkedBins(files, stbl)
|
||||
|
||||
|
||||
def printHelp():
|
||||
print("python3 "+os.path.basename(__file__)+" <dir with .profile files>\nThe default dir is "+defaultProfilesPath+"\n"+doTheFixes.__doc__)
|
||||
print("python3 " + os.path.basename(__file__) +
|
||||
" <dir with .profile files>\nThe default dir is " +
|
||||
defaultProfilesPath + "\n" + doTheFixes.__doc__)
|
||||
|
||||
|
||||
def main():
|
||||
"""The main function. Parses the commandline args, shows messages and calles the function actually doing the work."""
|
||||
print(repr(sys.argv))
|
||||
defaultProfilesPath="../etc"
|
||||
if len(sys.argv)>2 or (len(sys.argv)==2 and (sys.argv[1] == '-h' or sys.argv[1] == '--help') ):
|
||||
printHelp()
|
||||
exit(1)
|
||||
"""The main function. Parses the commandline args, shows messages and calles the function actually doing the work."""
|
||||
print(repr(sys.argv))
|
||||
defaultProfilesPath = "../etc"
|
||||
if len(sys.argv) > 2 or (len(sys.argv) == 2 and
|
||||
(sys.argv[1] == '-h' or sys.argv[1] == '--help')):
|
||||
printHelp()
|
||||
exit(1)
|
||||
|
||||
profilesPath=None
|
||||
if len(sys.argv)==2:
|
||||
if os.path.isdir(sys.argv[1]):
|
||||
profilesPath=os.path.abspath(sys.argv[1])
|
||||
else:
|
||||
if os.path.exists(sys.argv[1]):
|
||||
print(sys.argv[1]+" is not a dir")
|
||||
else:
|
||||
print(sys.argv[1]+" does not exist")
|
||||
printHelp()
|
||||
exit(1)
|
||||
else:
|
||||
print("Using default profiles dir: " + defaultProfilesPath)
|
||||
profilesPath=defaultProfilesPath
|
||||
profilesPath = None
|
||||
if len(sys.argv) == 2:
|
||||
if os.path.isdir(sys.argv[1]):
|
||||
profilesPath = os.path.abspath(sys.argv[1])
|
||||
else:
|
||||
if os.path.exists(sys.argv[1]):
|
||||
print(sys.argv[1] + " is not a dir")
|
||||
else:
|
||||
print(sys.argv[1] + " does not exist")
|
||||
printHelp()
|
||||
exit(1)
|
||||
else:
|
||||
print("Using default profiles dir: " + defaultProfilesPath)
|
||||
profilesPath = defaultProfilesPath
|
||||
|
||||
binDirs = [
|
||||
"/bin", "/usr/bin", "/usr/sbin", "/usr/local/bin", "/usr/local/sbin"
|
||||
]
|
||||
print("Binaries dirs are:")
|
||||
print(binDirs)
|
||||
doTheFixes(profilesPath, binDirs)
|
||||
|
||||
binDirs=["/bin","/usr/bin","/usr/sbin","/usr/local/bin","/usr/local/sbin"]
|
||||
print("Binaries dirs are:")
|
||||
print(binDirs)
|
||||
doTheFixes(profilesPath, binDirs)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
|
|
|||
|
|
@ -4,42 +4,46 @@
|
|||
|
||||
import os, re, shlex, subprocess, sys
|
||||
|
||||
|
||||
def run(srcdir, args):
|
||||
if srcdir: os.chdir(srcdir)
|
||||
if srcdir: os.chdir(srcdir)
|
||||
|
||||
dry_run=False
|
||||
escaped_args=[]
|
||||
# We need to modify the list as we go. So be sure to copy the list to be iterated!
|
||||
for a in args[:]:
|
||||
if a.startswith('--prefix'):
|
||||
# prefix should ALWAYS be /usr here. Discard user-set values
|
||||
args.remove(a)
|
||||
elif a == '--only-fix-mkdeb':
|
||||
# for us, not configure
|
||||
dry_run=True
|
||||
args.remove(a)
|
||||
else:
|
||||
escaped_args.append(shlex.quote(a))
|
||||
dry_run = False
|
||||
escaped_args = []
|
||||
# We need to modify the list as we go. So be sure to copy the list to be iterated!
|
||||
for a in args[:]:
|
||||
if a.startswith('--prefix'):
|
||||
# prefix should ALWAYS be /usr here. Discard user-set values
|
||||
args.remove(a)
|
||||
elif a == '--only-fix-mkdeb':
|
||||
# for us, not configure
|
||||
dry_run = True
|
||||
args.remove(a)
|
||||
else:
|
||||
escaped_args.append(shlex.quote(a))
|
||||
|
||||
# Fix up mkdeb.sh to include custom configure options.
|
||||
with open('mkdeb.sh', 'rb') as f:
|
||||
sh=str(f.read(), 'utf_8')
|
||||
rx=re.compile(r'^\./configure\s.*$', re.M)
|
||||
with open('mkdeb.sh', 'wb') as f:
|
||||
f.write(bytes(rx.sub('./configure --prefix=/usr '+(' '.join(escaped_args)), sh), 'utf_8'))
|
||||
# Fix up mkdeb.sh to include custom configure options.
|
||||
with open('mkdeb.sh', 'rb') as f:
|
||||
sh = str(f.read(), 'utf_8')
|
||||
rx = re.compile(r'^\./configure\s.*$', re.M)
|
||||
with open('mkdeb.sh', 'wb') as f:
|
||||
f.write(
|
||||
bytes(
|
||||
rx.sub('./configure --prefix=/usr ' + (' '.join(escaped_args)),
|
||||
sh), 'utf_8'))
|
||||
|
||||
if dry_run: return 0
|
||||
if dry_run: return 0
|
||||
|
||||
# now run configure && make
|
||||
if subprocess.call(['./configure', '--prefix=/usr']+args) == 0:
|
||||
subprocess.call(['make', 'deb'])
|
||||
# now run configure && make
|
||||
if subprocess.call(['./configure', '--prefix=/usr'] + args) == 0:
|
||||
subprocess.call(['make', 'deb'])
|
||||
|
||||
return 0
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) == 2 and sys.argv[1] == '--help':
|
||||
print('''Build a .deb of firejail with custom configure options
|
||||
if len(sys.argv) == 2 and sys.argv[1] == '--help':
|
||||
print('''Build a .deb of firejail with custom configure options
|
||||
|
||||
usage:
|
||||
{script} [--fj-src=SRCDIR] [--only-fix-mkdeb] [CONFIGURE_OPTIONS [...]]
|
||||
|
|
@ -51,24 +55,26 @@ usage:
|
|||
--only-fix-mkdeb: don't run configure or make after modifying mkdeb.sh
|
||||
CONFIGURE_OPTIONS: arguments for configure
|
||||
'''.format(script=sys.argv[0]))
|
||||
sys.exit(0)
|
||||
else:
|
||||
# Find the source directory
|
||||
srcdir=None
|
||||
args=sys.argv[1:]
|
||||
for a in args:
|
||||
if a.startswith('--fj-src='):
|
||||
args.remove(a)
|
||||
srcdir=a[9:]
|
||||
break
|
||||
if not(srcdir):
|
||||
# srcdir not manually specified, try to auto-detect
|
||||
srcdir=os.path.dirname(os.path.abspath(sys.argv[0]+'/..'))
|
||||
if not(os.path.isfile(srcdir+'/mkdeb.sh')):
|
||||
# Script is probably installed. Check the cwd.
|
||||
if os.path.isfile('./mkdeb.sh'):
|
||||
srcdir=None
|
||||
else:
|
||||
print('Error: Could not find the firejail source tree. Exiting.')
|
||||
sys.exit(1)
|
||||
sys.exit(run(srcdir, args))
|
||||
sys.exit(0)
|
||||
else:
|
||||
# Find the source directory
|
||||
srcdir = None
|
||||
args = sys.argv[1:]
|
||||
for a in args:
|
||||
if a.startswith('--fj-src='):
|
||||
args.remove(a)
|
||||
srcdir = a[9:]
|
||||
break
|
||||
if not (srcdir):
|
||||
# srcdir not manually specified, try to auto-detect
|
||||
srcdir = os.path.dirname(os.path.abspath(sys.argv[0] + '/..'))
|
||||
if not (os.path.isfile(srcdir + '/mkdeb.sh')):
|
||||
# Script is probably installed. Check the cwd.
|
||||
if os.path.isfile('./mkdeb.sh'):
|
||||
srcdir = None
|
||||
else:
|
||||
print(
|
||||
'Error: Could not find the firejail source tree. Exiting.'
|
||||
)
|
||||
sys.exit(1)
|
||||
sys.exit(run(srcdir, args))
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ if sys.argv[1] == '-':
|
|||
clipin_raw = sys.stdin.read()
|
||||
else:
|
||||
display = fjdisplay.getdisplay(sys.argv[1])
|
||||
clipin_raw = subprocess.check_output(['xsel','-b','--display',display])
|
||||
clipin_raw = subprocess.check_output(['xsel', '-b', '--display', display])
|
||||
|
||||
clipin = clipin_raw.strip()
|
||||
|
||||
|
|
@ -31,5 +31,6 @@ if sys.argv[2] == '-':
|
|||
print(clipin)
|
||||
else:
|
||||
display = fjdisplay.getdisplay(sys.argv[2])
|
||||
clipout = subprocess.Popen(['xsel','-b','-i','--display',display],stdin=subprocess.PIPE)
|
||||
clipout = subprocess.Popen(['xsel', '-b', '-i', '--display', display],
|
||||
stdin=subprocess.PIPE)
|
||||
clipout.communicate(clipin)
|
||||
|
|
|
|||
|
|
@ -8,23 +8,25 @@ usage = """fjdisplay.py name-of-firejail
|
|||
returns the display in the form of ':NNN'
|
||||
"""
|
||||
|
||||
|
||||
def getfirejails():
|
||||
output = subprocess.check_output(['firemon','--x11'])
|
||||
output = subprocess.check_output(['firemon', '--x11'])
|
||||
firejails = {}
|
||||
name = ''
|
||||
for line in output.split('\n'):
|
||||
namematch = re.search('--name=(\w+\S*)',line)
|
||||
namematch = re.search('--name=(\w+\S*)', line)
|
||||
if namematch:
|
||||
name = namematch.group(1)
|
||||
displaymatch = re.search('DISPLAY (:\d+)',line)
|
||||
name = namematch.group(1)
|
||||
displaymatch = re.search('DISPLAY (:\d+)', line)
|
||||
if displaymatch:
|
||||
firejails[name] = displaymatch.group(1)
|
||||
firejails[name] = displaymatch.group(1)
|
||||
return firejails
|
||||
|
||||
|
||||
def getdisplay(name):
|
||||
firejails = getfirejails()
|
||||
fjlist = '\n'.join(firejails.keys())
|
||||
namere = re.compile('^'+name+'.*', re.MULTILINE)
|
||||
namere = re.compile('^' + name + '.*', re.MULTILINE)
|
||||
matchingjails = namere.findall(fjlist)
|
||||
if len(matchingjails) == 1:
|
||||
return firejails[matchingjails[0]]
|
||||
|
|
@ -33,6 +35,7 @@ def getdisplay(name):
|
|||
else:
|
||||
raise NameError("ambiguous firejail name")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) > 2:
|
||||
print(usage)
|
||||
|
|
@ -40,4 +43,4 @@ if __name__ == '__main__':
|
|||
if len(sys.argv) == 1:
|
||||
print(getfirejails())
|
||||
if len(sys.argv) == 2:
|
||||
print (getdisplay(sys.argv[1]))
|
||||
print(getdisplay(sys.argv[1]))
|
||||
|
|
|
|||
|
|
@ -6,20 +6,26 @@ import subprocess
|
|||
|
||||
usage = """usage: fjresize.py firejail-name displaysize
|
||||
resize firejail xephyr windows.
|
||||
fjdisplay.py with no other arguments will list running named firejails with displays.
|
||||
fjdisplay.py with no other arguments will list running named firejails with
|
||||
displays.
|
||||
fjresize.py with only a firejail name will list valid resolutions.
|
||||
names can be shortened as long its unambiguous.
|
||||
names can be shortened as long as it's unambiguous.
|
||||
note: you may need to move the xephyr window for the resize to take effect
|
||||
example:
|
||||
fjresize.py browser 1280x800
|
||||
"""
|
||||
|
||||
|
||||
if len(sys.argv) == 2:
|
||||
out = subprocess.check_output(['xrandr','--display',fjdisplay.getdisplay(sys.argv[1])])
|
||||
out = subprocess.check_output(
|
||||
['xrandr', '--display',
|
||||
fjdisplay.getdisplay(sys.argv[1])])
|
||||
print(out)
|
||||
elif len(sys.argv) == 3:
|
||||
out = subprocess.check_output(['xrandr','--display',fjdisplay.getdisplay(sys.argv[1]),'--output','default','--mode',sys.argv[2]])
|
||||
out = subprocess.check_output([
|
||||
'xrandr', '--display',
|
||||
fjdisplay.getdisplay(sys.argv[1]), '--output', 'default', '--mode',
|
||||
sys.argv[2]
|
||||
])
|
||||
print(out)
|
||||
else:
|
||||
print(usage)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue