diff options
-rwxr-xr-x | contrib/jail_prober.py | 114 |
1 files changed, 63 insertions, 51 deletions
diff --git a/contrib/jail_prober.py b/contrib/jail_prober.py index dad790b57..67a5186ae 100755 --- a/contrib/jail_prober.py +++ b/contrib/jail_prober.py | |||
@@ -29,29 +29,38 @@ import os | |||
29 | import subprocess | 29 | import subprocess |
30 | 30 | ||
31 | 31 | ||
32 | def check_params(profilePath): | 32 | def check_params(profile_path): |
33 | """ | 33 | """ |
34 | Ensure the path to the profile is valid and that an actual profile has been | 34 | Ensure the path to the profile is valid and that an actual profile has been |
35 | passed (as opposed to a config or .local file). | 35 | passed (as opposed to a config or .local file). |
36 | 36 | ||
37 | :params profilePath: The absolute path to the problematic profile. | 37 | Args: |
38 | profile_path: The absolute path to the problematic profile | ||
39 | |||
40 | Raises: | ||
41 | FileNotFoundError: If the provided path isn't real | ||
42 | |||
43 | ValueError: If the provided path is real but doesn't point to | ||
44 | a Firejail profile | ||
38 | """ | 45 | """ |
39 | if not os.path.isfile(profilePath): | 46 | if not os.path.isfile(profile_path): |
40 | raise FileNotFoundError( | 47 | raise FileNotFoundError('The path %s is not a valid system path.' % |
41 | 'The path %s is not a valid system path.' % profilePath) | 48 | profile_path) |
42 | if not profilePath.endswith('.profile'): | 49 | if not profile_path.endswith('.profile'): |
43 | raise ValueError('%s is not a valid Firejail profile.' % profilePath) | 50 | raise ValueError('%s is not a valid Firejail profile.' % profile_path) |
44 | 51 | ||
45 | 52 | ||
46 | def get_args(profilePath): | 53 | def get_args(profile_path): |
47 | """ | 54 | """ |
48 | Read the profile, stripping out comments and newlines | 55 | Read the profile, stripping out comments and newlines |
49 | 56 | ||
50 | :params profilePath: The absolute path to the problematic profile. | 57 | Args: |
58 | profile_path: The absolute path to the problematic profile. | ||
51 | 59 | ||
52 | :returns profile: A list containing all active profile arguments | 60 | Returns: |
61 | A list containing all active profile arguments | ||
53 | """ | 62 | """ |
54 | with open(profilePath, 'r') as f: | 63 | with open(profile_path, 'r') as f: |
55 | profile = f.readlines() | 64 | profile = f.readlines() |
56 | profile = [ | 65 | profile = [ |
57 | arg.strip() for arg in profile | 66 | arg.strip() for arg in profile |
@@ -61,92 +70,95 @@ def get_args(profilePath): | |||
61 | return profile | 70 | return profile |
62 | 71 | ||
63 | 72 | ||
64 | def arg_converter(argList, style): | 73 | def arg_converter(arg_list, style): |
65 | """ | 74 | """ |
66 | Convert between firejail command-line arguments (--example=something) and | 75 | Convert between firejail command-line arguments (--example=something) and |
67 | profile arguments (example something) | 76 | profile arguments (example something) |
68 | 77 | ||
69 | :params argList: A list of firejail arguments | 78 | Args: |
79 | arg_list: A list of firejail arguments | ||
70 | 80 | ||
71 | :params style: Whether to convert arguments to command-line form or profile | 81 | style: String, one of {'to_profile', 'to_commandline'}. Whether to |
72 | form | 82 | convert arguments to command-line form or profile form |
73 | """ | 83 | """ |
74 | if style == 'to_profile': | 84 | if style == 'to_profile': |
75 | oldSep = '=' | 85 | old_sep = '=' |
76 | newSep = ' ' | 86 | new_sep = ' ' |
77 | prefix = '' | 87 | prefix = '' |
78 | elif style == 'to_commandline': | 88 | elif style == 'to_commandline': |
79 | oldSep = ' ' | 89 | old_sep = ' ' |
80 | newSep = '=' | 90 | new_sep = '=' |
81 | prefix = '--' | 91 | prefix = '--' |
82 | newArgs = [prefix + word.replace(oldSep, newSep) for word in argList] | 92 | new_args = [prefix + word.replace(old_sep, new_sep) for word in arg_list] |
83 | # Additional strip of '--' if converting to profile form | 93 | # Additional strip of '--' if converting to profile form |
84 | if style == 'to_profile': | 94 | if style == 'to_profile': |
85 | newArgs = [word[2:] for word in newArgs] | 95 | new_args = [word[2:] for word in new_args] |
86 | 96 | ||
87 | # Remove invalid '--include' args if converting to command-line form | 97 | # Remove invalid '--include' args if converting to command-line form |
88 | elif style == 'to_commandline': | 98 | elif style == 'to_commandline': |
89 | newArgs = [word for word in newArgs if 'include' not in word] | 99 | new_args = [word for word in new_args if 'include' not in word] |
90 | 100 | ||
91 | return newArgs | 101 | return new_args |
92 | 102 | ||
93 | 103 | ||
94 | def run_firejail(program, allArgs): | 104 | def run_firejail(program, all_args): |
95 | """ | 105 | """ |
96 | Attempt to run the program in firejail, incrementally adding to the number | 106 | Attempt to run the program in firejail, incrementally adding to the number |
97 | of firejail arguments. Initial run has no additional params besides | 107 | of firejail arguments. Initial run has no additional params besides |
98 | noprofile. | 108 | noprofile. |
99 | 109 | ||
100 | :params program: The program name. If it doesn't exist in the user's path | 110 | Args: |
101 | then the full path should be provided. | 111 | program: String, the program name. If it doesn't exist in $PATH then |
112 | the full path to the program should be provided | ||
102 | 113 | ||
103 | :params allArgs: A list of all Firejail arguments to try, in command-line | 114 | all_args: List, all Firejail arguments to try, in command-line format |
104 | format. | 115 | (i.e. prefixed by '--') |
105 | 116 | ||
106 | :returns goodArgs: A list of arguments that the user has reported to not | 117 | Returns: |
107 | affect the program | 118 | good_args: List, all Firejail arguments that the user has reported to |
119 | not adversely affect the program | ||
108 | 120 | ||
109 | :returns badArgs: A list of arguments that the user has reported to break | 121 | bad_args: List, all Firejail arguments that the user has reported to |
110 | the program when sandboxing with Firejail | 122 | break the program |
111 | """ | 123 | """ |
112 | goodArgs = ['firejail', '--noprofile', program] | 124 | good_args = ['firejail', '--noprofile', program] |
113 | badArgs = [] | 125 | bad_args = [] |
114 | allArgs.insert(0,"") | 126 | all_args.insert(0, "") |
115 | print('Attempting to run %s in Firejail' % program) | 127 | print('Attempting to run %s in Firejail' % program) |
116 | for arg in allArgs: | 128 | for arg in all_args: |
117 | if arg: | 129 | if arg: |
118 | print('Running with', arg) | 130 | print('Running with', arg) |
119 | else: | 131 | else: |
120 | print('Running without profile') | 132 | print('Running without profile') |
121 | #We are adding the argument in a copy of the actual list to avoid modify it now. | 133 | #We are adding the argument in a copy of the actual list to avoid modify it now. |
122 | myargs=goodArgs.copy() | 134 | myargs = good_args.copy() |
123 | if arg: | 135 | if arg: |
124 | myargs.insert(-1,arg) | 136 | myargs.insert(-1, arg) |
125 | subprocess.call(myargs) | 137 | subprocess.call(myargs) |
126 | ans = input('Did %s run correctly? [y]/n ' % program) | 138 | ans = input('Did %s run correctly? [y]/n ' % program) |
127 | if ans in ['n', 'N']: | 139 | if ans in ['n', 'N']: |
128 | badArgs.append(arg) | 140 | bad_args.append(arg) |
129 | elif arg: | 141 | elif arg: |
130 | goodArgs.insert(-1, arg) | 142 | good_args.insert(-1, arg) |
131 | print('\n') | 143 | print('\n') |
132 | # Don't include 'firejail', '--noprofile', or program name in arguments | 144 | # Don't include 'firejail', '--noprofile', or program name in arguments |
133 | goodArgs = goodArgs[2:-1] | 145 | good_args = good_args[2:-1] |
134 | 146 | ||
135 | return goodArgs, badArgs | 147 | return good_args, bad_args |
136 | 148 | ||
137 | 149 | ||
138 | def main(): | 150 | def main(): |
139 | profilePath = sys.argv[1] | 151 | profile_path = sys.argv[1] |
140 | program = sys.argv[2] | 152 | program = sys.argv[2] |
141 | # Quick error check and extract arguments | 153 | # Quick error check and extract arguments |
142 | check_params(profilePath) | 154 | check_params(profile_path) |
143 | profile = get_args(profilePath) | 155 | profile = get_args(profile_path) |
144 | allArgs = arg_converter(profile, 'to_commandline') | 156 | all_args = arg_converter(profile, 'to_commandline') |
145 | # Find out which profile options break the program when running in firejail | 157 | # Find out which profile options break the program when running in firejail |
146 | goodArgs, badArgs = run_firejail(program, allArgs) | 158 | good_args, bad_args = run_firejail(program, all_args) |
147 | 159 | ||
148 | goodArgs = arg_converter(goodArgs, 'to_profile') | 160 | good_args = arg_converter(good_args, 'to_profile') |
149 | badArgs = arg_converter(badArgs, 'to_profile') | 161 | bad_args = arg_converter(bad_args, 'to_profile') |
150 | 162 | ||
151 | print('\n###########################') | 163 | print('\n###########################') |
152 | print('Debugging completed.') | 164 | print('Debugging completed.') |
@@ -159,13 +171,13 @@ def main(): | |||
159 | 171 | ||
160 | print('These profile options break the program.') | 172 | print('These profile options break the program.') |
161 | print('```') | 173 | print('```') |
162 | for item in badArgs: | 174 | for item in bad_args: |
163 | print(item) | 175 | print(item) |
164 | print('```\n\n\n') | 176 | print('```\n\n\n') |
165 | 177 | ||
166 | print('This is a minimal working profile:') | 178 | print('This is a minimal working profile:') |
167 | print('```') | 179 | print('```') |
168 | for item in goodArgs: | 180 | for item in good_args: |
169 | print(item) | 181 | print(item) |
170 | print('```') | 182 | print('```') |
171 | 183 | ||