Merge lp:~apparmor-dev/apparmor/aa-fixes into lp:~apparmor-dev/apparmor/apparmor-ubuntu-citrain
- aa-fixes
- Merge into apparmor-ubuntu-citrain
Status: | Merged |
---|---|
Approved by: | Jamie Strandboge |
Approved revision: | 1507 |
Merged at revision: | 1500 |
Proposed branch: | lp:~apparmor-dev/apparmor/aa-fixes |
Merge into: | lp:~apparmor-dev/apparmor/apparmor-ubuntu-citrain |
Diff against target: |
1166 lines (+1101/-2) 10 files modified
debian/changelog (+26/-2) debian/patches/bare-capability-rule-support.patch (+89/-0) debian/patches/check-config-for-sysctl.patch (+274/-0) debian/patches/fix-typo-in-dbus_write.patch (+22/-0) debian/patches/increase-swap-size.patch (+30/-0) debian/patches/initialize-mount-flags.patch (+17/-0) debian/patches/limited-mount-rule-support.patch (+222/-0) debian/patches/series (+8/-0) debian/patches/test-mount-mediation.patch (+266/-0) debian/patches/test-v6-policy.patch (+147/-0) |
To merge this branch: | bzr merge lp:~apparmor-dev/apparmor/aa-fixes |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jamie Strandboge | Approve | ||
Review via email: mp+213170@code.launchpad.net |
Commit message
Description of the change
Is your branch in sync with latest trunk? Yes
Is debian/changelog properly formatted in the MP? Yes
Did you build your software in a clean sbuild/pbuilder chroot or ppa? Yes (security-proposed PPA)
Did you build your software in a clean sbuild/pbuilder chroot or ppa on armhf? Yes (security-proposed PPA)
Has your component TestPlan been executed successfully on emulator/armhf Touch build (eg, one of N4, N10, N7 (either), Galaxy Nexus) and clean Ubuntu Desktop VM? I've done an abbreviated version of the TestPlan, at jdstrand's request:
- Ran QRT's test-apparmor.py (to test the changes to the regression suite and aa.py)
- Created an LXC container, started it, and verified that it was confined (for LP: #1296459)
- Manually tested the Python utils (for LP: #1294825 and LP: #1294819)
+ Note that they still backtrace on the LXC abstractions due to LP: #1295346 and LP: #1298678)
- Launched apps and verified their confinement on Touch
- Did exploratory testing on Touch and Desktop
Has a 5 minute exploratory testing run been executed on an armhf Touch build? Yes (N7)
If you changed the packaging (debian/), did you subscribe a core-dev to this MP? N/A
What components might get impacted by your changes?
- The apparmor/aa.py Python module and the utils shipped in apparmor-utils
- apparmor_parser
- The in-tree regression tests (they don't get installed but are used for testing)
Have you requested review by the teams of these owning components? Yes, upstream AppArmor has acked all changes and jdstrand is the reviewer of this merge
Seth Arnold (seth-arnold) wrote : | # |
Looks good to me, thanks
Preview Diff
1 | === modified file 'debian/changelog' |
2 | --- debian/changelog 2014-03-26 16:15:34 +0000 |
3 | +++ debian/changelog 2014-03-28 00:01:01 +0000 |
4 | @@ -1,5 +1,6 @@ |
5 | -apparmor (2.8.95~2430-0ubuntu3) UNRELEASED; urgency=medium |
6 | +apparmor (2.8.95~2430-0ubuntu3) trusty; urgency=medium |
7 | |
8 | + [ Jamie Strandboge ] |
9 | * debian/lib/apparmor/functions: properly calculate number of profiles in |
10 | /var/lib/apparmor/profiles (LP: #1295816) |
11 | * autostart aa-notify via /etc/xdg/autostart instead of /etc/X11/Xsession.d |
12 | @@ -11,7 +12,30 @@ |
13 | * debian/notify/notify.conf: use_group should be set to "sudo" instead of |
14 | "admin" (LP: #1009666) |
15 | |
16 | - -- Jamie Strandboge <jamie@ubuntu.com> Wed, 26 Mar 2014 10:34:34 -0500 |
17 | + [ Tyler Hicks ] |
18 | + * debian/patches/initialize-mount-flags.patch: Initialize the variables |
19 | + containing mount rule flags to zero. Otherwise, the parser may set |
20 | + unexpected bits in the mount flags field for rules that do not specify |
21 | + mount flags. The uninitialized mount flag variables may have caused |
22 | + unexpected AppArmor denials during mount mediation. (LP: #1296459) |
23 | + * debian/patches/fix-typo-in-dbus_write.patch: Fix a bug in the |
24 | + apparmor/aa.py module that caused the utilities in the apparmor-utils |
25 | + package to write out network rules instead of dbus rules |
26 | + * debian/patches/limited-mount-rule-support.patch: Fix a bug in the |
27 | + apparmor/aa.py module that caused the utilities in the apparmor-utils |
28 | + package to traceback when encountering a mount rule (LP: #1294825) |
29 | + * debian/patches/bare-capability-rule-support.patch: Fix a bug in the |
30 | + apparmor/aa.py module that caused the utilities in the apparmor-utils |
31 | + package to traceback when encountering a bare capability rule |
32 | + (LP: #1294819) |
33 | + * debian/patches/check-config-for-sysctl.patch, |
34 | + debian/patches/increase-swap-size.patch: Fix bugs in the regression test |
35 | + suite that caused errors when running on ppc64el |
36 | + * debian/patches/test-v6-policy.patch, |
37 | + debian/patches/test-mount-mediation.patch: Improve the regression tests |
38 | + by increasing the mount rule test coverage |
39 | + |
40 | + -- Tyler Hicks <tyhicks@canonical.com> Thu, 27 Mar 2014 14:12:29 -0500 |
41 | |
42 | apparmor (2.8.95~2430-0ubuntu2) trusty; urgency=medium |
43 | |
44 | |
45 | === added file 'debian/patches/bare-capability-rule-support.patch' |
46 | --- debian/patches/bare-capability-rule-support.patch 1970-01-01 00:00:00 +0000 |
47 | +++ debian/patches/bare-capability-rule-support.patch 2014-03-28 00:01:01 +0000 |
48 | @@ -0,0 +1,89 @@ |
49 | +Description: utils: Basic support for bare capability rules |
50 | + . |
51 | + Bug: https://bugs.launchpad.net/bugs/1294819 |
52 | + . |
53 | + This patch as minimal support for bare capability rules ("capability,"). |
54 | + It prevents aa.py from emitting a traceback when encountering such a |
55 | + rule. |
56 | + . |
57 | + It only adds the ability to parse and write the bare rule. It doesn't |
58 | + attempt to be clever when deleting duplicate rules, such as realizing |
59 | + that "capability audit_control," can be deleted if "capability," is also |
60 | + present. |
61 | + . |
62 | + Signed-off-by: Tyler Hicks <tyhicks@canonical.com> |
63 | + Acked-by: Steve Beattie <steve@nxnw.org> |
64 | + Acked-by: Christian Boltz <apparmor@cboltz.de> |
65 | +Origin: commit, revision id: tyhicks@canonical.com-20140320192724-z0kqjl8kzx4khx57 |
66 | +Author: Tyler Hicks <tyhicks@canonical.com> |
67 | +Bug: https://launchpad.net/bugs/1294819 |
68 | +Last-Update: 2014-03-20 |
69 | +X-Bzr-Revision-Id: tyhicks@canonical.com-20140320192724-z0kqjl8kzx4khx57 |
70 | + |
71 | +=== modified file 'utils/apparmor/aa.py' |
72 | +--- old/utils/apparmor/aa.py 2014-03-20 19:25:42 +0000 |
73 | ++++ new/utils/apparmor/aa.py 2014-03-20 19:27:24 +0000 |
74 | +@@ -78,6 +78,9 @@ |
75 | + # To store the globs entered by users so they can be provided again |
76 | + user_globs = [] |
77 | + |
78 | ++# The key for representing bare rules such as "capability," or "file," |
79 | ++ALL = '_ALL' |
80 | ++ |
81 | + ## Variables used under logprof |
82 | + ### Were our |
83 | + t = hasher() # dict() |
84 | +@@ -2104,6 +2107,9 @@ |
85 | + deleted = [] |
86 | + if profilecaps and inccaps: |
87 | + for capname in profilecaps.keys(): |
88 | ++ # XXX The presence of a bare capability rule ("capability,") should |
89 | ++ # cause more specific capability rules |
90 | ++ # ("capability audit_control,") to be deleted |
91 | + if inccaps[capname].get('set', False) == 1: |
92 | + deleted.append(capname) |
93 | + for capname in deleted: |
94 | +@@ -2599,7 +2605,7 @@ |
95 | + ## Profile parsing regex |
96 | + RE_PROFILE_START = re.compile('^\s*(("??/.+?"??)|(profile\s+("??.+?"??)))\s+((flags=)?\((.+)\)\s+)?\{\s*(#.*)?$') |
97 | + RE_PROFILE_END = re.compile('^\s*\}\s*(#.*)?$') |
98 | +-RE_PROFILE_CAP = re.compile('^\s*(audit\s+)?(allow\s+|deny\s+)?capability\s+(\S+)\s*,\s*(#.*)?$') |
99 | ++RE_PROFILE_CAP = re.compile('^\s*(audit\s+)?(allow\s+|deny\s+)?capability(\s+\S+)?\s*,\s*(#.*)?$') |
100 | + RE_PROFILE_LINK = re.compile('^\s*(audit\s+)?(allow\s+|deny\s+)?link\s+(((subset)|(<=))\s+)?([\"\@\/].*?"??)\s+->\s*([\"\@\/].*?"??)\s*,\s*(#.*)?$') |
101 | + RE_PROFILE_CHANGE_PROFILE = re.compile('^\s*change_profile\s+->\s*("??.+?"??),(#.*)?$') |
102 | + RE_PROFILE_ALIAS = re.compile('^\s*alias\s+("??.+?"??)\s+->\s*("??.+?"??)\s*,(#.*)?$') |
103 | +@@ -2733,7 +2739,9 @@ |
104 | + if matches[1] and matches[1].strip() == 'deny': |
105 | + allow = 'deny' |
106 | + |
107 | +- capability = matches[2] |
108 | ++ capability = ALL |
109 | ++ if matches[2]: |
110 | ++ capability = matches[2].strip() |
111 | + |
112 | + profile_data[profile][hat][allow]['capability'][capability]['set'] = True |
113 | + profile_data[profile][hat][allow]['capability'][capability]['audit'] = audit |
114 | +@@ -3236,7 +3244,10 @@ |
115 | + if prof_data[allow]['capability'][cap].get('audit', False): |
116 | + audit = 'audit ' |
117 | + if prof_data[allow]['capability'][cap].get('set', False): |
118 | +- data.append('%s%s%scapability %s,' % (pre, audit, allowstr, cap)) |
119 | ++ if cap == ALL: |
120 | ++ data.append('%s%s%scapability,' % (pre, audit, allowstr)) |
121 | ++ else: |
122 | ++ data.append('%s%s%scapability %s,' % (pre, audit, allowstr, cap)) |
123 | + data.append('') |
124 | + |
125 | + return data |
126 | +@@ -3698,7 +3709,9 @@ |
127 | + if matches[1] and matches[1].strip() == 'deny': |
128 | + allow = 'deny' |
129 | + |
130 | +- capability = matches[2] |
131 | ++ capability = ALL |
132 | ++ if matches[2]: |
133 | ++ capability = matches[2].strip() |
134 | + |
135 | + if not write_prof_data[hat][allow]['capability'][capability].get('set', False): |
136 | + correct = False |
137 | + |
138 | |
139 | === added file 'debian/patches/check-config-for-sysctl.patch' |
140 | --- debian/patches/check-config-for-sysctl.patch 1970-01-01 00:00:00 +0000 |
141 | +++ debian/patches/check-config-for-sysctl.patch 2014-03-28 00:01:01 +0000 |
142 | @@ -0,0 +1,274 @@ |
143 | +Description: regression sysctl: skip if sysctl not available |
144 | + . |
145 | + Some kernels have CONFIG_SYSCALL_SYSCTL disabled, which is something to |
146 | + be encouraged. This patch separates out the two different kind of sysctl |
147 | + tests (syscall based and /proc/sys based) into separate shell functions, |
148 | + and then checks to see that the test environment supports each before |
149 | + invoking each shell function, issuing a warning (but not failing the |
150 | + tests) if not available. |
151 | + . |
152 | + Signed-off-by: Steve Beattie <steve@nxnw.org> |
153 | + Acked-by: John Johansen <john.johansen@canonical.com> |
154 | +Origin: commit, revision id: sbeattie@ubuntu.com-20140320182310-dxmze74scskktd6h |
155 | +Author: Steve Beattie <sbeattie@ubuntu.com> |
156 | +Last-Update: 2014-03-20 |
157 | +X-Bzr-Revision-Id: sbeattie@ubuntu.com-20140320182310-dxmze74scskktd6h |
158 | + |
159 | +=== modified file 'tests/regression/apparmor/syscall_sysctl.sh' |
160 | +--- old/tests/regression/apparmor/syscall_sysctl.sh 2010-12-20 20:29:10 +0000 |
161 | ++++ new/tests/regression/apparmor/syscall_sysctl.sh 2014-03-20 18:23:10 +0000 |
162 | +@@ -25,119 +25,140 @@ |
163 | + ## |
164 | + ## C. SYSCTL |
165 | + ## |
166 | ++ |
167 | ++test_syscall_sysctl() |
168 | ++{ |
169 | ++ settest syscall_sysctl |
170 | ++ |
171 | ++ runchecktest "SYSCTL (no confinement read only)" pass ro |
172 | ++ |
173 | ++ runchecktest "SYSCTL (no confinement rw)" pass |
174 | ++ |
175 | ++ genprofile $sysctlgood:r |
176 | ++ runchecktest "SYSCTL (confinement/good r w/ r perm)" pass ro |
177 | ++ |
178 | ++ genprofile $sysctlgood:r |
179 | ++ runchecktest "SYSCTL (confinement/good rw w/ r perm)" fail |
180 | ++ |
181 | ++ genprofile $sysctlgood:w |
182 | ++ runchecktest "SYSCTL (confinement/good r w/ w perm)" fail ro |
183 | ++ |
184 | ++ genprofile $sysctlgood:w |
185 | ++ runchecktest "SYSCTL (confinement/good rw w/ w perm)" fail |
186 | ++ |
187 | ++ genprofile $sysctlgood:rw |
188 | ++ runchecktest "SYSCTL (confinement/good r w/ rw perm)" pass ro |
189 | ++ |
190 | ++ genprofile $sysctlgood:rw |
191 | ++ runchecktest "SYSCTL (confinement/good rw w/ rw perm)" pass |
192 | ++ |
193 | ++ genprofile $sysctlbad:r |
194 | ++ runchecktest "SYSCTL (confinement/bad r w/ r perm)" fail ro |
195 | ++ |
196 | ++ genprofile $sysctlbad:r |
197 | ++ runchecktest "SYSCTL (confinement/bad rw w/ r perm)" fail ro |
198 | ++ |
199 | ++ genprofile $sysctlbad:w |
200 | ++ runchecktest "SYSCTL (confinement/bad r w/ w perm)" fail ro |
201 | ++ |
202 | ++ genprofile $sysctlbad:w |
203 | ++ runchecktest "SYSCTL (confinement/bad rw w/ w perm)" fail |
204 | ++ |
205 | ++ genprofile $sysctlbad:rw |
206 | ++ runchecktest "SYSCTL (confinement/bad r w/ rw perm)" fail ro |
207 | ++ |
208 | ++ genprofile $sysctlbad:rw |
209 | ++ runchecktest "SYSCTL (confinement/bad rw w/ rw perm)" fail |
210 | ++} |
211 | ++ |
212 | ++test_sysctl_proc() |
213 | ++{ |
214 | ++ settest sysctl_proc |
215 | ++ |
216 | ++ #unconfined |
217 | ++ runchecktest "SYSCTL /proc (read no confinement)" pass $sysctlgood r |
218 | ++ value=`cat $sysctlgood` |
219 | ++ runchecktest "SYSCTL /proc (write no confinement)" pass $sysctlgood w $value |
220 | ++ runchecktest "SYSCTL /proc (rw no confinement)" pass $sysctlgood rw |
221 | ++ |
222 | ++ #test with profile giving access to sysctlgood |
223 | ++ genprofile $sysctlgood:r |
224 | ++ runchecktest "SYSCTL /proc (confinement/good r w/ r perm)" pass $sysctlgood r |
225 | ++ |
226 | ++ genprofile $sysctlgood:w |
227 | ++ runchecktest "SYSCTL /proc (confinement/good r w/ w perm)" fail $sysctlgood r |
228 | ++ |
229 | ++ genprofile $sysctlgood:rw |
230 | ++ runchecktest "SYSCTL /proc (confinement/good r w/ rw perm)" pass $sysctlgood r |
231 | ++ |
232 | ++ genprofile $sysctlgood:r |
233 | ++ value=`cat $sysctlgood` |
234 | ++ runchecktest "SYSCTL /proc (confinement/good w w/ r perm)" fail $sysctlgood w $value |
235 | ++ |
236 | ++ genprofile $sysctlgood:w |
237 | ++ value=`cat $sysctlgood` |
238 | ++ runchecktest "SYSCTL /proc (confinement/good w w/ w perm)" pass $sysctlgood w $value |
239 | ++ |
240 | ++ genprofile $sysctlgood:rw |
241 | ++ value=`cat $sysctlgood` |
242 | ++ runchecktest "SYSCTL /proc (confinement/good w w/ rw perm)" pass $sysctlgood w $value |
243 | ++ |
244 | ++ genprofile $sysctlgood:r |
245 | ++ runchecktest "SYSCTL /proc (confinement/good rw w/ r perm)" fail $sysctlgood rw |
246 | ++ |
247 | ++ genprofile $sysctlgood:w |
248 | ++ runchecktest "SYSCTL /proc (confinement/good rw w/ w perm)" fail $sysctlgood rw |
249 | ++ |
250 | ++ genprofile $sysctlgood:rw |
251 | ++ runchecktest "SYSCTL /proc (confinement/good rw w/ rw perm)" pass $sysctlgood rw |
252 | ++ |
253 | ++ #test with profile giving access to sysctlbad but access to sysctlgood |
254 | ++ genprofile $sysctlbad:r |
255 | ++ runchecktest "SYSCTL /proc (confinement/bad r w/ r perm)" fail $sysctlgood r |
256 | ++ |
257 | ++ genprofile $sysctlbad:w |
258 | ++ runchecktest "SYSCTL /proc (confinement/bad r w/ w perm)" fail $sysctlgood r |
259 | ++ |
260 | ++ genprofile $sysctlbad:rw |
261 | ++ runchecktest "SYSCTL /proc (confinement/bad r w/ rw perm)" fail $sysctlgood r |
262 | ++ |
263 | ++ genprofile $sysctlbad:r |
264 | ++ value=`cat $sysctlgood` |
265 | ++ runchecktest "SYSCTL /proc (confinement/bad w w/ r perm)" fail $sysctlgood w $value |
266 | ++ |
267 | ++ genprofile $sysctlbad:w |
268 | ++ value=`cat $sysctlgood` |
269 | ++ runchecktest "SYSCTL /proc (confinement/bad w w/ w perm)" fail $sysctlgood w $value |
270 | ++ |
271 | ++ genprofile $sysctlbad:rw |
272 | ++ value=`cat $sysctlgood` |
273 | ++ runchecktest "SYSCTL /proc (confinement/bad w w/ rw perm)" fail $sysctlgood w $value |
274 | ++ |
275 | ++ genprofile $sysctlbad:r |
276 | ++ runchecktest "SYSCTL /proc (confinement/bad rw w/ r perm)" fail $sysctlgood rw |
277 | ++ |
278 | ++ genprofile $sysctlbad:w |
279 | ++ runchecktest "SYSCTL /proc (confinement/bad rw w/ w perm)" fail $sysctlgood rw |
280 | ++ |
281 | ++ genprofile $sysctlbad:rw |
282 | ++ runchecktest "SYSCTL /proc (confinement/bad rw w/ rw perm)" fail $sysctlgood rw |
283 | ++} |
284 | ++ |
285 | ++ |
286 | ++# check if the kernel supports CONFIG_SYSCTL_SYSCALL |
287 | ++# generally we want to encourage kernels to disable it, but if it's |
288 | ++# enabled we want to test against it |
289 | + settest syscall_sysctl |
290 | +- |
291 | +-runchecktest "SYSCTL (no confinement read only)" pass ro |
292 | +- |
293 | +-runchecktest "SYSCTL (no confinement rw)" pass |
294 | +- |
295 | +-genprofile $sysctlgood:r |
296 | +-runchecktest "SYSCTL (confinement/good r w/ r perm)" pass ro |
297 | +- |
298 | +-genprofile $sysctlgood:r |
299 | +-runchecktest "SYSCTL (confinement/good rw w/ r perm)" fail |
300 | +- |
301 | +-genprofile $sysctlgood:w |
302 | +-runchecktest "SYSCTL (confinement/good r w/ w perm)" fail ro |
303 | +- |
304 | +-genprofile $sysctlgood:w |
305 | +-runchecktest "SYSCTL (confinement/good rw w/ w perm)" fail |
306 | +- |
307 | +-genprofile $sysctlgood:rw |
308 | +-runchecktest "SYSCTL (confinement/good r w/ rw perm)" pass ro |
309 | +- |
310 | +-genprofile $sysctlgood:rw |
311 | +-runchecktest "SYSCTL (confinement/good rw w/ rw perm)" pass |
312 | +- |
313 | +-genprofile $sysctlbad:r |
314 | +-runchecktest "SYSCTL (confinement/bad r w/ r perm)" fail ro |
315 | +- |
316 | +-genprofile $sysctlbad:r |
317 | +-runchecktest "SYSCTL (confinement/bad rw w/ r perm)" fail ro |
318 | +- |
319 | +-genprofile $sysctlbad:w |
320 | +-runchecktest "SYSCTL (confinement/bad r w/ w perm)" fail ro |
321 | +- |
322 | +-genprofile $sysctlbad:w |
323 | +-runchecktest "SYSCTL (confinement/bad rw w/ w perm)" fail |
324 | +- |
325 | +-genprofile $sysctlbad:rw |
326 | +-runchecktest "SYSCTL (confinement/bad r w/ rw perm)" fail ro |
327 | +- |
328 | +-genprofile $sysctlbad:rw |
329 | +-runchecktest "SYSCTL (confinement/bad rw w/ rw perm)" fail |
330 | ++res=$(${test} ro) |
331 | ++if [ $? -ne 0 -a $res == "FAIL: sysctl read failed - Function not implemented" ] ; then |
332 | ++ echo " WARNING: syscall sysctl not implemented, skipping tests ..." |
333 | ++else |
334 | ++ test_syscall_sysctl |
335 | ++fi |
336 | + |
337 | + # now test /proc/sys/ paths |
338 | +- |
339 | +-settest sysctl_proc |
340 | +- |
341 | +-#unconfined |
342 | +-runchecktest "SYSCTL /proc (read no confinement)" pass $sysctlgood r |
343 | +-value=`cat $sysctlgood` |
344 | +-runchecktest "SYSCTL /proc (write no confinement)" pass $sysctlgood w $value |
345 | +-runchecktest "SYSCTL /proc (rw no confinement)" pass $sysctlgood rw |
346 | +- |
347 | +-#test with profile giving access to sysctlgood |
348 | +-genprofile $sysctlgood:r |
349 | +-runchecktest "SYSCTL /proc (confinement/good r w/ r perm)" pass $sysctlgood r |
350 | +- |
351 | +-genprofile $sysctlgood:w |
352 | +-runchecktest "SYSCTL /proc (confinement/good r w/ w perm)" fail $sysctlgood r |
353 | +- |
354 | +-genprofile $sysctlgood:rw |
355 | +-runchecktest "SYSCTL /proc (confinement/good r w/ rw perm)" pass $sysctlgood r |
356 | +- |
357 | +-genprofile $sysctlgood:r |
358 | +-value=`cat $sysctlgood` |
359 | +-runchecktest "SYSCTL /proc (confinement/good w w/ r perm)" fail $sysctlgood w $value |
360 | +- |
361 | +-genprofile $sysctlgood:w |
362 | +-value=`cat $sysctlgood` |
363 | +-runchecktest "SYSCTL /proc (confinement/good w w/ w perm)" pass $sysctlgood w $value |
364 | +- |
365 | +-genprofile $sysctlgood:rw |
366 | +-value=`cat $sysctlgood` |
367 | +-runchecktest "SYSCTL /proc (confinement/good w w/ rw perm)" pass $sysctlgood w $value |
368 | +- |
369 | +-genprofile $sysctlgood:r |
370 | +-runchecktest "SYSCTL /proc (confinement/good rw w/ r perm)" fail $sysctlgood rw |
371 | +- |
372 | +-genprofile $sysctlgood:w |
373 | +-runchecktest "SYSCTL /proc (confinement/good rw w/ w perm)" fail $sysctlgood rw |
374 | +- |
375 | +-genprofile $sysctlgood:rw |
376 | +-runchecktest "SYSCTL /proc (confinement/good rw w/ rw perm)" pass $sysctlgood rw |
377 | +- |
378 | +-#test with profile giving access to sysctlbad but access to sysctlgood |
379 | +-genprofile $sysctlbad:r |
380 | +-runchecktest "SYSCTL /proc (confinement/bad r w/ r perm)" fail $sysctlgood r |
381 | +- |
382 | +-genprofile $sysctlbad:w |
383 | +-runchecktest "SYSCTL /proc (confinement/bad r w/ w perm)" fail $sysctlgood r |
384 | +- |
385 | +-genprofile $sysctlbad:rw |
386 | +-runchecktest "SYSCTL /proc (confinement/bad r w/ rw perm)" fail $sysctlgood r |
387 | +- |
388 | +-genprofile $sysctlbad:r |
389 | +-value=`cat $sysctlgood` |
390 | +-runchecktest "SYSCTL /proc (confinement/bad w w/ r perm)" fail $sysctlgood w $value |
391 | +- |
392 | +-genprofile $sysctlbad:w |
393 | +-value=`cat $sysctlgood` |
394 | +-runchecktest "SYSCTL /proc (confinement/bad w w/ w perm)" fail $sysctlgood w $value |
395 | +- |
396 | +-genprofile $sysctlbad:rw |
397 | +-value=`cat $sysctlgood` |
398 | +-runchecktest "SYSCTL /proc (confinement/bad w w/ rw perm)" fail $sysctlgood w $value |
399 | +- |
400 | +-genprofile $sysctlbad:r |
401 | +-runchecktest "SYSCTL /proc (confinement/bad rw w/ r perm)" fail $sysctlgood rw |
402 | +- |
403 | +-genprofile $sysctlbad:w |
404 | +-runchecktest "SYSCTL /proc (confinement/bad rw w/ w perm)" fail $sysctlgood rw |
405 | +- |
406 | +-genprofile $sysctlbad:rw |
407 | +-runchecktest "SYSCTL /proc (confinement/bad rw w/ rw perm)" fail $sysctlgood rw |
408 | +- |
409 | +- |
410 | +- |
411 | ++if [ ! -f "${sysctlgood}" ] ; then |
412 | ++ echo " WARNING: proc sysctl path not found, /proc not mounted? Skipping tests ..." |
413 | ++else |
414 | ++ test_sysctl_proc |
415 | ++fi |
416 | + |
417 | |
418 | === added file 'debian/patches/fix-typo-in-dbus_write.patch' |
419 | --- debian/patches/fix-typo-in-dbus_write.patch 1970-01-01 00:00:00 +0000 |
420 | +++ debian/patches/fix-typo-in-dbus_write.patch 2014-03-28 00:01:01 +0000 |
421 | @@ -0,0 +1,22 @@ |
422 | +Description: utils: Fix typo in write_dbus() |
423 | + . |
424 | + Signed-off-by: Tyler Hicks <tyhicks@canonical.com> |
425 | + Acked-by: Steve Beattie <steve@nxnw.org> |
426 | +Origin: commit, revision id: tyhicks@canonical.com-20140320191940-ygolw53q0oaqw3k0 |
427 | +Author: Tyler Hicks <tyhicks@canonical.com> |
428 | +Last-Update: 2014-03-20 |
429 | +X-Bzr-Revision-Id: tyhicks@canonical.com-20140320191940-ygolw53q0oaqw3k0 |
430 | + |
431 | +=== modified file 'utils/apparmor/aa.py' |
432 | +--- old/utils/apparmor/aa.py 2014-03-16 15:06:42 +0000 |
433 | ++++ new/utils/apparmor/aa.py 2014-03-20 19:19:40 +0000 |
434 | +@@ -3265,7 +3265,7 @@ |
435 | + |
436 | + def write_dbus(prof_data, depth): |
437 | + data = write_dbus_rules(prof_data, depth, 'deny') |
438 | +- data += write_net_rules(prof_data, depth, 'allow') |
439 | ++ data += write_dbus_rules(prof_data, depth, 'allow') |
440 | + return data |
441 | + |
442 | + def write_link_rules(prof_data, depth, allow): |
443 | + |
444 | |
445 | === added file 'debian/patches/increase-swap-size.patch' |
446 | --- debian/patches/increase-swap-size.patch 1970-01-01 00:00:00 +0000 |
447 | +++ debian/patches/increase-swap-size.patch 2014-03-28 00:01:01 +0000 |
448 | @@ -0,0 +1,30 @@ |
449 | +Description: regression swap test: 640 KiB not enough swap for everyone |
450 | + . |
451 | + On ppc64el platforms, the minimum swapfile size is 640KiB. Our swap |
452 | + test aborts there because it creates a swapfile of size 512KiB. This |
453 | + patch adjusts the size to 768KiB, to satisfy ppc64el and to try |
454 | + to keep the size down for embedded and otherwise limited platforms |
455 | + (e.g. phones). |
456 | + . |
457 | + Signed-off-by: Steve Beattie <steve@nxnw.org> |
458 | + Acked-by: John Johansen <john.johansen@canonical.com> |
459 | +Origin: commit, revision id: sbeattie@ubuntu.com-20140320182851-iwz354gzejfxr3x6 |
460 | +Author: Steve Beattie <sbeattie@ubuntu.com> |
461 | +Last-Update: 2014-03-20 |
462 | +X-Bzr-Revision-Id: sbeattie@ubuntu.com-20140320182851-iwz354gzejfxr3x6 |
463 | + |
464 | +=== modified file 'tests/regression/apparmor/swap.sh' |
465 | +--- old/tests/regression/apparmor/swap.sh 2014-03-19 18:53:26 +0000 |
466 | ++++ new/tests/regression/apparmor/swap.sh 2014-03-20 18:28:51 +0000 |
467 | +@@ -29,7 +29,9 @@ |
468 | + |
469 | + swap_file=$tmpdir/swapfile |
470 | + |
471 | +-dd if=/dev/zero of=${swap_file} bs=1024 count=512 2> /dev/null |
472 | ++# ppc64el wants this to be larger than 640KiB |
473 | ++# arm/small machines want this as small as possible |
474 | ++dd if=/dev/zero of=${swap_file} bs=1024 count=768 2> /dev/null |
475 | + /sbin/mkswap -f ${swap_file} > /dev/null |
476 | + |
477 | + # TEST 1. Make sure can enable and disable swap unconfined |
478 | + |
479 | |
480 | === added file 'debian/patches/initialize-mount-flags.patch' |
481 | --- debian/patches/initialize-mount-flags.patch 1970-01-01 00:00:00 +0000 |
482 | +++ debian/patches/initialize-mount-flags.patch 2014-03-28 00:01:01 +0000 |
483 | @@ -0,0 +1,17 @@ |
484 | +Subject: Initialize mount flag variables |
485 | +Author: Steve Beattie <steve@nxnw.org> |
486 | +Origin: https://lists.ubuntu.com/archives/apparmor/2014-March/005498.html |
487 | + |
488 | +Index: apparmor-2.8.95~2430/parser/mount.c |
489 | +=================================================================== |
490 | +--- apparmor-2.8.95~2430.orig/parser/mount.c 2014-03-25 15:20:57.018085658 -0500 |
491 | ++++ apparmor-2.8.95~2430/parser/mount.c 2014-03-25 15:20:57.010085658 -0500 |
492 | +@@ -389,7 +389,7 @@ mnt_rule::mnt_rule(struct cond_entry *sr |
493 | + struct cond_entry *dst_conds __unused, char *mnt_point_p, |
494 | + int allow_p): |
495 | + mnt_point(mnt_point_p), device(device_p), trans(NULL), opts(NULL), |
496 | +- audit(0), deny(0) |
497 | ++ flags(0), inv_flags(0), audit(0), deny(0) |
498 | + { |
499 | + /* FIXME: dst_conds are ignored atm */ |
500 | + aa_class = AA_CLASS_MOUNT; |
501 | |
502 | === added file 'debian/patches/limited-mount-rule-support.patch' |
503 | --- debian/patches/limited-mount-rule-support.patch 1970-01-01 00:00:00 +0000 |
504 | +++ debian/patches/limited-mount-rule-support.patch 2014-03-28 00:01:01 +0000 |
505 | @@ -0,0 +1,222 @@ |
506 | +Description: utils: Add very limited support for mount rules |
507 | + . |
508 | + Bug: https://bugs.launchpad.net/bugs/1294825 |
509 | + . |
510 | + This patch is inspired by sbeattie's patch to add limited dbus rule |
511 | + support. It adds does very dumb parsing of mount rules. Basically, it |
512 | + stores mount, remount, and umount rules as raw strings wrapped in a |
513 | + class. |
514 | + . |
515 | + Signed-off-by: Tyler Hicks <tyhicks@canonical.com> |
516 | + Acked-by: Steve Beattie <steve@nxnw.org> |
517 | + Acked-by: Christian Boltz <apparmor@cboltz.de> |
518 | +Origin: commit, revision id: tyhicks@canonical.com-20140320192542-we2ydn5rk0p05dtt |
519 | +Author: Tyler Hicks <tyhicks@canonical.com> |
520 | +Bug: https://launchpad.net/bugs/1294825 |
521 | +Last-Update: 2014-03-20 |
522 | +X-Bzr-Revision-Id: tyhicks@canonical.com-20140320192542-we2ydn5rk0p05dtt |
523 | + |
524 | +=== modified file 'utils/apparmor/aa.py' |
525 | +--- old/utils/apparmor/aa.py 2014-03-20 19:19:40 +0000 |
526 | ++++ new/utils/apparmor/aa.py 2014-03-20 19:25:42 +0000 |
527 | +@@ -2616,6 +2616,7 @@ |
528 | + RE_NETWORK_FAMILY_TYPE = re.compile('\s+(\S+)\s+(\S+)\s*,$') |
529 | + RE_NETWORK_FAMILY = re.compile('\s+(\S+)\s*,$') |
530 | + RE_PROFILE_DBUS = re.compile('^\s*(audit\s+)?(allow\s+|deny\s+)?(dbus[^#]*\s*,)\s*(#.*)?$') |
531 | ++RE_PROFILE_MOUNT = re.compile('^\s*(audit\s+)?(allow\s+|deny\s+)?((mount|remount|umount)[^#]*\s*,)\s*(#.*)?$') |
532 | + |
533 | + # match anything that's not " or #, or matching quotes with anything except quotes inside |
534 | + __re_no_or_quoted_hash = '([^#"]|"[^"]*")*' |
535 | +@@ -2693,6 +2694,7 @@ |
536 | + profile_data[profile][hat]['allow']['netdomain'] = hasher() |
537 | + profile_data[profile][hat]['allow']['path'] = hasher() |
538 | + profile_data[profile][hat]['allow']['dbus'] = list() |
539 | ++ profile_data[profile][hat]['allow']['mount'] = list() |
540 | + # Save the initial comment |
541 | + if initial_comment: |
542 | + profile_data[profile][hat]['initial_comment'] = initial_comment |
543 | +@@ -2966,6 +2968,28 @@ |
544 | + dbus_rules.append(dbus_rule) |
545 | + profile_data[profile][hat][allow]['dbus'] = dbus_rules |
546 | + |
547 | ++ elif RE_PROFILE_MOUNT.search(line): |
548 | ++ matches = RE_PROFILE_MOUNT.search(line).groups() |
549 | ++ |
550 | ++ if not profile: |
551 | ++ raise AppArmorException(_('Syntax Error: Unexpected mount entry found in file: %s line: %s') % (file, lineno + 1)) |
552 | ++ |
553 | ++ audit = False |
554 | ++ if matches[0]: |
555 | ++ audit = True |
556 | ++ allow = 'allow' |
557 | ++ if matches[1] and matches[1].strip() == 'deny': |
558 | ++ allow = 'deny' |
559 | ++ mount = matches[2] |
560 | ++ |
561 | ++ mount_rule = parse_mount_rule(mount) |
562 | ++ mount_rule.audit = audit |
563 | ++ mount_rule.deny = (allow == 'deny') |
564 | ++ |
565 | ++ mount_rules = profile_data[profile][hat][allow].get('mount', list()) |
566 | ++ mount_rules.append(mount_rule) |
567 | ++ profile_data[profile][hat][allow]['mount'] = mount_rules |
568 | ++ |
569 | + elif RE_PROFILE_CHANGE_HAT.search(line): |
570 | + matches = RE_PROFILE_CHANGE_HAT.search(line).groups() |
571 | + |
572 | +@@ -3060,6 +3084,10 @@ |
573 | + # return aarules.DBUS_Rule() |
574 | + #print(line) |
575 | + |
576 | ++def parse_mount_rule(line): |
577 | ++ # XXX Do real parsing here |
578 | ++ return aarules.Raw_Mount_Rule(line) |
579 | ++ |
580 | + def separate_vars(vs): |
581 | + """Returns a list of all the values for a variable""" |
582 | + data = [] |
583 | +@@ -3268,6 +3296,24 @@ |
584 | + data += write_dbus_rules(prof_data, depth, 'allow') |
585 | + return data |
586 | + |
587 | ++def write_mount_rules(prof_data, depth, allow): |
588 | ++ pre = ' ' * depth |
589 | ++ data = [] |
590 | ++ |
591 | ++ # no mount rules, so return |
592 | ++ if not prof_data[allow].get('mount', False): |
593 | ++ return data |
594 | ++ |
595 | ++ for mount_rule in prof_data[allow]['mount']: |
596 | ++ data.append('%s%s' % (pre, mount_rule.serialize())) |
597 | ++ data.append('') |
598 | ++ return data |
599 | ++ |
600 | ++def write_mount(prof_data, depth): |
601 | ++ data = write_mount_rules(prof_data, depth, 'deny') |
602 | ++ data += write_mount_rules(prof_data, depth, 'allow') |
603 | ++ return data |
604 | ++ |
605 | + def write_link_rules(prof_data, depth, allow): |
606 | + pre = ' ' * depth |
607 | + data = [] |
608 | +@@ -3361,6 +3407,7 @@ |
609 | + data += write_capabilities(prof_data, depth) |
610 | + data += write_netdomain(prof_data, depth) |
611 | + data += write_dbus(prof_data, depth) |
612 | ++ data += write_mount(prof_data, depth) |
613 | + data += write_links(prof_data, depth) |
614 | + data += write_paths(prof_data, depth) |
615 | + data += write_change_profile(prof_data, depth) |
616 | +@@ -3509,6 +3556,7 @@ |
617 | + 'capability': write_capabilities, |
618 | + 'netdomain': write_netdomain, |
619 | + 'dbus': write_dbus, |
620 | ++ 'mount': write_mount, |
621 | + 'link': write_links, |
622 | + 'path': write_paths, |
623 | + 'change_profile': write_change_profile, |
624 | +@@ -3600,6 +3648,7 @@ |
625 | + data += write_capabilities(write_prof_data[name], depth) |
626 | + data += write_netdomain(write_prof_data[name], depth) |
627 | + data += write_dbus(write_prof_data[name], depth) |
628 | ++ data += write_mount(write_prof_data[name], depth) |
629 | + data += write_links(write_prof_data[name], depth) |
630 | + data += write_paths(write_prof_data[name], depth) |
631 | + data += write_change_profile(write_prof_data[name], depth) |
632 | + |
633 | +=== modified file 'utils/apparmor/rules.py' |
634 | +--- old/utils/apparmor/rules.py 2014-03-07 17:58:54 +0000 |
635 | ++++ new/utils/apparmor/rules.py 2014-03-20 19:25:42 +0000 |
636 | +@@ -55,3 +55,15 @@ |
637 | + return "%s%s%s" % ('audit ' if self.audit else '', |
638 | + 'deny ' if self.deny else '', |
639 | + self.rule) |
640 | ++ |
641 | ++class Raw_Mount_Rule(object): |
642 | ++ audit = False |
643 | ++ deny = False |
644 | ++ |
645 | ++ def __init__(self, rule): |
646 | ++ self.rule = rule |
647 | ++ |
648 | ++ def serialize(self): |
649 | ++ return "%s%s%s" % ('audit ' if self.audit else '', |
650 | ++ 'deny ' if self.deny else '', |
651 | ++ self.rule) |
652 | + |
653 | +=== added file 'utils/test/test-mount_parse.py' |
654 | +--- old/utils/test/test-mount_parse.py 1970-01-01 00:00:00 +0000 |
655 | ++++ new/utils/test/test-mount_parse.py 2014-03-20 19:25:42 +0000 |
656 | +@@ -0,0 +1,70 @@ |
657 | ++#! /usr/bin/env python |
658 | ++# ------------------------------------------------------------------ |
659 | ++# |
660 | ++# Copyright (C) 2014 Canonical Ltd. |
661 | ++# |
662 | ++# This program is free software; you can redistribute it and/or |
663 | ++# modify it under the terms of version 2 of the GNU General Public |
664 | ++# License published by the Free Software Foundation. |
665 | ++# |
666 | ++# ------------------------------------------------------------------ |
667 | ++ |
668 | ++import apparmor.aa as aa |
669 | ++import unittest |
670 | ++ |
671 | ++class AAParseMountTest(unittest.TestCase): |
672 | ++ |
673 | ++ def test_parse_plain_mount_rule(self): |
674 | ++ rule = 'mount,' |
675 | ++ mount = aa.parse_mount_rule(rule) |
676 | ++ self.assertEqual(rule, mount.serialize(), |
677 | ++ 'mount object returned "%s", expected "%s"' % (mount.serialize(), rule)) |
678 | ++ |
679 | ++ def test_parse_ro_mount(self): |
680 | ++ rule = 'mount -o ro,' |
681 | ++ mount = aa.parse_mount_rule(rule) |
682 | ++ self.assertEqual(rule, mount.serialize(), |
683 | ++ 'mount object returned "%s", expected "%s"' % (mount.serialize(), rule)) |
684 | ++ |
685 | ++ def test_parse_rw_mount_with_mount_points(self): |
686 | ++ rule = 'mount -o rw /dev/sdb1 -> /mnt/external,' |
687 | ++ mount = aa.parse_mount_rule(rule) |
688 | ++ self.assertEqual(rule, mount.serialize(), |
689 | ++ 'mount object returned "%s", expected "%s"' % (mount.serialize(), rule)) |
690 | ++ |
691 | ++class AAParseRemountTest(unittest.TestCase): |
692 | ++ |
693 | ++ def test_parse_plain_remount_rule(self): |
694 | ++ rule = 'remount,' |
695 | ++ mount = aa.parse_mount_rule(rule) |
696 | ++ self.assertEqual(rule, mount.serialize(), |
697 | ++ 'mount object returned "%s", expected "%s"' % (mount.serialize(), rule)) |
698 | ++ |
699 | ++ def test_parse_ro_remount(self): |
700 | ++ rule = 'remount -o ro,' |
701 | ++ mount = aa.parse_mount_rule(rule) |
702 | ++ self.assertEqual(rule, mount.serialize(), |
703 | ++ 'mount object returned "%s", expected "%s"' % (mount.serialize(), rule)) |
704 | ++ |
705 | ++ def test_parse_ro_remount_with_mount_point(self): |
706 | ++ rule = 'remount -o ro /,' |
707 | ++ mount = aa.parse_mount_rule(rule) |
708 | ++ self.assertEqual(rule, mount.serialize(), |
709 | ++ 'mount object returned "%s", expected "%s"' % (mount.serialize(), rule)) |
710 | ++ |
711 | ++class AAParseUmountTest(unittest.TestCase): |
712 | ++ |
713 | ++ def test_parse_plain_umount_rule(self): |
714 | ++ rule = 'umount,' |
715 | ++ mount = aa.parse_mount_rule(rule) |
716 | ++ self.assertEqual(rule, mount.serialize(), |
717 | ++ 'mount object returned "%s", expected "%s"' % (mount.serialize(), rule)) |
718 | ++ |
719 | ++ def test_parse_umount_with_mount_point(self): |
720 | ++ rule = 'umount /mnt/external,' |
721 | ++ mount = aa.parse_mount_rule(rule) |
722 | ++ self.assertEqual(rule, mount.serialize(), |
723 | ++ 'mount object returned "%s", expected "%s"' % (mount.serialize(), rule)) |
724 | ++ |
725 | ++if __name__ == '__main__': |
726 | ++ unittest.main() |
727 | + |
728 | |
729 | === modified file 'debian/patches/series' |
730 | --- debian/patches/series 2014-03-20 03:36:23 +0000 |
731 | +++ debian/patches/series 2014-03-28 00:01:01 +0000 |
732 | @@ -24,3 +24,11 @@ |
733 | fix-ppc-endian-ftbfs.patch |
734 | opt_arg.patch |
735 | tests-cond-dbus.patch |
736 | +initialize-mount-flags.patch |
737 | +fix-typo-in-dbus_write.patch |
738 | +limited-mount-rule-support.patch |
739 | +bare-capability-rule-support.patch |
740 | +check-config-for-sysctl.patch |
741 | +increase-swap-size.patch |
742 | +test-v6-policy.patch |
743 | +test-mount-mediation.patch |
744 | |
745 | === added file 'debian/patches/test-mount-mediation.patch' |
746 | --- debian/patches/test-mount-mediation.patch 1970-01-01 00:00:00 +0000 |
747 | +++ debian/patches/test-mount-mediation.patch 2014-03-28 00:01:01 +0000 |
748 | @@ -0,0 +1,266 @@ |
749 | +Description: tests: Improve mount rule tests |
750 | + . |
751 | + The mount.sh regression test script was not testing with actual AppArmor |
752 | + mount rules. This patch improves mkprofile.pl by adding the ability to |
753 | + generate mount rules and adds tests to mount.sh that verify mount |
754 | + mediation is working properly. |
755 | + . |
756 | + Signed-off-by: John Johansen <john.johansen@canonical.com> |
757 | + [tyhicks: Fixed a couple typos and added fstype tests] |
758 | + Signed-off-by: Tyler Hicks <tyhicks@canonical.com> |
759 | + Acked-by: Steve Beattie <steve@nxnw.org> |
760 | +Origin: commit, revision id: tyhicks@canonical.com-20140327021004-2ydtqsjx74mjujfv |
761 | +Author: John Johansen <john.johansen@canonical.com> |
762 | +Last-Update: 2014-03-27 |
763 | +X-Bzr-Revision-Id: tyhicks@canonical.com-20140327021004-2ydtqsjx74mjujfv |
764 | + |
765 | +=== modified file 'tests/regression/apparmor/mkprofile.pl' |
766 | +--- old/tests/regression/apparmor/mkprofile.pl 2013-09-20 13:48:56 +0000 |
767 | ++++ new/tests/regression/apparmor/mkprofile.pl 2014-03-27 02:10:04 +0000 |
768 | +@@ -174,6 +174,78 @@ |
769 | + } |
770 | + } |
771 | + |
772 | ++sub gen_mount($) { |
773 | ++ my $rule = shift; |
774 | ++ my @rules = split (/:/, $rule); |
775 | ++ if (@rules == 2) { |
776 | ++ if ($rules[1] =~ /^ALL$/) { |
777 | ++ push (@{$output_rules{$hat}}, " mount,\n"); |
778 | ++ } else { |
779 | ++ push (@{$output_rules{$hat}}, " mount $rules[1],\n"); |
780 | ++ } |
781 | ++ } elsif (@rules == 3) { |
782 | ++ push (@{$output_rules{$hat}}, " mount $rules[1] $rules[2],\n"); |
783 | ++ } elsif (@rules == 4) { |
784 | ++ push (@{$output_rules{$hat}}, " mount $rules[1] $rules[2] $rules[3],\n"); |
785 | ++ } elsif (@rules == 5) { |
786 | ++ push (@{$output_rules{$hat}}, " mount $rules[1] $rules[2] $rules[3] $rules[4],\n"); |
787 | ++ } elsif (@rules == 6) { |
788 | ++ push (@{$output_rules{$hat}}, " mount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5],\n"); |
789 | ++ } elsif (@rules == 7) { |
790 | ++ push (@{$output_rules{$hat}}, " mount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5] $rules[6],\n"); |
791 | ++ } else { |
792 | ++ (!$nowarn) && print STDERR "Warning: invalid mount description '$rule', ignored\n"; |
793 | ++ } |
794 | ++} |
795 | ++ |
796 | ++sub gen_remount($) { |
797 | ++ my $rule = shift; |
798 | ++ my @rules = split (/:/, $rule); |
799 | ++ if (@rules == 2) { |
800 | ++ if ($rules[1] =~ /^ALL$/) { |
801 | ++ push (@{$output_rules{$hat}}, " remount,\n"); |
802 | ++ } else { |
803 | ++ push (@{$output_rules{$hat}}, " remount $rules[1],\n"); |
804 | ++ } |
805 | ++ } elsif (@rules == 3) { |
806 | ++ push (@{$output_rules{$hat}}, " remount $rules[1] $rules[2],\n"); |
807 | ++ } elsif (@rules == 4) { |
808 | ++ push (@{$output_rules{$hat}}, " remount $rules[1] $rules[2] $rules[3],\n"); |
809 | ++ } elsif (@rules == 5) { |
810 | ++ push (@{$output_rules{$hat}}, " remount $rules[1] $rules[2] $rules[3] $rules[4],\n"); |
811 | ++ } elsif (@rules == 6) { |
812 | ++ push (@{$output_rules{$hat}}, " remount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5],\n"); |
813 | ++ } elsif (@rules == 7) { |
814 | ++ push (@{$output_rules{$hat}}, " remount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5] $rules[6],\n"); |
815 | ++ } else { |
816 | ++ (!$nowarn) && print STDERR "Warning: invalid remount description '$rule', ignored\n"; |
817 | ++ } |
818 | ++} |
819 | ++ |
820 | ++sub gen_umount($) { |
821 | ++ my $rule = shift; |
822 | ++ my @rules = split (/:/, $rule); |
823 | ++ if (@rules == 2) { |
824 | ++ if ($rules[1] =~ /^ALL$/) { |
825 | ++ push (@{$output_rules{$hat}}, " umount,\n"); |
826 | ++ } else { |
827 | ++ push (@{$output_rules{$hat}}, " umount $rules[1],\n"); |
828 | ++ } |
829 | ++ } elsif (@rules == 3) { |
830 | ++ push (@{$output_rules{$hat}}, " umount $rules[1] $rules[2],\n"); |
831 | ++ } elsif (@rules == 4) { |
832 | ++ push (@{$output_rules{$hat}}, " umount $rules[1] $rules[2] $rules[3],\n"); |
833 | ++ } elsif (@rules == 5) { |
834 | ++ push (@{$output_rules{$hat}}, " umount $rules[1] $rules[2] $rules[3] $rules[4],\n"); |
835 | ++ } elsif (@rules == 6) { |
836 | ++ push (@{$output_rules{$hat}}, " umount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5],\n"); |
837 | ++ } elsif (@rules == 7) { |
838 | ++ push (@{$output_rules{$hat}}, " umount $rules[1] $rules[2] $rules[3] $rules[4] $rules[5] $rules[6],\n"); |
839 | ++ } else { |
840 | ++ (!$nowarn) && print STDERR "Warning: invalid umount description '$rule', ignored\n"; |
841 | ++ } |
842 | ++} |
843 | ++ |
844 | + sub gen_file($) { |
845 | + my $rule = shift; |
846 | + my @rules = split (/:/, $rule); |
847 | +@@ -260,6 +332,12 @@ |
848 | + gen_network($rule); |
849 | + } elsif ($rule =~ /^cap:/) { |
850 | + gen_cap($rule); |
851 | ++ } elsif ($rule =~ /^mount:/) { |
852 | ++ gen_mount($rule); |
853 | ++ } elsif ($rule =~ /^remount:/) { |
854 | ++ gen_remount($rule); |
855 | ++ } elsif ($rule =~ /^umount:/) { |
856 | ++ gen_umount($rule); |
857 | + } elsif ($rule =~ /^flag:/) { |
858 | + gen_flag($rule); |
859 | + } elsif ($rule =~ /^hat:/) { |
860 | + |
861 | +=== modified file 'tests/regression/apparmor/mount.sh' |
862 | +--- old/tests/regression/apparmor/mount.sh 2012-02-24 12:29:08 +0000 |
863 | ++++ new/tests/regression/apparmor/mount.sh 2014-03-27 02:10:04 +0000 |
864 | +@@ -28,11 +28,29 @@ |
865 | + |
866 | + mount_file=$tmpdir/mountfile |
867 | + mount_point=$tmpdir/mountpoint |
868 | ++mount_bad=$tmpdir/mountbad |
869 | + loop_device="unset" |
870 | ++fstype="ext2" |
871 | ++ |
872 | ++setup_mnt() { |
873 | ++ /bin/mount -t${fstype} ${loop_device} ${mount_point} |
874 | ++# /bin/mount -t${fstype} ${loop_device} ${mount_bad} |
875 | ++} |
876 | ++remove_mnt() { |
877 | ++ mountpoint -q "${mount_point}" |
878 | ++ if [ $? -eq 0 ] ; then |
879 | ++ /bin/umount -t${fstype} ${mount_point} |
880 | ++ fi |
881 | ++ mountpoint -q "${mount_bad}" |
882 | ++ if [ $? -eq 0 ] ; then |
883 | ++ /bin/umount -t${fstype} ${mount_bad} |
884 | ++ fi |
885 | ++} |
886 | + |
887 | + dd if=/dev/zero of=${mount_file} bs=1024 count=512 2> /dev/null |
888 | +-/sbin/mkfs -text2 -F ${mount_file} > /dev/null 2> /dev/null |
889 | ++/sbin/mkfs -t${fstype} -F ${mount_file} > /dev/null 2> /dev/null |
890 | + /bin/mkdir ${mount_point} |
891 | ++/bin/mkdir ${mount_bad} |
892 | + |
893 | + # in a modular udev world, the devices won't exist until the loopback |
894 | + # module is loaded. |
895 | +@@ -56,32 +74,95 @@ |
896 | + fatalerror 'Unable to find a free loop device' |
897 | + fi |
898 | + |
899 | ++ |
900 | + # TEST 1. Make sure can mount and umount unconfined |
901 | +- |
902 | + runchecktest "MOUNT (unconfined)" pass mount ${loop_device} ${mount_point} |
903 | ++remove_mnt |
904 | ++ |
905 | ++setup_mnt |
906 | + runchecktest "UMOUNT (unconfined)" pass umount ${loop_device} ${mount_point} |
907 | +- |
908 | +-# TEST A2. confine MOUNT |
909 | +- |
910 | +-genprofile |
911 | +-runchecktest "MOUNT (confined)" fail mount ${loop_device} ${mount_point} |
912 | +- |
913 | +-# TEST A3. confine MOUNT - cap sys_admin is not sufficient to mount |
914 | +-genprofile capability:sys_admin |
915 | +-runchecktest "MOUNT (confined)" fail mount ${loop_device} ${mount_point} |
916 | +- |
917 | +-/bin/umount -text2 ${mount_point} |
918 | +- |
919 | +-# TEST A4. confine UMOUNT |
920 | +- |
921 | +-/bin/mount -text2 ${loop_device} ${mount_point} |
922 | +- |
923 | +-genprofile |
924 | +-runchecktest "UMOUNT (confined)" fail umount ${loop_device} ${mount_point} |
925 | +- |
926 | +-# TEST A4. confine UMOUNT - cap sys_admin allows unmount |
927 | +-genprofile capability:sys_admin |
928 | +-runchecktest "UMOUNT (confined)" pass umount ${loop_device} ${mount_point} |
929 | ++remove_mnt |
930 | ++ |
931 | ++# TEST A2. confine MOUNT no perms |
932 | ++genprofile |
933 | ++runchecktest "MOUNT (confined no perm)" fail mount ${loop_device} ${mount_point} |
934 | ++remove_mnt |
935 | ++ |
936 | ++setup_mnt |
937 | ++runchecktest "UMOUNT (confined no perm)" fail umount ${loop_device} ${mount_point} |
938 | ++remove_mnt |
939 | ++ |
940 | ++ |
941 | ++if [ "$(have_features mount)" != "true" ] ; then |
942 | ++ genprofile capability:sys_admin |
943 | ++ runchecktest "MOUNT (confined cap)" pass mount ${loop_device} ${mount_point} |
944 | ++ remove_mnt |
945 | ++ |
946 | ++ setup_mnt |
947 | ++ runchecktest "UMOUNT (confined cap)" pass umount ${loop_device} ${mount_point} |
948 | ++ remove_mnt |
949 | ++else |
950 | ++ echo " using mount rules ..." |
951 | ++ |
952 | ++ genprofile capability:sys_admin |
953 | ++ runchecktest "MOUNT (confined cap)" fail mount ${loop_device} ${mount_point} |
954 | ++ remove_mnt |
955 | ++ |
956 | ++ setup_mnt |
957 | ++ runchecktest "UMOUNT (confined cap)" fail umount ${loop_device} ${mount_point} |
958 | ++ remove_mnt |
959 | ++ |
960 | ++ |
961 | ++ genprofile mount:ALL |
962 | ++ runchecktest "MOUNT (confined mount:ALL)" fail mount ${loop_device} ${mount_point} |
963 | ++ remove_mnt |
964 | ++ |
965 | ++ |
966 | ++ genprofile "mount:-> ${mount_point}/" |
967 | ++ runchecktest "MOUNT (confined bad mntpnt mount -> mntpnt)" fail mount ${loop_device} ${mount_bad} |
968 | ++ remove_mnt |
969 | ++ |
970 | ++ runchecktest "MOUNT (confined mount -> mntpnt)" fail mount ${loop_device} ${mount_point} |
971 | ++ remove_mnt |
972 | ++ |
973 | ++ |
974 | ++ |
975 | ++ genprofile umount:ALL |
976 | ++ setup_mnt |
977 | ++ runchecktest "UMOUNT (confined umount:ALL)" fail umount ${loop_device} ${mount_point} |
978 | ++ remove_mnt |
979 | ++ |
980 | ++ |
981 | ++ genprofile mount:ALL cap:sys_admin |
982 | ++ runchecktest "MOUNT (confined cap mount:ALL)" pass mount ${loop_device} ${mount_point} |
983 | ++ remove_mnt |
984 | ++ |
985 | ++ |
986 | ++ genprofile cap:sys_admin "mount:-> ${mount_point}/" |
987 | ++ runchecktest "MOUNT (confined bad mntpnt cap mount -> mntpnt)" fail mount ${loop_device} ${mount_bad} |
988 | ++ remove_mnt |
989 | ++ |
990 | ++ runchecktest "MOUNT (confined cap mount -> mntpnt)" pass mount ${loop_device} ${mount_point} |
991 | ++ remove_mnt |
992 | ++ |
993 | ++ |
994 | ++ genprofile cap:sys_admin "mount:fstype=${fstype}XXX" |
995 | ++ runchecktest "MOUNT (confined cap mount bad fstype)" fail mount ${loop_device} ${mount_point} |
996 | ++ remove_mnt |
997 | ++ |
998 | ++ genprofile cap:sys_admin "mount:fstype=${fstype}" |
999 | ++ runchecktest "MOUNT (confined cap mount fstype)" pass mount ${loop_device} ${mount_point} |
1000 | ++ remove_mnt |
1001 | ++ |
1002 | ++ |
1003 | ++ genprofile cap:sys_admin umount:ALL |
1004 | ++ setup_mnt |
1005 | ++ runchecktest "UMOUNT (confined cap umount:ALL)" pass umount ${loop_device} ${mount_point} |
1006 | ++ remove_mnt |
1007 | ++ |
1008 | ++fi |
1009 | ++ |
1010 | ++#need tests for move mount, remount, bind mount, pivot root, chroot |
1011 | + |
1012 | + # cleanup, umount file |
1013 | + /bin/umount ${loop_device} > /dev/null 2> /dev/null || /sbin/losetup -d ${loop_device} > /dev/null 2> /dev/null |
1014 | + |
1015 | |
1016 | === added file 'debian/patches/test-v6-policy.patch' |
1017 | --- debian/patches/test-v6-policy.patch 1970-01-01 00:00:00 +0000 |
1018 | +++ debian/patches/test-v6-policy.patch 2014-03-28 00:01:01 +0000 |
1019 | @@ -0,0 +1,147 @@ |
1020 | +Description: tests: Update the regression tests for v6 policy |
1021 | + . |
1022 | + This updates the regression tests for v6 policy. It refactors the |
1023 | + required_features test into a have_features fn, and a new |
1024 | + requires_features fn (renamed to catch all instances make sure they |
1025 | + where right) |
1026 | + . |
1027 | + The have_features fn is then applied to several test to make them |
1028 | + conditionally apply based off of availability of the feature |
1029 | + and policy version. |
1030 | + . |
1031 | + Signed-off-by: John Johansen <john.johansen@canonical.com> |
1032 | + Acked-by: Tyler Hicks <tyhicks@canonical.com> |
1033 | +Origin: commit, revision id: tyhicks@canonical.com-20140327020859-njwpwlyvqjbrurvl |
1034 | +Author: John Johansen <john.johansen@canonical.com> |
1035 | +Last-Update: 2014-03-27 |
1036 | +X-Bzr-Revision-Id: tyhicks@canonical.com-20140327020859-njwpwlyvqjbrurvl |
1037 | + |
1038 | +=== modified file 'tests/regression/apparmor/dbus_eavesdrop.sh' |
1039 | +--- old/tests/regression/apparmor/dbus_eavesdrop.sh 2013-12-06 19:19:33 +0000 |
1040 | ++++ new/tests/regression/apparmor/dbus_eavesdrop.sh 2014-03-27 02:08:59 +0000 |
1041 | +@@ -18,7 +18,7 @@ |
1042 | + bin=$pwd |
1043 | + |
1044 | + . $bin/prologue.inc |
1045 | +-required_features dbus |
1046 | ++requires_features dbus |
1047 | + . $bin/dbus.inc |
1048 | + |
1049 | + args="--session" |
1050 | + |
1051 | +=== modified file 'tests/regression/apparmor/dbus_message.sh' |
1052 | +--- old/tests/regression/apparmor/dbus_message.sh 2013-08-29 19:34:13 +0000 |
1053 | ++++ new/tests/regression/apparmor/dbus_message.sh 2014-03-27 02:08:59 +0000 |
1054 | +@@ -18,7 +18,7 @@ |
1055 | + bin=$pwd |
1056 | + |
1057 | + . $bin/prologue.inc |
1058 | +-required_features dbus |
1059 | ++requires_features dbus |
1060 | + . $bin/dbus.inc |
1061 | + |
1062 | + listnames="--type=method_call --session --name=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListNames" |
1063 | + |
1064 | +=== modified file 'tests/regression/apparmor/dbus_service.sh' |
1065 | +--- old/tests/regression/apparmor/dbus_service.sh 2013-08-20 19:14:03 +0000 |
1066 | ++++ new/tests/regression/apparmor/dbus_service.sh 2014-03-27 02:08:59 +0000 |
1067 | +@@ -17,7 +17,7 @@ |
1068 | + bin=$pwd |
1069 | + |
1070 | + . $bin/prologue.inc |
1071 | +-required_features dbus |
1072 | ++requires_features dbus |
1073 | + . $bin/dbus.inc |
1074 | + |
1075 | + service="--$bus --name=$dest $path $iface" |
1076 | + |
1077 | +=== modified file 'tests/regression/apparmor/prologue.inc' |
1078 | +--- old/tests/regression/apparmor/prologue.inc 2013-09-28 00:33:09 +0000 |
1079 | ++++ new/tests/regression/apparmor/prologue.inc 2014-03-27 02:08:59 +0000 |
1080 | +@@ -21,19 +21,32 @@ |
1081 | + # |
1082 | + # For this file, functions are first, entry point code is at end, see "MAIN" |
1083 | + |
1084 | +-required_features() |
1085 | ++#use $() to retreive the failure message or "true" if success |
1086 | ++have_features() |
1087 | + { |
1088 | + if [ ! -e "/sys/kernel/security/apparmor/features/" ] ; then |
1089 | +- echo "Kernel feature masks not supported. Skipping tests ..." |
1090 | +- exit 0 |
1091 | ++ echo "Kernel feature masks not supported." |
1092 | ++ return 1; |
1093 | + fi |
1094 | + |
1095 | + for f in $@ ; do |
1096 | + if [ ! -e "/sys/kernel/security/apparmor/features/$f" ] ; then |
1097 | +- echo "Required feature $f not available. Skipping tests ..." |
1098 | +- exit 0 |
1099 | ++ echo "Required feature '$f' not available." |
1100 | ++ return 2; |
1101 | + fi |
1102 | + done |
1103 | ++ |
1104 | ++ echo "true" |
1105 | ++ return 0; |
1106 | ++} |
1107 | ++ |
1108 | ++requires_features() |
1109 | ++{ |
1110 | ++ local res=$(have_features $@) |
1111 | ++ if [ "$res" != "true" ] ; then |
1112 | ++ echo "$res. Skipping tests ..." |
1113 | ++ exit 0 |
1114 | ++ fi |
1115 | + } |
1116 | + |
1117 | + requires_query_interface() |
1118 | + |
1119 | +=== modified file 'tests/regression/apparmor/tcp.sh' |
1120 | +--- old/tests/regression/apparmor/tcp.sh 2011-03-02 13:02:45 +0000 |
1121 | ++++ new/tests/regression/apparmor/tcp.sh 2014-03-27 02:08:59 +0000 |
1122 | +@@ -15,6 +15,7 @@ |
1123 | + bin=$pwd |
1124 | + |
1125 | + . $bin/prologue.inc |
1126 | ++requires_features network |
1127 | + |
1128 | + port=34567 |
1129 | + ip="127.0.0.1" |
1130 | + |
1131 | +=== modified file 'tests/regression/apparmor/unix_fd_server.sh' |
1132 | +--- old/tests/regression/apparmor/unix_fd_server.sh 2013-10-29 17:35:51 +0000 |
1133 | ++++ new/tests/regression/apparmor/unix_fd_server.sh 2014-03-27 02:08:59 +0000 |
1134 | +@@ -132,10 +132,12 @@ |
1135 | + sleep 1 |
1136 | + rm -f ${socket} |
1137 | + |
1138 | +-# FAIL - confined client, no access to the socket file |
1139 | +- |
1140 | +-genprofile $file:$okperm $socket:rw $fd_client:px -- image=$fd_client $file:$okperm |
1141 | +-runchecktest "fd passing; confined client w/o socket access" fail $file $socket $fd_client |
1142 | +- |
1143 | +-sleep 1 |
1144 | +-rm -f ${socket} |
1145 | ++if [ "$(have_features policy/versions/v6)" == "true" ] ; then |
1146 | ++ # FAIL - confined client, no access to the socket file |
1147 | ++ |
1148 | ++ genprofile $file:$okperm $socket:rw $fd_client:px -- image=$fd_client $file:$okperm |
1149 | ++ runchecktest "fd passing; confined client w/o socket access" fail $file $socket $fd_client |
1150 | ++ |
1151 | ++ sleep 1 |
1152 | ++ rm -f ${socket} |
1153 | ++fi |
1154 | + |
1155 | +=== modified file 'tests/regression/apparmor/unix_socket_file.sh' |
1156 | +--- old/tests/regression/apparmor/unix_socket_file.sh 2013-10-29 17:35:51 +0000 |
1157 | ++++ new/tests/regression/apparmor/unix_socket_file.sh 2014-03-27 02:08:59 +0000 |
1158 | +@@ -27,6 +27,7 @@ |
1159 | + bin=$pwd |
1160 | + |
1161 | + . $bin/prologue.inc |
1162 | ++requires_features policy/versions/v6 |
1163 | + |
1164 | + client=$bin/unix_socket_file_client |
1165 | + socket=${tmpdir}/unix_socket_file.sock |
1166 | + |
Looks great, thanks!