aboutsummaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorLibravatar Fred-Barclay <Fred-Barclay@users.noreply.github.com>2018-08-24 12:09:16 -0500
committerLibravatar Fred-Barclay <Fred-Barclay@users.noreply.github.com>2018-08-24 12:09:16 -0500
commitce1fcbab3d20a2eb39ce2b6b70537b3f05de6415 (patch)
tree4cca5f201efccb97662e7c63edc9467b339801af /contrib
parentFixup obs.profile (no python) (diff)
downloadfirejail-ce1fcbab3d20a2eb39ce2b6b70537b3f05de6415.tar.gz
firejail-ce1fcbab3d20a2eb39ce2b6b70537b3f05de6415.tar.zst
firejail-ce1fcbab3d20a2eb39ce2b6b70537b3f05de6415.zip
Add python program to more easily debug profiles
Should help with issues like #1946 where the user needs to comment out all profile lines and then re-enable them individually to test
Diffstat (limited to 'contrib')
-rwxr-xr-xcontrib/jail_prober.py163
1 files changed, 163 insertions, 0 deletions
diff --git a/contrib/jail_prober.py b/contrib/jail_prober.py
new file mode 100755
index 000000000..a5f279cb4
--- /dev/null
+++ b/contrib/jail_prober.py
@@ -0,0 +1,163 @@
1#!/usr/bin/env python3
2"""
3Figure out which profile options may be causing a particular program to break
4when run in firejail.
5
6Instead of having to comment out each line in a profile by hand, and then
7enable each line individually until the bad line or lines are found, this
8largely automates the process. Users only have to provide the path to the
9profile, program name, and answer 'y' for yes or 'n' for no when prompted.
10
11After completion, you'll be provided with some information to copy and then
12paste into a GitHub issue in the Firejail project repository:
13https://github.com/netblue30/firejail/issues
14
15Paths to the profile should be absolute. If the program is in your path, then
16you only have to type the profile name. Else, you'll need to provide the
17absolute path to the profile.
18
19Examples:
20python jail_prober.py /etc/firejail/spotify.profile spotify
21python jail_prober.py /usr/local/etc/firejail/firefox.profile /usr/bin/firefox
22"""
23
24import sys
25import os
26import subprocess
27
28
29def check_params(profilePath):
30 """
31 Ensure the path to the profile is valid and that an actual profile has been
32 passed (as opposed to a config or .local file).
33
34 :params profilePath: The absolute path to the problematic profile.
35 """
36 if not os.path.isfile(profilePath):
37 raise FileNotFoundError(
38 'The path %s is not a valid system path.' % profilePath)
39 if not profilePath.endswith('.profile'):
40 raise ValueError('%s is not a valid Firejail profile.' % profilePath)
41
42
43def get_args(profilePath):
44 """
45 Read the profile, stripping out comments and newlines
46
47 :params profilePath: The absolute path to the problematic profile.
48
49 :returns profile: A list containing all active profile arguments
50 """
51 with open(profilePath, 'r') as f:
52 profile = f.readlines()
53 profile = [
54 arg.strip() for arg in profile
55 if not arg.startswith('#') and arg.strip() != ''
56 ]
57
58 return profile
59
60
61def arg_converter(argList, style):
62 """
63 Convert between firejail command-line arguments (--example=something) and
64 profile arguments (example something)
65
66 :params argList: A list of firejail arguments
67
68 :params style: Whether to convert arguments to command-line form or profile
69 form
70 """
71 if style == 'to_profile':
72 oldSep = '='
73 newSep = ' '
74 prefix = ''
75 elif style == 'to_commandline':
76 oldSep = ' '
77 newSep = '='
78 prefix = '--'
79 newArgs = [prefix + word.replace(oldSep, newSep) for word in argList]
80 # Additional strip of '--' if converting to profile form
81 if style == 'to_profile':
82 newArgs = [word[2:] for word in newArgs]
83
84 # Remove invalid '--include' args if converting to command-line form
85 elif style == 'to_commandline':
86 newArgs = [word for word in newArgs if 'include' not in word]
87
88 return newArgs
89
90
91def run_firejail(program, allArgs):
92 """
93 Attempt to run the program in firejail, incrementally adding to the number
94 of firejail arguments. Initial run has no additional params besides
95 noprofile.
96
97 :params program: The program name. If it doesn't exist in the user's path
98 then the full path should be provided.
99
100 :params allArgs: A list of all Firejail arguments to try, in command-line
101 format.
102
103 :returns goodArgs: A list of arguments that the user has reported to not
104 affect the program
105
106 :returns badArgs: A list of arguments that the user has reported to break
107 the program when sandboxing with Firejail
108 """
109 goodArgs = ['firejail', '--noprofile', program]
110 badArgs = []
111 print('Attempting to run %s in Firejail' % program)
112 for arg in allArgs:
113 print('Running with', arg)
114 subprocess.call(goodArgs)
115 ans = input('Did %s run correctly? [y]/n ' % program)
116 if ans == 'n' or ans == 'N':
117 badArgs.append(arg)
118 else:
119 goodArgs.insert(-1, arg)
120 print('\n')
121 # Don't include 'firejail', '--noprofile', or program name in arguments
122 goodArgs = goodArgs[2:-1]
123
124 return goodArgs, badArgs
125
126
127def main():
128 profilePath = sys.argv[1]
129 program = sys.argv[2]
130 # Quick error check and extract arguments
131 check_params(profilePath)
132 profile = get_args(profilePath)
133 allArgs = arg_converter(profile, 'to_commandline')
134 # Find out which profile options break the program when running in firejail
135 goodArgs, badArgs = run_firejail(program, allArgs)
136
137 goodArgs = arg_converter(goodArgs, 'to_profile')
138 badArgs = arg_converter(badArgs, 'to_profile')
139
140 print('\n###########################')
141 print('Debugging completed.')
142 print(
143 'Please copy the following and report it to the Firejail development',
144 'team on GitHub at %s \n\n' %
145 'https://github.com/netblue30/firejail/issues')
146
147 subprocess.call(['firejail', '--version'])
148
149 print('These profile options break the program.')
150 print('```')
151 for item in badArgs:
152 print(item)
153 print('```\n\n\n')
154
155 print('This is a minimal working profile:')
156 print('```')
157 for item in goodArgs:
158 print(item)
159 print('```')
160
161
162if __name__ == '__main__':
163 main()