mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-04 08:15:21 +00:00
Compare commits
1188 Commits
v4.1.0-bet
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
93768757f5 | ||
|
7255edec09 | ||
|
7757c7130c | ||
|
e58f65d0c1 | ||
|
d72cc8f09e | ||
|
b80179834d | ||
|
5993ff21d2 | ||
|
0e755d24bb | ||
|
db74dda3c6 | ||
|
6f5a4219d7 | ||
|
0e58e3d7fb | ||
|
e7daccedc6 | ||
|
59e7fdd96a | ||
|
468f0096ee | ||
|
d993dfbb02 | ||
|
ba336533ac | ||
|
0d34f12d7e | ||
|
ebba635fa9 | ||
|
e477ccacfa | ||
|
9c5064529a | ||
|
862d8ec9fc | ||
|
fbd266c63f | ||
|
fcbf8e34ec | ||
|
01ab33202a | ||
|
24216d79e9 | ||
|
bef673f3c6 | ||
|
8210308508 | ||
|
a8875460ed | ||
|
eae49bf8de | ||
|
144d782ae8 | ||
|
df1a4c8782 | ||
|
4c30a0ac65 | ||
|
60ca491f21 | ||
|
43fa5f88a7 | ||
|
bb03d9ee08 | ||
|
d9866f0a24 | ||
|
fedcab2ad0 | ||
|
b6caed3b57 | ||
|
ae70dc38f8 | ||
|
51bdbec119 | ||
|
b8dee97ed3 | ||
|
8b2e2c3358 | ||
|
3faddfcf46 | ||
|
05458768cf | ||
|
cb0d66d55a | ||
|
0de9678d4f | ||
|
617d3021e8 | ||
|
63b46dd3d7 | ||
|
67382dcf15 | ||
|
d61295a249 | ||
|
a2f2ca6119 | ||
|
61e09c6ffa | ||
|
45a7cc1ed0 | ||
|
dc78be4db6 | ||
|
ea97cbedef | ||
|
514bf114b2 | ||
|
0430080a16 | ||
|
0f36070a54 | ||
|
392849e518 | ||
|
e8cd6e704a | ||
|
95d7f37520 | ||
|
c54c4a7e01 | ||
|
375470144f | ||
|
73bcf488b2 | ||
|
117df51e4a | ||
|
37185f50a4 | ||
|
b40ac50f49 | ||
|
87e0151c7c | ||
|
b9ed931c90 | ||
|
63ce02c01d | ||
|
e82ee9f4f4 | ||
|
4e8781c2a9 | ||
|
9ac6047f6c | ||
|
73f4f650e7 | ||
|
12e3557896 | ||
|
d8c57da6ba | ||
|
4de3b64e52 | ||
|
71a71e0fa7 | ||
|
36d32a81a2 | ||
|
84fbd87334 | ||
|
e757ca8e14 | ||
|
6673be07aa | ||
|
d3a49ff566 | ||
|
3e7ddc1ce5 | ||
|
2448655188 | ||
|
49cb0fe248 | ||
|
ab46c224cb | ||
|
b6ad58bbbe | ||
|
520db7a16c | ||
|
a966eac143 | ||
|
6841df4fe3 | ||
|
7fbbf791d3 | ||
|
f1773f4083 | ||
|
238221f379 | ||
|
efb13aac0a | ||
|
e4f3ef72ab | ||
|
69c248a431 | ||
|
ad16a5c5c0 | ||
|
380dbb84b8 | ||
|
000b56a323 | ||
|
630fd1c285 | ||
|
f78aa36547 | ||
|
ab9d359405 | ||
|
1c2f3582fe | ||
|
ccf74a7d0c | ||
|
1c9dc33949 | ||
|
9696d9e13f | ||
|
a833528f36 | ||
|
b2bfde5af0 | ||
|
fc636c7ff3 | ||
|
021f701e59 | ||
|
f16dd60f14 | ||
|
66cb0af47c | ||
|
2a37040415 | ||
|
dfbd2dc4b1 | ||
|
0ea74cd19d | ||
|
0f76632aec | ||
|
a13d8cfffb | ||
|
83e9be1035 | ||
|
91c5e9639c | ||
|
37a4b6cb81 | ||
|
a431a6e80b | ||
|
61a3a4862e | ||
|
2c685c0a17 | ||
|
7a8a28d47a | ||
|
17f91ba6e2 | ||
|
9a04cd58a6 | ||
|
c35d5eb6b2 | ||
|
6648f2cbeb | ||
|
f977530f39 | ||
|
58f5c2b7e8 | ||
|
6d2a0f6ba7 | ||
|
fd89e3185c | ||
|
237b17329f | ||
|
a606397417 | ||
|
b4ab583520 | ||
|
0dfa2fb9f2 | ||
|
af396a46ee | ||
|
9d2aca7945 | ||
|
d068678112 | ||
|
fbea9f00df | ||
|
3d25f1c80f | ||
|
a7003f4d49 | ||
|
bb422c1f01 | ||
|
76338c29f2 | ||
|
00a1152700 | ||
|
5f0fcfcae9 | ||
|
74ad177d07 | ||
|
2d58858c27 | ||
|
8cf0bda8d2 | ||
|
ddba3bb5b5 | ||
|
d68dea45f1 | ||
|
1f25a876ad | ||
|
9f70004058 | ||
|
ac81cafa4f | ||
|
bf207941ad | ||
|
ec2c363125 | ||
|
61d5f1a56f | ||
|
2634352a75 | ||
|
7af7fd35e5 | ||
|
65f8bd4d82 | ||
|
22023ce70b | ||
|
520227e4ea | ||
|
f9c20e4786 | ||
|
9fceca5b88 | ||
|
ba5e007287 | ||
|
1009a66e0c | ||
|
9a9f290099 | ||
|
9a035cb0ee | ||
|
d223751de0 | ||
|
2bfdcb780f | ||
|
6e643a1dab | ||
|
3c6db7c14b | ||
|
23deb55149 | ||
|
e426cc983d | ||
|
b019f9ef08 | ||
|
f8b5e5d9a4 | ||
|
d9d1776579 | ||
|
edf42d4f79 | ||
|
f382920950 | ||
|
3356f5ea0a | ||
|
e80ebea43f | ||
|
df41185eb2 | ||
|
421558041b | ||
|
d315f2b279 | ||
|
e637884554 | ||
|
f826e1dbea | ||
|
6e16efe703 | ||
|
0ee95d7e38 | ||
|
b46f7a426c | ||
|
db376c0458 | ||
|
29b4716377 | ||
|
229811de9a | ||
|
b850f19622 | ||
|
9f4dfdd57e | ||
|
2dacf287f2 | ||
|
34d889f6e9 | ||
|
1e74ae32ea | ||
|
cd7586776c | ||
|
2e7da63183 | ||
|
5aed9e8a50 | ||
|
79f2ea72b0 | ||
|
97dc70606b | ||
|
be143350fd | ||
|
9fabe25a9f | ||
|
f584505ac3 | ||
|
bef7b32d24 | ||
|
bece53da7b | ||
|
09330c63fa | ||
|
4b756c908c | ||
|
f9ba11a91e | ||
|
272ad36df8 | ||
|
c0e27e0dcb | ||
|
559754c6a4 | ||
|
b15a74ed7a | ||
|
170315d35f | ||
|
a5bae11cfd | ||
|
81c1b86373 | ||
|
d2d0f36244 | ||
|
50734c9689 | ||
|
e55646c41c | ||
|
52da04d951 | ||
|
59a636b403 | ||
|
e36b57857f | ||
|
84c3e629e4 | ||
|
c8dc701666 | ||
|
527054e0ab | ||
|
a0af1797de | ||
|
9b4d747f5e | ||
|
62123c6feb | ||
|
9cb72734eb | ||
|
e0f8bd4400 | ||
|
556396a172 | ||
|
2e875f22fe | ||
|
672bfcb72b | ||
|
e892093c06 | ||
|
acc0811c37 | ||
|
16fd1dab67 | ||
|
2a7b84cd73 | ||
|
c99a73f1a0 | ||
|
8652b61f67 | ||
|
2800aaedd0 | ||
|
d0cf1bff72 | ||
|
4094bc1a05 | ||
|
35275230a8 | ||
|
6da9502774 | ||
|
08f7fe6905 | ||
|
93c5a613b1 | ||
|
f38f156a76 | ||
|
1ac569ca2b | ||
|
0429251776 | ||
|
05237241cc | ||
|
2a81dfce1a | ||
|
7e0bc91a37 | ||
|
37a82e8b17 | ||
|
d9dedcb51c | ||
|
93c660e376 | ||
|
05a48f676b | ||
|
d94ff137ef | ||
|
f3178d79b8 | ||
|
ee3b5d746f | ||
|
fba1ced1bc | ||
|
6e9ff1fa61 | ||
|
6d0834da8e | ||
|
699507f90a | ||
|
b7ce9b81fa | ||
|
d6951bab60 | ||
|
2c1ed72cbb | ||
|
c07b0093d8 | ||
|
eda0461d58 | ||
|
763c0d9d61 | ||
|
90048417bb | ||
|
e6bedaac1d | ||
|
e8d5401a18 | ||
|
717e019928 | ||
|
3f37b671c3 | ||
|
b1097077f5 | ||
|
726cb2e1f1 | ||
|
3b012c3a24 | ||
|
95036df4a1 | ||
|
4808e34257 | ||
|
89c4ab100d | ||
|
330d202586 | ||
|
ec2549be2a | ||
|
b50ec6ca36 | ||
|
e56751cec0 | ||
|
89e2aa76eb | ||
|
09218c3d2f | ||
|
648336489e | ||
|
06e349345e | ||
|
711bbac5eb | ||
|
89c1aac5af | ||
|
521a81ebfb | ||
|
f8532f2d20 | ||
|
52c969c980 | ||
|
a7babf2391 | ||
|
e72ef56789 | ||
|
1d7a9c6765 | ||
|
7d33bde1ea | ||
|
62c3cf913a | ||
|
3b1819db37 | ||
|
004dc61959 | ||
|
260ef98a95 | ||
|
bd46a02e47 | ||
|
94c5cf047f | ||
|
71ea87966a | ||
|
c0fcd1698b | ||
|
3389230437 | ||
|
17ee87ad6b | ||
|
5526138483 | ||
|
18c0d003ef | ||
|
9c6ae3cf5c | ||
|
87e5a34252 | ||
|
7d5a021023 | ||
|
b50f516a78 | ||
|
02b7e41ef3 | ||
|
e510dfd0e7 | ||
|
d9028aea4e | ||
|
e278575799 | ||
|
70f2bfe306 | ||
|
a65924c28a | ||
|
5d8baf08b7 | ||
|
c9cd3606b0 | ||
|
5dba8b05b5 | ||
|
e69781ac73 | ||
|
d6e23dc80a | ||
|
b3cccb7c85 | ||
|
a8319dcf0c | ||
|
41a90d4177 | ||
|
b50eb2d18e | ||
|
115ff87df7 | ||
|
05ec9ee0f4 | ||
|
0e28172ca6 | ||
|
88c81906de | ||
|
ca8619313a | ||
|
b698daaf62 | ||
|
f25c2c4d9e | ||
|
d7ffb13e4e | ||
|
9b43c479a8 | ||
|
0d9e8312b8 | ||
|
fcd814bc51 | ||
|
26cd35b8b7 | ||
|
2518f525de | ||
|
d4a76c456d | ||
|
bcf1f7017e | ||
|
1d9e2c170a | ||
|
366c13f7dc | ||
|
96d327d28a | ||
|
af1a39653e | ||
|
6f480cb819 | ||
|
59d0708818 | ||
|
887ff42043 | ||
|
e3840b0dad | ||
|
446d6c51ce | ||
|
3aa71afd73 | ||
|
fa2d082741 | ||
|
c1ecdb4f26 | ||
|
2e88bcf9f3 | ||
|
a041f2beb8 | ||
|
27f5b623f7 | ||
|
ee08bfbc90 | ||
|
2678d0ca35 | ||
|
663e5bf90b | ||
|
8504cda668 | ||
|
7702b40359 | ||
|
99c5837195 | ||
|
5d71e19753 | ||
|
3347685898 | ||
|
c5642f9d43 | ||
|
7461536d52 | ||
|
675a99ac7b | ||
|
d4e795fe6d | ||
|
75959225b3 | ||
|
072d17a237 | ||
|
68c0dddf23 | ||
|
5d7fe96fd0 | ||
|
8c84b36b32 | ||
|
cda9153772 | ||
|
d8ddd665fc | ||
|
7b8232fe29 | ||
|
393444b7ba | ||
|
0e8afc278d | ||
|
c25f2d3407 | ||
|
b718c53b97 | ||
|
306b656ba2 | ||
|
ccf1b25d3d | ||
|
f34a7d0b28 | ||
|
491def4385 | ||
|
8138bc60d1 | ||
|
59d9d001a1 | ||
|
182db98c2a | ||
|
0d992be695 | ||
|
a23d44e28b | ||
|
896944d24d | ||
|
fe9c305ccd | ||
|
c09501ad59 | ||
|
4e1a8feb03 | ||
|
01d0cfbad9 | ||
|
08a67f3e20 | ||
|
d37496073b | ||
|
ec2cb47a47 | ||
|
d9ecaf60bc | ||
|
2c784709b2 | ||
|
08f9466d1c | ||
|
e4af4402c2 | ||
|
541c8ad94d | ||
|
ff2bd885e3 | ||
|
0a13a56f5c | ||
|
7ce768244d | ||
|
aecb02a22e | ||
|
f6042bf34d | ||
|
17b979cd55 | ||
|
4118ced01a | ||
|
90938de5c4 | ||
|
0dbfefc1a6 | ||
|
89e8fe9c1c | ||
|
b5894687ed | ||
|
171e0b1fa9 | ||
|
37666dd736 | ||
|
46a6c3b061 | ||
|
7726c86b79 | ||
|
ef25cb160f | ||
|
bc067f8a8f | ||
|
2df4bbd39b | ||
|
2b9f2d2cb7 | ||
|
63857a7972 | ||
|
315d999013 | ||
|
d4f75cec2b | ||
|
fa0746f2e2 | ||
|
e4943576d5 | ||
|
1aca4a1dcf | ||
|
ddd9af1aec | ||
|
0d6e447d24 | ||
|
3740f78c11 | ||
|
089539cbfc | ||
|
377753b5bf | ||
|
4c8ae4760b | ||
|
abe588cea4 | ||
|
69355d41f7 | ||
|
65e2cfa4e3 | ||
|
e949653b1a | ||
|
096c8df52b | ||
|
4623da695e | ||
|
7243029359 | ||
|
3b3dada5d9 | ||
|
0d1c694a66 | ||
|
a54e4e2cf9 | ||
|
6da10ef98f | ||
|
1f32c1175e | ||
|
dbf4c27154 | ||
|
ca0b695c0c | ||
|
d1108183a7 | ||
|
305ef867fb | ||
|
60218409cc | ||
|
f0c96c0d68 | ||
|
f490480558 | ||
|
ee3dfb4a5d | ||
|
c1dcc44201 | ||
|
4c3954f13d | ||
|
699d7b5c83 | ||
|
fda4f8140f | ||
|
b398ec61c9 | ||
|
372dcc8250 | ||
|
eaec0aa9d2 | ||
|
3516dcaa30 | ||
|
f43221d945 | ||
|
c9d41a3ebb | ||
|
ef2f6aa565 | ||
|
04ff259668 | ||
|
40e07b4561 | ||
|
1f08b5125d | ||
|
d364e2498a | ||
|
195a175b00 | ||
|
23c6e17f7f | ||
|
be2add00df | ||
|
07eef2823f | ||
|
bd500e2391 | ||
|
5edca7f64f | ||
|
af936812ee | ||
|
52fc40a9cb | ||
|
765d5b87ef | ||
|
64b920607b | ||
|
94ed11edff | ||
|
4473a42af7 | ||
|
ad3ecbd60a | ||
|
eb5a4f8628 | ||
|
7f12ccf695 | ||
|
616833d57d | ||
|
ce5e5a15fb | ||
|
b527256c0d | ||
|
6076d8c49a | ||
|
5554dd3b5b | ||
|
c9c29f02b1 | ||
|
4476eb8288 | ||
|
e030ff7ea9 | ||
|
f11c2032da | ||
|
a3d3a96ec5 | ||
|
8c12d358b0 | ||
|
8beac326a5 | ||
|
791935b9f8 | ||
|
b6654416b0 | ||
|
8ed0bddcc9 | ||
|
2fb0fa9964 | ||
|
e065dfb35a | ||
|
a82b16f059 | ||
|
e38db72fea | ||
|
541d3f4489 | ||
|
d9b3603f48 | ||
|
df5060c3d7 | ||
|
1ff9306c93 | ||
|
819802cdb3 | ||
|
b0b45b01c0 | ||
|
ae20b62c31 | ||
|
537fec8b36 | ||
|
2843c0f155 | ||
|
d06260859b | ||
|
2afdf1b214 | ||
|
2fe23fef17 | ||
|
e64bd1ccdf | ||
|
6faa8950ed | ||
|
ca0afa1afb | ||
|
ab1a455f05 | ||
|
ce87b44bae | ||
|
c1712c882c | ||
|
59124362d3 | ||
|
930218193b | ||
|
e80d5bd3d4 | ||
|
e71e27be70 | ||
|
bf2054d963 | ||
|
df0358062d | ||
|
0e8377cde9 | ||
|
dbe13a0b9d | ||
|
db7e3109cc | ||
|
3e7e9bf01f | ||
|
d52b301ee8 | ||
|
db87670698 | ||
|
2a87a92136 | ||
|
bc0426ef18 | ||
|
187c244056 | ||
|
45a945acd3 | ||
|
472181ae75 | ||
|
a20409cf1e | ||
|
1b87b7be5e | ||
|
c45ce5502e | ||
|
7abfc1baf7 | ||
|
125ef7a8cb | ||
|
71282550bb | ||
|
a5df123056 | ||
|
09573220d2 | ||
|
46335d58cf | ||
|
de61d374ec | ||
|
792aca634e | ||
|
eff9f442a3 | ||
|
4286423fe2 | ||
|
dad66f663b | ||
|
5730fb6d2d | ||
|
8711c7754b | ||
|
84bf3dee2d | ||
|
c56cbad5ea | ||
|
5f8863c7ca | ||
|
c268e5d11b | ||
|
473e791e4e | ||
|
083dc9652b | ||
|
3987bf0f33 | ||
|
e085a23b40 | ||
|
a410f347a3 | ||
|
b5ff20b5f1 | ||
|
697e53d752 | ||
|
dc583bc1d4 | ||
|
8af71cd5f5 | ||
|
4591ed63ba | ||
|
783f012074 | ||
|
d7a73847de | ||
|
dfe9d713f0 | ||
|
b4e6f0449b | ||
|
226ab5f050 | ||
|
49bc2d855f | ||
|
2747013d9b | ||
|
e1ae6fa81c | ||
|
55889ef783 | ||
|
532d4be050 | ||
|
52e0be286b | ||
|
0c4e452b46 | ||
|
af883bb706 | ||
|
87b60e4e94 | ||
|
c5016e1227 | ||
|
f9fc09d98c | ||
|
7b1f482541 | ||
|
cce5bd6e95 | ||
|
8e586e5492 | ||
|
4c64266f2b | ||
|
46b5abdddc | ||
|
a5b57609db | ||
|
c6ba1bd2fb | ||
|
ab3ca1a93f | ||
|
d5d2aa4d03 | ||
|
ef4ee955f4 | ||
|
b4caf8782c | ||
|
0e46a51738 | ||
|
61c332d25a | ||
|
41be573b75 | ||
|
2eaea1783f | ||
|
0c4f70d81b | ||
|
0da42927e4 | ||
|
8cef7278aa | ||
|
13caf52705 | ||
|
4c79c382cf | ||
|
da7288c710 | ||
|
594f391502 | ||
|
d8a96615d8 | ||
|
c7be379d1b | ||
|
91849b31e0 | ||
|
54fc2c2ba1 | ||
|
d01373a748 | ||
|
10f9574a71 | ||
|
6346163f56 | ||
|
0ab4fc0580 | ||
|
1f2175d854 | ||
|
03acee5939 | ||
|
b378da1f9c | ||
|
12787648a7 | ||
|
b5b1944f58 | ||
|
5bc1cd763c | ||
|
5585a4fc9e | ||
|
c157eb0cb6 | ||
|
e86fe8c96c | ||
|
49babf1d17 | ||
|
1ebd991155 | ||
|
e56dbc2084 | ||
|
cc31a0da22 | ||
|
9221d291ec | ||
|
e53cda33a3 | ||
|
7bd505aa65 | ||
|
5b874f45f3 | ||
|
0217af9d82 | ||
|
94d494d8fe | ||
|
965a678cb7 | ||
|
f2a6860767 | ||
|
002bf1339c | ||
|
42297559e8 | ||
|
a6c2efcb4a | ||
|
4fa3a02127 | ||
|
c67061c64f | ||
|
7a98040b1b | ||
|
fa28d65f44 | ||
|
fc3f27e255 | ||
|
8729c65bfe | ||
|
861be3904b | ||
|
503a89e5ef | ||
|
3ba204a635 | ||
|
6f961edaf9 | ||
|
f6a733de6a | ||
|
4831a854fe | ||
|
c9cfbb4668 | ||
|
38399e7720 | ||
|
4765bcd7bc | ||
|
998ee0595e | ||
|
54561af112 | ||
|
39cd3f6f21 | ||
|
5a44cbe661 | ||
|
4cfeb4a9ad | ||
|
b3ce87af23 | ||
|
62f93b400e | ||
|
bcf8c968db | ||
|
ebb82952bc | ||
|
14ceb92ca0 | ||
|
124f8efddc | ||
|
a0adb01631 | ||
|
f82c8471f5 | ||
|
7f68ed174c | ||
|
dfa331dfff | ||
|
d4582f232f | ||
|
8967dee5b9 | ||
|
d482aab419 | ||
|
219626c503 | ||
|
0acc138712 | ||
|
6336465edf | ||
|
32bf95bb1e | ||
|
b0422d5572 | ||
|
6405608442 | ||
|
237b5c0f73 | ||
|
3b7ee81f04 | ||
|
c6545b44bb | ||
|
265a1656d1 | ||
|
5f06df3868 | ||
|
af6dfe5b81 | ||
|
afd6aa0581 | ||
|
76647b33b1 | ||
|
c81eacacac | ||
|
ee8300545e | ||
|
6592daff90 | ||
|
3fa40935f5 | ||
|
1620887463 | ||
|
1b46ab10fd | ||
|
dfb7abf2a6 | ||
|
be38da7570 | ||
|
ed8b6cb663 | ||
|
9e05668d5a | ||
|
a0f551d5b7 | ||
|
9413658277 | ||
|
8efe442717 | ||
|
dcce4bc62f | ||
|
4c8c4a1d77 | ||
|
17a09d2987 | ||
|
625a919bb8 | ||
|
e32c267332 | ||
|
ab633ea82f | ||
|
08070fd2bb | ||
|
0a6f745621 | ||
|
f962bf65a9 | ||
|
a6ae543ae2 | ||
|
1486e04cdf | ||
|
7a7f88ddf3 | ||
|
e296d5b04c | ||
|
790c795f90 | ||
|
ef0d5b4cde | ||
|
667816fe43 | ||
|
e7807b3761 | ||
|
29637f19c9 | ||
|
5271d6a74a | ||
|
486c8c26fe | ||
|
c80ef6fb59 | ||
|
e750c6c66c | ||
|
065c1d67ca | ||
|
f98c1098b0 | ||
|
ffd38b7ac4 | ||
|
23df780544 | ||
|
a2ace0d5d7 | ||
|
29c618a11b | ||
|
f01a40a77c | ||
|
25676c4694 | ||
|
77cabf7dba | ||
|
3365e492a7 | ||
|
90143494fc | ||
|
1462e1c4b0 | ||
|
03215f46c4 | ||
|
ef880d325f | ||
|
7ce6819c53 | ||
|
be47567d27 | ||
|
2ab2c8f8a1 | ||
|
5c17df0219 | ||
|
42c8745e73 | ||
|
2b44cc09a6 | ||
|
85d57b7f06 | ||
|
5abbf31ce1 | ||
|
61d75a11ef | ||
|
817d5eed1d | ||
|
ba765e0eab | ||
|
a12004f96c | ||
|
63c944a01a | ||
|
f171f5ebc8 | ||
|
2e42c33f48 | ||
|
4fc3aacc8f | ||
|
7049d7b0c6 | ||
|
692e6850ba | ||
|
45e4c27cf0 | ||
|
371a9ff9ec | ||
|
7d537efcb0 | ||
|
9629bc8b6f | ||
|
1c2d79de7f | ||
|
43355fada5 | ||
|
c57d727482 | ||
|
b4cb33b488 | ||
|
7fa4b82235 | ||
|
fa33d7199b | ||
|
2c2e0478f8 | ||
|
699b598593 | ||
|
215fab71a5 | ||
|
cff25b8d17 | ||
|
8ed810756b | ||
|
5556de53c0 | ||
|
32116a50b0 | ||
|
72f9952a5f | ||
|
cd8b75abc0 | ||
|
ff03702fde | ||
|
e5a960a685 | ||
|
0eca26c6c2 | ||
|
78ea948e4b | ||
|
045bb7d77e | ||
|
e20400f10f | ||
|
63e3a04e30 | ||
|
50452e1147 | ||
|
3034c0772e | ||
|
4fb3dbc7b3 | ||
|
318fb30446 | ||
|
c3af6228fd | ||
|
97d7fa3f5f | ||
|
40e9b2a961 | ||
|
8c799f4eec | ||
|
027b508da8 | ||
|
bf7b80c478 | ||
|
25f16b239d | ||
|
369029dc07 | ||
|
84650beb2f | ||
|
cca842b897 | ||
|
05ddc61246 | ||
|
31e60baab2 | ||
|
57c57f198c | ||
|
4b410b67f1 | ||
|
d275dfdd42 | ||
|
fcee32a37e | ||
|
5d2a38e816 | ||
|
9d5b86bc9d | ||
|
8e431ebcd9 | ||
|
cd4bb05f20 | ||
|
1cc2a3bd86 | ||
|
ba60bfff85 | ||
|
c489631770 | ||
|
59957aa1d8 | ||
|
50f260df51 | ||
|
3ed5adb665 | ||
|
03b5a29b05 | ||
|
83270fcf68 | ||
|
67ee5f8b39 | ||
|
a3299ba133 | ||
|
58664c106c | ||
|
0551be806e | ||
|
728a8717e9 | ||
|
f66ada256a | ||
|
695e472b2c | ||
|
531f47676d | ||
|
c93d560f89 | ||
|
61a7ba2822 | ||
|
c5bbe79338 | ||
|
c5e495c56d | ||
|
a37c65957f | ||
|
b66dfd8bfb | ||
|
0da12fe7cb | ||
|
3a02d6d14c | ||
|
f5ed9cffe3 | ||
|
2e8a75195c | ||
|
578ab8da9d | ||
|
fe9b2542ca | ||
|
a0e6fbe32a | ||
|
792d1a5568 | ||
|
52babe8054 | ||
|
96718ea4d1 | ||
|
f9edc7d4c1 | ||
|
b2f713dd83 | ||
|
f2c398405b | ||
|
5cd3362a81 | ||
|
1d3d48cc2a | ||
|
b24a820e7a | ||
|
8212fa8be4 | ||
|
e0127767fd | ||
|
1cb11f5a89 | ||
|
2fdb5c799c | ||
|
fa58d3611a | ||
|
6d7b5df947 | ||
|
c768a7dc79 | ||
|
049b35dff0 | ||
|
f249c6d58f | ||
|
90c7af69c5 | ||
|
e8f1ac4791 | ||
|
9a1b538298 | ||
|
3469c62b36 | ||
|
472d002a96 | ||
|
459e5f9649 | ||
|
b3de4ef022 | ||
|
3302ae98e4 | ||
|
8a6eb170e1 | ||
|
76dcf46d4f | ||
|
a315d89a2b | ||
|
60f1b55ab5 | ||
|
d164e877f5 | ||
|
00e4908d9f | ||
|
62cdb6fd79 | ||
|
6a23c26a12 | ||
|
29e00fe11f | ||
|
239ae21b69 | ||
|
7031b5aeee | ||
|
9967ba9873 | ||
|
d305028502 | ||
|
11d121409d | ||
|
dfe771602d | ||
|
3c2aae3a22 | ||
|
b4adff2ce0 | ||
|
0307619ed9 | ||
|
1f60021979 | ||
|
4f006a660c | ||
|
46d994ddcd | ||
|
9cc40e2dca | ||
|
98c60e477d | ||
|
95f3bdf66b | ||
|
5fb91616e3 | ||
|
d9304c7653 | ||
|
d27377a62f | ||
|
434e34bb51 | ||
|
e1d8bf1888 | ||
|
1df91e2c8c | ||
|
c95ac4d350 | ||
|
cc04181578 | ||
|
9588b06e0f | ||
|
57bcb02629 | ||
|
5cfdf9867f | ||
|
1c4322a095 | ||
|
b7669222dc | ||
|
b925d8acff | ||
|
7b5f4c0d6f | ||
|
53e322b755 | ||
|
662a26d133 | ||
|
b81ea65c1c | ||
|
cd1dddc222 | ||
|
ea7e75cde7 | ||
|
aba2d18eb3 | ||
|
36ae21e3fa | ||
|
ce0cfccfd7 | ||
|
2068ea8720 | ||
|
93c7035148 | ||
|
841cedb976 | ||
|
b4aa00de51 | ||
|
e448885b76 | ||
|
cf51f7aadd | ||
|
420945139c | ||
|
74a67394ac | ||
|
c5b17d85ea | ||
|
9d2cde168e | ||
|
f63fcdc8d2 | ||
|
1979af7710 | ||
|
4286d3a79f | ||
|
967685352c | ||
|
6f5cdb7b44 | ||
|
4caf0aff81 | ||
|
32ee85cef8 | ||
|
92fcdcab9e | ||
|
4b0adc63f5 | ||
|
f58fe9cd52 | ||
|
2b45586fa9 | ||
|
a2d52fedb2 | ||
|
8c16fb2700 | ||
|
0a5a9c465f | ||
|
f21a243ce4 | ||
|
5bcf05dd3d | ||
|
7a85f6282f | ||
|
e27b0ad2b6 | ||
|
e7ec01f075 | ||
|
2e77129e15 | ||
|
4af8acee6f | ||
|
a513d02297 | ||
|
a422d2ea17 | ||
|
015b41aeb4 | ||
|
48bf4d1df9 | ||
|
95c648c0d2 | ||
|
926929da16 | ||
|
d0d6975a1f | ||
|
b6adc6b9e5 | ||
|
ae5a16bfd1 | ||
|
82e4b4ba00 | ||
|
af5cd5002b | ||
|
88719dbb7b | ||
|
5b391a5a4f | ||
|
d9ee417dc3 | ||
|
9689e3a39f | ||
|
cb110eaf98 | ||
|
a31343c5f7 | ||
|
f24fc4841f | ||
|
eb365b374d | ||
|
55db4af979 | ||
|
22cf88b7c7 | ||
|
e1972eb22f | ||
|
4c32ad8fb7 | ||
|
508ace452d | ||
|
d7cf845437 | ||
|
f6f3279c10 | ||
|
f9a2c3c0eb | ||
|
5b98577a4d | ||
|
630b38238d | ||
|
7ff8f21d04 | ||
|
142d72100c | ||
|
c63d37f193 | ||
|
77b20c9ba1 | ||
|
8d644e0d18 | ||
|
df917755f2 | ||
|
0828ab67b2 | ||
|
aa24194981 | ||
|
d1cecd5f46 | ||
|
b39a535cb9 | ||
|
15a02e0948 | ||
|
45964d34e7 | ||
|
00dedf10ad | ||
|
7cc7f47424 | ||
|
9ea0d4f89b | ||
|
a2df3143d1 | ||
|
53e3116350 | ||
|
d199c2ae33 | ||
|
74f7e9c295 | ||
|
06dbaca1c8 | ||
|
8df57ba89c | ||
|
e36ef0ed43 | ||
|
5ebbe788ea | ||
|
3c40aab1a0 | ||
|
bfa9147182 | ||
|
14f54f3df2 | ||
|
2ce217b873 | ||
|
edb4a72c8c | ||
|
5db4908fd7 | ||
|
930fca1e39 | ||
|
369c9e73de | ||
|
48901f2118 | ||
|
c471acbe44 | ||
|
cdb3e4a14e | ||
|
ea2c957f14 | ||
|
04da4c86b0 | ||
|
f05112b5e9 | ||
|
a15768b0bf | ||
|
50d26beb00 | ||
|
d273055ebf | ||
|
823d14df80 | ||
|
f575817b68 | ||
|
db1ca4f5e8 | ||
|
c10b39f3fe | ||
|
e5479bd7ef | ||
|
cbe8d295a5 | ||
|
f7b5d0e783 | ||
|
3d1a3493af | ||
|
6a5432b2b0 | ||
|
4ccf567d31 | ||
|
4fe3e30abc | ||
|
82a4e70248 | ||
|
d5777c0403 | ||
|
e48ab421b5 | ||
|
ab16377838 | ||
|
ac704a5ba6 | ||
|
a8b6c90d29 | ||
|
45a3bbb2c9 | ||
|
99261bad11 | ||
|
c6edb65fc1 | ||
|
6a1e9f916b | ||
|
b43f1c4073 | ||
|
81950dae4e | ||
|
e9d6e0ba14 | ||
|
a5da9d5b5d | ||
|
e2d55844a2 | ||
|
1f8227e671 | ||
|
179c1c1ba7 | ||
|
8d6270e1fe | ||
|
8eff7cd98f | ||
|
02e2ce0ad9 | ||
|
5d0fd65a69 | ||
|
4276e80ed5 | ||
|
183d00e087 | ||
|
209dd851b3 | ||
|
19b4aeb338 | ||
|
8791c7c48d | ||
|
4dd3ce0097 | ||
|
4d3b094d9e | ||
|
3478558904 | ||
|
01435aaaa3 | ||
|
030f991320 | ||
|
c47943f1af | ||
|
2e841655cf | ||
|
88287d4eec | ||
|
cb0f84e101 | ||
|
099d7aca5d | ||
|
d48cdea589 | ||
|
bb5e69f8db | ||
|
c1480d761f | ||
|
776c56bd7e | ||
|
e23633ff0e | ||
|
f7c9932c11 | ||
|
8eb7e7f63b | ||
|
6d20a10606 | ||
|
bcbed6d1e7 | ||
|
04c9ffbb19 | ||
|
5be4295b5a | ||
|
ffc46247ad | ||
|
6c8a5bedff | ||
|
38e06cf09a | ||
|
ed0b539c94 | ||
|
2ff8ec918b | ||
|
fda39282bd | ||
|
39bb6606a8 | ||
|
2ea82b866d | ||
|
d3dd7b6d40 | ||
|
4009fd77f1 | ||
|
372ad8f6b9 | ||
|
68376e7fee | ||
|
1966c36c1d | ||
|
62e7220271 | ||
|
1a8d8f3695 | ||
|
a522e11129 | ||
|
e53f300821 | ||
|
b496786a18 | ||
|
213d480ff2 | ||
|
6b0dcf9627 | ||
|
aca065a208 | ||
|
42cd79e3db | ||
|
48483f2ff8 | ||
|
d8e86fee75 | ||
|
cb943e4efc | ||
|
8c80c56252 | ||
|
68d42c3e37 | ||
|
bb460ba467 | ||
|
254b324a83 | ||
|
645320ae84 | ||
|
2d7440350f | ||
|
645b1406d1 | ||
|
3cb61b6b41 | ||
|
e2c407c614 | ||
|
3f5180527d | ||
|
b52c9bb860 | ||
|
5b141dd580 | ||
|
d3603a1f20 | ||
|
7867a46e2e | ||
|
c382efe119 | ||
|
eeabac1db4 | ||
|
b08d04dab9 | ||
|
a56516851e | ||
|
248e5673ef | ||
|
07fe0e9a1b | ||
|
c86c87e886 | ||
|
d35a6939be | ||
|
bdc8889cc0 | ||
|
2bd1884654 | ||
|
bcab725670 | ||
|
61b1501f48 | ||
|
4b6df10fe3 | ||
|
62ff290c02 | ||
|
247bdd5deb | ||
|
df4d7cb8da | ||
|
398f0790de | ||
|
4a7a8fa213 | ||
|
e5fd0fc636 | ||
|
436ebda9b5 | ||
|
65e6620014 | ||
|
0c4cda2f1c | ||
|
49b9a20997 | ||
|
c4bb6969f5 | ||
|
9cb591c5a7 | ||
|
225ea202cf | ||
|
7dc167ea48 | ||
|
80bdd22ed7 | ||
|
7a081cfc67 | ||
|
b8de035542 | ||
|
1940b1b7cd | ||
|
9fe5a6d853 | ||
|
b5af7d5492 | ||
|
2b32130280 | ||
|
37cac653d1 | ||
|
4628f8e880 | ||
|
43b30b694c | ||
|
762df7e753 | ||
|
0d5ae170d4 | ||
|
79670745d6 | ||
|
78f138c37f | ||
|
66e1439293 | ||
|
6a55fb5613 | ||
|
7ff045583d | ||
|
dba7669443 | ||
|
ebeb89cbce | ||
|
93f3a0fa99 | ||
|
3731488ab6 | ||
|
f9621054d7 | ||
|
2097e82d4a | ||
|
39f84c3767 | ||
|
c5c7565357 | ||
|
e0504e697a | ||
|
729e28e8b2 | ||
|
c6181c2dbe | ||
|
0f42187672 | ||
|
bdedaf61c8 | ||
|
3ac53e75d0 | ||
|
0f09501a84 | ||
|
ef95c96f45 | ||
|
c9f8c97021 | ||
|
ab5f180b08 | ||
|
8cb2e4ca9f | ||
|
1f7d7cd0e0 | ||
|
7562c48c74 | ||
|
74f254212a | ||
|
cf3428f774 | ||
|
b6e9df3495 | ||
|
159c179193 | ||
|
8865ff69d8 | ||
|
65c84071bb | ||
|
0ec0e2b035 | ||
|
90c1358e49 | ||
|
2b1ddef16e | ||
|
df189243d1 | ||
|
37555e876c | ||
|
8ae0a531e2 | ||
|
95c419dc45 | ||
|
8195500a1e | ||
|
204c0c5a3a | ||
|
4c8a27457e | ||
|
a3eca67f38 | ||
|
2083994513 | ||
|
bf5db67284 |
44
.gitignore
vendored
44
.gitignore
vendored
@@ -1,4 +1,4 @@
|
|||||||
apparmor-
|
apparmor-*
|
||||||
cscope.*
|
cscope.*
|
||||||
binutils/aa-enabled
|
binutils/aa-enabled
|
||||||
binutils/aa-enabled.1
|
binutils/aa-enabled.1
|
||||||
@@ -7,10 +7,22 @@ binutils/aa-exec.1
|
|||||||
binutils/aa-features-abi
|
binutils/aa-features-abi
|
||||||
binutils/aa-features-abi.1
|
binutils/aa-features-abi.1
|
||||||
binutils/aa-load
|
binutils/aa-load
|
||||||
|
binutils/aa-load.8
|
||||||
binutils/aa-status
|
binutils/aa-status
|
||||||
binutils/aa-status.8
|
binutils/aa-status.8
|
||||||
binutils/cJSON.o
|
binutils/cJSON.o
|
||||||
binutils/po/*.mo
|
binutils/po/*.mo
|
||||||
|
changehat/mod_apparmor/.libs
|
||||||
|
changehat/mod_apparmor/mod_apparmor.8
|
||||||
|
changehat/mod_apparmor/mod_apparmor.8.html
|
||||||
|
changehat/mod_apparmor/mod_apparmor.la
|
||||||
|
changehat/mod_apparmor/mod_apparmor.lo
|
||||||
|
changehat/mod_apparmor/mod_apparmor.slo
|
||||||
|
changehat/mod_apparmor/mod_apparmor.so
|
||||||
|
changehat/mod_apparmor/pod2htmd.tmp
|
||||||
|
changehat/pam_apparmor/get_options.o
|
||||||
|
changehat/pam_apparmor/pam_apparmor.o
|
||||||
|
changehat/pam_apparmor/pam_apparmor.so
|
||||||
parser/po/*.mo
|
parser/po/*.mo
|
||||||
parser/af_names.h
|
parser/af_names.h
|
||||||
parser/cap_names.h
|
parser/cap_names.h
|
||||||
@@ -109,6 +121,18 @@ libraries/libapparmor/src/tst_aalogmisc
|
|||||||
libraries/libapparmor/src/tst_aalogmisc.log
|
libraries/libapparmor/src/tst_aalogmisc.log
|
||||||
libraries/libapparmor/src/tst_aalogmisc.o
|
libraries/libapparmor/src/tst_aalogmisc.o
|
||||||
libraries/libapparmor/src/tst_aalogmisc.trs
|
libraries/libapparmor/src/tst_aalogmisc.trs
|
||||||
|
libraries/libapparmor/src/tst_aalogparse_cpp
|
||||||
|
libraries/libapparmor/src/tst_aalogparse_cpp.log
|
||||||
|
libraries/libapparmor/src/tst_aalogparse_cpp.o
|
||||||
|
libraries/libapparmor/src/tst_aalogparse_cpp.trs
|
||||||
|
libraries/libapparmor/src/tst_aalogparse_reentrancy
|
||||||
|
libraries/libapparmor/src/tst_aalogparse_reentrancy.log
|
||||||
|
libraries/libapparmor/src/tst_aalogparse_reentrancy.o
|
||||||
|
libraries/libapparmor/src/tst_aalogparse_reentrancy.trs
|
||||||
|
libraries/libapparmor/src/tst_aalogparse_oldname
|
||||||
|
libraries/libapparmor/src/tst_aalogparse_oldname.log
|
||||||
|
libraries/libapparmor/src/tst_aalogparse_oldname.o
|
||||||
|
libraries/libapparmor/src/tst_aalogparse_oldname.trs
|
||||||
libraries/libapparmor/src/tst_features
|
libraries/libapparmor/src/tst_features
|
||||||
libraries/libapparmor/src/tst_features.log
|
libraries/libapparmor/src/tst_features.log
|
||||||
libraries/libapparmor/src/tst_features.o
|
libraries/libapparmor/src/tst_features.o
|
||||||
@@ -169,7 +193,6 @@ libraries/libapparmor/testsuite/libaalogparse.test/Makefile
|
|||||||
libraries/libapparmor/testsuite/libaalogparse.test/Makefile.in
|
libraries/libapparmor/testsuite/libaalogparse.test/Makefile.in
|
||||||
libraries/libapparmor/testsuite/test_multi/out
|
libraries/libapparmor/testsuite/test_multi/out
|
||||||
libraries/libapparmor/testsuite/test_multi_multi-test_multi.o
|
libraries/libapparmor/testsuite/test_multi_multi-test_multi.o
|
||||||
changehat/mod_apparmor/.libs
|
|
||||||
utils/*.8
|
utils/*.8
|
||||||
utils/*.8.html
|
utils/*.8.html
|
||||||
utils/*.5
|
utils/*.5
|
||||||
@@ -180,7 +203,6 @@ utils/apparmor/*.pyc
|
|||||||
utils/apparmor/rule/*.pyc
|
utils/apparmor/rule/*.pyc
|
||||||
utils/apparmor.egg-info/
|
utils/apparmor.egg-info/
|
||||||
utils/build/
|
utils/build/
|
||||||
!utils/emacs/apparmor-mode.el
|
|
||||||
utils/htmlcov/
|
utils/htmlcov/
|
||||||
utils/test/common_test.pyc
|
utils/test/common_test.pyc
|
||||||
utils/test/.coverage
|
utils/test/.coverage
|
||||||
@@ -209,11 +231,13 @@ tests/regression/apparmor/chgrp
|
|||||||
tests/regression/apparmor/chmod
|
tests/regression/apparmor/chmod
|
||||||
tests/regression/apparmor/chown
|
tests/regression/apparmor/chown
|
||||||
tests/regression/apparmor/clone
|
tests/regression/apparmor/clone
|
||||||
|
tests/regression/apparmor/complain
|
||||||
tests/regression/apparmor/dbus_eavesdrop
|
tests/regression/apparmor/dbus_eavesdrop
|
||||||
tests/regression/apparmor/dbus_message
|
tests/regression/apparmor/dbus_message
|
||||||
tests/regression/apparmor/dbus_service
|
tests/regression/apparmor/dbus_service
|
||||||
tests/regression/apparmor/dbus_unrequested_reply
|
tests/regression/apparmor/dbus_unrequested_reply
|
||||||
tests/regression/apparmor/deleted
|
tests/regression/apparmor/deleted
|
||||||
|
tests/regression/apparmor/disconnected_mount_complain
|
||||||
tests/regression/apparmor/env_check
|
tests/regression/apparmor/env_check
|
||||||
tests/regression/apparmor/environ
|
tests/regression/apparmor/environ
|
||||||
tests/regression/apparmor/exec
|
tests/regression/apparmor/exec
|
||||||
@@ -226,10 +250,12 @@ tests/regression/apparmor/fchown
|
|||||||
tests/regression/apparmor/fd_inheritance
|
tests/regression/apparmor/fd_inheritance
|
||||||
tests/regression/apparmor/fd_inheritor
|
tests/regression/apparmor/fd_inheritor
|
||||||
tests/regression/apparmor/fork
|
tests/regression/apparmor/fork
|
||||||
|
tests/regression/apparmor/getcon_verify
|
||||||
tests/regression/apparmor/introspect
|
tests/regression/apparmor/introspect
|
||||||
tests/regression/apparmor/io_uring
|
tests/regression/apparmor/io_uring
|
||||||
tests/regression/apparmor/link
|
tests/regression/apparmor/link
|
||||||
tests/regression/apparmor/link_subset
|
tests/regression/apparmor/link_subset
|
||||||
|
tests/regression/apparmor/linkat_tmpfile
|
||||||
tests/regression/apparmor/mkdir
|
tests/regression/apparmor/mkdir
|
||||||
tests/regression/apparmor/mmap
|
tests/regression/apparmor/mmap
|
||||||
tests/regression/apparmor/mount
|
tests/regression/apparmor/mount
|
||||||
@@ -284,3 +310,15 @@ tests/regression/apparmor/xattrs_profile
|
|||||||
tests/regression/apparmor/coredump
|
tests/regression/apparmor/coredump
|
||||||
**/__pycache__/
|
**/__pycache__/
|
||||||
*.orig
|
*.orig
|
||||||
|
|
||||||
|
# Patterns related to spread integration tests
|
||||||
|
*.img
|
||||||
|
*.iso
|
||||||
|
*.lock
|
||||||
|
*.log
|
||||||
|
*.qcow2
|
||||||
|
*.run
|
||||||
|
.spread-reuse.yaml
|
||||||
|
.spread-reuse.*.yaml
|
||||||
|
spread-artifacts/
|
||||||
|
spread-logs/
|
||||||
|
248
.gitlab-ci.yml
248
.gitlab-ci.yml
@@ -1,28 +1,51 @@
|
|||||||
|
spec:
|
||||||
|
inputs:
|
||||||
|
build-test-images:
|
||||||
|
default: false
|
||||||
|
type: boolean
|
||||||
|
description: Explicitly build virtual machine images used by integration tests.
|
||||||
---
|
---
|
||||||
image: ubuntu:latest
|
image: ubuntu:latest
|
||||||
|
|
||||||
# XXX - add a deploy stage to publish man pages, docs, and coverage
|
# XXX - add a deploy stage to publish man pages, docs, and coverage
|
||||||
# reports
|
# reports
|
||||||
|
|
||||||
|
workflow:
|
||||||
|
rules:
|
||||||
|
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
|
||||||
|
- if: $CI_COMMIT_TAG
|
||||||
|
- if: $CI_COMMIT_BRANCH
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- build
|
- build
|
||||||
- test
|
- test
|
||||||
|
- spread
|
||||||
|
|
||||||
.ubuntu-before_script:
|
.ubuntu-common:
|
||||||
|
interruptible: true
|
||||||
before_script:
|
before_script:
|
||||||
- export DEBIAN_FRONTEND=noninteractive
|
# Install build-dependencies by loading the package list from the ubuntu/debian cloud-init profile.
|
||||||
|
- printf '\e[0K%s:%s:%s[collapsed=true]\r\e[0K%s\n' section_start "$(date +%s)" install_deps "Installing dependencies..."
|
||||||
- apt-get update -qq
|
- apt-get update -qq
|
||||||
- apt-get install --no-install-recommends -y gcc perl liblocale-gettext-perl linux-libc-dev lsb-release make
|
- apt-get install --yes yq make lsb-release
|
||||||
|
- |
|
||||||
|
printf 'include .image-garden.mk\n$(info $(UBUNTU_CLOUD_INIT_USER_DATA_TEMPLATE))\n.PHONY: nothing\nnothing:\n' \
|
||||||
|
| make -f - nothing \
|
||||||
|
| yq '.packages | .[]' \
|
||||||
|
| xargs apt-get install --yes --no-install-recommends
|
||||||
|
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" install_deps
|
||||||
|
after_script:
|
||||||
|
# Inspect the kernel and lsb-release.
|
||||||
- lsb_release -a
|
- lsb_release -a
|
||||||
- uname -a
|
- uname -a
|
||||||
|
|
||||||
.install-c-build-deps: &install-c-build-deps
|
|
||||||
- apt-get install --no-install-recommends -y build-essential apache2-dev autoconf autoconf-archive automake bison dejagnu flex libpam-dev libtool pkg-config python3-all-dev python3-setuptools ruby-dev swig zlib1g-dev
|
|
||||||
|
|
||||||
build-all:
|
build-all:
|
||||||
stage: build
|
stage: build
|
||||||
extends:
|
extends:
|
||||||
- .ubuntu-before_script
|
- .ubuntu-common
|
||||||
|
script:
|
||||||
|
# Run the spread prepare section to build everything.
|
||||||
|
- yq -r '.prepare' <spread.yaml | SPREAD_PATH=. bash -xeu
|
||||||
artifacts:
|
artifacts:
|
||||||
name: ${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
|
name: ${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
|
||||||
expire_in: 30 days
|
expire_in: 30 days
|
||||||
@@ -35,39 +58,33 @@ build-all:
|
|||||||
- changehat/mod_apparmor/
|
- changehat/mod_apparmor/
|
||||||
- changehat/pam_apparmor/
|
- changehat/pam_apparmor/
|
||||||
- profiles/
|
- profiles/
|
||||||
script:
|
|
||||||
- *install-c-build-deps
|
|
||||||
- cd libraries/libapparmor && ./autogen.sh && ./configure --with-perl --with-python --prefix=/usr && make && cd ../.. || { cat config.log ; exit 1 ; }
|
|
||||||
- make -C parser
|
|
||||||
- make -C binutils
|
|
||||||
- make -C utils
|
|
||||||
- make -C changehat/mod_apparmor
|
|
||||||
- make -C changehat/pam_apparmor
|
|
||||||
- make -C profiles
|
|
||||||
|
|
||||||
test-libapparmor:
|
test-libapparmor:
|
||||||
stage: test
|
stage: test
|
||||||
needs: ["build-all"]
|
needs: ["build-all"]
|
||||||
extends:
|
extends:
|
||||||
- .ubuntu-before_script
|
- .ubuntu-common
|
||||||
script:
|
script:
|
||||||
- *install-c-build-deps
|
# This is to touch the built files in the test stage to avoid needless rebuilding
|
||||||
|
- make -C libraries/libapparmor --touch
|
||||||
- make -C libraries/libapparmor check
|
- make -C libraries/libapparmor check
|
||||||
|
|
||||||
test-parser:
|
test-parser:
|
||||||
stage: test
|
stage: test
|
||||||
needs: ["build-all"]
|
needs: ["build-all"]
|
||||||
extends:
|
extends:
|
||||||
- .ubuntu-before_script
|
- .ubuntu-common
|
||||||
script:
|
script:
|
||||||
- *install-c-build-deps
|
# This is to touch the built files in the test stage to avoid needless rebuilding
|
||||||
|
- make -C parser --touch
|
||||||
|
- make -C parser -j $(nproc) tst_binaries
|
||||||
- make -C parser check
|
- make -C parser check
|
||||||
|
|
||||||
test-binutils:
|
test-binutils:
|
||||||
stage: test
|
stage: test
|
||||||
needs: ["build-all"]
|
needs: ["build-all"]
|
||||||
extends:
|
extends:
|
||||||
- .ubuntu-before_script
|
- .ubuntu-common
|
||||||
script:
|
script:
|
||||||
- make -C binutils check
|
- make -C binutils check
|
||||||
|
|
||||||
@@ -75,9 +92,15 @@ test-utils:
|
|||||||
stage: test
|
stage: test
|
||||||
needs: ["build-all"]
|
needs: ["build-all"]
|
||||||
extends:
|
extends:
|
||||||
- .ubuntu-before_script
|
- .ubuntu-common
|
||||||
script:
|
script:
|
||||||
|
# This is to touch the built files in the test stage to avoid needless rebuilding
|
||||||
|
- make -C utils --touch
|
||||||
|
|
||||||
|
# TODO: move those to cloud-init list?
|
||||||
|
- printf '\e[0K%s:%s:%s[collapsed=true]\r\e[0K%s\n' section_start "$(date +%s)" install_extra_deps "Installing additional dependencies..."
|
||||||
- apt-get install --no-install-recommends -y libc6-dev libjs-jquery libjs-jquery-throttle-debounce libjs-jquery-isonscreen libjs-jquery-tablesorter flake8 python3-coverage python3-notify2 python3-psutil python3-setuptools python3-tk python3-ttkthemes python3-gi
|
- apt-get install --no-install-recommends -y libc6-dev libjs-jquery libjs-jquery-throttle-debounce libjs-jquery-isonscreen libjs-jquery-tablesorter flake8 python3-coverage python3-notify2 python3-psutil python3-setuptools python3-tk python3-ttkthemes python3-gi
|
||||||
|
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" install_extra_deps
|
||||||
|
|
||||||
# See apparmor/apparmor#221
|
# See apparmor/apparmor#221
|
||||||
- make -C parser/tst gen_dbus
|
- make -C parser/tst gen_dbus
|
||||||
@@ -93,16 +116,20 @@ test-mod-apparmor:
|
|||||||
stage: test
|
stage: test
|
||||||
needs: ["build-all"]
|
needs: ["build-all"]
|
||||||
extends:
|
extends:
|
||||||
- .ubuntu-before_script
|
- .ubuntu-common
|
||||||
script:
|
script:
|
||||||
|
# This is to touch the built files in the test stage to avoid needless rebuilding
|
||||||
|
- make -C changehat/mod_apparmor --touch
|
||||||
- make -C changehat/mod_apparmor check
|
- make -C changehat/mod_apparmor check
|
||||||
|
|
||||||
test-profiles:
|
test-profiles:
|
||||||
stage: test
|
stage: test
|
||||||
needs: ["build-all"]
|
needs: ["build-all"]
|
||||||
extends:
|
extends:
|
||||||
- .ubuntu-before_script
|
- .ubuntu-common
|
||||||
script:
|
script:
|
||||||
|
# This is to touch the built files in the test stage to avoid needless rebuilding
|
||||||
|
- make -C profiles --touch
|
||||||
- make -C profiles check-parser
|
- make -C profiles check-parser
|
||||||
- make -C profiles check-abstractions.d
|
- make -C profiles check-abstractions.d
|
||||||
- make -C profiles check-local
|
- make -C profiles check-local
|
||||||
@@ -111,13 +138,15 @@ shellcheck:
|
|||||||
stage: test
|
stage: test
|
||||||
needs: []
|
needs: []
|
||||||
extends:
|
extends:
|
||||||
- .ubuntu-before_script
|
- .ubuntu-common
|
||||||
script:
|
script:
|
||||||
|
- printf '\e[0K%s:%s:%s[collapsed=true]\r\e[0K%s\n' section_start "$(date +%s)" install_extra_deps "Installing additional dependencies..."
|
||||||
- apt-get install --no-install-recommends -y python3-minimal file shellcheck xmlstarlet
|
- apt-get install --no-install-recommends -y python3-minimal file shellcheck xmlstarlet
|
||||||
|
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" install_extra_deps
|
||||||
- shellcheck --version
|
- shellcheck --version
|
||||||
- './tests/bin/shellcheck-tree --format=checkstyle
|
- "./tests/bin/shellcheck-tree --format=checkstyle
|
||||||
| xmlstarlet tr tests/checkstyle2junit.xslt
|
| xmlstarlet tr tests/checkstyle2junit.xslt
|
||||||
> shellcheck.xml'
|
> shellcheck.xml"
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
reports:
|
reports:
|
||||||
@@ -139,29 +168,170 @@ variables:
|
|||||||
SAST_EXCLUDED_ANALYZERS: "eslint,flawfinder,semgrep,spotbugs"
|
SAST_EXCLUDED_ANALYZERS: "eslint,flawfinder,semgrep,spotbugs"
|
||||||
SAST_BANDIT_EXCLUDED_PATHS: "*/tst/*, */test/*"
|
SAST_BANDIT_EXCLUDED_PATHS: "*/tst/*, */test/*"
|
||||||
|
|
||||||
.send-to-coverity: &send-to-coverity
|
|
||||||
- curl https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME
|
|
||||||
--form token=$COVERITY_SCAN_TOKEN --form email=$GITLAB_USER_EMAIL
|
|
||||||
--form file=@$(ls apparmor-*-cov-int.tar.gz) --form version="$(git describe --tags)"
|
|
||||||
--form description="$(git describe --tags) / $CI_COMMIT_TITLE / $CI_COMMIT_REF_NAME:$CI_PIPELINE_ID"
|
|
||||||
|
|
||||||
coverity:
|
coverity:
|
||||||
stage: .post
|
stage: .post
|
||||||
|
interruptible: true
|
||||||
extends:
|
extends:
|
||||||
- .ubuntu-before_script
|
- .ubuntu-common
|
||||||
only:
|
|
||||||
refs:
|
|
||||||
- master
|
|
||||||
script:
|
script:
|
||||||
|
- printf '\e[0K%s:%s:%s[collapsed=true]\r\e[0K%s\n' section_start "$(date +%s)" install_extra_deps "Installing additional dependencies..."
|
||||||
- apt-get install --no-install-recommends -y curl git texlive-latex-recommended
|
- apt-get install --no-install-recommends -y curl git texlive-latex-recommended
|
||||||
- *install-c-build-deps
|
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" install_extra_deps
|
||||||
- curl -o /tmp/cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64
|
- curl -o /tmp/cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64
|
||||||
--form project=$COVERITY_SCAN_PROJECT_NAME --form token=$COVERITY_SCAN_TOKEN
|
--form project=$COVERITY_SCAN_PROJECT_NAME --form token=$COVERITY_SCAN_TOKEN
|
||||||
- tar xfz /tmp/cov-analysis-linux64.tgz
|
- tar xfz /tmp/cov-analysis-linux64.tgz
|
||||||
- COV_VERSION=$(ls -dt cov-analysis-linux64-* | head -1)
|
- COV_VERSION=$(ls -dt cov-analysis-linux64-* | head -1)
|
||||||
- PATH=$PATH:$(pwd)/$COV_VERSION/bin
|
- PATH=$PATH:$(pwd)/$COV_VERSION/bin
|
||||||
- make coverity
|
- make coverity
|
||||||
- *send-to-coverity
|
- curl https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME
|
||||||
|
--form token=$COVERITY_SCAN_TOKEN --form email=$GITLAB_USER_EMAIL
|
||||||
|
--form file=@$(ls apparmor-*-cov-int.tar.gz) --form version="$(git describe --tags)"
|
||||||
|
--form description="$(git describe --tags) / $CI_COMMIT_TITLE / $CI_COMMIT_REF_NAME:$CI_PIPELINE_ID"
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- "apparmor-*.tar.gz"
|
- "apparmor-*.tar.gz"
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PROJECT_PATH == "apparmor/apparmor"
|
||||||
|
|
||||||
|
.image-garden-x86_64:
|
||||||
|
stage: spread
|
||||||
|
interruptible: true
|
||||||
|
# TODO: use tagged release once container tagging is improved upstream.
|
||||||
|
image: registry.gitlab.com/zygoon/image-garden:latest
|
||||||
|
tags:
|
||||||
|
- linux
|
||||||
|
- x86_64
|
||||||
|
- kvm
|
||||||
|
variables:
|
||||||
|
ARCH: x86_64
|
||||||
|
GARDEN_DL_DIR: dl
|
||||||
|
CACHE_POLICY: pull-push
|
||||||
|
CACHE_COMPRESSION_LEVEL: fastest
|
||||||
|
before_script:
|
||||||
|
# Restore the mtime of the .image-garden.mk file. This helps make determine
|
||||||
|
# if there's actually something to do correctly. Git does not preserve the
|
||||||
|
# mtime of files during checkout.
|
||||||
|
- git restore-mtime .image-garden.mk
|
||||||
|
# Prepare the image in dry-run mode. This helps in debugging cache misses
|
||||||
|
# when files are not cached correctly by the runner, causing the build section
|
||||||
|
# below to always do hevy-duty work.
|
||||||
|
- printf '\e[0K%s:%s:%s[collapsed=true]\r\e[0K%s\n' section_start "$(date +%s)" prepare_image_dry_run "Prepare image (dry run)"
|
||||||
|
- image-garden make --dry-run --debug "$GARDEN_SYSTEM.$ARCH.run" "$GARDEN_SYSTEM.$ARCH.qcow2" "$GARDEN_SYSTEM.seed.iso" "$GARDEN_SYSTEM.user-data" "$GARDEN_SYSTEM.meta-data"
|
||||||
|
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" prepare_image_dry_run
|
||||||
|
script:
|
||||||
|
# Prepare the image, for real.
|
||||||
|
- printf '\e[0K%s:%s:%s[collapsed=true]\r\e[0K%s\n' section_start "$(date +%s)" prepare_image "Prepare image"
|
||||||
|
# If there's nothing to do then remove all the files that we would normally
|
||||||
|
# cache so that GitLab skips the cache upload step. This saves significant
|
||||||
|
# time required to re-compress and upload unchanged content.
|
||||||
|
# The idea for how to do is is documented at
|
||||||
|
# https://olex.biz/2025/04/gitlab-ci-prevent-cache-reupload-without-changes/
|
||||||
|
# The GitLab issue requesting a proper feature is
|
||||||
|
# https://gitlab.com/gitlab-org/gitlab/-/issues/226068
|
||||||
|
- |
|
||||||
|
if image-garden make --question "$GARDEN_SYSTEM.$ARCH.run" "$GARDEN_SYSTEM.$ARCH.qcow2" "$GARDEN_SYSTEM.seed.iso" "$GARDEN_SYSTEM.user-data" "$GARDEN_SYSTEM.meta-data"; then
|
||||||
|
rm -f "$GARDEN_SYSTEM".* efi-code.*.img efi-vars.*.img
|
||||||
|
rm -rf "$GARDEN_DL_DIR"
|
||||||
|
else
|
||||||
|
image-garden make "$GARDEN_SYSTEM.$ARCH.run" "$GARDEN_SYSTEM.$ARCH.qcow2" "$GARDEN_SYSTEM.seed.iso" "$GARDEN_SYSTEM.user-data" "$GARDEN_SYSTEM.meta-data"
|
||||||
|
fi
|
||||||
|
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" prepare_image
|
||||||
|
cache:
|
||||||
|
# Cache the base image (pre-customization).
|
||||||
|
- key: image-garden-base-${GARDEN_SYSTEM}.${ARCH}
|
||||||
|
policy: $CACHE_POLICY
|
||||||
|
when: always
|
||||||
|
paths:
|
||||||
|
- $GARDEN_DL_DIR
|
||||||
|
# Those are never mutated so they are safe to share.
|
||||||
|
- efi-code.*.img
|
||||||
|
- efi-vars.*.img
|
||||||
|
# Cache the customized system. This cache depends on .image-garden.mk file
|
||||||
|
# so that any customization updates are immediately acted upon.
|
||||||
|
- key:
|
||||||
|
prefix: image-garden-custom-${GARDEN_SYSTEM}.${ARCH}-
|
||||||
|
files:
|
||||||
|
- .image-garden.mk
|
||||||
|
policy: $CACHE_POLICY
|
||||||
|
when: always
|
||||||
|
paths:
|
||||||
|
- $GARDEN_SYSTEM.*
|
||||||
|
- $GARDEN_SYSTEM.seed.iso
|
||||||
|
- $GARDEN_SYSTEM.meta-data
|
||||||
|
- $GARDEN_SYSTEM.user-data
|
||||||
|
|
||||||
|
# This job builds and caches the image that the job below looks at.
|
||||||
|
image-ubuntu-cloud-24.04-x86_64:
|
||||||
|
extends: .image-garden-x86_64
|
||||||
|
variables:
|
||||||
|
GARDEN_SYSTEM: ubuntu-cloud-24.04
|
||||||
|
needs: []
|
||||||
|
dependencies: []
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_TAG
|
||||||
|
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||||
|
changes:
|
||||||
|
paths:
|
||||||
|
- .image-garden.mk
|
||||||
|
- .gitlab-ci.yml
|
||||||
|
compare_to: "refs/heads/master"
|
||||||
|
- if: $CI_COMMIT_BRANCH && "$[[ inputs.build-test-images ]]" == "true"
|
||||||
|
|
||||||
|
.spread-x86_64:
|
||||||
|
extends: .image-garden-x86_64
|
||||||
|
variables:
|
||||||
|
# GitLab project identifier of zygoon/spread-dist can be seen on
|
||||||
|
# https://gitlab.com/zygoon/spread-dist, under the three-dot menu on
|
||||||
|
# top-right.
|
||||||
|
SPREAD_GITLAB_PROJECT_ID: "65375371"
|
||||||
|
# Git revision of spread to install.
|
||||||
|
# This must have been built via spread-dist.
|
||||||
|
# TODO: switch to upstream 1.0 release when available.
|
||||||
|
SPREAD_REV: 413817eda7bec07a3885e0717c178b965f8924e1
|
||||||
|
# Run all the tasks for a given system.
|
||||||
|
SPREAD_ARGS: "garden:$GARDEN_SYSTEM:"
|
||||||
|
SPREAD_GOARCH: amd64
|
||||||
|
before_script:
|
||||||
|
# Restore the mtime of the .image-garden.mk file. This helps make determine
|
||||||
|
# if there's actually something to do correctly. Git does not preserve the
|
||||||
|
# mtime of files during checkout.
|
||||||
|
- git restore-mtime .image-garden.mk
|
||||||
|
# Prepare the image in dry-run mode. This helps in debugging cache misses
|
||||||
|
# when files are not cached correctly by the runner, causing the build section
|
||||||
|
# below to always do hevy-duty work.
|
||||||
|
- printf '\e[0K%s:%s:%s[collapsed=true]\r\e[0K%s\n' section_start "$(date +%s)" prepare_image_dry_run "Prepare image (dry run)"
|
||||||
|
- image-garden make --dry-run --debug "$GARDEN_SYSTEM.$ARCH.run" "$GARDEN_SYSTEM.$ARCH.qcow2" "$GARDEN_SYSTEM.seed.iso" "$GARDEN_SYSTEM.user-data" "$GARDEN_SYSTEM.meta-data"
|
||||||
|
- stat .image-garden.mk "$GARDEN_SYSTEM".* || true
|
||||||
|
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" prepare_image_dry_run
|
||||||
|
# Install the selected revision of spread.
|
||||||
|
- printf '\e[0K%s:%s:%s[collapsed=true]\r\e[0K%s\n' section_start "$(date +%s)" install_spread "Installing spread..."
|
||||||
|
# Install pre-built spread from https://gitlab.com/zygoon/spread-dist generic package repository.
|
||||||
|
- |
|
||||||
|
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --location --output spread "${CI_API_V4_URL}/projects/${SPREAD_GITLAB_PROJECT_ID}/packages/generic/spread/${SPREAD_REV}/spread.${SPREAD_GOARCH}"
|
||||||
|
- chmod +x spread
|
||||||
|
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" install_spread
|
||||||
|
script:
|
||||||
|
- printf '\e[0K%s:%s:%s\r\e[0K%s\n' section_start "$(date +%s)" run_spread "Running spread for $GARDEN_SYSTEM..."
|
||||||
|
# TODO: transform to inject ^...$ to properly select jobs to run.
|
||||||
|
- mkdir -p spread-logs spread-artifacts
|
||||||
|
- ./spread -list $SPREAD_ARGS |
|
||||||
|
split --number=l/"${CI_NODE_INDEX:-1}"/"${CI_NODE_TOTAL:-1}" |
|
||||||
|
xargs --verbose ./spread -v -artifacts ./spread-artifacts -v | tee spread-logs/"$GARDEN_SYSTEM".log
|
||||||
|
- printf '\e[0K%s:%s:%s\r\e[0K\n' section_end "$(date +%s)" run_spread
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- spread-logs
|
||||||
|
- spread-artifacts
|
||||||
|
when: always
|
||||||
|
|
||||||
|
spread-ubuntu-cloud-24.04-x86_64:
|
||||||
|
extends: .spread-x86_64
|
||||||
|
variables:
|
||||||
|
GARDEN_SYSTEM: ubuntu-cloud-24.04
|
||||||
|
SPREAD_ARGS: garden:$GARDEN_SYSTEM:tests/regression/ garden:$GARDEN_SYSTEM:tests/profiles/
|
||||||
|
CACHE_POLICY: pull
|
||||||
|
dependencies: []
|
||||||
|
needs:
|
||||||
|
- job: image-ubuntu-cloud-24.04-x86_64
|
||||||
|
optional: true
|
||||||
|
parallel: 4
|
||||||
|
129
.image-garden.mk
Normal file
129
.image-garden.mk
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
# This file is read by image-garden when spread is allocating test machines.
|
||||||
|
# All the package installation happens through cloud-init profiles defined
|
||||||
|
# below.
|
||||||
|
|
||||||
|
# NOTE: Should the kernel be out of date, just increment this value. Make will
|
||||||
|
# re-create the image whenever the .image-garden.mk file is more recent than
|
||||||
|
# the image itself. In reality all you need is touch(1), but this is more apt.
|
||||||
|
unused=1
|
||||||
|
|
||||||
|
# This is the cloud-init user-data profile for all Debian systems. Note that it
|
||||||
|
# is an extension of the default profile necessary for operation of
|
||||||
|
# image-garden.
|
||||||
|
define DEBIAN_CLOUD_INIT_USER_DATA_TEMPLATE
|
||||||
|
$(CLOUD_INIT_USER_DATA_TEMPLATE)
|
||||||
|
packages:
|
||||||
|
- apache2-dev
|
||||||
|
- attr
|
||||||
|
- autoconf
|
||||||
|
- autoconf-archive
|
||||||
|
- automake
|
||||||
|
- bison
|
||||||
|
- build-essential
|
||||||
|
- dejagnu
|
||||||
|
- dosfstools
|
||||||
|
- flake8
|
||||||
|
- flex
|
||||||
|
- fuse-overlayfs
|
||||||
|
- gdb
|
||||||
|
- gettext
|
||||||
|
- libdbus-1-dev
|
||||||
|
- libpam0g-dev
|
||||||
|
- libtool
|
||||||
|
- liburing-dev
|
||||||
|
- pkg-config
|
||||||
|
- proftpd-core
|
||||||
|
- python3-all-dev
|
||||||
|
- python3-gi
|
||||||
|
- python3-notify2
|
||||||
|
- python3-psutil
|
||||||
|
- python3-setuptools
|
||||||
|
- python3-tk
|
||||||
|
- python3-ttkthemes
|
||||||
|
- swig
|
||||||
|
- tinyproxy
|
||||||
|
# Update all the packages. This allows us to be on the up-to-date kernel
|
||||||
|
# version that we cannot otherwise easily select with cloud init alone. Note
|
||||||
|
# that we do not need to reboot the system as image garden shuts down the image
|
||||||
|
# after first boot. On subsequent boot we will be running the latest kernel.
|
||||||
|
package_upgrade: true
|
||||||
|
package_update: true
|
||||||
|
endef
|
||||||
|
|
||||||
|
# Ubuntu shares cloud-init profile with Debian.
|
||||||
|
UBUNTU_CLOUD_INIT_USER_DATA_TEMPLATE=$(DEBIAN_CLOUD_INIT_USER_DATA_TEMPLATE)
|
||||||
|
|
||||||
|
# This is the cloud-init user-data profile for openSUSE Tumbleweed.
|
||||||
|
define OPENSUSE_tumbleweed_CLOUD_INIT_USER_DATA_TEMPLATE
|
||||||
|
$(CLOUD_INIT_USER_DATA_TEMPLATE)
|
||||||
|
- sed -i -e 's/security=selinux/security=apparmor/g' /etc/default/grub
|
||||||
|
- update-bootloader
|
||||||
|
packages:
|
||||||
|
- apache2-devel
|
||||||
|
- attr
|
||||||
|
- autoconf
|
||||||
|
- autoconf-archive
|
||||||
|
- automake
|
||||||
|
- bison
|
||||||
|
- dbus-1-devel
|
||||||
|
- dejagnu
|
||||||
|
- dosfstools
|
||||||
|
- flex
|
||||||
|
- fuse-overlayfs
|
||||||
|
- gcc
|
||||||
|
- gcc-c++
|
||||||
|
- gdb
|
||||||
|
- gettext
|
||||||
|
- gobject-introspection
|
||||||
|
- libtool
|
||||||
|
- liburing2-devel
|
||||||
|
- make
|
||||||
|
- pam-devel
|
||||||
|
- pkg-config
|
||||||
|
- python3-devel
|
||||||
|
- python3-flake8
|
||||||
|
- python3-notify2
|
||||||
|
- python3-psutil
|
||||||
|
- python3-setuptools
|
||||||
|
- python3-setuptools
|
||||||
|
- python3-tk
|
||||||
|
- python311
|
||||||
|
- python311-devel
|
||||||
|
- swig
|
||||||
|
- which
|
||||||
|
# See above for rationale.
|
||||||
|
package_upgrade: true
|
||||||
|
package_update: true
|
||||||
|
endef
|
||||||
|
|
||||||
|
define FEDORA_CLOUD_INIT_USER_DATA_TEMPLATE
|
||||||
|
$(CLOUD_INIT_USER_DATA_TEMPLATE)
|
||||||
|
packages:
|
||||||
|
- attr
|
||||||
|
- autoconf
|
||||||
|
- autoconf-archive
|
||||||
|
- automake
|
||||||
|
- bison
|
||||||
|
- dbus-devel
|
||||||
|
- dejagnu
|
||||||
|
- dosfstools
|
||||||
|
- flex
|
||||||
|
- gdb
|
||||||
|
- gettext
|
||||||
|
- httpd-devel
|
||||||
|
- libstdc++-static
|
||||||
|
- libtool
|
||||||
|
- liburing-devel
|
||||||
|
- pam-devel
|
||||||
|
- perl
|
||||||
|
- pkg-config
|
||||||
|
- python3-devel
|
||||||
|
- python3-flake8
|
||||||
|
- python3-gobject-base
|
||||||
|
- python3-notify2
|
||||||
|
- python3-tkinter
|
||||||
|
- swig
|
||||||
|
# See above for rationale.
|
||||||
|
package_upgrade: true
|
||||||
|
package_update: true
|
||||||
|
endef
|
5
Makefile
5
Makefile
@@ -54,12 +54,9 @@ snapshot: clean
|
|||||||
.PHONY: coverity
|
.PHONY: coverity
|
||||||
coverity: snapshot
|
coverity: snapshot
|
||||||
cd $(SNAPSHOT_NAME)/libraries/libapparmor && ./configure --with-python
|
cd $(SNAPSHOT_NAME)/libraries/libapparmor && ./configure --with-python
|
||||||
$(foreach dir, libraries/libapparmor utils, \
|
|
||||||
cov-build --dir $(COVERITY_DIR) --no-command --fs-capture-search $(SNAPSHOT_NAME)/$(dir); \
|
|
||||||
mv $(COVERITY_DIR)/build-log.txt $(COVERITY_DIR)/build-log-python-$(subst /,.,$(dir)).txt ;)
|
|
||||||
cov-build --dir $(COVERITY_DIR) -- sh -c \
|
cov-build --dir $(COVERITY_DIR) -- sh -c \
|
||||||
"$(foreach dir, $(filter-out utils profiles tests, $(DIRS)), \
|
"$(foreach dir, $(filter-out utils profiles tests, $(DIRS)), \
|
||||||
$(MAKE) -C $(SNAPSHOT_NAME)/$(dir);) "
|
$(MAKE) -j $$(nproc) -C $(SNAPSHOT_NAME)/$(dir);) "
|
||||||
tar -cvzf $(SNAPSHOT_NAME)-$(COVERITY_DIR).tar.gz $(COVERITY_DIR)
|
tar -cvzf $(SNAPSHOT_NAME)-$(COVERITY_DIR).tar.gz $(COVERITY_DIR)
|
||||||
|
|
||||||
.PHONY: export_dir
|
.PHONY: export_dir
|
||||||
|
66
README.md
66
README.md
@@ -111,13 +111,21 @@ $ export PYTHON_VERSION=3
|
|||||||
$ export PYTHON_VERSIONS=python3
|
$ export PYTHON_VERSIONS=python3
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note that, in general, the build steps can be run in parallel, while the test
|
||||||
|
steps do not gain much speedup from being run in parallel. This is because the
|
||||||
|
test steps spawn a handful of long-lived test runner processes that mostly
|
||||||
|
run their tests sequentially and do not use `make`'s jobserver. Moreover,
|
||||||
|
process spawning overhead constitutes a significant part of test runtime, so
|
||||||
|
reworking the test harnesses to add parallelism (which would be a major undertaking
|
||||||
|
for the harnesses that do not have it already) would not produce much of a speedup.
|
||||||
|
|
||||||
### libapparmor:
|
### libapparmor:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ cd ./libraries/libapparmor
|
$ cd ./libraries/libapparmor
|
||||||
$ sh ./autogen.sh
|
$ sh ./autogen.sh
|
||||||
$ sh ./configure --prefix=/usr --with-perl --with-python # see below
|
$ sh ./configure --prefix=/usr --with-perl --with-python # see below
|
||||||
$ make
|
$ make -j $(nproc)
|
||||||
$ make check
|
$ make check
|
||||||
$ make install
|
$ make install
|
||||||
```
|
```
|
||||||
@@ -130,7 +138,7 @@ generate Ruby bindings to libapparmor.]
|
|||||||
|
|
||||||
```
|
```
|
||||||
$ cd binutils
|
$ cd binutils
|
||||||
$ make
|
$ make -j $(nproc)
|
||||||
$ make check
|
$ make check
|
||||||
$ make install
|
$ make install
|
||||||
```
|
```
|
||||||
@@ -139,7 +147,8 @@ $ make install
|
|||||||
|
|
||||||
```
|
```
|
||||||
$ cd parser
|
$ cd parser
|
||||||
$ make # depends on libapparmor having been built first
|
$ make -j $(nproc) # depends on libapparmor having been built first
|
||||||
|
$ make -j $(nproc) tst_binaries # a build step of make check that can be parallelized
|
||||||
$ make check
|
$ make check
|
||||||
$ make install
|
$ make install
|
||||||
```
|
```
|
||||||
@@ -149,7 +158,7 @@ $ make install
|
|||||||
|
|
||||||
```
|
```
|
||||||
$ cd utils
|
$ cd utils
|
||||||
$ make
|
$ make -j $(nproc)
|
||||||
$ make check PYFLAKES=/usr/bin/pyflakes3
|
$ make check PYFLAKES=/usr/bin/pyflakes3
|
||||||
$ make install
|
$ make install
|
||||||
```
|
```
|
||||||
@@ -158,7 +167,7 @@ $ make install
|
|||||||
|
|
||||||
```
|
```
|
||||||
$ cd changehat/mod_apparmor
|
$ cd changehat/mod_apparmor
|
||||||
$ make # depends on libapparmor having been built first
|
$ make -j $(nproc) # depends on libapparmor having been built first
|
||||||
$ make install
|
$ make install
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -167,7 +176,7 @@ $ make install
|
|||||||
|
|
||||||
```
|
```
|
||||||
$ cd changehat/pam_apparmor
|
$ cd changehat/pam_apparmor
|
||||||
$ make # depends on libapparmor having been built first
|
$ make -j $(nproc) # depends on libapparmor having been built first
|
||||||
$ make install
|
$ make install
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -197,6 +206,46 @@ usage and how to update and add tests. Below is a quick overview of their
|
|||||||
location and how to run them.
|
location and how to run them.
|
||||||
|
|
||||||
|
|
||||||
|
Using spread with local virtual machines
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
It may be convenient to use the spread tool to provision and run the test suite
|
||||||
|
in an ephemeral virtual machine. This allows testing in isolation from the
|
||||||
|
host, as well as testing across different commonly used distributions and their
|
||||||
|
real kernels.
|
||||||
|
|
||||||
|
Image Garden is available as a snap. If you wish to use it this way then snap
|
||||||
|
then install the snap with:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo snap install image-garden
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need to install snapd first, see https://snapcraft.io/docs/installing-snapd
|
||||||
|
|
||||||
|
Alternatively you may build image-garden and spread from source, and install
|
||||||
|
dependencies manually.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo apt install git golang whois ovmf genisoimage qemu-utils qemu-system
|
||||||
|
go install github.com/snapcore/spread/cmd/spread@latest
|
||||||
|
git clone https://gitlab.com/zygoon/image-garden
|
||||||
|
make -C image-garden
|
||||||
|
sudo make -C image-garden install
|
||||||
|
image-garden make ubuntu-cloud-24.10.x86_64.run
|
||||||
|
cd $APPARMOR_PATH
|
||||||
|
git clean -xdf
|
||||||
|
~/go/bin/spread -artifacts ./spread-artifacts -v ubuntu-cloud-24.10
|
||||||
|
# or ~/go/bin/spread -v garden:ubuntu-cloud-24.04:tests/regression/apparmor:at_secure
|
||||||
|
```
|
||||||
|
|
||||||
|
Running the `run_spread.sh` script, with `image-garden` snap installed or with
|
||||||
|
`spread` on `PATH` will run all the tests across several supported systems
|
||||||
|
(Debian, Ubuntu and openSUSE).
|
||||||
|
|
||||||
|
If you include a `bzImage` file in the root of the repository then that kernel
|
||||||
|
will be used in the integration test. Please look at `spread.yaml` for details.
|
||||||
|
|
||||||
Regression tests
|
Regression tests
|
||||||
----------------
|
----------------
|
||||||
For details on structure and adding tests, see
|
For details on structure and adding tests, see
|
||||||
@@ -207,7 +256,7 @@ To run:
|
|||||||
### Regression tests - using apparmor userspace installed on host
|
### Regression tests - using apparmor userspace installed on host
|
||||||
```
|
```
|
||||||
$ cd tests/regression/apparmor (requires root)
|
$ cd tests/regression/apparmor (requires root)
|
||||||
$ make USE_SYSTEM=1
|
$ make -j $(nproc) USE_SYSTEM=1
|
||||||
$ sudo make tests USE_SYSTEM=1
|
$ sudo make tests USE_SYSTEM=1
|
||||||
$ sudo bash open.sh -r # runs and saves the last testcase from open.sh
|
$ sudo bash open.sh -r # runs and saves the last testcase from open.sh
|
||||||
```
|
```
|
||||||
@@ -220,7 +269,7 @@ $ sudo bash open.sh -r # runs and saves the last testcase from open.sh
|
|||||||
|
|
||||||
```
|
```
|
||||||
$ cd tests/regression/apparmor (requires root)
|
$ cd tests/regression/apparmor (requires root)
|
||||||
$ make
|
$ make -j $(nproc)
|
||||||
$ sudo make tests
|
$ sudo make tests
|
||||||
$ sudo bash open.sh -r # runs and saves the last testcase from open.sh
|
$ sudo bash open.sh -r # runs and saves the last testcase from open.sh
|
||||||
```
|
```
|
||||||
@@ -354,6 +403,7 @@ The aa-notify tool's Python dependencies can be satisfied by installing the
|
|||||||
following packages (Debian package names, other distros may vary):
|
following packages (Debian package names, other distros may vary):
|
||||||
* python3-notify2
|
* python3-notify2
|
||||||
* python3-psutil
|
* python3-psutil
|
||||||
|
* python3-sqlite (part of the python3.NN-stdlib package)
|
||||||
* python3-tk
|
* python3-tk
|
||||||
* python3-ttkthemes
|
* python3-ttkthemes
|
||||||
* python3-gi
|
* python3-gi
|
||||||
|
@@ -21,7 +21,7 @@ DESTDIR=/
|
|||||||
BINDIR=${DESTDIR}/usr/bin
|
BINDIR=${DESTDIR}/usr/bin
|
||||||
SBINDIR=${DESTDIR}/usr/sbin
|
SBINDIR=${DESTDIR}/usr/sbin
|
||||||
LOCALEDIR=/usr/share/locale
|
LOCALEDIR=/usr/share/locale
|
||||||
MANPAGES=aa-enabled.1 aa-exec.1 aa-features-abi.1 aa-status.8
|
MANPAGES=aa-enabled.1 aa-exec.1 aa-features-abi.1 aa-load.8 aa-status.8
|
||||||
|
|
||||||
WARNINGS = -Wall
|
WARNINGS = -Wall
|
||||||
CPP_WARNINGS =
|
CPP_WARNINGS =
|
||||||
|
@@ -80,6 +80,109 @@ aa-exec.
|
|||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
|
=head1 RESTRICTIONS
|
||||||
|
|
||||||
|
aa-exec uses I<aa_change_profile(3)> to change application confinement.
|
||||||
|
The use of I<aa_change_profile(3)> may be restricted by policy in ways
|
||||||
|
that will cause failure or results different than expected.
|
||||||
|
|
||||||
|
Even when using I<aa-exec> from unconfined restrictions in policy can
|
||||||
|
causes failure or the confinement entered to be different than requested
|
||||||
|
|
||||||
|
See the unpriviled unconfined restriction documentation for more detail.
|
||||||
|
https://gitlab.com/apparmor/apparmor/-/wikis/unprivileged_unconfined_restriction
|
||||||
|
|
||||||
|
=head1 STACKING
|
||||||
|
|
||||||
|
aa-exec can be used to setup a stack of profiles as confinement. When an
|
||||||
|
application is confined by a stack, all profiles in the stack are checked
|
||||||
|
as if they were the profile confining the application. The resulting
|
||||||
|
mediation is the intersection of what is allowed by each profile in the
|
||||||
|
stack.
|
||||||
|
|
||||||
|
The profiles in a stack are treated independently. Each profile can have
|
||||||
|
its own flags and profile transitions. During an exec each profile gets
|
||||||
|
to specify its transition and the results brought together to form a
|
||||||
|
new canonicalized stack.
|
||||||
|
|
||||||
|
The profile separator indicating a stack is the character sequence I<//&>.
|
||||||
|
Thus a stack can be expressed using
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
$ aa-exec -p "unconfined//&firefox" -- bash
|
||||||
|
$ ps -Z
|
||||||
|
LABEL PID TTY TIME CMD
|
||||||
|
unconfined 30714 pts/12 00:00:00 bash
|
||||||
|
firefox//&unconfined (unconfined) 31160 pts/12 00:00:00 bash
|
||||||
|
firefox//&unconfined (unconfined) 31171 pts/12 00:00:00 ps
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head1 NAMESPACES
|
||||||
|
|
||||||
|
aa-exec can be used to enter confinement in another policy namespace
|
||||||
|
if the policy namespaces exists, is visible, and the profile exists in
|
||||||
|
the namespace. Note applications launched within the namespace will
|
||||||
|
not be able to exit the namespace, and may be restricted by additional
|
||||||
|
confinement around namespacing. Files and resources visible to the
|
||||||
|
parent that launches the application may not be visible in the policy
|
||||||
|
namespace resulting in access denials.
|
||||||
|
|
||||||
|
To enter a policy namespace the profile is prefixed with the namespace's
|
||||||
|
name, using a I<:> prefix and suffix.
|
||||||
|
|
||||||
|
Eg.
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
$ aa-exec -p :ex1:unconfined -- bash
|
||||||
|
$ ps -Z
|
||||||
|
LABEL PID TTY TIME CMD
|
||||||
|
- 30714 pts/12 00:00:00 bash
|
||||||
|
unconfined 34372 pts/12 00:00:00 bash
|
||||||
|
unconfined 34379 pts/12 00:00:00 ps
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
Confinement of processes outside of the namespace may not be visible
|
||||||
|
in which case the confinement will be represented with a -. If policy
|
||||||
|
is stacked only part of the confinement might be visible. However
|
||||||
|
confinement is usually fully visible from the parent policy namespace.
|
||||||
|
|
||||||
|
Eg. the confinement of the child can be queried in the parent to see
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
$ ps -Z 34372
|
||||||
|
LABEL PID TTY STAT TIME COMMAND
|
||||||
|
:ex1:unconfined 34372 pts/12 S+ 0:00 bash
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
And in the case of stacking with namespaces
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
$ aa-exec -p "unconfined//&:ex1:unconfined" -- bash
|
||||||
|
$ ps -Z
|
||||||
|
LABEL PID TTY TIME CMD
|
||||||
|
- 30714 pts/12 00:00:00 bash
|
||||||
|
unconfined 36298 pts/12 00:00:00 bash
|
||||||
|
unconfined 36305 pts/12 00:00:00 ps
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
while from the parent namespace the full confinement can be seen
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
$ ps -Z 36298
|
||||||
|
LABEL PID TTY STAT TIME COMMAND
|
||||||
|
unconfined//&:ex1:unconfined 36298 pts/12 S+ 0:00 bash
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
=head1 BUGS
|
=head1 BUGS
|
||||||
|
|
||||||
If you find any bugs, please report them at
|
If you find any bugs, please report them at
|
||||||
@@ -87,7 +190,7 @@ L<https://gitlab.com/apparmor/apparmor/-/issues>
|
|||||||
|
|
||||||
=head1 SEE ALSO
|
=head1 SEE ALSO
|
||||||
|
|
||||||
aa-stack(8), aa-namespace(8), apparmor(7), apparmor.d(5), aa_change_profile(3),
|
apparmor(7), apparmor.d(5), aa_change_profile(3),
|
||||||
aa_change_onexec(3) and L<https://wiki.apparmor.net>.
|
aa_change_onexec(3) and L<https://wiki.apparmor.net>.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
77
binutils/aa-load.pod
Normal file
77
binutils/aa-load.pod
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# This publication is intellectual property of Canonical Ltd. Its contents
|
||||||
|
# can be duplicated, either in part or in whole, provided that a copyright
|
||||||
|
# label is visibly located on each copy.
|
||||||
|
#
|
||||||
|
# All information found in this book has been compiled with utmost
|
||||||
|
# attention to detail. However, this does not guarantee complete accuracy.
|
||||||
|
# Neither Canonical Ltd, the authors, nor the translators shall be held
|
||||||
|
# liable for possible errors or the consequences thereof.
|
||||||
|
#
|
||||||
|
# Many of the software and hardware descriptions cited in this book
|
||||||
|
# are registered trademarks. All trade names are subject to copyright
|
||||||
|
# restrictions and may be registered trade marks. Canonical Ltd
|
||||||
|
# essentially adheres to the manufacturer's spelling.
|
||||||
|
#
|
||||||
|
# Names of products and trademarks appearing in this book (with or without
|
||||||
|
# specific notation) are likewise subject to trademark and trade protection
|
||||||
|
# laws and may thus fall under copyright restrictions.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
aa-load - load precompiled AppArmor policy from cache location(s)
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
B<aa-load> [options] (cache file|cache dir|cache base dir)+
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
B<aa-load> loads precompiled AppArmor policy from the specified locations.
|
||||||
|
|
||||||
|
=head1 OPTIONS
|
||||||
|
|
||||||
|
B<aa-load> accepts the following arguments:
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item -f, --force
|
||||||
|
|
||||||
|
Force B<aa-load> to load a policy even if its abi does not match the kernel abi.
|
||||||
|
|
||||||
|
=item -d, --debug
|
||||||
|
|
||||||
|
Display debug messages.
|
||||||
|
|
||||||
|
=item -v, --verbose
|
||||||
|
|
||||||
|
Display progress and error messages.
|
||||||
|
|
||||||
|
=item -n, --dry-run
|
||||||
|
|
||||||
|
Do not actually load the specified policy/policies into the kernel.
|
||||||
|
|
||||||
|
=item -h, --help
|
||||||
|
|
||||||
|
Display a brief usage guide.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head1 EXIT STATUS
|
||||||
|
|
||||||
|
Upon exiting, B<aa-load> returns 0 upon success and 1 upon an error loading
|
||||||
|
the precompiled policy.
|
||||||
|
|
||||||
|
=head1 BUGS
|
||||||
|
|
||||||
|
If you find any bugs, please report them at
|
||||||
|
L<https://gitlab.com/apparmor/apparmor/-/issues>.
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
apparmor(7), apparmor.d(5), apparmor_parser(8), and L<https://wiki.apparmor.net>.
|
||||||
|
|
||||||
|
=cut
|
@@ -117,13 +117,13 @@ display only counts for selected information.
|
|||||||
=item --filter.mode=filter
|
=item --filter.mode=filter
|
||||||
|
|
||||||
Allows specifying a posix regular expression filter that will be
|
Allows specifying a posix regular expression filter that will be
|
||||||
applied against the displayed processess and profiles apparmor profile
|
applied against the displayed processes and profiles apparmor profile
|
||||||
mode, reducing the output.
|
mode, reducing the output.
|
||||||
|
|
||||||
=item --filter.profiles=filter
|
=item --filter.profiles=filter
|
||||||
|
|
||||||
Allows specifying a posix regular expression filter that will be
|
Allows specifying a posix regular expression filter that will be
|
||||||
applied against the displayed processess and profiles confining
|
applied against the displayed processes and profiles confining
|
||||||
profile, reducing the output.
|
profile, reducing the output.
|
||||||
|
|
||||||
=item --filter.pid=filter
|
=item --filter.pid=filter
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -309,9 +310,8 @@ static int load_arg(char *arg)
|
|||||||
|
|
||||||
static void print_usage(const char *command)
|
static void print_usage(const char *command)
|
||||||
{
|
{
|
||||||
printf("Usage: %s [OPTIONS] (cache file|cache dir|cache base dir)]*\n"
|
printf("Usage: %s [OPTIONS] (cache file|cache dir|cache base dir)+\n"
|
||||||
"Load Precompiled AppArmor policy from a cache location or \n"
|
"Load precompiled AppArmor policy from cache location(s)\n\n"
|
||||||
"locations.\n\n"
|
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" -f, --force load policy even if abi does not match the kernel\n"
|
" -f, --force load policy even if abi does not match the kernel\n"
|
||||||
" -d, --debug display debug messages\n"
|
" -d, --debug display debug messages\n"
|
||||||
|
@@ -20,6 +20,8 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#define _(s) gettext(s)
|
||||||
|
|
||||||
#include <sys/apparmor.h>
|
#include <sys/apparmor.h>
|
||||||
#include <sys/apparmor_private.h>
|
#include <sys/apparmor_private.h>
|
||||||
@@ -156,14 +158,14 @@ static int open_profiles(FILE **fp)
|
|||||||
|
|
||||||
ret = stat("/sys/module/apparmor", &st);
|
ret = stat("/sys/module/apparmor", &st);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
eprintf("apparmor not present.\n");
|
eprintf(_("apparmor not present.\n"));
|
||||||
return AA_EXIT_DISABLED;
|
return AA_EXIT_DISABLED;
|
||||||
}
|
}
|
||||||
dprintf("apparmor module is loaded.\n");
|
dprintf(_("apparmor module is loaded.\n"));
|
||||||
|
|
||||||
ret = aa_find_mountpoint(&apparmorfs);
|
ret = aa_find_mountpoint(&apparmorfs);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
eprintf("apparmor filesystem is not mounted.\n");
|
eprintf(_("apparmor filesystem is not mounted.\n"));
|
||||||
return AA_EXIT_NO_CONTROL;
|
return AA_EXIT_NO_CONTROL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,9 +178,9 @@ static int open_profiles(FILE **fp)
|
|||||||
*fp = fopen(apparmor_profiles, "r");
|
*fp = fopen(apparmor_profiles, "r");
|
||||||
if (*fp == NULL) {
|
if (*fp == NULL) {
|
||||||
if (errno == EACCES) {
|
if (errno == EACCES) {
|
||||||
eprintf("You do not have enough privilege to read the profile set.\n");
|
eprintf(_("You do not have enough privilege to read the profile set.\n"));
|
||||||
} else {
|
} else {
|
||||||
eprintf("Could not open %s: %s", apparmor_profiles, strerror(errno));
|
eprintf(_("Could not open %s: %s"), apparmor_profiles, strerror(errno));
|
||||||
}
|
}
|
||||||
return AA_EXIT_NO_PERM;
|
return AA_EXIT_NO_PERM;
|
||||||
}
|
}
|
||||||
@@ -351,7 +353,7 @@ static int get_processes(struct profile *profiles,
|
|||||||
continue;
|
continue;
|
||||||
} else if (rc == -1 ||
|
} else if (rc == -1 ||
|
||||||
asprintf(&exe, "/proc/%s/exe", entry->d_name) == -1) {
|
asprintf(&exe, "/proc/%s/exe", entry->d_name) == -1) {
|
||||||
eprintf("ERROR: Failed to allocate memory\n");
|
eprintf(_("ERROR: Failed to allocate memory\n"));
|
||||||
ret = AA_EXIT_INTERNAL_ERROR;
|
ret = AA_EXIT_INTERNAL_ERROR;
|
||||||
goto exit;
|
goto exit;
|
||||||
} else if (mode) {
|
} else if (mode) {
|
||||||
@@ -374,7 +376,7 @@ static int get_processes(struct profile *profiles,
|
|||||||
// ensure enough space for NUL terminator
|
// ensure enough space for NUL terminator
|
||||||
real_exe = calloc(PATH_MAX + 1, sizeof(char));
|
real_exe = calloc(PATH_MAX + 1, sizeof(char));
|
||||||
if (real_exe == NULL) {
|
if (real_exe == NULL) {
|
||||||
eprintf("ERROR: Failed to allocate memory\n");
|
eprintf(_("ERROR: Failed to allocate memory\n"));
|
||||||
ret = AA_EXIT_INTERNAL_ERROR;
|
ret = AA_EXIT_INTERNAL_ERROR;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -488,7 +490,7 @@ static int filter_processes(struct process *processes,
|
|||||||
*
|
*
|
||||||
* Return: 0 on success, else shell error code
|
* Return: 0 on success, else shell error code
|
||||||
*/
|
*/
|
||||||
static int simple_filtered_count(FILE *outf, filters_t *filters,
|
static int simple_filtered_count(FILE *outf, filters_t *filters, bool json,
|
||||||
struct profile *profiles, size_t nprofiles)
|
struct profile *profiles, size_t nprofiles)
|
||||||
{
|
{
|
||||||
struct profile *filtered = NULL;
|
struct profile *filtered = NULL;
|
||||||
@@ -497,7 +499,13 @@ static int simple_filtered_count(FILE *outf, filters_t *filters,
|
|||||||
|
|
||||||
ret = filter_profiles(profiles, nprofiles, filters,
|
ret = filter_profiles(profiles, nprofiles, filters,
|
||||||
&filtered, &nfiltered);
|
&filtered, &nfiltered);
|
||||||
|
|
||||||
|
if (!json) {
|
||||||
fprintf(outf, "%zd\n", nfiltered);
|
fprintf(outf, "%zd\n", nfiltered);
|
||||||
|
} else {
|
||||||
|
fprintf(outf, "\"profile_count\": %zd", nfiltered);
|
||||||
|
}
|
||||||
|
|
||||||
free_profiles(filtered, nfiltered);
|
free_profiles(filtered, nfiltered);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -512,7 +520,7 @@ static int simple_filtered_count(FILE *outf, filters_t *filters,
|
|||||||
*
|
*
|
||||||
* Return: 0 on success, else shell error code
|
* Return: 0 on success, else shell error code
|
||||||
*/
|
*/
|
||||||
static int simple_filtered_process_count(FILE *outf, filters_t *filters,
|
static int simple_filtered_process_count(FILE *outf, filters_t *filters, bool json,
|
||||||
struct process *processes, size_t nprocesses) {
|
struct process *processes, size_t nprocesses) {
|
||||||
struct process *filtered = NULL;
|
struct process *filtered = NULL;
|
||||||
size_t nfiltered;
|
size_t nfiltered;
|
||||||
@@ -520,7 +528,12 @@ static int simple_filtered_process_count(FILE *outf, filters_t *filters,
|
|||||||
|
|
||||||
ret = filter_processes(processes, nprocesses, filters, &filtered,
|
ret = filter_processes(processes, nprocesses, filters, &filtered,
|
||||||
&nfiltered);
|
&nfiltered);
|
||||||
|
if (!json) {
|
||||||
fprintf(outf, "%zd\n", nfiltered);
|
fprintf(outf, "%zd\n", nfiltered);
|
||||||
|
} else {
|
||||||
|
fprintf(outf, "\"process_count\": %zd", nfiltered);
|
||||||
|
}
|
||||||
|
|
||||||
free_processes(filtered, nfiltered);
|
free_processes(filtered, nfiltered);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -539,7 +552,12 @@ static int compare_processes_by_executable(const void *a, const void *b) {
|
|||||||
|
|
||||||
static void json_header(FILE *outf)
|
static void json_header(FILE *outf)
|
||||||
{
|
{
|
||||||
fprintf(outf, "{\"version\": \"%s\", ", aa_status_json_version);
|
fprintf(outf, "{\"version\": \"%s\"", aa_status_json_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void json_seperator(FILE *outf)
|
||||||
|
{
|
||||||
|
fprintf(outf, ", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void json_footer(FILE *outf)
|
static void json_footer(FILE *outf)
|
||||||
@@ -582,7 +600,7 @@ static int detailed_profiles(FILE *outf, filters_t *filters, bool json,
|
|||||||
*/
|
*/
|
||||||
subfilters.mode = &mode_filter;
|
subfilters.mode = &mode_filter;
|
||||||
if (regcomp(&mode_filter, profile_statuses[i], REG_NOSUB) != 0) {
|
if (regcomp(&mode_filter, profile_statuses[i], REG_NOSUB) != 0) {
|
||||||
eprintf("Error: failed to compile sub filter '%s'\n",
|
eprintf(_("Error: failed to compile sub filter '%s'\n"),
|
||||||
profile_statuses[i]);
|
profile_statuses[i]);
|
||||||
return AA_EXIT_INTERNAL_ERROR;
|
return AA_EXIT_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
@@ -607,7 +625,7 @@ static int detailed_profiles(FILE *outf, filters_t *filters, bool json,
|
|||||||
free_profiles(filtered, nfiltered);
|
free_profiles(filtered, nfiltered);
|
||||||
}
|
}
|
||||||
if (json)
|
if (json)
|
||||||
fprintf(outf, "}, ");
|
fprintf(outf, "}");
|
||||||
|
|
||||||
return AA_EXIT_ENABLED;
|
return AA_EXIT_ENABLED;
|
||||||
}
|
}
|
||||||
@@ -648,7 +666,7 @@ static int detailed_processes(FILE *outf, filters_t *filters, bool json,
|
|||||||
*/
|
*/
|
||||||
subfilters.mode = &mode_filter;
|
subfilters.mode = &mode_filter;
|
||||||
if (regcomp(&mode_filter, process_statuses[i], REG_NOSUB) != 0) {
|
if (regcomp(&mode_filter, process_statuses[i], REG_NOSUB) != 0) {
|
||||||
eprintf("Error: failed to compile sub filter '%s'\n",
|
eprintf(_("Error: failed to compile sub filter '%s'\n"),
|
||||||
profile_statuses[i]);
|
profile_statuses[i]);
|
||||||
return AA_EXIT_INTERNAL_ERROR;
|
return AA_EXIT_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
@@ -700,7 +718,7 @@ static int detailed_processes(FILE *outf, filters_t *filters, bool json,
|
|||||||
fprintf(outf, "]");
|
fprintf(outf, "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(outf, "}\n");
|
fprintf(outf, "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@@ -710,7 +728,7 @@ exit:
|
|||||||
|
|
||||||
static int print_legacy(const char *command)
|
static int print_legacy(const char *command)
|
||||||
{
|
{
|
||||||
printf("Usage: %s [OPTIONS]\n"
|
printf(_("Usage: %s [OPTIONS]\n"
|
||||||
"Legacy options and their equivalent command\n"
|
"Legacy options and their equivalent command\n"
|
||||||
" --profiled --count --profiles\n"
|
" --profiled --count --profiles\n"
|
||||||
" --enforced --count --profiles --mode=enforced\n"
|
" --enforced --count --profiles --mode=enforced\n"
|
||||||
@@ -718,7 +736,7 @@ static int print_legacy(const char *command)
|
|||||||
" --kill --count --profiles --mode=kill\n"
|
" --kill --count --profiles --mode=kill\n"
|
||||||
" --prompt --count --profiles --mode=prompt\n"
|
" --prompt --count --profiles --mode=prompt\n"
|
||||||
" --special-unconfined --count --profiles --mode=unconfined\n"
|
" --special-unconfined --count --profiles --mode=unconfined\n"
|
||||||
" --process-mixed --count --ps --mode=mixed\n",
|
" --process-mixed --count --ps --mode=mixed\n"),
|
||||||
command);
|
command);
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
@@ -729,7 +747,7 @@ static int usage_filters(void)
|
|||||||
{
|
{
|
||||||
long unsigned int i;
|
long unsigned int i;
|
||||||
|
|
||||||
printf("Usage of filters\n"
|
printf(_("Usage of filters\n"
|
||||||
"Filters are used to reduce the output of information to only\n"
|
"Filters are used to reduce the output of information to only\n"
|
||||||
"those entries that will match the filter. Filters use posix\n"
|
"those entries that will match the filter. Filters use posix\n"
|
||||||
"regular expression syntax. The possible values for exes that\n"
|
"regular expression syntax. The possible values for exes that\n"
|
||||||
@@ -739,7 +757,7 @@ static int usage_filters(void)
|
|||||||
" --filter.profiles: regular expression to match displayed profile names\n"
|
" --filter.profiles: regular expression to match displayed profile names\n"
|
||||||
" --filter.pid: regular expression to match displayed processes pids\n"
|
" --filter.pid: regular expression to match displayed processes pids\n"
|
||||||
" --filter.exe: regular expression to match executable\n"
|
" --filter.exe: regular expression to match executable\n"
|
||||||
);
|
));
|
||||||
for (i = 0; i < ARRAY_SIZE(process_statuses); i++) {
|
for (i = 0; i < ARRAY_SIZE(process_statuses); i++) {
|
||||||
printf("%s%s", i ? ", " : "", process_statuses[i]);
|
printf("%s%s", i ? ", " : "", process_statuses[i]);
|
||||||
}
|
}
|
||||||
@@ -757,7 +775,7 @@ static int print_usage(const char *command, bool error)
|
|||||||
status = EXIT_FAILURE;
|
status = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Usage: %s [OPTIONS]\n"
|
printf(_("Usage: %s [OPTIONS]\n"
|
||||||
"Displays various information about the currently loaded AppArmor policy.\n"
|
"Displays various information about the currently loaded AppArmor policy.\n"
|
||||||
"Default if no options given\n"
|
"Default if no options given\n"
|
||||||
" --show=all\n\n"
|
" --show=all\n\n"
|
||||||
@@ -774,7 +792,7 @@ static int print_usage(const char *command, bool error)
|
|||||||
" --verbose (default) displays data points about loaded policy set\n"
|
" --verbose (default) displays data points about loaded policy set\n"
|
||||||
" --quiet don't output error messages\n"
|
" --quiet don't output error messages\n"
|
||||||
" -h[(legacy|filters)] this message, or info on the specified option\n"
|
" -h[(legacy|filters)] this message, or info on the specified option\n"
|
||||||
" --help[=(legacy|filters)] this message, or info on the specified option\n",
|
" --help[=(legacy|filters)] this message, or info on the specified option\n"),
|
||||||
command);
|
command);
|
||||||
|
|
||||||
exit(status);
|
exit(status);
|
||||||
@@ -851,7 +869,7 @@ static int parse_args(int argc, char **argv)
|
|||||||
} else if (strcmp(optarg, "filters") == 0) {
|
} else if (strcmp(optarg, "filters") == 0) {
|
||||||
usage_filters();
|
usage_filters();
|
||||||
} else {
|
} else {
|
||||||
eprintf("Error: Invalid --help option '%s'.\n", optarg);
|
eprintf(_("Error: Invalid --help option '%s'.\n"), optarg);
|
||||||
print_usage(argv[0], true);
|
print_usage(argv[0], true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -919,7 +937,7 @@ static int parse_args(int argc, char **argv)
|
|||||||
} else if (strcmp(optarg, "processes") == 0) {
|
} else if (strcmp(optarg, "processes") == 0) {
|
||||||
opt_show = SHOW_PROCESSES;
|
opt_show = SHOW_PROCESSES;
|
||||||
} else {
|
} else {
|
||||||
eprintf("Error: Invalid --show option '%s'.\n", optarg);
|
eprintf(_("Error: Invalid --show option '%s'.\n"), optarg);
|
||||||
print_usage(argv[0], true);
|
print_usage(argv[0], true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -941,7 +959,7 @@ static int parse_args(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
eprintf("Error: Invalid command.\n");
|
eprintf(_("Error: Invalid command.\n"));
|
||||||
print_usage(argv[0], true);
|
print_usage(argv[0], true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -966,7 +984,7 @@ int main(int argc, char **argv)
|
|||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
int pos = parse_args(argc, argv);
|
int pos = parse_args(argc, argv);
|
||||||
if (pos < argc) {
|
if (pos < argc) {
|
||||||
eprintf("Error: Unknown options.\n");
|
eprintf(_("Error: Unknown options.\n"));
|
||||||
print_usage(progname, true);
|
print_usage(progname, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -978,24 +996,24 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
init_filters(&filters, &filter_set);
|
init_filters(&filters, &filter_set);
|
||||||
if (regcomp(filters.mode, opt_mode, REG_NOSUB) != 0) {
|
if (regcomp(filters.mode, opt_mode, REG_NOSUB) != 0) {
|
||||||
eprintf("Error: failed to compile mode filter '%s'\n",
|
eprintf(_("Error: failed to compile mode filter '%s'\n"),
|
||||||
opt_mode);
|
opt_mode);
|
||||||
return AA_EXIT_INTERNAL_ERROR;
|
return AA_EXIT_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
if (regcomp(filters.profile, opt_profiles, REG_NOSUB) != 0) {
|
if (regcomp(filters.profile, opt_profiles, REG_NOSUB) != 0) {
|
||||||
eprintf("Error: failed to compile profiles filter '%s'\n",
|
eprintf(_("Error: failed to compile profiles filter '%s'\n"),
|
||||||
opt_profiles);
|
opt_profiles);
|
||||||
ret = AA_EXIT_INTERNAL_ERROR;
|
ret = AA_EXIT_INTERNAL_ERROR;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (regcomp(filters.pid, opt_pid, REG_NOSUB) != 0) {
|
if (regcomp(filters.pid, opt_pid, REG_NOSUB) != 0) {
|
||||||
eprintf("Error: failed to compile ps filter '%s'\n",
|
eprintf(_("Error: failed to compile ps filter '%s'\n"),
|
||||||
opt_pid);
|
opt_pid);
|
||||||
ret = AA_EXIT_INTERNAL_ERROR;
|
ret = AA_EXIT_INTERNAL_ERROR;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (regcomp(filters.exe, opt_exe, REG_NOSUB) != 0) {
|
if (regcomp(filters.exe, opt_exe, REG_NOSUB) != 0) {
|
||||||
eprintf("Error: failed to compile exe filter '%s'\n",
|
eprintf(_("Error: failed to compile exe filter '%s'\n"),
|
||||||
opt_exe);
|
opt_exe);
|
||||||
ret = AA_EXIT_INTERNAL_ERROR;
|
ret = AA_EXIT_INTERNAL_ERROR;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -1010,7 +1028,7 @@ int main(int argc, char **argv)
|
|||||||
outf_save = outf;
|
outf_save = outf;
|
||||||
outf = open_memstream(&buffer, &buffer_size);
|
outf = open_memstream(&buffer, &buffer_size);
|
||||||
if (!outf) {
|
if (!outf) {
|
||||||
eprintf("Failed to open memstream: %m\n");
|
eprintf(_("Failed to open memstream: %m\n"));
|
||||||
return AA_EXIT_INTERNAL_ERROR;
|
return AA_EXIT_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1020,16 +1038,20 @@ int main(int argc, char **argv)
|
|||||||
* have policy associated.
|
* have policy associated.
|
||||||
*/
|
*/
|
||||||
ret = get_profiles(fp, &profiles, &nprofiles);
|
ret = get_profiles(fp, &profiles, &nprofiles);
|
||||||
if (ret != 0) {
|
if (ret == AA_EXIT_NO_POLICY) {
|
||||||
eprintf("Failed to get profiles: %d....\n", ret);
|
eprintf(_("No policy loaded into the kernel\n"));
|
||||||
|
} else if (ret != 0 && !opt_json) {
|
||||||
|
eprintf(_("Failed to retrieve profiles from kernel: %d....\n"), ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt_json)
|
if (opt_json)
|
||||||
json_header(outf);
|
json_header(outf);
|
||||||
if (opt_show & SHOW_PROFILES) {
|
if (opt_show & SHOW_PROFILES) {
|
||||||
|
if (opt_json)
|
||||||
|
json_seperator(outf);
|
||||||
if (opt_count) {
|
if (opt_count) {
|
||||||
ret = simple_filtered_count(outf, &filters,
|
ret = simple_filtered_count(outf, &filters, opt_json,
|
||||||
profiles, nprofiles);
|
profiles, nprofiles);
|
||||||
} else {
|
} else {
|
||||||
ret = detailed_profiles(outf, &filters, opt_json,
|
ret = detailed_profiles(outf, &filters, opt_json,
|
||||||
@@ -1040,14 +1062,17 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (opt_show & SHOW_PROCESSES) {
|
if (opt_show & SHOW_PROCESSES) {
|
||||||
|
if (opt_json)
|
||||||
|
json_seperator(outf);
|
||||||
|
|
||||||
struct process *processes = NULL;
|
struct process *processes = NULL;
|
||||||
size_t nprocesses = 0;
|
size_t nprocesses = 0;
|
||||||
|
|
||||||
ret = get_processes(profiles, nprofiles, &processes, &nprocesses);
|
ret = get_processes(profiles, nprofiles, &processes, &nprocesses);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
eprintf("Failed to get processes: %d....\n", ret);
|
eprintf(_("Failed to get confinement information from processes: %d....\n"), ret);
|
||||||
} else if (opt_count) {
|
} else if (opt_count) {
|
||||||
ret = simple_filtered_process_count(outf, &filters,
|
ret = simple_filtered_process_count(outf, &filters, opt_json,
|
||||||
processes, nprocesses);
|
processes, nprocesses);
|
||||||
} else {
|
} else {
|
||||||
ret = detailed_processes(outf, &filters, opt_json,
|
ret = detailed_processes(outf, &filters, opt_json,
|
||||||
@@ -1071,14 +1096,14 @@ int main(int argc, char **argv)
|
|||||||
outf = outf_save;
|
outf = outf_save;
|
||||||
json = cJSON_Parse(buffer);
|
json = cJSON_Parse(buffer);
|
||||||
if (!json) {
|
if (!json) {
|
||||||
eprintf("Failed to parse json output");
|
eprintf(_("Failed to parse json output"));
|
||||||
ret = AA_EXIT_INTERNAL_ERROR;
|
ret = AA_EXIT_INTERNAL_ERROR;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
pretty = cJSON_Print(json);
|
pretty = cJSON_Print(json);
|
||||||
if (!pretty) {
|
if (!pretty) {
|
||||||
eprintf("Failed to print pretty json");
|
eprintf(_("Failed to print pretty json"));
|
||||||
ret = AA_EXIT_INTERNAL_ERROR;
|
ret = AA_EXIT_INTERNAL_ERROR;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@@ -1,14 +1,14 @@
|
|||||||
# SOME DESCRIPTIVE TITLE.
|
# Translations for aa_enabled
|
||||||
# Copyright (C) YEAR Canonical Ltd
|
# Copyright (C) 2024 Canonical Ltd
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
# This file is distributed under the same license as the AppArmor package.
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
# John Johansen <john.johansen@canonical.com>, 2020.
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
|
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
|
||||||
"POT-Creation-Date: 2020-10-14 03:52-0700\n"
|
"POT-Creation-Date: 2024-08-31 15:59-0700\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@@ -1,14 +1,14 @@
|
|||||||
# SOME DESCRIPTIVE TITLE.
|
# Translations for aa_exec
|
||||||
# Copyright (C) YEAR Canonical Ltd
|
# Copyright (C) 2024 Canonical Ltd
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
# This file is distributed under the same license as the AppArmor package.
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
# John Johansen <john.johansen@canonical.com>, 2020.
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
|
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
|
||||||
"POT-Creation-Date: 2020-10-14 03:52-0700\n"
|
"POT-Creation-Date: 2024-08-31 15:59-0700\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@@ -1,14 +1,14 @@
|
|||||||
# SOME DESCRIPTIVE TITLE.
|
# Translations for aa_features_abi
|
||||||
# Copyright (C) YEAR Canonical Ltd
|
# Copyright (C) 2024 Canonical Ltd
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
# This file is distributed under the same license as the AppArmor package.
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
# John Johansen <john.johansen@canonical.com>, 2011.
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
|
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
|
||||||
"POT-Creation-Date: 2020-10-14 03:52-0700\n"
|
"POT-Creation-Date: 2024-08-31 15:59-0700\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
34
binutils/po/aa_load.pot
Normal file
34
binutils/po/aa_load.pot
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Translations for aa_load
|
||||||
|
# Copyright (C) 2024 Canonical Ltd
|
||||||
|
# This file is distributed under the same license as the AppArmor package.
|
||||||
|
# John Johansen <john.johansen@canonical.com>, 2020.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
|
||||||
|
"POT-Creation-Date: 2024-08-31 15:59-0700\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=CHARSET\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: ../aa_load.c:40
|
||||||
|
msgid "aa-load: WARN: "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_load.c:41
|
||||||
|
msgid "aa-load: ERROR: "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_load.c:51
|
||||||
|
msgid "\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_load.c:52
|
||||||
|
msgid "aa-load: DEBUG: "
|
||||||
|
msgstr ""
|
179
binutils/po/aa_status.pot
Normal file
179
binutils/po/aa_status.pot
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR Canonical Ltd
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
|
||||||
|
"POT-Creation-Date: 2025-04-26 11:12-0700\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=CHARSET\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: ../aa_status.c:161
|
||||||
|
msgid "apparmor not present.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:164
|
||||||
|
msgid "apparmor module is loaded.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:168
|
||||||
|
msgid "apparmor filesystem is not mounted.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:181
|
||||||
|
msgid "You do not have enough privilege to read the profile set.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:183
|
||||||
|
#, c-format
|
||||||
|
msgid "Could not open %s: %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:356 ../aa_status.c:379
|
||||||
|
msgid "ERROR: Failed to allocate memory\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:587 ../aa_status.c:653 ../aa_status.c:603 ../aa_status.c:669
|
||||||
|
#, c-format
|
||||||
|
msgid "Error: failed to compile sub filter '%s'\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:715 ../aa_status.c:731
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"Usage: %s [OPTIONS]\n"
|
||||||
|
"Legacy options and their equivalent command\n"
|
||||||
|
" --profiled --count --profiles\n"
|
||||||
|
" --enforced --count --profiles --mode=enforced\n"
|
||||||
|
" --complaining --count --profiles --mode=complain\n"
|
||||||
|
" --kill --count --profiles --mode=kill\n"
|
||||||
|
" --prompt --count --profiles --mode=prompt\n"
|
||||||
|
" --special-unconfined --count --profiles --mode=unconfined\n"
|
||||||
|
" --process-mixed --count --ps --mode=mixed\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:734 ../aa_status.c:750
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"Usage of filters\n"
|
||||||
|
"Filters are used to reduce the output of information to only\n"
|
||||||
|
"those entries that will match the filter. Filters use posix\n"
|
||||||
|
"regular expression syntax. The possible values for exes that\n"
|
||||||
|
"support filters are below\n"
|
||||||
|
"\n"
|
||||||
|
" --filter.mode: regular expression to match the profile "
|
||||||
|
"mode modes: enforce, complain, kill, unconfined, mixed\n"
|
||||||
|
" --filter.profiles: regular expression to match displayed profile names\n"
|
||||||
|
" --filter.pid: regular expression to match displayed processes pids\n"
|
||||||
|
" --filter.exe: regular expression to match executable\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:762 ../aa_status.c:778
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"Usage: %s [OPTIONS]\n"
|
||||||
|
"Displays various information about the currently loaded AppArmor policy.\n"
|
||||||
|
"Default if no options given\n"
|
||||||
|
" --show=all\n"
|
||||||
|
"\n"
|
||||||
|
"OPTIONS (one only):\n"
|
||||||
|
" --enabled returns error code if AppArmor not enabled\n"
|
||||||
|
" --show=X What information to show. {profiles,processes,all}\n"
|
||||||
|
" --count print the number of entries. Implies --quiet\n"
|
||||||
|
" --filter.mode=filter see filters\n"
|
||||||
|
" --filter.profiles=filter see filters\n"
|
||||||
|
" --filter.pid=filter see filters\n"
|
||||||
|
" --filter.exe=filter see filters\n"
|
||||||
|
" --json displays multiple data points in machine-readable JSON "
|
||||||
|
"format\n"
|
||||||
|
" --pretty-json same data as --json, formatted for human consumption as "
|
||||||
|
"well\n"
|
||||||
|
" --verbose (default) displays data points about loaded policy set\n"
|
||||||
|
" --quiet don't output error messages\n"
|
||||||
|
" -h[(legacy|filters)] this message, or info on the specified option\n"
|
||||||
|
" --help[=(legacy|filters)] this message, or info on the specified option\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:856 ../aa_status.c:872
|
||||||
|
#, c-format
|
||||||
|
msgid "Error: Invalid --help option '%s'.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:924 ../aa_status.c:940
|
||||||
|
#, c-format
|
||||||
|
msgid "Error: Invalid --show option '%s'.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:946 ../aa_status.c:962
|
||||||
|
msgid "Error: Invalid command.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:971 ../aa_status.c:987
|
||||||
|
msgid "Error: Unknown options.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:983 ../aa_status.c:999
|
||||||
|
#, c-format
|
||||||
|
msgid "Error: failed to compile mode filter '%s'\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:988 ../aa_status.c:1004
|
||||||
|
#, c-format
|
||||||
|
msgid "Error: failed to compile profiles filter '%s'\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:994 ../aa_status.c:1010
|
||||||
|
#, c-format
|
||||||
|
msgid "Error: failed to compile ps filter '%s'\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:1000 ../aa_status.c:1016
|
||||||
|
#, c-format
|
||||||
|
msgid "Error: failed to compile exe filter '%s'\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:1015 ../aa_status.c:1031
|
||||||
|
#, c-format
|
||||||
|
msgid "Failed to open memstream: %m\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:1026
|
||||||
|
#, c-format
|
||||||
|
msgid "Failed to get profiles: %d....\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:1050
|
||||||
|
#, c-format
|
||||||
|
msgid "Failed to get processes: %d....\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:1076 ../aa_status.c:1099
|
||||||
|
msgid "Failed to parse json output"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:1083 ../aa_status.c:1106
|
||||||
|
msgid "Failed to print pretty json"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:1044
|
||||||
|
#, c-format
|
||||||
|
msgid "Failed to retrieve profiles from kernel: %d....\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:1073
|
||||||
|
#, c-format
|
||||||
|
msgid "Failed to get confinement information from processes: %d....\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_status.c:1042
|
||||||
|
msgid "No policy loaded into the kernel\n"
|
||||||
|
msgstr ""
|
67
binutils/po/be.po
Normal file
67
binutils/po/be.po
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Belarusian translation for apparmor
|
||||||
|
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2020-05-05 21:55+0000\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: Belarusian <be@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2020-05-06 05:41+0000\n"
|
||||||
|
"X-Generator: Launchpad (build fbdff7602bd10fb883bf7e2ddcc7fd5a16f60398)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr ""
|
71
binutils/po/ca.po
Normal file
71
binutils/po/ca.po
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# Catalan translation for apparmor
|
||||||
|
# Copyright (c) 2024 Rosetta Contributors and Canonical Ltd 2024
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2024.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2024-09-14 10:17+0000\n"
|
||||||
|
"Last-Translator: Walter Garcia-Fontes <walter.garcia@upf.edu>\n"
|
||||||
|
"Language-Team: Catalan <ca@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2024-09-15 07:16+0000\n"
|
||||||
|
"X-Generator: Launchpad (build 1b1ed1ad2dbfc71ee62b5c5491c975135a771bf0)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
"%s: [opcions]\n"
|
||||||
|
" opcions:\n"
|
||||||
|
" -q | --quiet No imprimeixis cap missatge\n"
|
||||||
|
" -h | --help Imprimeix l'ajuda\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr "opcions desconegudes o incompatibles\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr "opció desconeguda «%s»\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr "Sí\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr "No - no esta disponible a aquest sistema\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr "No - desactivat a l'inici.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr "Potser - la interfície de política no està disponible.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr "Potser - permisos insuficient per determinar la disponibilitat.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr "Error - '%s'\n"
|
67
binutils/po/cs.po
Normal file
67
binutils/po/cs.po
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Czech translation for apparmor
|
||||||
|
# Copyright (c) 2022 Rosetta Contributors and Canonical Ltd 2022
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2022-01-09 11:59+0000\n"
|
||||||
|
"Last-Translator: Marek Hladík <mhladik@seznam.cz>\n"
|
||||||
|
"Language-Team: Czech <cs@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2022-01-10 06:32+0000\n"
|
||||||
|
"X-Generator: Launchpad (build 1682fd44eec4f62371f0bed122a83482daf08e23)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr "neznámé nebo nekompatibilní volby\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr "neznámá volba '%s'\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr "Ano\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr "Ne - není v tomto systému k dispozici.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr "Ne - zakázáno při startu.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr "Možná - rozhraní zásad není k dispozici.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr "Možná - nedostatečná oprávnění k určení dostupnosti.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr "Chyba - '%s'\n"
|
67
binutils/po/en_AU.po
Normal file
67
binutils/po/en_AU.po
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# English (Australia) translation for apparmor
|
||||||
|
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2020-11-28 04:45+0000\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: English (Australia) <en_AU@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2020-11-29 06:26+0000\n"
|
||||||
|
"X-Generator: Launchpad (build 12d09381f8e8eee3115395875b132e165fa96574)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr ""
|
67
binutils/po/en_CA.po
Normal file
67
binutils/po/en_CA.po
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# English (Canada) translation for apparmor
|
||||||
|
# Copyright (c) 2021 Rosetta Contributors and Canonical Ltd 2021
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2021-10-01 04:55+0000\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: English (Canada) <en_CA@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2021-10-02 06:17+0000\n"
|
||||||
|
"X-Generator: Launchpad (build 1ce78163f6a09ed42b4201fe7d3f0e3a2eba7d02)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr ""
|
71
binutils/po/et.po
Normal file
71
binutils/po/et.po
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# Estonian translation for apparmor
|
||||||
|
# Copyright (c) 2023 Rosetta Contributors and Canonical Ltd 2023
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2023.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2023-07-04 08:52+0000\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: Estonian <et@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2023-07-05 04:31+0000\n"
|
||||||
|
"X-Generator: Launchpad (build beda0e9dd2b131780db60fe479d4b43618b27243)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
"%s: [valikud]\n"
|
||||||
|
" valikud:\n"
|
||||||
|
" -q | --quiet Ärge printige sõnumeid välja\n"
|
||||||
|
" -h | --help Prindi abiinfo\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr "tundmatud või ühildumatud valikud\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr "tundmatu valik '%s'\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr "Jah\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr "Ei – pole selles süsteemis saadaval.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr "Ei – käivitamisel keelatud.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr "Võib-olla – poliisiliides pole saadaval.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr "Võib-olla - kättesaadavuse määramiseks pole piisavalt õigusi.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr "Viga – '%s'\n"
|
67
binutils/po/gl.po
Normal file
67
binutils/po/gl.po
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Galician translation for apparmor
|
||||||
|
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2020-04-21 14:59+0000\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: Galician <gl@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2020-04-22 06:10+0000\n"
|
||||||
|
"X-Generator: Launchpad (build aad6b57d58e2f621954298e262c1cc904860f5d2)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr ""
|
71
binutils/po/he.po
Normal file
71
binutils/po/he.po
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# Hebrew translation for apparmor
|
||||||
|
# Copyright (c) 2023 Rosetta Contributors and Canonical Ltd 2023
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2023.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2023-10-05 05:12+0000\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: Hebrew <he@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2023-10-06 08:32+0000\n"
|
||||||
|
"X-Generator: Launchpad (build bd6cfd0cfc024dbe1dcd7d5d91165fb4f6a6c596)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
"%s: [אפשרויות]\n"
|
||||||
|
" אפשרויות:\n"
|
||||||
|
" -q | --quiet לא להציג הודעות\n"
|
||||||
|
" -h | --help הצגת עזרה\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr "אפשרויות לא ידועות או לא נתמכות\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr "האפשרות ‚%s’ לא מוכרת\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr "כן\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr "לא - לא זמין במערכת הזאת.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr "לא - מושבת בעלייה.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr "אולי - מנשק המדיניות לא זמין.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr "אולי - אין מספיק הרשאות לקבוע זמינות.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr "שגיאה - ‚%s’\n"
|
67
binutils/po/hi.po
Normal file
67
binutils/po/hi.po
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Hindi translation for apparmor
|
||||||
|
# Copyright (c) 2023 Rosetta Contributors and Canonical Ltd 2023
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2023.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2023-01-09 07:39+0000\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: Hindi <hi@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2023-01-10 06:22+0000\n"
|
||||||
|
"X-Generator: Launchpad (build 87bfee1fd14ea3245297d63eeec1e4c8a1d203a8)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr ""
|
71
binutils/po/hr.po
Normal file
71
binutils/po/hr.po
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# Croatian translation for apparmor
|
||||||
|
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2021-10-03 10:17+0000\n"
|
||||||
|
"Last-Translator: gogo <trebelnik2@gmail.com>\n"
|
||||||
|
"Language-Team: Croatian <hr@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2021-10-04 06:23+0000\n"
|
||||||
|
"X-Generator: Launchpad (build 1ce78163f6a09ed42b4201fe7d3f0e3a2eba7d02)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
"%s: [mogućnosti]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Ne prikazuj poruke\n"
|
||||||
|
" -h | --help Prikaži pomoć\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr "nepoznata ili nepotpuna mogućnost\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr "nepoznata mogućnost '%s'\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr "Da\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr "Ne - nedostupno na ovom sustavu.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr "Ne - onemogućeno pri pokretanju.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr "Možda - pravilo sučelja nedostupno.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr "Možda - nedovoljna dozvola za određivanje dostupnosti.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr "Greška - '%s'\n"
|
72
binutils/po/it.po
Normal file
72
binutils/po/it.po
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
# Italian translation for apparmor
|
||||||
|
# Copyright (c) 2022 Rosetta Contributors and Canonical Ltd 2022
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2022-06-30 17:54+0000\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: Italian <it@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2022-07-01 04:30+0000\n"
|
||||||
|
"X-Generator: Launchpad (build f48158886a49da429840bcd298f0c7ed60f9ad7b)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
"%s: [opzioni]\n"
|
||||||
|
" opzioni:\n"
|
||||||
|
" -q | --quiet Non stampa nessun messaggio\n"
|
||||||
|
" -h | --help Stampa la guida\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr "opzioni sconosciute o incompatibili\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr "opzione sconosciuta '%s'\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr "Si\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr "No - non disponibile su questo sistema.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr "No - disabilitato all'avvio.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr "Forse - interfaccia dei criteri non disponibile.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr ""
|
||||||
|
"Forse - autorizzazioni insufficienti per determinare la disponibilità.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr "Errore - '%s'\n"
|
72
binutils/po/ka.po
Normal file
72
binutils/po/ka.po
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
# Georgian translation for apparmor
|
||||||
|
# Copyright (c) 2023 Rosetta Contributors and Canonical Ltd 2023
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2023.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2023-06-26 15:06+0000\n"
|
||||||
|
"Last-Translator: NorwayFun <temuri.doghonadze@gmail.com>\n"
|
||||||
|
"Language-Team: Georgian <ka@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2023-06-27 04:31+0000\n"
|
||||||
|
"X-Generator: Launchpad (build aedf8597c50c1abc5fb7f9e871e686dfcb381fde)\n"
|
||||||
|
"Language: aa\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
"%s: [პარამეტრები]\n"
|
||||||
|
" პარამეტრები:\n"
|
||||||
|
" -q | --quiet შეტყობინებები გამოტანილი არ იქნება\n"
|
||||||
|
" -h | --help დახმარების გამოტანა\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr "უცნობი ან შეუთავსებელი პარამეტრები\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr "უცნობი პარამეტრი \"%s\"-სთვის\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr "დიახ\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr "არა - მიუწვდომელია ამ სისტემაზე\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr "არა - გამორთულია ჩატვირთვისას\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr "შეიძლება - პოლიტიკის ინტერფეისი ხელმისაწვდომი არაა.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr "შეიძლება - არასაკმარისი წვდომები ხელმისაწვდომობის დასადგენად.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr "შეცდომა - \"%s\"\n"
|
67
binutils/po/kab.po
Normal file
67
binutils/po/kab.po
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Kabyle translation for apparmor
|
||||||
|
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2020-04-29 14:31+0000\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: Kabyle <kab@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2020-04-30 05:44+0000\n"
|
||||||
|
"X-Generator: Launchpad (build fbdff7602bd10fb883bf7e2ddcc7fd5a16f60398)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr ""
|
73
binutils/po/my.po
Normal file
73
binutils/po/my.po
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# Burmese translation for apparmor
|
||||||
|
# Copyright (c) 2022 Rosetta Contributors and Canonical Ltd 2022
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2022.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2022-06-26 11:50+0000\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: Burmese <my@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2022-06-27 04:30+0000\n"
|
||||||
|
"X-Generator: Launchpad (build 51a2e4fa2e9b8e45f00904ad7f53546f45ac48a5)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
"%s- [options]\n"
|
||||||
|
" ရွေးချယ်စရာများ-\n"
|
||||||
|
" -q | --quiet မည်သည့်စာတိုကိုမှ ပရင့်မထုတ်ပါနှင့်။\n"
|
||||||
|
" -h | --help ပရင့်အကူအညီ\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr "အမည်မသိ သို့မဟုတ် သဟဇာတမဖြစ်သော ရွေးချယ်စရာများ\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr "အမည်မသိရွေးချယ်မှု '%s'\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr "ဟုတ်\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr "မဟုတ်ပါ - ဤစနစ်တွင် မရနိုင်ပါ။\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr "မဟုတ်ပါ - boot တွင် ပိတ်ထားပါသည်။\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr "ဖြစ်နိုင်ပါသည် - မူဝါဒ interface ကို မရနိုင်ပါ။\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr ""
|
||||||
|
"ဖြစ်နိုင်ပါသည် - ရရှိနိုင်မှုကို ဆုံးဖြတ်ရန်အတွက် ခွင့်ပြုချက်များမှာ "
|
||||||
|
"လုံလောက်မှုမရှိပါ။\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr "အမှား- '%s'\n"
|
67
binutils/po/oc.po
Normal file
67
binutils/po/oc.po
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Occitan (post 1500) translation for apparmor
|
||||||
|
# Copyright (c) 2021 Rosetta Contributors and Canonical Ltd 2021
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2021-01-14 18:26+0000\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: Occitan (post 1500) <oc@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2021-01-15 07:59+0000\n"
|
||||||
|
"X-Generator: Launchpad (build 511b4a3b6512aa3d421c5f7d74f3527e78bff26e)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr ""
|
71
binutils/po/pl.po
Normal file
71
binutils/po/pl.po
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# Polish translation for apparmor
|
||||||
|
# Copyright (c) 2021 Rosetta Contributors and Canonical Ltd 2021
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2021-07-22 20:10+0000\n"
|
||||||
|
"Last-Translator: Marek Adamski <Unknown>\n"
|
||||||
|
"Language-Team: Polish <pl@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2021-07-23 06:03+0000\n"
|
||||||
|
"X-Generator: Launchpad (build 7edebbcd0516593cf020aaa3c59299732a7c73cc)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
"%s: [opcje]\n"
|
||||||
|
" opcje:\n"
|
||||||
|
" -q | --quiet Nie wyświetlaj żadnych komunikatów\n"
|
||||||
|
" -h | --help Wyświetl pomoc\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr "nieznane lub niekompatybilne opcje\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr "nieznana opcja '%s'\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr "Tak\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr "Nie - nie jest dostępne w tym systemie.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr "Nie - wyłączone podczas rozruchu.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr "Może - interfejs zasad nie jest dostępny.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr "Może - brak wystarczających uprawnień do określenia dostępności.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr "Błąd - '%s'\n"
|
71
binutils/po/pt_BR.po
Normal file
71
binutils/po/pt_BR.po
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# Brazilian Portuguese translation for apparmor
|
||||||
|
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2020-04-27 20:32+0000\n"
|
||||||
|
"Last-Translator: Rodrigo Farias <Unknown>\n"
|
||||||
|
"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2020-04-28 05:52+0000\n"
|
||||||
|
"X-Generator: Launchpad (build d1105341713c5be348effe2a5142c4a210ce4cde)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" opções:\n"
|
||||||
|
" -q | --quiet Não imprimir nenhum mensagem\n"
|
||||||
|
" -h | --help Assistente de impressão\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr "opções incompatíveis ou desconhecidas\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr "opção desconhecida '%s'\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr "Sim\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr "Não - não disponível neste sistema.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr "Não - desabilitado na inicialização.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr "Talvez - interface de política não disponível.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr "Talvez - permissões insuficientes para determinar disponibilidade.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr "Erro - '%s'\n"
|
@@ -1,21 +1,26 @@
|
|||||||
# Romanian translation for apparmor
|
# Romanian translation for apparmor, "apparmor-binutils" component.
|
||||||
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
# Mesajele în limba română pentru pachetul „apparmor”, componenta „apparmor-binutils”.
|
||||||
|
# Copyright © 2020 Rosetta Contributors and Canonical Ltd.
|
||||||
|
# Copyright © 2024 Canonical Ltd.
|
||||||
# This file is distributed under the same license as the apparmor package.
|
# This file is distributed under the same license as the apparmor package.
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
#
|
||||||
|
# Daniel Slavu <Unknown>, feb-2020.
|
||||||
|
# Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>, sep-2024.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: apparmor\n"
|
"Project-Id-Version: apparmor-binutils\n"
|
||||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
"Report-Msgid-Bugs-To: <apparmor@lists.ubuntu.com>\n"
|
||||||
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
"PO-Revision-Date: 2020-02-20 21:47+0000\n"
|
"PO-Revision-Date: 2024-09-23 22:45+0000\n"
|
||||||
"Last-Translator: Daniel Slavu <Unknown>\n"
|
"Last-Translator: Remus-Gabriel Chelu <Unknown>\n"
|
||||||
"Language-Team: Romanian <ro@li.org>\n"
|
"Language-Team: Romanian <debian-l10n-romanian@lists.debian.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2020-02-21 05:39+0000\n"
|
"X-Launchpad-Export-Date: 2024-09-25 04:33+0000\n"
|
||||||
"X-Generator: Launchpad (build 19413b719a8df7423ab1390528edadce9e0e4aca)\n"
|
"X-Generator: Launchpad (build 1b1ed1ad2dbfc71ee62b5c5491c975135a771bf0)\n"
|
||||||
|
"Language: ro\n"
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
#: ../aa_enabled.c:26
|
||||||
#, c-format
|
#, c-format
|
||||||
@@ -27,8 +32,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"%s: [opțiuni]\n"
|
"%s: [opțiuni]\n"
|
||||||
" opțiuni:\n"
|
" opțiuni:\n"
|
||||||
" -q | --calm Nu imprima niciun mesaj\n"
|
" -q | --quiet nu afișează niciun mesaj\n"
|
||||||
" -h | - ajutor Imprimare ajutor\n"
|
" -h | --help imprimă ajutorul\n"
|
||||||
|
|
||||||
#: ../aa_enabled.c:45
|
#: ../aa_enabled.c:45
|
||||||
#, c-format
|
#, c-format
|
||||||
@@ -38,7 +43,7 @@ msgstr "opțiuni necunoscute sau incompatibile\n"
|
|||||||
#: ../aa_enabled.c:55
|
#: ../aa_enabled.c:55
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "unknown option '%s'\n"
|
msgid "unknown option '%s'\n"
|
||||||
msgstr "opțiune necunoscută '%s'\n"
|
msgstr "opțiune necunoscută „%s”\n"
|
||||||
|
|
||||||
#: ../aa_enabled.c:64
|
#: ../aa_enabled.c:64
|
||||||
#, c-format
|
#, c-format
|
||||||
@@ -58,7 +63,8 @@ msgstr "Nu - dezactivat la pornire.\n"
|
|||||||
#: ../aa_enabled.c:77
|
#: ../aa_enabled.c:77
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Maybe - policy interface not available.\n"
|
msgid "Maybe - policy interface not available.\n"
|
||||||
msgstr "Poate - interfața politică nu este disponibilă.\n"
|
msgstr ""
|
||||||
|
"Poate - interfața politică (de directive politice) nu este disponibilă.\n"
|
||||||
|
|
||||||
#: ../aa_enabled.c:81
|
#: ../aa_enabled.c:81
|
||||||
#, c-format
|
#, c-format
|
||||||
@@ -69,4 +75,4 @@ msgstr ""
|
|||||||
#: ../aa_enabled.c:84
|
#: ../aa_enabled.c:84
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Error - '%s'\n"
|
msgid "Error - '%s'\n"
|
||||||
msgstr "Eroare - '%s'\n"
|
msgstr "Eroare - „%s”\n"
|
||||||
|
67
binutils/po/sr.po
Normal file
67
binutils/po/sr.po
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Serbian translation for apparmor
|
||||||
|
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2020-11-23 18:06+0000\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: Serbian <sr@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2020-11-24 05:55+0000\n"
|
||||||
|
"X-Generator: Launchpad (build c35ff22711d15549e2303ae18ae521fd91f6bf00)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr ""
|
71
binutils/po/uk.po
Normal file
71
binutils/po/uk.po
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# Ukrainian translation for apparmor
|
||||||
|
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2020-05-19 21:48+0000\n"
|
||||||
|
"Last-Translator: Nazarii Ritter <nazariy.ritter@gmail.com>\n"
|
||||||
|
"Language-Team: Ukrainian <uk@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2020-05-20 05:42+0000\n"
|
||||||
|
"X-Generator: Launchpad (build 0385b538081bc4718df6fb844a3afc89729c94ce)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
"%s: [опції]\n"
|
||||||
|
" опції:\n"
|
||||||
|
" -q | --quiet Не виводити жодних повідомлень\n"
|
||||||
|
" -h | --help Вивести довідку\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr "невідомі або несумісні опції\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr "невідомий параметр «%s»\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr "Так\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr "Ні – недоступно на цій системі.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr "Ні – вимкнено під час завантаження.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr "Можливо – інтерфейс політики недоступний.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr "Можливо – недостатньо дозволів для визначення наявності.\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr "Помилка - '%s'\n"
|
71
binutils/po/zh_CN.po
Normal file
71
binutils/po/zh_CN.po
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# Chinese (Simplified) translation for apparmor
|
||||||
|
# Copyright (c) 2020 Rosetta Contributors and Canonical Ltd 2020
|
||||||
|
# This file is distributed under the same license as the apparmor package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: apparmor\n"
|
||||||
|
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: 2020-05-14 09:16+0000\n"
|
||||||
|
"Last-Translator: 玉堂白鹤 <yjwork@qq.com>\n"
|
||||||
|
"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Launchpad-Export-Date: 2020-05-15 05:51+0000\n"
|
||||||
|
"X-Generator: Launchpad (build 0385b538081bc4718df6fb844a3afc89729c94ce)\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
"%s: [选项]\n"
|
||||||
|
" 选项:\n"
|
||||||
|
" -q | --quiet 不要打印任何消息\n"
|
||||||
|
" -h | --help 打印帮助\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr "未知或不兼容的选项\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr "未知选项 '%s'\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr "是\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr "否 - 在此系统上不可用。\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr "否 - 引导时被禁用。\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr "也许 - 策略界面不可用\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr "也许 - 没有足够的权限确定可用性。\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr "错误 - '%s'\n"
|
@@ -35,17 +35,14 @@ VERSION=$(shell cat $(COMMONDIR)/Version)
|
|||||||
pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
|
pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
|
||||||
map = $(foreach a,$(2),$(call $(1),$(a)))
|
map = $(foreach a,$(2),$(call $(1),$(a)))
|
||||||
|
|
||||||
AWK:=$(shell which awk)
|
AWK?=$(or $(shell which awk),$(error awk utility required for build but not available))
|
||||||
ifndef AWK
|
|
||||||
$(error awk utility required for build but not available)
|
|
||||||
endif
|
|
||||||
|
|
||||||
define nl
|
define nl
|
||||||
|
|
||||||
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
REPO_VERSION_CMD=[ -x /usr/bin/git ] && /usr/bin/git describe --tags --long --abbrev=16 --match 'v*' 2> /dev/null || awk '{ print $2 }' common/.stamp_rev
|
REPO_VERSION_CMD=[ -x /usr/bin/git ] && /usr/bin/git describe --tags --long --abbrev=16 --match 'v*' 2> /dev/null || $(AWK) '{ print $2 }' common/.stamp_rev
|
||||||
|
|
||||||
ifndef PYTHON_VERSIONS
|
ifndef PYTHON_VERSIONS
|
||||||
PYTHON_VERSIONS = $(call map, pathsearch, python3)
|
PYTHON_VERSIONS = $(call map, pathsearch, python3)
|
||||||
|
@@ -1 +1 @@
|
|||||||
4.1.0~beta1
|
5.0.0~alpha1
|
||||||
|
@@ -92,6 +92,8 @@ if test "$ac_cv_prog_cc_c99" = "no"; then
|
|||||||
AC_MSG_ERROR([C99 mode is required to build libapparmor])
|
AC_MSG_ERROR([C99 mode is required to build libapparmor])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AC_PROG_CXX
|
||||||
|
|
||||||
m4_ifndef([AX_CHECK_COMPILE_FLAG], [AC_MSG_ERROR(['autoconf-archive' missing])])
|
m4_ifndef([AX_CHECK_COMPILE_FLAG], [AC_MSG_ERROR(['autoconf-archive' missing])])
|
||||||
EXTRA_CFLAGS="-Wall $EXTRA_WARNINGS -fPIC"
|
EXTRA_CFLAGS="-Wall $EXTRA_WARNINGS -fPIC"
|
||||||
AX_CHECK_COMPILE_FLAG([-flto-partition=none], , , [-Werror])
|
AX_CHECK_COMPILE_FLAG([-flto-partition=none], , , [-Werror])
|
||||||
@@ -99,6 +101,7 @@ AS_VAR_IF([ax_cv_check_cflags__Werror__flto_partition_none], [yes],
|
|||||||
[EXTRA_CFLAGS="$EXTRA_CFLAGS -flto-partition=none"]
|
[EXTRA_CFLAGS="$EXTRA_CFLAGS -flto-partition=none"]
|
||||||
,)
|
,)
|
||||||
AC_SUBST([AM_CFLAGS], ["$EXTRA_CFLAGS"])
|
AC_SUBST([AM_CFLAGS], ["$EXTRA_CFLAGS"])
|
||||||
|
AC_SUBST([AM_CXXFLAGS], ["$EXTRA_CFLAGS"])
|
||||||
|
|
||||||
AC_OUTPUT(
|
AC_OUTPUT(
|
||||||
Makefile
|
Makefile
|
||||||
|
@@ -28,9 +28,9 @@ aa_change_hat - change to or from a "hat" within a AppArmor profile
|
|||||||
|
|
||||||
B<#include E<lt>sys/apparmor.hE<gt>>
|
B<#include E<lt>sys/apparmor.hE<gt>>
|
||||||
|
|
||||||
B<int aa_change_hat (char *subprofile, unsigned long magic_token);>
|
B<int aa_change_hat (const char *subprofile, unsigned long magic_token);>
|
||||||
|
|
||||||
B<int aa_change_hatv (char *subprofiles[], unsigned long magic_token);>
|
B<int aa_change_hatv (const char *subprofiles[], unsigned long magic_token);>
|
||||||
|
|
||||||
B<int aa_change_hat_vargs (unsigned long magic_token, ...);>
|
B<int aa_change_hat_vargs (unsigned long magic_token, ...);>
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
aa_change_profile, aa_change_onexec - change a tasks profile
|
aa_change_profile, aa_change_onexec - change a task's profile
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
@@ -58,8 +58,8 @@ The aa_change_onexec() function is like the aa_change_profile() function
|
|||||||
except it specifies that the profile transition should take place on the
|
except it specifies that the profile transition should take place on the
|
||||||
next exec instead of immediately. The delayed profile change takes
|
next exec instead of immediately. The delayed profile change takes
|
||||||
precedence over any exec transition rules within the confining profile.
|
precedence over any exec transition rules within the confining profile.
|
||||||
Delaying the profile boundary has a couple of advantages, it removes the
|
Delaying the profile boundary has a couple of advantages: it removes the
|
||||||
need for stub transition profiles and the exec boundary is a natural security
|
need for stub transition profiles, and the exec boundary is a natural security
|
||||||
layer where potentially sensitive memory is unmapped.
|
layer where potentially sensitive memory is unmapped.
|
||||||
|
|
||||||
=head1 RETURN VALUE
|
=head1 RETURN VALUE
|
||||||
|
@@ -54,7 +54,7 @@ B<typedef struct aa_features aa_features;>
|
|||||||
|
|
||||||
B<int aa_features_new(aa_features **features, int dirfd, const char *path);>
|
B<int aa_features_new(aa_features **features, int dirfd, const char *path);>
|
||||||
|
|
||||||
B<int aa_features_new_from_file(aa_features **features, int fd);>
|
B<int aa_features_new_from_file(aa_features **features, int file);>
|
||||||
|
|
||||||
B<int aa_features_new_from_string(aa_features **features, const char *string, size_t size);>
|
B<int aa_features_new_from_string(aa_features **features, const char *string, size_t size);>
|
||||||
|
|
||||||
|
@@ -58,6 +58,9 @@ appropriately.
|
|||||||
|
|
||||||
=head1 ERRORS
|
=head1 ERRORS
|
||||||
|
|
||||||
|
# podchecker warns about duplicate link targets for EACCES, EBUSY, ENOENT,
|
||||||
|
# and ENOMEM, but this is a warning that is safe to ignore.
|
||||||
|
|
||||||
B<aa_is_enabled>
|
B<aa_is_enabled>
|
||||||
|
|
||||||
=over 4
|
=over 4
|
||||||
|
@@ -41,7 +41,7 @@ result is an intersection of all profiles which are stacked. Stacking profiles
|
|||||||
together is desirable when wanting to ensure that confinement will never become
|
together is desirable when wanting to ensure that confinement will never become
|
||||||
more permissive. When changing between two profiles, as performed with
|
more permissive. When changing between two profiles, as performed with
|
||||||
aa_change_profile(2), there is always the possibility that the new profile is
|
aa_change_profile(2), there is always the possibility that the new profile is
|
||||||
more permissive than the old profile but that possibility is eliminated when
|
more permissive than the old profile, but that possibility is eliminated when
|
||||||
using aa_stack_profile().
|
using aa_stack_profile().
|
||||||
|
|
||||||
To stack a profile with the current confinement context, a task can use the
|
To stack a profile with the current confinement context, a task can use the
|
||||||
@@ -68,7 +68,7 @@ The aa_stack_onexec() function is like the aa_stack_profile() function
|
|||||||
except it specifies that the stacking should take place on the next exec
|
except it specifies that the stacking should take place on the next exec
|
||||||
instead of immediately. The delayed profile change takes precedence over any
|
instead of immediately. The delayed profile change takes precedence over any
|
||||||
exec transition rules within the confining profile. Delaying the stacking
|
exec transition rules within the confining profile. Delaying the stacking
|
||||||
boundary has a couple of advantages, it removes the need for stub transition
|
boundary has a couple of advantages: it removes the need for stub transition
|
||||||
profiles and the exec boundary is a natural security layer where potentially
|
profiles and the exec boundary is a natural security layer where potentially
|
||||||
sensitive memory is unmapped.
|
sensitive memory is unmapped.
|
||||||
|
|
||||||
|
@@ -19,6 +19,10 @@
|
|||||||
#ifndef __LIBAALOGPARSE_H_
|
#ifndef __LIBAALOGPARSE_H_
|
||||||
#define __LIBAALOGPARSE_H_
|
#define __LIBAALOGPARSE_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define AA_RECORD_EXEC_MMAP 1
|
#define AA_RECORD_EXEC_MMAP 1
|
||||||
#define AA_RECORD_READ 2
|
#define AA_RECORD_READ 2
|
||||||
#define AA_RECORD_WRITE 4
|
#define AA_RECORD_WRITE 4
|
||||||
@@ -26,10 +30,10 @@
|
|||||||
#define AA_RECORD_LINK 16
|
#define AA_RECORD_LINK 16
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is just for convenience now that we have two
|
* Enum representing which syntax version the log entry used.
|
||||||
* wildly different grammars.
|
* Support for V1 parsing was completely removed in 2011 and that enum entry
|
||||||
|
* is only still there for API compatibility reasons.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
AA_RECORD_SYNTAX_V1,
|
AA_RECORD_SYNTAX_V1,
|
||||||
@@ -48,70 +52,23 @@ typedef enum
|
|||||||
AA_RECORD_STATUS /* Configuration change */
|
AA_RECORD_STATUS /* Configuration change */
|
||||||
} aa_record_event_type;
|
} aa_record_event_type;
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* With the sole exception of active_hat, this is a 1:1
|
* Use this preprocessor dance to maintain backcompat for field names
|
||||||
* mapping from the keys that the new syntax uses.
|
* This will break C code that used the C++ reserved keywords "namespace"
|
||||||
|
* and "class" as identifiers, but this is bad practice anyways, and we
|
||||||
|
* hope that we are the only ones in a given C file that messed up this way
|
||||||
*
|
*
|
||||||
* Some examples of the old syntax and how they're mapped with the aa_log_record struct:
|
* TODO: document this in a man page for aalogparse?
|
||||||
*
|
*/
|
||||||
* "PERMITTING r access to /path (program_name(12345) profile /profile active hat)"
|
#if defined(SWIG) && defined(__cplusplus)
|
||||||
* - operation: access
|
#error "SWIG and __cplusplus are defined together"
|
||||||
* - requested_mask: r
|
#elif !defined(SWIG) && !defined(__cplusplus)
|
||||||
* - pid: 12345
|
/* Use SWIG's %rename feature to preserve backcompat */
|
||||||
* - profile: /profile
|
#define class rule_class
|
||||||
* - name: /path
|
#define namespace aa_namespace
|
||||||
* - info: program_name
|
#endif
|
||||||
* - active_hat: hat
|
|
||||||
*
|
|
||||||
* "REJECTING mkdir on /path/to/something (bash(23415) profile /bin/freak-aa-out active /bin/freak-aa-out"
|
|
||||||
* - operation: mkdir
|
|
||||||
* - name: /path/to/something
|
|
||||||
* - info: bash
|
|
||||||
* - pid: 23415
|
|
||||||
* - profile: /bin/freak-aa-out
|
|
||||||
* - active_hat: /bin/freak-aa-out
|
|
||||||
*
|
|
||||||
* "REJECTING xattr set on /path/to/something (bash(23415) profile /bin/freak-aa-out active /bin/freak-aa-out)"
|
|
||||||
* - operation: xattr
|
|
||||||
* - attribute: set
|
|
||||||
* - name: /path/to/something
|
|
||||||
* - info: bash
|
|
||||||
* - pid: 23415
|
|
||||||
* - profile: /bin/freak-aa-out
|
|
||||||
* - active_hat: /bin/freak-aa-out
|
|
||||||
*
|
|
||||||
* "PERMITTING attribute (something) change to /else (bash(23415) profile /bin/freak-aa-out active /bin/freak-aa-out)"
|
|
||||||
* - operation: setattr
|
|
||||||
* - attribute: something
|
|
||||||
* - name: /else
|
|
||||||
* - info: bash
|
|
||||||
* - pid: 23415
|
|
||||||
* - profile: /bin/freak-aa-out
|
|
||||||
* - active_hat: /bin/freak-aa-out
|
|
||||||
*
|
|
||||||
* "PERMITTING access to capability 'cap' (bash(23415) profile /bin/freak-aa-out active /bin/freak-aa-out)"
|
|
||||||
* - operation: capability
|
|
||||||
* - name: cap
|
|
||||||
* - info: bash
|
|
||||||
* - pid: 23415
|
|
||||||
* - profile: /bin/freak-aa-out
|
|
||||||
* - active_hat: /bin/freak-aa-out
|
|
||||||
*
|
|
||||||
* "LOGPROF-HINT unknown_hat TESTHAT pid=27764 profile=/change_hat_test/test_hat active=/change_hat_test/test_hat"
|
|
||||||
* - operation: change_hat
|
|
||||||
* - name: TESTHAT
|
|
||||||
* - info: unknown_hat
|
|
||||||
* - pid: 27764
|
|
||||||
* - profile: /change_hat_test/test_hat
|
|
||||||
* - active_hat: /change_hat_test/test_hat
|
|
||||||
*
|
|
||||||
* "LOGPROF-HINT fork pid=27764 child=38229"
|
|
||||||
* - operation: clone
|
|
||||||
* - task: 38229
|
|
||||||
* - pid: 27764
|
|
||||||
**/
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct aa_log_record
|
||||||
{
|
{
|
||||||
aa_record_syntax_version version;
|
aa_record_syntax_version version;
|
||||||
aa_record_event_type event; /* Event type */
|
aa_record_event_type event; /* Event type */
|
||||||
@@ -134,7 +91,7 @@ typedef struct
|
|||||||
char *comm; /* Command that triggered msg */
|
char *comm; /* Command that triggered msg */
|
||||||
char *name;
|
char *name;
|
||||||
char *name2;
|
char *name2;
|
||||||
char *namespace;
|
char *aa_namespace;
|
||||||
char *attribute;
|
char *attribute;
|
||||||
unsigned long parent;
|
unsigned long parent;
|
||||||
char *info;
|
char *info;
|
||||||
@@ -149,8 +106,6 @@ typedef struct
|
|||||||
char *net_foreign_addr;
|
char *net_foreign_addr;
|
||||||
unsigned long net_foreign_port;
|
unsigned long net_foreign_port;
|
||||||
|
|
||||||
char *execpath;
|
|
||||||
|
|
||||||
char *dbus_bus;
|
char *dbus_bus;
|
||||||
char *dbus_path;
|
char *dbus_path;
|
||||||
char *dbus_interface;
|
char *dbus_interface;
|
||||||
@@ -163,10 +118,11 @@ typedef struct
|
|||||||
char *flags;
|
char *flags;
|
||||||
char *src_name;
|
char *src_name;
|
||||||
|
|
||||||
char *class;
|
char *rule_class;
|
||||||
|
|
||||||
char *net_addr;
|
char *net_addr;
|
||||||
char *peer_addr;
|
char *peer_addr;
|
||||||
|
char *execpath;
|
||||||
} aa_log_record;
|
} aa_log_record;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -177,7 +133,7 @@ typedef struct
|
|||||||
* @return Parsed data.
|
* @return Parsed data.
|
||||||
*/
|
*/
|
||||||
aa_log_record *
|
aa_log_record *
|
||||||
parse_record(char *str);
|
parse_record(const char *str);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees all struct data.
|
* Frees all struct data.
|
||||||
@@ -186,5 +142,9 @@ parse_record(char *str);
|
|||||||
void
|
void
|
||||||
free_record(aa_log_record *record);
|
free_record(aa_log_record *record);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -105,8 +105,8 @@ extern int aa_getpeercon(int fd, char **label, char **mode);
|
|||||||
#define AA_QUERY_CMD_LABEL "label"
|
#define AA_QUERY_CMD_LABEL "label"
|
||||||
#define AA_QUERY_CMD_LABEL_SIZE sizeof(AA_QUERY_CMD_LABEL)
|
#define AA_QUERY_CMD_LABEL_SIZE sizeof(AA_QUERY_CMD_LABEL)
|
||||||
|
|
||||||
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
|
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allowed,
|
||||||
int *audit);
|
int *audited);
|
||||||
extern int aa_query_file_path_len(uint32_t mask, const char *label,
|
extern int aa_query_file_path_len(uint32_t mask, const char *label,
|
||||||
size_t label_len, const char *path,
|
size_t label_len, const char *path,
|
||||||
size_t path_len, int *allowed, int *audited);
|
size_t path_len, int *allowed, int *audited);
|
||||||
@@ -152,16 +152,16 @@ extern int aa_features_new_from_kernel(aa_features **features);
|
|||||||
extern aa_features *aa_features_ref(aa_features *features);
|
extern aa_features *aa_features_ref(aa_features *features);
|
||||||
extern void aa_features_unref(aa_features *features);
|
extern void aa_features_unref(aa_features *features);
|
||||||
|
|
||||||
extern int aa_features_write_to_fd(aa_features *features, int fd);
|
extern int aa_features_write_to_fd(const aa_features *features, int fd);
|
||||||
extern int aa_features_write_to_file(aa_features *features,
|
extern int aa_features_write_to_file(const aa_features *features,
|
||||||
int dirfd, const char *path);
|
int dirfd, const char *path);
|
||||||
extern bool aa_features_is_equal(aa_features *features1,
|
extern bool aa_features_is_equal(const aa_features *features1,
|
||||||
aa_features *features2);
|
const aa_features *features2);
|
||||||
extern int aa_features_check(int dirfd, const char *path,
|
extern int aa_features_check(int dirfd, const char *path,
|
||||||
aa_features *features);
|
aa_features *features);
|
||||||
extern bool aa_features_supports(aa_features *features, const char *str);
|
extern bool aa_features_supports(const aa_features *features, const char *str);
|
||||||
extern char *aa_features_id(aa_features *features);
|
extern char *aa_features_id(const aa_features *features);
|
||||||
extern char *aa_features_value(aa_features *features, const char *str, size_t *len);
|
extern char *aa_features_value(const aa_features *features, const char *str, size_t *len);
|
||||||
|
|
||||||
typedef struct aa_kernel_interface aa_kernel_interface;
|
typedef struct aa_kernel_interface aa_kernel_interface;
|
||||||
extern int aa_kernel_interface_new(aa_kernel_interface **kernel_interface,
|
extern int aa_kernel_interface_new(aa_kernel_interface **kernel_interface,
|
||||||
|
@@ -32,10 +32,10 @@ INCLUDES = $(all_includes)
|
|||||||
#
|
#
|
||||||
# After changing the AA_LIB_* variables, also update EXPECTED_SO_NAME.
|
# After changing the AA_LIB_* variables, also update EXPECTED_SO_NAME.
|
||||||
|
|
||||||
AA_LIB_CURRENT = 20
|
AA_LIB_CURRENT = 25
|
||||||
AA_LIB_REVISION = 0
|
AA_LIB_REVISION = 2
|
||||||
AA_LIB_AGE = 19
|
AA_LIB_AGE = 24
|
||||||
EXPECTED_SO_NAME = libapparmor.so.1.19.0
|
EXPECTED_SO_NAME = libapparmor.so.1.24.2
|
||||||
|
|
||||||
SUFFIXES = .pc.in .pc
|
SUFFIXES = .pc.in .pc
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ include $(COMMONDIR)/Make.rules
|
|||||||
|
|
||||||
BUILT_SOURCES = grammar.h scanner.h af_protos.h
|
BUILT_SOURCES = grammar.h scanner.h af_protos.h
|
||||||
AM_LFLAGS = -v
|
AM_LFLAGS = -v
|
||||||
AM_YFLAGS = -d -p aalogparse_
|
AM_YFLAGS = -Wno-yacc -d -p aalogparse_
|
||||||
AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_srcdir)/include/
|
AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_srcdir)/include/
|
||||||
scanner.h: scanner.l
|
scanner.h: scanner.l
|
||||||
$(LEX) -v $<
|
$(LEX) -v $<
|
||||||
@@ -52,7 +52,7 @@ scanner.h: scanner.l
|
|||||||
scanner.c: scanner.l
|
scanner.c: scanner.l
|
||||||
|
|
||||||
af_protos.h:
|
af_protos.h:
|
||||||
echo '#include <netinet/in.h>' | $(CC) $(CPPFLAGS) -E -dM - | LC_ALL=C sed -n -e "/IPPROTO_MAX/d" -e "s/^\#define[ \\t]\\+IPPROTO_\\([A-Z0-9_]\\+\\)\\(.*\\)$$/AA_GEN_PROTO_ENT(\\UIPPROTO_\\1, \"\\L\\1\")/p" > $@
|
echo '#include <netinet/in.h>' | $(CC) $(CPPFLAGS) -E -dD - | LC_ALL=C sed -n -e "/IPPROTO_MAX/d" -e "s/^\#define[ \\t]\\+IPPROTO_\\([A-Z0-9_]\\+\\)\\(.*\\)$$/AA_GEN_PROTO_ENT(\\UIPPROTO_\\1, \"\\L\\1\")/p" > $@
|
||||||
|
|
||||||
lib_LTLIBRARIES = libapparmor.la
|
lib_LTLIBRARIES = libapparmor.la
|
||||||
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h PMurHash.h
|
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h PMurHash.h
|
||||||
@@ -73,6 +73,16 @@ CLEANFILES = libapparmor.pc
|
|||||||
tst_aalogmisc_SOURCES = tst_aalogmisc.c
|
tst_aalogmisc_SOURCES = tst_aalogmisc.c
|
||||||
tst_aalogmisc_LDADD = .libs/libapparmor.a
|
tst_aalogmisc_LDADD = .libs/libapparmor.a
|
||||||
|
|
||||||
|
tst_aalogparse_cpp_SOURCES = tst_aalogparse_cpp.cpp
|
||||||
|
tst_aalogparse_cpp_LDADD = .libs/libapparmor.a
|
||||||
|
|
||||||
|
tst_aalogparse_oldname_SOURCES = tst_aalogparse_oldname.c
|
||||||
|
tst_aalogparse_oldname_LDADD = .libs/libapparmor.a
|
||||||
|
|
||||||
|
tst_aalogparse_reentrancy_SOURCES = tst_aalogparse_reentrancy.c
|
||||||
|
tst_aalogparse_reentrancy_LDADD = .libs/libapparmor.a
|
||||||
|
tst_aalogparse_reentrancy_LDFLAGS = -pthread
|
||||||
|
|
||||||
tst_features_SOURCES = tst_features.c
|
tst_features_SOURCES = tst_features.c
|
||||||
tst_features_LDADD = .libs/libapparmor.a
|
tst_features_LDADD = .libs/libapparmor.a
|
||||||
|
|
||||||
@@ -80,7 +90,7 @@ tst_kernel_SOURCES = tst_kernel.c
|
|||||||
tst_kernel_LDADD = .libs/libapparmor.a
|
tst_kernel_LDADD = .libs/libapparmor.a
|
||||||
tst_kernel_LDFLAGS = -pthread
|
tst_kernel_LDFLAGS = -pthread
|
||||||
|
|
||||||
check_PROGRAMS = tst_aalogmisc tst_features tst_kernel
|
check_PROGRAMS = tst_aalogmisc tst_aalogparse_cpp tst_aalogparse_reentrancy tst_aalogparse_oldname tst_features tst_kernel
|
||||||
TESTS = $(check_PROGRAMS)
|
TESTS = $(check_PROGRAMS)
|
||||||
|
|
||||||
.PHONY: check-local
|
.PHONY: check-local
|
||||||
|
@@ -399,6 +399,10 @@ static bool walk_one(const char **str, const struct component *component,
|
|||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
cur++;
|
cur++;
|
||||||
|
|
||||||
|
/* Partial match, continue to search */
|
||||||
|
if (i == component->len && !isbrace_space_or_nul(*cur))
|
||||||
|
i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return false if a full match was not found */
|
/* Return false if a full match was not found */
|
||||||
@@ -604,11 +608,11 @@ void aa_features_unref(aa_features *features)
|
|||||||
*
|
*
|
||||||
* Returns: 0 on success, -1 on error with errno set
|
* Returns: 0 on success, -1 on error with errno set
|
||||||
*/
|
*/
|
||||||
int aa_features_write_to_fd(aa_features *features, int fd)
|
int aa_features_write_to_fd(const aa_features *features, int fd)
|
||||||
{
|
{
|
||||||
size_t size;
|
size_t size;
|
||||||
ssize_t retval;
|
ssize_t retval;
|
||||||
char *string;
|
const char *string;
|
||||||
|
|
||||||
string = features->string;
|
string = features->string;
|
||||||
size = strlen(string);
|
size = strlen(string);
|
||||||
@@ -632,7 +636,7 @@ int aa_features_write_to_fd(aa_features *features, int fd)
|
|||||||
*
|
*
|
||||||
* Returns: 0 on success, -1 on error with errno set
|
* Returns: 0 on success, -1 on error with errno set
|
||||||
*/
|
*/
|
||||||
int aa_features_write_to_file(aa_features *features,
|
int aa_features_write_to_file(const aa_features *features,
|
||||||
int dirfd, const char *path)
|
int dirfd, const char *path)
|
||||||
{
|
{
|
||||||
autoclose int fd = -1;
|
autoclose int fd = -1;
|
||||||
@@ -653,7 +657,7 @@ int aa_features_write_to_file(aa_features *features,
|
|||||||
*
|
*
|
||||||
* Returns: true if they're equal, false if they're not or either are NULL
|
* Returns: true if they're equal, false if they're not or either are NULL
|
||||||
*/
|
*/
|
||||||
bool aa_features_is_equal(aa_features *features1, aa_features *features2)
|
bool aa_features_is_equal(const aa_features *features1, const aa_features *features2)
|
||||||
{
|
{
|
||||||
return features1 && features2 &&
|
return features1 && features2 &&
|
||||||
strcmp(features1->string, features2->string) == 0;
|
strcmp(features1->string, features2->string) == 0;
|
||||||
@@ -697,7 +701,7 @@ int aa_features_check(int dirfd, const char *path,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *features_lookup(aa_features *features, const char *str)
|
static const char *features_lookup(const aa_features *features, const char *str)
|
||||||
{
|
{
|
||||||
const char *features_string = features->string;
|
const char *features_string = features->string;
|
||||||
struct component components[32];
|
struct component components[32];
|
||||||
@@ -739,7 +743,7 @@ static const char *features_lookup(aa_features *features, const char *str)
|
|||||||
*
|
*
|
||||||
* Returns: a bool specifying the support status of @str feature
|
* Returns: a bool specifying the support status of @str feature
|
||||||
*/
|
*/
|
||||||
bool aa_features_supports(aa_features *features, const char *str)
|
bool aa_features_supports(const aa_features *features, const char *str)
|
||||||
{
|
{
|
||||||
const char *value = features_lookup(features, str);
|
const char *value = features_lookup(features, str);
|
||||||
|
|
||||||
@@ -760,7 +764,7 @@ bool aa_features_supports(aa_features *features, const char *str)
|
|||||||
* EISDIR - @str is not a leaf node in the feature tree
|
* EISDIR - @str is not a leaf node in the feature tree
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *aa_features_value(aa_features *features, const char *str, size_t *len)
|
char *aa_features_value(const aa_features *features, const char *str, size_t *len)
|
||||||
{
|
{
|
||||||
const char *start, *cur = features_lookup(features, str);
|
const char *start, *cur = features_lookup(features, str);
|
||||||
|
|
||||||
@@ -803,7 +807,7 @@ char *aa_features_value(aa_features *features, const char *str, size_t *len)
|
|||||||
* Returns: a string identifying @features which must be freed by the
|
* Returns: a string identifying @features which must be freed by the
|
||||||
* caller or NULL, with errno set, upon error
|
* caller or NULL, with errno set, upon error
|
||||||
*/
|
*/
|
||||||
char *aa_features_id(aa_features *features)
|
char *aa_features_id(const aa_features *features)
|
||||||
{
|
{
|
||||||
return strdup(features->hash);
|
return strdup(features->hash);
|
||||||
}
|
}
|
||||||
|
@@ -15,17 +15,15 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* aalogparse_error now requires visibility of the aa_log_record type
|
||||||
|
* Also include in a %code requires block to add it to the header
|
||||||
|
*/
|
||||||
|
%code requires{
|
||||||
|
#include <aalogparse.h>
|
||||||
|
}
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
|
||||||
/* set the following to non-zero to get bison to emit debugging
|
|
||||||
* information about tokens given and rules matched.
|
|
||||||
* Also:
|
|
||||||
* Uncomment the %defines
|
|
||||||
* parse.error
|
|
||||||
* parse.trace
|
|
||||||
*/
|
|
||||||
#define YYDEBUG 0
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <aalogparse.h>
|
#include <aalogparse.h>
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
@@ -41,12 +39,10 @@
|
|||||||
#define debug_unused_ unused_
|
#define debug_unused_ unused_
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
aa_log_record *ret_record;
|
|
||||||
|
|
||||||
/* Since we're a library, on any errors we don't want to print out any
|
/* Since we're a library, on any errors we don't want to print out any
|
||||||
* error messages. We should probably add a debug interface that does
|
* error messages. We should probably add a debug interface that does
|
||||||
* emit messages when asked for. */
|
* emit messages when asked for. */
|
||||||
void aalogparse_error(unused_ void *scanner, debug_unused_ char const *s)
|
void aalogparse_error(unused_ void *scanner, aa_log_record *ret_record, debug_unused_ char const *s)
|
||||||
{
|
{
|
||||||
#if (YYDEBUG != 0)
|
#if (YYDEBUG != 0)
|
||||||
printf("ERROR: %s\n", s);
|
printf("ERROR: %s\n", s);
|
||||||
@@ -89,9 +85,10 @@ aa_record_event_type lookup_aa_event(unsigned int type)
|
|||||||
%define parse.trace
|
%define parse.trace
|
||||||
*/
|
*/
|
||||||
|
|
||||||
%define api.pure
|
%define api.pure full
|
||||||
%lex-param{void *scanner}
|
%lex-param{void *scanner}
|
||||||
%parse-param{void *scanner}
|
%parse-param{void *scanner}
|
||||||
|
%parse-param{aa_log_record *ret_record}
|
||||||
|
|
||||||
%union
|
%union
|
||||||
{
|
{
|
||||||
@@ -284,8 +281,9 @@ audit_user_msg: TOK_KEY_MSG TOK_EQUALS audit_id audit_user_msg_tail
|
|||||||
|
|
||||||
audit_id: TOK_AUDIT TOK_OPEN_PAREN TOK_AUDIT_DIGITS TOK_PERIOD TOK_AUDIT_DIGITS TOK_COLON TOK_AUDIT_DIGITS TOK_CLOSE_PAREN TOK_COLON
|
audit_id: TOK_AUDIT TOK_OPEN_PAREN TOK_AUDIT_DIGITS TOK_PERIOD TOK_AUDIT_DIGITS TOK_COLON TOK_AUDIT_DIGITS TOK_CLOSE_PAREN TOK_COLON
|
||||||
{
|
{
|
||||||
if (!asprintf(&ret_record->audit_id, "%s.%s:%s", $3, $5, $7))
|
if (!asprintf(&ret_record->audit_id, "%s.%s:%s", $3, $5, $7)) {
|
||||||
yyerror(scanner, YY_("Out of memory"));
|
yyerror(scanner, ret_record, YY_("Out of memory"));
|
||||||
|
}
|
||||||
ret_record->epoch = atol($3);
|
ret_record->epoch = atol($3);
|
||||||
ret_record->audit_sub_id = atoi($7);
|
ret_record->audit_sub_id = atoi($7);
|
||||||
free($3);
|
free($3);
|
||||||
@@ -308,7 +306,7 @@ key: TOK_KEY_OPERATION TOK_EQUALS TOK_QUOTED_STRING
|
|||||||
| TOK_KEY_NAME TOK_EQUALS safe_string
|
| TOK_KEY_NAME TOK_EQUALS safe_string
|
||||||
{ ret_record->name = $3;}
|
{ ret_record->name = $3;}
|
||||||
| TOK_KEY_NAMESPACE TOK_EQUALS safe_string
|
| TOK_KEY_NAMESPACE TOK_EQUALS safe_string
|
||||||
{ ret_record->namespace = $3;}
|
{ ret_record->aa_namespace = $3;}
|
||||||
| TOK_KEY_NAME2 TOK_EQUALS safe_string
|
| TOK_KEY_NAME2 TOK_EQUALS safe_string
|
||||||
{ ret_record->name2 = $3;}
|
{ ret_record->name2 = $3;}
|
||||||
| TOK_KEY_MASK TOK_EQUALS TOK_QUOTED_STRING
|
| TOK_KEY_MASK TOK_EQUALS TOK_QUOTED_STRING
|
||||||
@@ -440,7 +438,7 @@ key: TOK_KEY_OPERATION TOK_EQUALS TOK_QUOTED_STRING
|
|||||||
ret_record->info = $1;
|
ret_record->info = $1;
|
||||||
}
|
}
|
||||||
| TOK_KEY_CLASS TOK_EQUALS TOK_QUOTED_STRING
|
| TOK_KEY_CLASS TOK_EQUALS TOK_QUOTED_STRING
|
||||||
{ ret_record->class = $3; }
|
{ ret_record->rule_class = $3; }
|
||||||
;
|
;
|
||||||
|
|
||||||
apparmor_event:
|
apparmor_event:
|
||||||
@@ -477,31 +475,3 @@ protocol: TOK_QUOTED_STRING
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
%%
|
%%
|
||||||
|
|
||||||
aa_log_record *
|
|
||||||
_parse_yacc(char *str)
|
|
||||||
{
|
|
||||||
/* yydebug = 1; */
|
|
||||||
YY_BUFFER_STATE lex_buf;
|
|
||||||
yyscan_t scanner;
|
|
||||||
|
|
||||||
ret_record = NULL;
|
|
||||||
ret_record = malloc(sizeof(aa_log_record));
|
|
||||||
|
|
||||||
_init_log_record(ret_record);
|
|
||||||
|
|
||||||
if (ret_record == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
#if (YYDEBUG != 0)
|
|
||||||
yydebug = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
aalogparse_lex_init(&scanner);
|
|
||||||
lex_buf = aalogparse__scan_string(str, scanner);
|
|
||||||
/* Ignore return value to return an AA_RECORD_INVALID event */
|
|
||||||
(void)aalogparse_parse(scanner);
|
|
||||||
aalogparse__delete_buffer(lex_buf, scanner);
|
|
||||||
aalogparse_lex_destroy(scanner);
|
|
||||||
return ret_record;
|
|
||||||
}
|
|
||||||
|
@@ -34,13 +34,42 @@
|
|||||||
#include <aalogparse.h>
|
#include <aalogparse.h>
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
|
#include "grammar.h"
|
||||||
|
#include "scanner.h"
|
||||||
|
|
||||||
/* This is mostly just a wrapper around the code in grammar.y */
|
/* This is mostly just a wrapper around the code in grammar.y */
|
||||||
aa_log_record *parse_record(char *str)
|
aa_log_record *parse_record(const char *str)
|
||||||
{
|
{
|
||||||
|
YY_BUFFER_STATE lex_buf;
|
||||||
|
yyscan_t scanner;
|
||||||
|
aa_log_record *ret_record;
|
||||||
|
|
||||||
if (str == NULL)
|
if (str == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return _parse_yacc(str);
|
ret_record = malloc(sizeof(aa_log_record));
|
||||||
|
|
||||||
|
_init_log_record(ret_record);
|
||||||
|
|
||||||
|
if (ret_record == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct string_buf string_buf = {.buf = NULL, .buf_len = 0, .buf_alloc = 0};
|
||||||
|
|
||||||
|
#if (YYDEBUG != 0)
|
||||||
|
/* Warning: this is still a global even in reentrant parsers */
|
||||||
|
aalogparse_debug = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
aalogparse_lex_init_extra(&string_buf, &scanner);
|
||||||
|
lex_buf = aalogparse__scan_string(str, scanner);
|
||||||
|
/* Ignore return value to return an AA_RECORD_INVALID event */
|
||||||
|
(void)aalogparse_parse(scanner, ret_record);
|
||||||
|
aalogparse__delete_buffer(lex_buf, scanner);
|
||||||
|
aalogparse_lex_destroy(scanner);
|
||||||
|
/* free(NULL) is a no-op */
|
||||||
|
free(string_buf.buf);
|
||||||
|
return ret_record;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_record(aa_log_record *record)
|
void free_record(aa_log_record *record)
|
||||||
@@ -63,8 +92,8 @@ void free_record(aa_log_record *record)
|
|||||||
free(record->name);
|
free(record->name);
|
||||||
if (record->name2 != NULL)
|
if (record->name2 != NULL)
|
||||||
free(record->name2);
|
free(record->name2);
|
||||||
if (record->namespace != NULL)
|
if (record->aa_namespace != NULL)
|
||||||
free(record->namespace);
|
free(record->aa_namespace);
|
||||||
if (record->attribute != NULL)
|
if (record->attribute != NULL)
|
||||||
free(record->attribute);
|
free(record->attribute);
|
||||||
if (record->info != NULL)
|
if (record->info != NULL)
|
||||||
@@ -110,8 +139,8 @@ void free_record(aa_log_record *record)
|
|||||||
if (record->execpath != NULL)
|
if (record->execpath != NULL)
|
||||||
free(record->execpath);
|
free(record->execpath);
|
||||||
|
|
||||||
if (record->class != NULL)
|
if (record->rule_class != NULL)
|
||||||
free(record->class);
|
free(record->rule_class);
|
||||||
|
|
||||||
free(record);
|
free(record);
|
||||||
}
|
}
|
||||||
|
@@ -19,8 +19,14 @@
|
|||||||
#ifndef __AA_LOG_PARSER_H__
|
#ifndef __AA_LOG_PARSER_H__
|
||||||
#define __AA_LOG_PARSER_H__
|
#define __AA_LOG_PARSER_H__
|
||||||
|
|
||||||
|
// Internal-only type
|
||||||
|
struct string_buf {
|
||||||
|
char *buf;
|
||||||
|
unsigned int buf_len;
|
||||||
|
unsigned int buf_alloc;
|
||||||
|
};
|
||||||
|
|
||||||
extern void _init_log_record(aa_log_record *record);
|
extern void _init_log_record(aa_log_record *record);
|
||||||
extern aa_log_record *_parse_yacc(char *str);
|
|
||||||
extern char *hex_to_string(char *str);
|
extern char *hex_to_string(char *str);
|
||||||
extern char *ipproto_to_string(unsigned int proto);
|
extern char *ipproto_to_string(unsigned int proto);
|
||||||
|
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
%option nounput
|
%option nounput
|
||||||
%option noyy_top_state
|
%option noyy_top_state
|
||||||
%option reentrant
|
%option reentrant
|
||||||
|
%option extra-type="struct string_buf*"
|
||||||
%option prefix="aalogparse_"
|
%option prefix="aalogparse_"
|
||||||
%option bison-bridge
|
%option bison-bridge
|
||||||
%option header-file="scanner.h"
|
%option header-file="scanner.h"
|
||||||
@@ -34,40 +35,37 @@
|
|||||||
|
|
||||||
#define YY_NO_INPUT
|
#define YY_NO_INPUT
|
||||||
|
|
||||||
unsigned int string_buf_alloc = 0;
|
void string_buf_reset(struct string_buf* char_buf)
|
||||||
unsigned int string_buf_len = 0;
|
|
||||||
char *string_buf = NULL;
|
|
||||||
|
|
||||||
void string_buf_reset()
|
|
||||||
{
|
{
|
||||||
/* rewind buffer to zero, possibly doing initial allocation too */
|
/* rewind buffer to zero, possibly doing initial allocation too */
|
||||||
string_buf_len = 0;
|
char_buf->buf_len = 0;
|
||||||
if (string_buf == NULL) {
|
if (char_buf->buf == NULL) {
|
||||||
string_buf_alloc = 128;
|
char_buf->buf_alloc = 128;
|
||||||
string_buf = malloc(string_buf_alloc);
|
char_buf->buf = malloc(char_buf->buf_alloc);
|
||||||
assert(string_buf != NULL);
|
assert(char_buf->buf != NULL);
|
||||||
}
|
}
|
||||||
/* always start with a valid but empty string */
|
/* always start with a valid but empty string */
|
||||||
string_buf[0] = '\0';
|
char_buf->buf[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
void string_buf_append(unsigned int length, char *text)
|
void string_buf_append(struct string_buf* char_buf, unsigned int length, char *text)
|
||||||
{
|
{
|
||||||
unsigned int current_length = string_buf_len;
|
unsigned int current_length = char_buf->buf_len;
|
||||||
|
|
||||||
/* handle calling ..._append before ..._reset */
|
/* handle calling ..._append before ..._reset */
|
||||||
if (string_buf == NULL) string_buf_reset();
|
if (char_buf->buf == NULL) string_buf_reset(char_buf);
|
||||||
|
|
||||||
string_buf_len += length;
|
char_buf->buf_len += length;
|
||||||
/* expand allocation if this append would exceed the allocation */
|
/* expand allocation if this append would exceed the allocation */
|
||||||
while (string_buf_len >= string_buf_alloc) {
|
while (char_buf->buf_len >= char_buf->buf_alloc) {
|
||||||
string_buf_alloc *= 2;
|
// TODO: overflow?
|
||||||
string_buf = realloc(string_buf, string_buf_alloc);
|
char_buf->buf_alloc *= 2;
|
||||||
assert(string_buf != NULL);
|
char_buf->buf = realloc(char_buf->buf, char_buf->buf_alloc);
|
||||||
|
assert(char_buf->buf != NULL);
|
||||||
}
|
}
|
||||||
/* copy and unconditionally terminate */
|
/* copy and unconditionally terminate */
|
||||||
memcpy(string_buf+current_length, text, length);
|
memcpy(char_buf->buf+current_length, text, length);
|
||||||
string_buf[string_buf_len] = '\0';
|
char_buf->buf[char_buf->buf_len] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
%}
|
%}
|
||||||
@@ -232,7 +230,7 @@ yy_flex_debug = 0;
|
|||||||
{open_paren} { return(TOK_OPEN_PAREN); }
|
{open_paren} { return(TOK_OPEN_PAREN); }
|
||||||
{close_paren} { BEGIN(INITIAL); return(TOK_CLOSE_PAREN); }
|
{close_paren} { BEGIN(INITIAL); return(TOK_CLOSE_PAREN); }
|
||||||
{ws} { }
|
{ws} { }
|
||||||
\" { string_buf_reset(); BEGIN(quoted_string); }
|
\" { string_buf_reset(yyextra); BEGIN(quoted_string); }
|
||||||
{ID}+ {
|
{ID}+ {
|
||||||
yylval->t_str = strdup(yytext);
|
yylval->t_str = strdup(yytext);
|
||||||
BEGIN(INITIAL);
|
BEGIN(INITIAL);
|
||||||
@@ -241,20 +239,20 @@ yy_flex_debug = 0;
|
|||||||
{equals} { return(TOK_EQUALS); }
|
{equals} { return(TOK_EQUALS); }
|
||||||
}
|
}
|
||||||
|
|
||||||
\" { string_buf_reset(); BEGIN(quoted_string); }
|
\" { string_buf_reset(yyextra); BEGIN(quoted_string); }
|
||||||
<quoted_string>\" { /* End of the quoted string */
|
<quoted_string>\" { /* End of the quoted string */
|
||||||
BEGIN(INITIAL);
|
BEGIN(INITIAL);
|
||||||
yylval->t_str = strdup(string_buf);
|
yylval->t_str = strdup(yyextra->buf);
|
||||||
return(TOK_QUOTED_STRING);
|
return(TOK_QUOTED_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
<quoted_string>\\(.|\n) { string_buf_append(1, &yytext[1]); }
|
<quoted_string>\\(.|\n) { string_buf_append(yyextra, 1, &yytext[1]); }
|
||||||
|
|
||||||
<quoted_string>[^\\\n\"]+ { string_buf_append(yyleng, yytext); }
|
<quoted_string>[^\\\n\"]+ { string_buf_append(yyextra, yyleng, yytext); }
|
||||||
|
|
||||||
<safe_string>{
|
<safe_string>{
|
||||||
\" { string_buf_reset(); BEGIN(quoted_string); }
|
\" { string_buf_reset(yyextra); BEGIN(quoted_string); }
|
||||||
{hexstring} { yylval->t_str = hex_to_string(yytext); BEGIN(INITIAL); return(TOK_HEXSTRING);}
|
{hexstring} { yylval->t_str = hex_to_string(yytext); BEGIN(INITIAL); return(TOK_HEXSTRING);}
|
||||||
{equals} { return(TOK_EQUALS); }
|
{equals} { return(TOK_EQUALS); }
|
||||||
. { /* eek, error! try another state */ BEGIN(INITIAL); yyless(0); }
|
. { /* eek, error! try another state */ BEGIN(INITIAL); yyless(0); }
|
||||||
|
20
libraries/libapparmor/src/tst_aalogparse_cpp.cpp
Normal file
20
libraries/libapparmor/src/tst_aalogparse_cpp.cpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#include <aalogparse.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
|
const char* log_line = "[23342.075380] audit: type=1400 audit(1725487203.971:1831): apparmor=\"DENIED\" operation=\"open\" class=\"file\" profile=\"snap-update-ns.firmware-updater\" name=\"/proc/202964/maps\" pid=202964 comm=\"5\" requested_mask=\"r\" denied_mask=\"r\" fsuid=1000 ouid=0";
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
/* Very basic test to ensure we can do aalogparse stuff in C++ */
|
||||||
|
aa_log_record *record = parse_record(log_line);
|
||||||
|
MY_TEST(record != NULL, "Log failed to parse");
|
||||||
|
MY_TEST(record->version == AA_RECORD_SYNTAX_V2, "Log should have parsed as v2 form");
|
||||||
|
MY_TEST(record->aa_namespace == NULL, "Log should have NULL namespace");
|
||||||
|
MY_TEST((record->rule_class != NULL) && (strcmp(record->rule_class, "file") == 0), "Log should have file class");
|
||||||
|
free_record(record);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
20
libraries/libapparmor/src/tst_aalogparse_oldname.c
Normal file
20
libraries/libapparmor/src/tst_aalogparse_oldname.c
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#include <aalogparse.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
|
const char* log_line = "[23342.075380] audit: type=1400 audit(1725487203.971:1831): apparmor=\"DENIED\" operation=\"open\" class=\"file\" profile=\"snap-update-ns.firmware-updater\" name=\"/proc/202964/maps\" pid=202964 comm=\"5\" requested_mask=\"r\" denied_mask=\"r\" fsuid=1000 ouid=0";
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
/* Very basic test to ensure we can use the C++-incompatible field names */
|
||||||
|
aa_log_record *record = parse_record(log_line);
|
||||||
|
MY_TEST(record != NULL, "Log failed to parse");
|
||||||
|
MY_TEST(record->version == AA_RECORD_SYNTAX_V2, "Log should have parsed as v2 form");
|
||||||
|
MY_TEST(record->namespace == NULL, "Log should have NULL namespace");
|
||||||
|
MY_TEST((record->class != NULL) && (strcmp(record->class, "file") == 0), "Log should have file class");
|
||||||
|
free_record(record);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
154
libraries/libapparmor/src/tst_aalogparse_reentrancy.c
Normal file
154
libraries/libapparmor/src/tst_aalogparse_reentrancy.c
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
#include <pthread.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <aalogparse.h>
|
||||||
|
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
|
const char* log_line = "[23342.075380] audit: type=1400 audit(1725487203.971:1831): apparmor=\"DENIED\" operation=\"open\" class=\"file\" profile=\"snap-update-ns.firmware-updater\" name=\"/proc/202964/maps\" pid=202964 comm=\"5\" requested_mask=\"r\" denied_mask=\"r\" fsuid=1000 ouid=0";
|
||||||
|
const char* log_line_2 = "[ 4074.372559] audit: type=1400 audit(1725553393.143:793): apparmor=\"DENIED\" operation=\"capable\" class=\"cap\" profile=\"/usr/lib/snapd/snap-confine\" pid=19034 comm=\"snap-confine\" capability=12 capname=\"net_admin\"";
|
||||||
|
|
||||||
|
static int pthread_barrier_ok(int barrier_result) {
|
||||||
|
return barrier_result == 0 || barrier_result == PTHREAD_BARRIER_SERIAL_THREAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nullcmp_and_strcmp(const void *s1, const void *s2)
|
||||||
|
{
|
||||||
|
/* Return 0 if both pointers are NULL & non-zero if only one is NULL */
|
||||||
|
if (!s1 || !s2)
|
||||||
|
return s1 != s2;
|
||||||
|
|
||||||
|
return strcmp(s1, s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int aa_log_record_eq(aa_log_record *record1, aa_log_record *record2) {
|
||||||
|
int are_eq = 1;
|
||||||
|
|
||||||
|
are_eq &= (record1->version == record2->version);
|
||||||
|
are_eq &= (record1->event == record2->event);
|
||||||
|
are_eq &= (record1->pid == record2->pid);
|
||||||
|
are_eq &= (record1->peer_pid == record2->peer_pid);
|
||||||
|
are_eq &= (record1->task == record2->task);
|
||||||
|
are_eq &= (record1->magic_token == record2->magic_token);
|
||||||
|
are_eq &= (record1->epoch == record2->epoch);
|
||||||
|
are_eq &= (record1->audit_sub_id == record2->audit_sub_id);
|
||||||
|
|
||||||
|
are_eq &= (record1->bitmask == record2->bitmask);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->audit_id, record2->audit_id) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->operation, record2->operation) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->denied_mask, record2->denied_mask) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->requested_mask, record2->requested_mask) == 0);
|
||||||
|
are_eq &= (record1->fsuid == record2->fsuid);
|
||||||
|
are_eq &= (record1->ouid == record2->ouid);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->profile, record2->profile) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->peer_profile, record2->peer_profile) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->comm, record2->comm) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->name, record2->name) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->name2, record2->name2) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->namespace, record2->namespace) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->attribute, record2->attribute) == 0);
|
||||||
|
are_eq &= (record1->parent == record2->parent);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->info, record2->info) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->peer_info, record2->peer_info) == 0);
|
||||||
|
are_eq &= (record1->error_code == record2->error_code);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->active_hat, record2->active_hat) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->net_family, record2->net_family) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->net_protocol, record2->net_protocol) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->net_sock_type, record2->net_sock_type) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->net_local_addr, record2->net_local_addr) == 0);
|
||||||
|
are_eq &= (record1->net_local_port == record2->net_local_port);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->net_foreign_addr, record2->net_foreign_addr) == 0);
|
||||||
|
are_eq &= (record1->net_foreign_port == record2->net_foreign_port);
|
||||||
|
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->execpath, record2->execpath) == 0);
|
||||||
|
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->dbus_bus, record2->dbus_bus) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->dbus_path, record2->dbus_path) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->dbus_interface, record2->dbus_interface) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->dbus_member, record2->dbus_member) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->signal, record2->signal) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->peer, record2->peer) == 0);
|
||||||
|
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->fs_type, record2->fs_type) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->flags, record2->flags) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->src_name, record2->src_name) == 0);
|
||||||
|
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->class, record2->class) == 0);
|
||||||
|
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->net_addr, record2->net_addr) == 0);
|
||||||
|
are_eq &= (nullcmp_and_strcmp(record1->peer_addr, record2->peer_addr) == 0);
|
||||||
|
return are_eq;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char* log;
|
||||||
|
pthread_barrier_t *barrier;
|
||||||
|
} pthread_parse_args;
|
||||||
|
|
||||||
|
void* pthread_parse_log(void* args) {
|
||||||
|
pthread_parse_args *args_real = (pthread_parse_args *) args;
|
||||||
|
int barrier_wait_result = pthread_barrier_wait(args_real->barrier);
|
||||||
|
/* Return NULL and fail test if barrier wait fails */
|
||||||
|
if (!pthread_barrier_ok(barrier_wait_result)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
aa_log_record *record = parse_record(args_real->log);
|
||||||
|
return (void*) record;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NUM_THREADS 16
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
pthread_t thread_ids[NUM_THREADS];
|
||||||
|
pthread_barrier_t barrier;
|
||||||
|
int barrier_wait_result;
|
||||||
|
aa_log_record* parsed_logs[NUM_THREADS];
|
||||||
|
int rc = 0;
|
||||||
|
/* Set up arguments to be passed to threads */
|
||||||
|
pthread_parse_args args = {.log=log_line, .barrier=&barrier};
|
||||||
|
pthread_parse_args args2 = {.log=log_line_2, .barrier=&barrier};
|
||||||
|
|
||||||
|
MY_TEST(NUM_THREADS > 2, "Test requires more than 2 threads");
|
||||||
|
|
||||||
|
/* Use barrier to synchronize the start of log parsing among all the threads
|
||||||
|
* This increases the likelihood of tickling race conditions, if there are any
|
||||||
|
*/
|
||||||
|
MY_TEST(pthread_barrier_init(&barrier, NULL, NUM_THREADS+1) == 0,
|
||||||
|
"Could not init pthread barrier");
|
||||||
|
for (int i=0; i<NUM_THREADS; i++) {
|
||||||
|
if (i%2 == 0) {
|
||||||
|
pthread_create(&thread_ids[i], NULL, pthread_parse_log, (void *) &args);
|
||||||
|
} else {
|
||||||
|
pthread_create(&thread_ids[i], NULL, pthread_parse_log, (void *) &args2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Final barrier_wait to set off the thread race */
|
||||||
|
barrier_wait_result = pthread_barrier_wait(&barrier);
|
||||||
|
MY_TEST(pthread_barrier_ok(barrier_wait_result), "Could not wait on pthread barrier");
|
||||||
|
|
||||||
|
/* Wait for threads to finish parsing the logs */
|
||||||
|
for (int i=0; i<NUM_THREADS; i++) {
|
||||||
|
MY_TEST(pthread_join(thread_ids[i], (void*) &parsed_logs[i]) == 0, "Could not join thread");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that all logs parsed and are equal */
|
||||||
|
for (int i=0; i<NUM_THREADS; i++) {
|
||||||
|
MY_TEST(parsed_logs[i] != NULL, "Log failed to parse");
|
||||||
|
MY_TEST(parsed_logs[i]->version == AA_RECORD_SYNTAX_V2, "Log should have parsed as v2 form");
|
||||||
|
MY_TEST(parsed_logs[i]->event == AA_RECORD_DENIED, "Log should have parsed as denied");
|
||||||
|
|
||||||
|
/* Also check i==0 and i==1 as a sanity check for aa_log_record_eq */
|
||||||
|
if (i%2 == 0) {
|
||||||
|
MY_TEST(aa_log_record_eq(parsed_logs[0], parsed_logs[i]), "Log 0 != Log even");
|
||||||
|
} else {
|
||||||
|
MY_TEST(aa_log_record_eq(parsed_logs[1], parsed_logs[i]), "Log 1 != Log odd");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MY_TEST(!aa_log_record_eq(parsed_logs[0], parsed_logs[1]), "Log 0 and log 1 shouldn't be equal");
|
||||||
|
/* Clean up */
|
||||||
|
MY_TEST(pthread_barrier_destroy(&barrier) == 0, "Could not destroy pthread barrier");
|
||||||
|
for (int i=0; i<NUM_THREADS; i++) {
|
||||||
|
free_record(parsed_logs[i]);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
@@ -1,3 +1,3 @@
|
|||||||
SUBDIRS = perl python ruby
|
SUBDIRS = perl python ruby
|
||||||
|
|
||||||
EXTRA_DIST = SWIG/*.i java/Makefile.am
|
EXTRA_DIST = SWIG/*.i
|
||||||
|
@@ -5,9 +5,98 @@
|
|||||||
#include <sys/apparmor.h>
|
#include <sys/apparmor.h>
|
||||||
#include <sys/apparmor_private.h>
|
#include <sys/apparmor_private.h>
|
||||||
|
|
||||||
|
// Include static_assert if the C compiler supports it
|
||||||
|
// static_assert standardized since C11, assert.h not needed since C23
|
||||||
|
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && __STDC_VERSION__ < 202311L
|
||||||
|
#include <assert.h>
|
||||||
|
#endif
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%include "typemaps.i"
|
%include "typemaps.i"
|
||||||
|
%include <cstring.i>
|
||||||
|
%include <stdint.i>
|
||||||
|
%include <exception.i>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SWIG 4.3 included https://github.com/swig/swig/pull/2907 to distinguish
|
||||||
|
* between Py_None being returned as a default void and Py_None being returned
|
||||||
|
* as the equivalent of C NULL. Unfortunately, this turns into an API breaking
|
||||||
|
* change with our use of %append_output when we want the Python function to
|
||||||
|
* return something even when the C function has a void return type. Thus, we
|
||||||
|
* need an additional macro to smooth over the differences. Include all affected
|
||||||
|
* languages, even ones we don't build bindings for, for completeness.
|
||||||
|
*/
|
||||||
|
#if SWIG_VERSION >= 0x040300
|
||||||
|
#ifdef SWIGPYTHON
|
||||||
|
#define ISVOID_APPEND_OUTPUT(value) {$result = SWIG_Python_AppendOutput($result, value, 1);}
|
||||||
|
#elif defined(SWIGRUBY)
|
||||||
|
#define ISVOID_APPEND_OUTPUT(value) {$result = SWIG_Ruby_AppendOutput($result, value, 1);}
|
||||||
|
#elif defined(SWIGPHP)
|
||||||
|
#define ISVOID_APPEND_OUTPUT(value) {$result = SWIG_Php_AppendOutput($result, value, 1);}
|
||||||
|
#else
|
||||||
|
#define ISVOID_APPEND_OUTPUT(value) %append_output(value)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define ISVOID_APPEND_OUTPUT(value) %append_output(value)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
%newobject parse_record;
|
||||||
|
%delobject free_record;
|
||||||
|
/*
|
||||||
|
* Despite its name, %delobject does not hook up destructors to language
|
||||||
|
* deletion mechanisms. Instead, it sets flags so that manually calling the
|
||||||
|
* free function and then deleting by language mechanisms doesn't cause a
|
||||||
|
* double-free.
|
||||||
|
*
|
||||||
|
* Additionally, we can manually extend the struct with a C++-like
|
||||||
|
* destructor. This ensures that the record struct is freed
|
||||||
|
* automatically when the high-level object goes out of scope.
|
||||||
|
*/
|
||||||
|
%extend aa_log_record {
|
||||||
|
~aa_log_record() {
|
||||||
|
free_record($self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate a no-op free_record wrapper to avoid making a double-free footgun.
|
||||||
|
* Use rename directive to avoid colliding with the actual free_record, which
|
||||||
|
* we use above to clean up when the higher-level language deletes the object.
|
||||||
|
*
|
||||||
|
* Ideally we would not expose a free_record at all, but we need to maintain
|
||||||
|
* backwards compatibility with the existing high-level code that uses it.
|
||||||
|
*/
|
||||||
|
%rename(free_record) noop_free_record;
|
||||||
|
#ifdef SWIGPYTHON
|
||||||
|
%pythonprepend noop_free_record %{
|
||||||
|
import warnings
|
||||||
|
warnings.warn("free_record is now a no-op as the record's memory is handled automatically", DeprecationWarning)
|
||||||
|
%}
|
||||||
|
#endif
|
||||||
|
%feature("autodoc",
|
||||||
|
"This function used to free aa_log_record objects. Freeing is now handled "
|
||||||
|
"automatically, so this no-op function remains for backwards compatibility.") noop_free_record;
|
||||||
|
%inline %{
|
||||||
|
void noop_free_record(aa_log_record *record) {(void) record;}
|
||||||
|
%}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do not autogenerate a wrapper around free_record. This does not prevent us
|
||||||
|
* from calling it ourselves in %extend C code.
|
||||||
|
*/
|
||||||
|
%ignore free_record;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Map names to preserve backwards compatibility
|
||||||
|
*/
|
||||||
|
#ifdef SWIGPYTHON
|
||||||
|
%rename("_class") aa_log_record::rule_class;
|
||||||
|
#else
|
||||||
|
%rename("class") aa_log_record::rule_class;
|
||||||
|
#endif
|
||||||
|
%rename("namespace") aa_log_record::aa_namespace;
|
||||||
|
|
||||||
%include <aalogparse.h>
|
%include <aalogparse.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,18 +110,75 @@
|
|||||||
|
|
||||||
/* apparmor.h */
|
/* apparmor.h */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* label is a heap-allocated pointer, but when label and mode occur together,
|
||||||
|
* the freeing of label must be deferred because mode points into label.
|
||||||
|
*
|
||||||
|
* %cstring_output_allocate((char **label, char **mode), free(*$1))
|
||||||
|
* does not handle multi-argument typemaps correctly, so we write our own
|
||||||
|
* typemap based on it instead.
|
||||||
|
*/
|
||||||
|
%typemap(in,noblock=1,numinputs=0) (char **label, char **mode) ($*1_ltype temp_label = 0, $*2_ltype temp_mode = 0) {
|
||||||
|
$1 = &temp_label;
|
||||||
|
$2 = &temp_mode;
|
||||||
|
}
|
||||||
|
%typemap(freearg,match="in") (char **label, char **mode) ""
|
||||||
|
%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") (char **label, char **mode) {
|
||||||
|
ISVOID_APPEND_OUTPUT(SWIG_FromCharPtr(*$1));
|
||||||
|
ISVOID_APPEND_OUTPUT(SWIG_FromCharPtr(*$2));
|
||||||
|
free(*$1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* mode also occurs in combination with con in aa_splitcon
|
||||||
|
* typemap based on %cstring_mutable but with substantial modifications
|
||||||
|
*/
|
||||||
|
%typemap(in,numinputs=1,fragment="SWIG_AsCharPtrAndSize") (char *con, char **mode) ($*2_ltype temp_mode = 0) {
|
||||||
|
int alloc_status = 0;
|
||||||
|
$1_ltype con_ptr = NULL;
|
||||||
|
size_t con_len = 0;
|
||||||
|
int char_ptr_res = SWIG_AsCharPtrAndSize($input, &con_ptr, &con_len, &alloc_status);
|
||||||
|
if (!SWIG_IsOK(char_ptr_res)) {
|
||||||
|
%argument_fail(char_ptr_res, "char *con", $symname, $argnum);
|
||||||
|
}
|
||||||
|
if (alloc_status != SWIG_NEWOBJ) {
|
||||||
|
// Unconditionally copy because the C function modifies the string in place
|
||||||
|
$1 = %new_copy_array(con_ptr, con_len+1, char);
|
||||||
|
} else {
|
||||||
|
$1 = con_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
$2 = &temp_mode;
|
||||||
|
}
|
||||||
|
%typemap(freearg,noblock=1,match="in") (char *con, char **mode) {
|
||||||
|
%delete_array($1);
|
||||||
|
}
|
||||||
|
%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") (char *con, char **mode) {
|
||||||
|
/*
|
||||||
|
* aa_splitcon returns either con or NULL so we don't need to explicitly
|
||||||
|
* append it to the output, and we don't need the ISVOID helper here
|
||||||
|
*
|
||||||
|
* SWIG_FromCharPtr does NULL checks for us
|
||||||
|
*/
|
||||||
|
%append_output(SWIG_FromCharPtr(*$2));
|
||||||
|
}
|
||||||
|
|
||||||
|
%exception aa_splitcon {
|
||||||
|
$action
|
||||||
|
if (result == NULL) {
|
||||||
|
SWIG_exception_fail(SWIG_ValueError, "received invalid confinement context");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern char *aa_splitcon(char *con, char **mode);
|
extern char *aa_splitcon(char *con, char **mode);
|
||||||
|
|
||||||
/* apparmor_private.h */
|
|
||||||
|
|
||||||
extern int _aa_is_blacklisted(const char *name);
|
|
||||||
|
|
||||||
#ifdef SWIGPYTHON
|
#ifdef SWIGPYTHON
|
||||||
%exception {
|
%exception {
|
||||||
$action
|
$action
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
|
// Unfortunately SWIG_exception does not support OSError
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
return NULL;
|
SWIG_fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -41,33 +187,248 @@ extern int _aa_is_blacklisted(const char *name);
|
|||||||
|
|
||||||
/* apparmor.h */
|
/* apparmor.h */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* aa_is_enabled returns a boolean as an int with failure reason in errno
|
||||||
|
* Therefore, aa_is_enabled either returns True or throws an exception
|
||||||
|
*
|
||||||
|
* Keep that behavior for backwards compatibilty but return a boolean on Python
|
||||||
|
* where it makes more sense, which isn't a breaking change because a boolean is
|
||||||
|
* a subclass of int
|
||||||
|
*/
|
||||||
|
#ifdef SWIGPYTHON
|
||||||
|
%typemap(out) int {
|
||||||
|
$result = PyBool_FromLong($1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
extern int aa_is_enabled(void);
|
extern int aa_is_enabled(void);
|
||||||
extern int aa_find_mountpoint(char **mnt);
|
|
||||||
|
#ifdef SWIGPYTHON
|
||||||
|
// Based on SWIG's argcargv.i but we don't have an argc
|
||||||
|
%typemap(in,fragment="SWIG_AsCharPtr") const char *subprofiles[] (Py_ssize_t seq_len=0, int* alloc_tracking = NULL) {
|
||||||
|
void* arg_as_ptr = NULL;
|
||||||
|
int res_convertptr = SWIG_ConvertPtr($input, &arg_as_ptr, $descriptor(char*[]), 0);
|
||||||
|
if (SWIG_IsOK(res_convertptr)) {
|
||||||
|
$1 = %static_cast(arg_as_ptr, $1_ltype);
|
||||||
|
} else {
|
||||||
|
// Clear error that would be set if ptr conversion failed
|
||||||
|
PyErr_Clear();
|
||||||
|
|
||||||
|
int is_list = PyList_Check($input);
|
||||||
|
if (is_list || PyTuple_Check($input)) {
|
||||||
|
seq_len = PySequence_Length($input);
|
||||||
|
/*
|
||||||
|
* %new_array zero-inits for cleaner error handling and memory cleanup
|
||||||
|
* %delete_array(NULL) is no-op (either free or delete), and
|
||||||
|
* alloc_tracking of 0 is uninit
|
||||||
|
*
|
||||||
|
* Further note: SWIG_exception_fail jumps to the freearg typemap
|
||||||
|
*/
|
||||||
|
$1 = %new_array(seq_len+1, char *);
|
||||||
|
if ($1 == NULL) {
|
||||||
|
SWIG_exception_fail(SWIG_MemoryError, "could not allocate C subprofiles");
|
||||||
|
}
|
||||||
|
|
||||||
|
alloc_tracking = %new_array(seq_len, int);
|
||||||
|
if (alloc_tracking == NULL) {
|
||||||
|
SWIG_exception_fail(SWIG_MemoryError, "could not allocate C alloc track arr");
|
||||||
|
}
|
||||||
|
for (Py_ssize_t i=0; i<seq_len; i++) {
|
||||||
|
PyObject *o = is_list ? PyList_GetItem($input, i) : PyTuple_GetItem($input, i);
|
||||||
|
if (o == NULL) {
|
||||||
|
// Failed to get item-Python already set exception info
|
||||||
|
SWIG_fail;
|
||||||
|
} else if (o == Py_None) {
|
||||||
|
// SWIG_AsCharPtr(Py_None, ...) succeeds with ptr output being NULL
|
||||||
|
SWIG_exception_fail(SWIG_ValueError, "sequence contains a None object");
|
||||||
|
}
|
||||||
|
int res = SWIG_AsCharPtr(o, &$1[i], &alloc_tracking[i]);
|
||||||
|
if (!SWIG_IsOK(res)) {
|
||||||
|
// Could emit idx of error here, maybe?
|
||||||
|
SWIG_exception_fail(SWIG_ArgError(res), "sequence does not contain all strings");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SWIG_exception_fail(SWIG_TypeError, "subprofiles is not a list or tuple");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%typemap(freearg,noblock=1) const char *subprofiles[] {
|
||||||
|
/*
|
||||||
|
* If static_assert is present, use it to verify the assumption that
|
||||||
|
* allocation uninitialized (0) != SWIG_NEWOBJ
|
||||||
|
*/
|
||||||
|
%#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
||||||
|
/*
|
||||||
|
* Some older versions of SWIG place this right after a goto label
|
||||||
|
* This would then be a label followed by a declaration, a C23 extension (!)
|
||||||
|
* To ensure this works for older SWIG versions and older compilers,
|
||||||
|
* make this a block element with curly braces.
|
||||||
|
*/
|
||||||
|
{static_assert(SWIG_NEWOBJ != 0, "SWIG_NEWOBJ is 0");}
|
||||||
|
%#endif
|
||||||
|
if ($1 != NULL && alloc_tracking$argnum != NULL) {
|
||||||
|
for (Py_ssize_t i=0; i<seq_len$argnum; i++) {
|
||||||
|
if (alloc_tracking$argnum[i] == SWIG_NEWOBJ) {
|
||||||
|
%delete_array($1[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%delete_array(alloc_tracking$argnum);
|
||||||
|
%delete_array($1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SWIGPERL
|
||||||
|
// Copied from perl's argcargv.i, which should be good enough for us
|
||||||
|
%typemap(in) (const char *subprofiles[]) {
|
||||||
|
int i;
|
||||||
|
SSize_t len;
|
||||||
|
AV *av = (AV *)SvRV($input);
|
||||||
|
if (SvTYPE(av) != SVt_PVAV) {
|
||||||
|
SWIG_croak("in method '$symname', Expecting reference to argv array");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
len = av_len(av) + 1;
|
||||||
|
$1 = (char **) malloc((len+1)*sizeof(char *));
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
SV **tv = av_fetch(av, i, 0);
|
||||||
|
$1[i] = SvPV_nolen(*tv);
|
||||||
|
}
|
||||||
|
$1[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
%typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) (const char *subprofiles[]) {
|
||||||
|
AV *av = (AV *)SvRV($input);
|
||||||
|
$1 = SvTYPE(av) == SVt_PVAV;
|
||||||
|
}
|
||||||
|
|
||||||
|
%typemap(freearg) (const char *subprofiles[]) {
|
||||||
|
free((void *)$1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* These should not receive the VOID_Object typemap */
|
||||||
extern int aa_change_hat(const char *subprofile, unsigned long magic_token);
|
extern int aa_change_hat(const char *subprofile, unsigned long magic_token);
|
||||||
extern int aa_change_profile(const char *profile);
|
extern int aa_change_profile(const char *profile);
|
||||||
extern int aa_change_onexec(const char *profile);
|
extern int aa_change_onexec(const char *profile);
|
||||||
extern int aa_change_hatv(const char *subprofiles[], unsigned long token);
|
extern int aa_change_hatv(const char *subprofiles[], unsigned long token);
|
||||||
extern int aa_change_hat_vargs(unsigned long token, int count, ...);
|
|
||||||
extern int aa_stack_profile(const char *profile);
|
extern int aa_stack_profile(const char *profile);
|
||||||
extern int aa_stack_onexec(const char *profile);
|
extern int aa_stack_onexec(const char *profile);
|
||||||
extern int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
|
|
||||||
char **mode);
|
/*
|
||||||
extern int aa_getprocattr(pid_t tid, const char *attr, char **buf, char **mode);
|
* aa_find_mountpoint mnt is an output pointer to a heap-allocated string
|
||||||
|
*
|
||||||
|
* This is a replica of %cstring_output_allocate(char **mnt, free(*$1))
|
||||||
|
* that uses the ISVOID helper to work correctly on SWIG 4.3 or later.
|
||||||
|
*/
|
||||||
|
%typemap(in,noblock=1,numinputs=0) (char **mnt) ($*1_ltype temp_mnt = 0) {
|
||||||
|
$1 = &temp_mnt;
|
||||||
|
}
|
||||||
|
%typemap(freearg,match="in") (char **mnt) ""
|
||||||
|
%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") (char **mnt) {
|
||||||
|
ISVOID_APPEND_OUTPUT(SWIG_FromCharPtr(*$1));
|
||||||
|
free(*$1);
|
||||||
|
}
|
||||||
|
/* The other errno-based functions should not always be returning the int value:
|
||||||
|
* - Python exceptions signal success/failure status instead via the %exception
|
||||||
|
* handler above.
|
||||||
|
* - Perl (the other binding) has $! for accessing errno but would check the int
|
||||||
|
* return status first.
|
||||||
|
*
|
||||||
|
* The generated C code for (out) resets the return value to None
|
||||||
|
* before appending the returned data (argout generated by %cstring stuff)
|
||||||
|
*/
|
||||||
|
#ifdef SWIGPYTHON
|
||||||
|
%typemap(out,noblock=1) int {
|
||||||
|
#if defined(VOID_Object)
|
||||||
|
$result = VOID_Object;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We can't use "typedef int pid_t" because we still support systems
|
||||||
|
* with 16-bit PIDs and SWIG can't find sys/types.h
|
||||||
|
*
|
||||||
|
* Capture the passed-in value as a long because pid_t is guaranteed
|
||||||
|
* to be a signed integer and because the aalogparse struct uses
|
||||||
|
* (unsigned) longs to store pid values. While intmax_t would be more
|
||||||
|
* technically correct, if sizeof(pid_t) > sizeof(long) then aalogparse
|
||||||
|
* itself would also need fixing.
|
||||||
|
*/
|
||||||
|
%typemap(in,noblock=1,fragment="SWIG_AsVal_long") pid_t (int conv_pid, long pid_large) {
|
||||||
|
%#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
||||||
|
static_assert(sizeof(pid_t) <= sizeof(long),
|
||||||
|
"pid_t type is too large to be stored in a long");
|
||||||
|
%#endif
|
||||||
|
conv_pid = SWIG_AsVal_long($input, &pid_large);
|
||||||
|
if (!SWIG_IsOK(conv_pid)) {
|
||||||
|
%argument_fail(conv_pid, "pid_t", $symname, $argnum);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Cast the long to a pid_t and then cast back to check for overflow
|
||||||
|
* Technically this is implementation-defined behaviour but we should be fine
|
||||||
|
*/
|
||||||
|
$1 = (pid_t) pid_large;
|
||||||
|
if ((long) $1 != pid_large) {
|
||||||
|
SWIG_exception_fail(SWIG_OverflowError, "pid_t is too large");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int aa_find_mountpoint(char **mnt);
|
||||||
|
extern int aa_getprocattr(pid_t tid, const char *attr, char **label, char **mode);
|
||||||
extern int aa_gettaskcon(pid_t target, char **label, char **mode);
|
extern int aa_gettaskcon(pid_t target, char **label, char **mode);
|
||||||
extern int aa_getcon(char **label, char **mode);
|
extern int aa_getcon(char **label, char **mode);
|
||||||
extern int aa_getpeercon_raw(int fd, char *buf, socklen_t *len, char **mode);
|
|
||||||
extern int aa_getpeercon(int fd, char **label, char **mode);
|
extern int aa_getpeercon(int fd, char **label, char **mode);
|
||||||
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
|
|
||||||
int *audit);
|
/*
|
||||||
extern int aa_query_file_path_len(uint32_t mask, const char *label,
|
* Typemaps for the boolean outputs of the query functions
|
||||||
size_t label_len, const char *path,
|
* Use boolean types for Python and int types elsewhere
|
||||||
size_t path_len, int *allowed, int *audited);
|
*/
|
||||||
|
#ifdef SWIGPYTHON
|
||||||
|
// TODO: find a way to deduplicate these
|
||||||
|
%typemap(in, numinputs=0) int *allowed (int temp) {
|
||||||
|
$1 = &temp;
|
||||||
|
}
|
||||||
|
%typemap(argout) int *allowed {
|
||||||
|
ISVOID_APPEND_OUTPUT(PyBool_FromLong(*$1));
|
||||||
|
}
|
||||||
|
|
||||||
|
%typemap(in, numinputs=0) int *audited (int temp) {
|
||||||
|
$1 = &temp;
|
||||||
|
}
|
||||||
|
%typemap(argout) int *audited {
|
||||||
|
ISVOID_APPEND_OUTPUT(PyBool_FromLong(*$1));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
%apply int *OUTPUT { int *allowed };
|
||||||
|
%apply int *OUTPUT { int *audited };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Sync this with the apparmor.h */
|
||||||
|
/* Permission flags for the AA_CLASS_FILE mediation class */
|
||||||
|
#define AA_MAY_EXEC (1 << 0)
|
||||||
|
#define AA_MAY_WRITE (1 << 1)
|
||||||
|
#define AA_MAY_READ (1 << 2)
|
||||||
|
#define AA_MAY_APPEND (1 << 3)
|
||||||
|
#define AA_MAY_CREATE (1 << 4)
|
||||||
|
#define AA_MAY_DELETE (1 << 5)
|
||||||
|
#define AA_MAY_OPEN (1 << 6)
|
||||||
|
#define AA_MAY_RENAME (1 << 7)
|
||||||
|
#define AA_MAY_SETATTR (1 << 8)
|
||||||
|
#define AA_MAY_GETATTR (1 << 9)
|
||||||
|
#define AA_MAY_SETCRED (1 << 10)
|
||||||
|
#define AA_MAY_GETCRED (1 << 11)
|
||||||
|
#define AA_MAY_CHMOD (1 << 12)
|
||||||
|
#define AA_MAY_CHOWN (1 << 13)
|
||||||
|
#define AA_MAY_LOCK 0x8000
|
||||||
|
#define AA_EXEC_MMAP 0x10000
|
||||||
|
#define AA_MAY_LINK 0x40000
|
||||||
|
#define AA_MAY_ONEXEC 0x20000000
|
||||||
|
#define AA_MAY_CHANGE_PROFILE 0x40000000
|
||||||
|
|
||||||
extern int aa_query_file_path(uint32_t mask, const char *label,
|
extern int aa_query_file_path(uint32_t mask, const char *label,
|
||||||
const char *path, int *allowed, int *audited);
|
const char *path, int *allowed, int *audited);
|
||||||
extern int aa_query_link_path_len(const char *label, size_t label_len,
|
|
||||||
const char *target, size_t target_len,
|
|
||||||
const char *link, size_t link_len,
|
|
||||||
int *allowed, int *audited);
|
|
||||||
extern int aa_query_link_path(const char *label, const char *target,
|
extern int aa_query_link_path(const char *label, const char *target,
|
||||||
const char *link, int *allowed, int *audited);
|
const char *link, int *allowed, int *audited);
|
||||||
|
|
||||||
|
@@ -1,21 +0,0 @@
|
|||||||
WRAPPERFILES = apparmorlogparse_wrap.c
|
|
||||||
|
|
||||||
BUILT_SOURCES = apparmorlogparse_wrap.c
|
|
||||||
|
|
||||||
all-local: apparmorlogparse_wrap.o
|
|
||||||
$(CC) -module apparmorlogparse_wrap.o -o libaalogparse.so
|
|
||||||
|
|
||||||
apparmorlogparse_wrap.o: apparmorlogparse_wrap.c
|
|
||||||
$(CC) -c apparmorlogparse_wrap.c $(CFLAGS) -I../../src -I/usr/include/classpath -fno-strict-aliasing -o apparmorlogparse_wrap.o
|
|
||||||
|
|
||||||
clean-local:
|
|
||||||
rm -rf org
|
|
||||||
|
|
||||||
apparmorlogparse_wrap.c: org/aalogparse ../SWIG/*.i
|
|
||||||
$(SWIG) -java -I../SWIG -I../../src -outdir org/aalogparse \
|
|
||||||
-package org.aalogparse -o apparmorlogparse_wrap.c libaalogparse.i
|
|
||||||
|
|
||||||
org/aalogparse:
|
|
||||||
mkdir -p org/aalogparse
|
|
||||||
|
|
||||||
EXTRA_DIST = $(BUILT_SOURCES)
|
|
@@ -15,6 +15,7 @@ PYTHON_DIST_BUILD_PATH = '$(builddir)/../build/$$($(PYTHON) buildpath.py)'
|
|||||||
TESTS = test_python.py
|
TESTS = test_python.py
|
||||||
TESTS_ENVIRONMENT = \
|
TESTS_ENVIRONMENT = \
|
||||||
LD_LIBRARY_PATH='$(top_builddir)/src/.libs:$(PYTHON_DIST_BUILD_PATH)' \
|
LD_LIBRARY_PATH='$(top_builddir)/src/.libs:$(PYTHON_DIST_BUILD_PATH)' \
|
||||||
PYTHONPATH='$(PYTHON_DIST_BUILD_PATH)'
|
PYTHONPATH='$(PYTHON_DIST_BUILD_PATH)' \
|
||||||
|
PYTHONDONTWRITEBYTECODE='1'
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
@@ -7,7 +7,7 @@ import sysconfig
|
|||||||
import setuptools
|
import setuptools
|
||||||
|
|
||||||
|
|
||||||
if tuple(map(int, setuptools.__version__.split("."))) >= (62, 1):
|
if tuple(map(int, setuptools.__version__.split(".")[:2])) >= (62, 1):
|
||||||
identifier = sys.implementation.cache_tag
|
identifier = sys.implementation.cache_tag
|
||||||
else:
|
else:
|
||||||
identifier = "%d.%d" % sys.version_info[:2]
|
identifier = "%d.%d" % sys.version_info[:2]
|
||||||
|
@@ -55,10 +55,100 @@ NO_VALUE_MAP = {
|
|||||||
'fsuid': int(ctypes.c_ulong(-1).value),
|
'fsuid': int(ctypes.c_ulong(-1).value),
|
||||||
'ouid': int(ctypes.c_ulong(-1).value),
|
'ouid': int(ctypes.c_ulong(-1).value),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class AAPythonBindingsTests(unittest.TestCase):
|
class AAPythonBindingsTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# REPORT ALL THE OUTPUT
|
||||||
|
self.maxDiff = None
|
||||||
|
|
||||||
|
def test_aa_splitcon(self):
|
||||||
|
AA_SPLITCON_EXPECT = [
|
||||||
|
("unconfined", "unconfined", None),
|
||||||
|
("unconfined\n", "unconfined", None),
|
||||||
|
("/bin/ping (enforce)", "/bin/ping", "enforce"),
|
||||||
|
("/bin/ping (enforce)\n", "/bin/ping", "enforce"),
|
||||||
|
("/usr/sbin/rsyslog (complain)", "/usr/sbin/rsyslog", "complain"),
|
||||||
|
]
|
||||||
|
for context, expected_label, expected_mode in AA_SPLITCON_EXPECT:
|
||||||
|
actual_label, actual_mode = libapparmor.aa_splitcon(context)
|
||||||
|
if expected_label is None:
|
||||||
|
self.assertIsNone(actual_label)
|
||||||
|
else:
|
||||||
|
self.assertIsInstance(actual_label, str)
|
||||||
|
self.assertEqual(expected_label, actual_label)
|
||||||
|
|
||||||
|
if expected_mode is None:
|
||||||
|
self.assertIsNone(actual_mode)
|
||||||
|
else:
|
||||||
|
self.assertIsInstance(actual_mode, str)
|
||||||
|
self.assertEqual(expected_mode, actual_mode)
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
libapparmor.aa_splitcon("")
|
||||||
|
|
||||||
|
def test_aa_is_enabled(self):
|
||||||
|
aa_enabled = libapparmor.aa_is_enabled()
|
||||||
|
self.assertIsInstance(aa_enabled, bool)
|
||||||
|
|
||||||
|
@unittest.skipUnless(libapparmor.aa_is_enabled(), "AppArmor is not enabled")
|
||||||
|
def test_aa_find_mountpoint(self):
|
||||||
|
mount_point = libapparmor.aa_find_mountpoint()
|
||||||
|
self.assertIsInstance(mount_point, str)
|
||||||
|
self.assertGreater(len(mount_point), 0, "mount point should not be empty")
|
||||||
|
self.assertTrue(os.path.isdir(mount_point))
|
||||||
|
|
||||||
|
# TODO: test commented out functions (or at least their prototypes)
|
||||||
|
# extern int aa_change_profile(const char *profile);
|
||||||
|
# extern int aa_change_onexec(const char *profile);
|
||||||
|
@unittest.skipUnless(libapparmor.aa_is_enabled(), "AppArmor is not enabled")
|
||||||
|
def test_change_hats(self):
|
||||||
|
# Changing hats will fail because we have no valid hats to change to
|
||||||
|
# However, we still verify that we get an OSError instead of a TypeError
|
||||||
|
with self.assertRaises(OSError):
|
||||||
|
libapparmor.aa_change_hat("nonexistent_profile", 12345678)
|
||||||
|
|
||||||
|
with self.assertRaises(OSError):
|
||||||
|
libapparmor.aa_change_hatv(["nonexistent_1", "nonexistent_2"], 0xabcdef)
|
||||||
|
libapparmor.aa_change_hatv(("nonexistent_1", "nonexistent_2"), 0xabcdef)
|
||||||
|
|
||||||
|
# extern int aa_stack_profile(const char *profile);
|
||||||
|
# extern int aa_stack_onexec(const char *profile);
|
||||||
|
# extern int aa_getprocattr(pid_t tid, const char *attr, char **label, char **mode);
|
||||||
|
# extern int aa_gettaskcon(pid_t target, char **label, char **mode);
|
||||||
|
|
||||||
|
@unittest.skipUnless(libapparmor.aa_is_enabled(), "AppArmor is not enabled")
|
||||||
|
def test_aa_gettaskcon(self):
|
||||||
|
# Our test harness should be running us as unconfined
|
||||||
|
# Get our own pid and this should be equivalent to aa_getcon
|
||||||
|
pid = os.getpid()
|
||||||
|
|
||||||
|
label, mode = libapparmor.aa_gettaskcon(pid)
|
||||||
|
self.assertEqual(label, "unconfined", "aa_gettaskcon label should be unconfined")
|
||||||
|
self.assertIsNone(mode, "aa_gettaskcon mode should be unconfined")
|
||||||
|
|
||||||
|
@unittest.skipUnless(libapparmor.aa_is_enabled(), "AppArmor is not enabled")
|
||||||
|
def test_aa_getcon(self):
|
||||||
|
# Our test harness should be running us as unconfined
|
||||||
|
label, mode = libapparmor.aa_getcon()
|
||||||
|
self.assertEqual(label, "unconfined", "aa_getcon label should be unconfined")
|
||||||
|
self.assertIsNone(mode, "aa_getcon mode should be unconfined")
|
||||||
|
|
||||||
|
# extern int aa_getpeercon(int fd, char **label, char **mode);
|
||||||
|
|
||||||
|
# extern int aa_query_file_path(uint32_t mask, const char *label,
|
||||||
|
# const char *path, int *allowed, int *audited);
|
||||||
|
@unittest.skipUnless(libapparmor.aa_is_enabled(), "AppArmor is not enabled")
|
||||||
|
def test_aa_query_file_path(self):
|
||||||
|
aa_query_mask = libapparmor.AA_MAY_EXEC | libapparmor.AA_MAY_READ | libapparmor.AA_MAY_WRITE
|
||||||
|
allowed, audited = libapparmor.aa_query_file_path(aa_query_mask, "unconfined", "/tmp/hello")
|
||||||
|
self.assertTrue(allowed)
|
||||||
|
self.assertFalse(audited)
|
||||||
|
# extern int aa_query_link_path(const char *label, const char *target,
|
||||||
|
# const char *link, int *allowed, int *audited);
|
||||||
|
|
||||||
|
|
||||||
|
class AALogParsePythonBindingsTests(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
# REPORT ALL THE OUTPUT
|
# REPORT ALL THE OUTPUT
|
||||||
self.maxDiff = None
|
self.maxDiff = None
|
||||||
@@ -118,6 +208,9 @@ class AAPythonBindingsTests(unittest.TestCase):
|
|||||||
# FIXME: out files should report log version?
|
# FIXME: out files should report log version?
|
||||||
# FIXME: or can we just deprecate v1 logs?
|
# FIXME: or can we just deprecate v1 logs?
|
||||||
continue
|
continue
|
||||||
|
elif key == "thisown":
|
||||||
|
# SWIG generates this key to track memory allocation
|
||||||
|
continue
|
||||||
elif key in NO_VALUE_MAP:
|
elif key in NO_VALUE_MAP:
|
||||||
if NO_VALUE_MAP[key] == value:
|
if NO_VALUE_MAP[key] == value:
|
||||||
continue
|
continue
|
||||||
@@ -142,7 +235,7 @@ def main():
|
|||||||
def stub_test(self, testname=f):
|
def stub_test(self, testname=f):
|
||||||
self._runtest(testname)
|
self._runtest(testname)
|
||||||
stub_test.__doc__ = "test " + f
|
stub_test.__doc__ = "test " + f
|
||||||
setattr(AAPythonBindingsTests, 'test_' + f, stub_test)
|
setattr(AALogParsePythonBindingsTests, 'test_' + f, stub_test)
|
||||||
return unittest.main(verbosity=2)
|
return unittest.main(verbosity=2)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -107,7 +107,7 @@ int print_results(aa_log_record *record)
|
|||||||
print_string("Name", record->name);
|
print_string("Name", record->name);
|
||||||
print_string("Command", record->comm);
|
print_string("Command", record->comm);
|
||||||
print_string("Name2", record->name2);
|
print_string("Name2", record->name2);
|
||||||
print_string("Namespace", record->namespace);
|
print_string("Namespace", record->aa_namespace);
|
||||||
print_string("Attribute", record->attribute);
|
print_string("Attribute", record->attribute);
|
||||||
print_long("Task", record->task, 0);
|
print_long("Task", record->task, 0);
|
||||||
print_long("Parent", record->parent, 0);
|
print_long("Parent", record->parent, 0);
|
||||||
@@ -142,7 +142,7 @@ int print_results(aa_log_record *record)
|
|||||||
|
|
||||||
print_string("Execpath", record->execpath);
|
print_string("Execpath", record->execpath);
|
||||||
|
|
||||||
print_string("Class", record->class);
|
print_string("Class", record->rule_class);
|
||||||
|
|
||||||
print_long("Epoch", record->epoch, 0);
|
print_long("Epoch", record->epoch, 0);
|
||||||
print_long("Audit subid", (long) record->audit_sub_id, 0);
|
print_long("Audit subid", (long) record->audit_sub_id, 0);
|
||||||
|
@@ -1,2 +1,4 @@
|
|||||||
profile unconfined {
|
profile unconfined {
|
||||||
|
change_profile -> system_tor,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,2 +1,4 @@
|
|||||||
/home/cb/bin/hello.sh {
|
/home/cb/bin/hello.sh {
|
||||||
|
/usr/bin/rm mrix,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,2 +1,4 @@
|
|||||||
/usr/bin/wireshark {
|
/usr/bin/wireshark {
|
||||||
|
/usr/lib64/wireshark/extcap/androiddump mrix,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/bin/ping {
|
/bin/ping {
|
||||||
ping2 ix,
|
/bin/ping mrix,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/bin/ping {
|
/bin/ping {
|
||||||
/bin/ping ix,
|
/bin/ping mrix,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/bin/ping {
|
/bin/ping {
|
||||||
/bin/ping ix,
|
/bin/ping mrix,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,4 @@
|
|||||||
|
/home/steve/aa-regression-tests/link {
|
||||||
|
/tmp/sdtest.8236-29816-IN8243/target l,
|
||||||
|
|
||||||
|
}
|
1
libraries/libapparmor/testsuite/test_multi/testcase36.in
Normal file
1
libraries/libapparmor/testsuite/test_multi/testcase36.in
Normal file
@@ -0,0 +1 @@
|
|||||||
|
2025-01-27T13:01:36.226987+05:30 sec-plucky-amd64 kernel: audit: type=1400 audit(1737963096.225:3240): apparmor="AUDIT" operation="getattr" class="file" profile="/usr/sbin/mosquitto" name="/etc/mosquitto/pwfile" pid=8119 comm="mosquitto" requested_mask="r" fsuid=122 ouid=122
|
15
libraries/libapparmor/testsuite/test_multi/testcase36.out
Normal file
15
libraries/libapparmor/testsuite/test_multi/testcase36.out
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
START
|
||||||
|
File: testcase36.in
|
||||||
|
Event type: AA_RECORD_AUDIT
|
||||||
|
Audit ID: 1737963096.225:3240
|
||||||
|
Operation: getattr
|
||||||
|
Mask: r
|
||||||
|
fsuid: 122
|
||||||
|
ouid: 122
|
||||||
|
Profile: /usr/sbin/mosquitto
|
||||||
|
Name: /etc/mosquitto/pwfile
|
||||||
|
Command: mosquitto
|
||||||
|
PID: 8119
|
||||||
|
Class: file
|
||||||
|
Epoch: 1737963096
|
||||||
|
Audit subid: 3240
|
@@ -0,0 +1,4 @@
|
|||||||
|
/usr/sbin/mosquitto {
|
||||||
|
/etc/mosquitto/pwfile r,
|
||||||
|
|
||||||
|
}
|
@@ -1,3 +1,4 @@
|
|||||||
/tmp/apparmor-2.8.0/tests/regression/apparmor/dbus_service {
|
/tmp/apparmor-2.8.0/tests/regression/apparmor/dbus_service {
|
||||||
dbus send bus=system path=/org/freedesktop/systemd1 interface=org.freedesktop.systemd1.Manager member=LookupDynamicUserByName peer=( name=org.freedesktop.systemd1, label=unconfined),
|
dbus send bus=system path=/org/freedesktop/systemd1 interface=org.freedesktop.systemd1.Manager member=LookupDynamicUserByName peer=(label=unconfined),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1 @@
|
|||||||
|
[ 310.308737] audit: type=1400 audit(1724847289.985:631): apparmor="ALLOWED" operation="getsockname" class="net" profile="/usr/bin/wg" pid=15374 comm="wg" laddr=::ffff:127.0.0.1 lport=53131 faddr=::ffff:127.0.0.1 fport=51821 saddr=::ffff:127.0.0.1 src=53131 family="inet6" sock_type="dgram" protocol=17 requested="getattr" denied="getattr"
|
@@ -0,0 +1,20 @@
|
|||||||
|
START
|
||||||
|
File: testcase_network_12.in
|
||||||
|
Event type: AA_RECORD_ALLOWED
|
||||||
|
Audit ID: 1724847289.985:631
|
||||||
|
Operation: getsockname
|
||||||
|
Mask: getattr
|
||||||
|
Denied Mask: getattr
|
||||||
|
Profile: /usr/bin/wg
|
||||||
|
Command: wg
|
||||||
|
PID: 15374
|
||||||
|
Network family: inet6
|
||||||
|
Socket type: dgram
|
||||||
|
Protocol: udp
|
||||||
|
Local addr: ::ffff:127.0.0.1
|
||||||
|
Foreign addr: ::ffff:127.0.0.1
|
||||||
|
Local port: 53131
|
||||||
|
Foreign port: 51821
|
||||||
|
Class: net
|
||||||
|
Epoch: 1724847289
|
||||||
|
Audit subid: 631
|
@@ -0,0 +1,4 @@
|
|||||||
|
/usr/bin/wg {
|
||||||
|
network (getattr) inet6 dgram ip=::ffff:127.0.0.1 port=53131,
|
||||||
|
|
||||||
|
}
|
@@ -37,8 +37,8 @@ MANPAGES=apparmor.d.5 apparmor.7 apparmor_parser.8 aa-teardown.8 apparmor_xattrs
|
|||||||
# default behavior changed in version 3.6
|
# default behavior changed in version 3.6
|
||||||
# parse.error=verbose supported from 3.0 so just test on that
|
# parse.error=verbose supported from 3.0 so just test on that
|
||||||
# TODO move to autoconf
|
# TODO move to autoconf
|
||||||
BISON_MAJOR:=$(shell bison --version | awk '/^bison/ { print ($$NF) }' | awk -F. '{print $$1 }')
|
BISON_MAJOR:=$(shell bison --version | ${AWK} '/^bison/ { print ($$NF) }' | ${AWK} -F. '{print $$1 }')
|
||||||
USE_PARSE_ERROR:=$(shell test ${BISON_MAJOR} -ge 3 && echo true)
|
USE_PARSE_ERROR:=$(shell test "${BISON_MAJOR}" -ge 3 && echo true)
|
||||||
|
|
||||||
YACC := bison
|
YACC := bison
|
||||||
YFLAGS := -d
|
YFLAGS := -d
|
||||||
@@ -105,12 +105,12 @@ SRCS = parser_common.c parser_include.c parser_interface.c parser_lex.c \
|
|||||||
parser_alias.c common_optarg.c lib.c network.cc \
|
parser_alias.c common_optarg.c lib.c network.cc \
|
||||||
mount.cc dbus.cc profile.cc rule.cc signal.cc ptrace.cc \
|
mount.cc dbus.cc profile.cc rule.cc signal.cc ptrace.cc \
|
||||||
af_rule.cc af_unix.cc policy_cache.c default_features.c userns.cc \
|
af_rule.cc af_unix.cc policy_cache.c default_features.c userns.cc \
|
||||||
mqueue.cc io_uring.cc all_rule.cc cond_expr.cc
|
mqueue.cc io_uring.cc all_rule.cc cond_expr.cc variable.cc symtab.cc
|
||||||
STATIC_HDRS = af_rule.h af_unix.h capability.h common_optarg.h dbus.h \
|
STATIC_HDRS = af_rule.h af_unix.h capability.h common_optarg.h dbus.h \
|
||||||
file_cache.h immunix.h lib.h mount.h network.h parser.h \
|
file_cache.h immunix.h lib.h mount.h network.h parser.h \
|
||||||
parser_include.h parser_version.h policy_cache.h policydb.h \
|
parser_include.h parser_version.h policy_cache.h policydb.h \
|
||||||
profile.h ptrace.h rule.h signal.h userns.h mqueue.h io_uring.h \
|
profile.h ptrace.h rule.h signal.h userns.h mqueue.h io_uring.h \
|
||||||
common_flags.h bignum.h all_rule.h cond_expr.h
|
common_flags.h bignum.h all_rule.h cond_expr.h variable.h symtab.h
|
||||||
|
|
||||||
SPECIAL_HDRS = parser_yacc.h unit_test.h base_cap_names.h
|
SPECIAL_HDRS = parser_yacc.h unit_test.h base_cap_names.h
|
||||||
GENERATED_HDRS = af_names.h generated_af_names.h \
|
GENERATED_HDRS = af_names.h generated_af_names.h \
|
||||||
@@ -331,6 +331,13 @@ all_rule.o: all_rule.cc $(HDRS)
|
|||||||
cond_expr.o: cond_expr.cc $(HDRS)
|
cond_expr.o: cond_expr.cc $(HDRS)
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
variable.o: variable.cc $(HDRS)
|
||||||
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
symtab.o: symtab.cc $(HDRS)
|
||||||
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
|
||||||
parser_version.h: Makefile
|
parser_version.h: Makefile
|
||||||
@echo \#define PARSER_VERSION \"$(VERSION)\" > .ver
|
@echo \#define PARSER_VERSION \"$(VERSION)\" > .ver
|
||||||
@mv -f .ver $@
|
@mv -f .ver $@
|
||||||
@@ -365,6 +372,9 @@ cap_names.h: generated_cap_names.h base_cap_names.h
|
|||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
.PHONY: tst_binaries
|
||||||
|
tst_binaries: $(TESTS)
|
||||||
|
|
||||||
tst_lib: lib.c parser.h $(filter-out lib.o, ${TEST_OBJECTS})
|
tst_lib: lib.c parser.h $(filter-out lib.o, ${TEST_OBJECTS})
|
||||||
$(CXX) $(TEST_CFLAGS) -o $@ $< $(filter-out $(<:.c=.o), ${TEST_OBJECTS}) $(TEST_LDFLAGS) $(TEST_LDLIBS)
|
$(CXX) $(TEST_CFLAGS) -o $@ $< $(filter-out $(<:.c=.o), ${TEST_OBJECTS}) $(TEST_LDFLAGS) $(TEST_LDLIBS)
|
||||||
tst_%: parser_%.c parser.h $(filter-out parser_%.o, ${TEST_OBJECTS})
|
tst_%: parser_%.c parser.h $(filter-out parser_%.o, ${TEST_OBJECTS})
|
||||||
@@ -372,7 +382,7 @@ tst_%: parser_%.c parser.h $(filter-out parser_%.o, ${TEST_OBJECTS})
|
|||||||
|
|
||||||
errnos.h:
|
errnos.h:
|
||||||
echo '#include <errno.h>' > dump.c
|
echo '#include <errno.h>' > dump.c
|
||||||
$(CC) -E -dD dump.c | awk '/^#define E/ { printf "{ \"%s\", %s },\n", $$2, $$2 }' > errnos.h
|
$(CC) $(CPPFLAGS) -E -dD dump.c | $(AWK) '/^#define E/ { printf "{ \"%s\", %s },\n", $$2, $$2 }' > errnos.h
|
||||||
rm -f dump.c
|
rm -f dump.c
|
||||||
|
|
||||||
.SILENT: check
|
.SILENT: check
|
||||||
|
@@ -53,7 +53,7 @@ public:
|
|||||||
sock_type_n(-1), proto(NULL), proto_n(0), label(NULL),
|
sock_type_n(-1), proto(NULL), proto_n(0), label(NULL),
|
||||||
peer_label(NULL) { }
|
peer_label(NULL) { }
|
||||||
|
|
||||||
virtual ~af_rule()
|
~af_rule() override
|
||||||
{
|
{
|
||||||
free(sock_type);
|
free(sock_type);
|
||||||
free(proto);
|
free(proto);
|
||||||
@@ -73,12 +73,12 @@ public:
|
|||||||
virtual bool has_peer_conds(void) { return peer_label ? true : false; }
|
virtual bool has_peer_conds(void) { return peer_label ? true : false; }
|
||||||
virtual ostream &dump_local(ostream &os);
|
virtual ostream &dump_local(ostream &os);
|
||||||
virtual ostream &dump_peer(ostream &os);
|
virtual ostream &dump_peer(ostream &os);
|
||||||
virtual ostream &dump(ostream &os);
|
ostream &dump(ostream &os) override;
|
||||||
virtual int expand_variables(void);
|
int expand_variables(void) override;
|
||||||
virtual int gen_policy_re(Profile &prof) = 0;
|
int gen_policy_re(Profile &prof) override = 0;
|
||||||
|
|
||||||
virtual bool is_mergeable(void) { return true; }
|
bool is_mergeable(void) override { return true; }
|
||||||
virtual int cmp(rule_t const &rhs) const
|
int cmp(rule_t const &rhs) const override
|
||||||
{
|
{
|
||||||
int res = perms_rule_t::cmp(rhs);
|
int res = perms_rule_t::cmp(rhs);
|
||||||
if (res)
|
if (res)
|
||||||
|
@@ -30,6 +30,8 @@
|
|||||||
#include "profile.h"
|
#include "profile.h"
|
||||||
#include "af_unix.h"
|
#include "af_unix.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
/* See unix(7) for autobind address definition */
|
/* See unix(7) for autobind address definition */
|
||||||
#define autobind_address_pattern "\\x00[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]";
|
#define autobind_address_pattern "\\x00[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]";
|
||||||
|
|
||||||
|
@@ -41,13 +41,13 @@ public:
|
|||||||
unix_rule(unsigned int type_p, audit_t audit_p, rule_mode_t rule_mode_p);
|
unix_rule(unsigned int type_p, audit_t audit_p, rule_mode_t rule_mode_p);
|
||||||
unix_rule(perm32_t perms, struct cond_entry *conds,
|
unix_rule(perm32_t perms, struct cond_entry *conds,
|
||||||
struct cond_entry *peer_conds);
|
struct cond_entry *peer_conds);
|
||||||
virtual ~unix_rule()
|
~unix_rule() override
|
||||||
{
|
{
|
||||||
free(addr);
|
free(addr);
|
||||||
free(peer_addr);
|
free(peer_addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual bool valid_prefix(const prefixes &p, const char *&error) {
|
bool valid_prefix(const prefixes &p, const char *&error) override {
|
||||||
// priority is partially supported for unix rules
|
// priority is partially supported for unix rules
|
||||||
// rules that get downgraded to just network socket
|
// rules that get downgraded to just network socket
|
||||||
// won't support them but the fine grained do.
|
// won't support them but the fine grained do.
|
||||||
@@ -57,17 +57,17 @@ public:
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
virtual bool has_peer_conds(void) {
|
bool has_peer_conds(void) override {
|
||||||
return af_rule::has_peer_conds() || peer_addr;
|
return af_rule::has_peer_conds() || peer_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ostream &dump_local(ostream &os);
|
ostream &dump_local(ostream &os) override;
|
||||||
virtual ostream &dump_peer(ostream &os);
|
ostream &dump_peer(ostream &os) override;
|
||||||
virtual int expand_variables(void);
|
int expand_variables(void) override;
|
||||||
virtual int gen_policy_re(Profile &prof);
|
int gen_policy_re(Profile &prof) override;
|
||||||
|
|
||||||
// inherit is_mergable() from af_rule
|
// inherit is_mergable() from af_rule
|
||||||
virtual int cmp(rule_t const &rhs) const
|
int cmp(rule_t const &rhs) const override
|
||||||
{
|
{
|
||||||
int res = af_rule::cmp(rhs);
|
int res = af_rule::cmp(rhs);
|
||||||
if (res)
|
if (res)
|
||||||
@@ -80,7 +80,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void warn_once(const char *name) override;
|
void warn_once(const char *name) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __AA_AF_UNIX_H */
|
#endif /* __AA_AF_UNIX_H */
|
||||||
|
@@ -31,7 +31,7 @@ class all_rule: public prefix_rule_t {
|
|||||||
public:
|
public:
|
||||||
all_rule(void): prefix_rule_t(RULE_TYPE_ALL) { }
|
all_rule(void): prefix_rule_t(RULE_TYPE_ALL) { }
|
||||||
|
|
||||||
virtual bool valid_prefix(const prefixes &p, const char *&error) {
|
bool valid_prefix(const prefixes &p, const char *&error) override {
|
||||||
if (p.priority != 0) {
|
if (p.priority != 0) {
|
||||||
error = _("priority prefix not allowed on all rules");
|
error = _("priority prefix not allowed on all rules");
|
||||||
return false;
|
return false;
|
||||||
@@ -43,30 +43,30 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
int expand_variables(void)
|
int expand_variables(void) override
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
virtual ostream &dump(ostream &os) {
|
ostream &dump(ostream &os) override {
|
||||||
prefix_rule_t::dump(os);
|
prefix_rule_t::dump(os);
|
||||||
|
|
||||||
os << "all";
|
os << "all";
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
virtual bool is_mergeable(void) { return true; }
|
bool is_mergeable(void) override { return true; }
|
||||||
virtual int cmp(rule_t const &rhs) const
|
int cmp(rule_t const &rhs) const override
|
||||||
{
|
{
|
||||||
return prefix_rule_t::cmp(rhs);
|
return prefix_rule_t::cmp(rhs);
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void add_implied_rules(Profile &prof);
|
void add_implied_rules(Profile &prof) override;
|
||||||
|
|
||||||
virtual int gen_policy_re(Profile &prof unused) { return RULE_OK; };
|
int gen_policy_re(Profile &prof unused) override { return RULE_OK; };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void warn_once(const char *name unused, const char *msg unused) { };
|
void warn_once(const char *name unused, const char *msg unused) override { };
|
||||||
virtual void warn_once(const char *name unused) { };
|
void warn_once(const char *name unused) override { };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __AA_ALL_H */
|
#endif /* __AA_ALL_H */
|
||||||
|
@@ -80,7 +80,7 @@ B<ALIAS RULE> = 'alias' I<ABS PATH> '-E<gt>' I<REWRITTEN ABS PATH> ','
|
|||||||
|
|
||||||
B<INCLUDE> = ( '#include' | 'include' ) [ 'if exists' ] ( I<ABS PATH> | I<MAGIC PATH> )
|
B<INCLUDE> = ( '#include' | 'include' ) [ 'if exists' ] ( I<ABS PATH> | I<MAGIC PATH> )
|
||||||
|
|
||||||
B<ABI> = ( 'abi' ) ( I<ABS PATH> | I<MAGIC PATH> ) ','
|
B<ABI> = ( 'abi' ) ( I<ABS PATH> | I<MAGIC PATH> | '<kernel>' | '<default>' ) ','
|
||||||
|
|
||||||
B<ABS PATH> = '"' path '"' (the path is passed to open(2))
|
B<ABS PATH> = '"' path '"' (the path is passed to open(2))
|
||||||
|
|
||||||
@@ -114,7 +114,8 @@ B<XATTR VALUE FILEGLOB> = I<FILEGLOB>
|
|||||||
B<PROFILE FLAG CONDS> = [ 'flags=' ] '(' comma or white space separated list of I<PROFILE FLAGS> ')'
|
B<PROFILE FLAG CONDS> = [ 'flags=' ] '(' comma or white space separated list of I<PROFILE FLAGS> ')'
|
||||||
|
|
||||||
B<PROFILE FLAGS> = I<PROFILE MODE> | I<AUDIT_MODE> | 'mediate_deleted'
|
B<PROFILE FLAGS> = I<PROFILE MODE> | I<AUDIT_MODE> | 'mediate_deleted'
|
||||||
| 'attach_disconnected' | 'attach_disconneced.path='I<ABS PATH> | 'chroot_relative'
|
| 'attach_disconnected' | 'attach_disconnected.path='I<ABS PATH> | 'chroot_relative'
|
||||||
|
| 'attach_disconnected.ipc' | 'attach_disconnected.ipc='I<ABS PATH>
|
||||||
| 'debug' | 'interruptible' | 'kill.signal='I<SIGNAL> | 'error='I<ERROR CODE>
|
| 'debug' | 'interruptible' | 'kill.signal='I<SIGNAL> | 'error='I<ERROR CODE>
|
||||||
|
|
||||||
B<ERROR CODE> = (case insensitive error code name starting with 'E'; see errno(3))
|
B<ERROR CODE> = (case insensitive error code name starting with 'E'; see errno(3))
|
||||||
@@ -175,7 +176,7 @@ B<NETWORK PEER EXPR> = 'peer' '=' '(' ( I<NETWORK IP COND> | I<NETWORK PORT COND
|
|||||||
|
|
||||||
B<NETWORK IP COND> = 'ip' '=' ( 'none' | I<NETWORK IPV4> | I<NETWORK IPV6> )
|
B<NETWORK IP COND> = 'ip' '=' ( 'none' | I<NETWORK IPV4> | I<NETWORK IPV6> )
|
||||||
|
|
||||||
B<NETWORK PORT COND> = 'port' '=' ( I<NETWORK PORT> )
|
B<NETWORK PORT COND> = 'port' '=' ( I<NETWORK PORT> | I<NETWORK PORT> '-' I<NETWORK PORT> )
|
||||||
|
|
||||||
B<NETWORK IPV4> = IPv4, represented by four 8-bit decimal numbers separated by '.'
|
B<NETWORK IPV4> = IPv4, represented by four 8-bit decimal numbers separated by '.'
|
||||||
|
|
||||||
@@ -388,7 +389,7 @@ aa_change_hat(2) can take advantage of subprofiles to run under different
|
|||||||
confinements, dependent on program logic. Several aa_change_hat(2)-aware
|
confinements, dependent on program logic. Several aa_change_hat(2)-aware
|
||||||
applications exist, including an Apache module, mod_apparmor(5); a PAM
|
applications exist, including an Apache module, mod_apparmor(5); a PAM
|
||||||
module, pam_apparmor; and a Tomcat valve, tomcat_apparmor. Applications
|
module, pam_apparmor; and a Tomcat valve, tomcat_apparmor. Applications
|
||||||
written or modified to use change_profile(2) transition permanently to the
|
written or modified to use aa_change_profile(2) transition permanently to the
|
||||||
specified profile. libvirt is one such application.
|
specified profile. libvirt is one such application.
|
||||||
|
|
||||||
=head2 Profile Head
|
=head2 Profile Head
|
||||||
@@ -560,6 +561,14 @@ allowed. Its intent is a debug and policy development tool.
|
|||||||
attach disconnected objects to the supplied path instead of the root of
|
attach disconnected objects to the supplied path instead of the root of
|
||||||
the namespace.
|
the namespace.
|
||||||
|
|
||||||
|
=item B<attach_disconnected.ipc> A subset of attach_disconnected, but specific
|
||||||
|
for IPC namespaces. It allows attaching disconnected IPC paths without having
|
||||||
|
to allow attaching all types of files.
|
||||||
|
|
||||||
|
=item B<attach_disconnected.ipc>=I<ABS PATH> Like attach_disconnected.ipc, but
|
||||||
|
attach disconnected posix mqueue to the supplied path instead of the root of
|
||||||
|
the namespace.
|
||||||
|
|
||||||
=item B<chroot_relative> This forces file names to be relative to a
|
=item B<chroot_relative> This forces file names to be relative to a
|
||||||
chroot and behave as if the chroot is a mount namespace.
|
chroot and behave as if the chroot is a mount namespace.
|
||||||
|
|
||||||
@@ -604,7 +613,7 @@ modes:
|
|||||||
|
|
||||||
=item B<Ux>
|
=item B<Ux>
|
||||||
|
|
||||||
- unconfined execute -- scrub the environment
|
- unconfined execute -- use ld.so(8) secure-execution mode
|
||||||
|
|
||||||
=item B<px>
|
=item B<px>
|
||||||
|
|
||||||
@@ -612,7 +621,7 @@ modes:
|
|||||||
|
|
||||||
=item B<Px>
|
=item B<Px>
|
||||||
|
|
||||||
- discrete profile execute -- scrub the environment
|
- discrete profile execute -- use ld.so(8) secure-execution mode
|
||||||
|
|
||||||
=item B<cx>
|
=item B<cx>
|
||||||
|
|
||||||
@@ -620,7 +629,7 @@ modes:
|
|||||||
|
|
||||||
=item B<Cx>
|
=item B<Cx>
|
||||||
|
|
||||||
- transition to subprofile on execute -- scrub the environment
|
- transition to subprofile on execute -- use ld.so(8) secure-execution mode
|
||||||
|
|
||||||
=item B<ix>
|
=item B<ix>
|
||||||
|
|
||||||
@@ -632,7 +641,7 @@ modes:
|
|||||||
|
|
||||||
=item B<Pix>
|
=item B<Pix>
|
||||||
|
|
||||||
- discrete profile execute with inherit fallback -- scrub the environment
|
- discrete profile execute with inherit fallback -- use ld.so(8) secure-execution mode
|
||||||
|
|
||||||
=item B<cix>
|
=item B<cix>
|
||||||
|
|
||||||
@@ -640,7 +649,7 @@ modes:
|
|||||||
|
|
||||||
=item B<Cix>
|
=item B<Cix>
|
||||||
|
|
||||||
- transition to subprofile on execute with inherit fallback -- scrub the environment
|
- transition to subprofile on execute with inherit fallback -- use ld.so(8) secure-execution mode
|
||||||
|
|
||||||
=item B<pux>
|
=item B<pux>
|
||||||
|
|
||||||
@@ -648,7 +657,7 @@ modes:
|
|||||||
|
|
||||||
=item B<PUx>
|
=item B<PUx>
|
||||||
|
|
||||||
- discrete profile execute with fallback to unconfined -- scrub the environment
|
- discrete profile execute with fallback to unconfined -- use ld.so(8) secure-execution mode
|
||||||
|
|
||||||
=item B<cux>
|
=item B<cux>
|
||||||
|
|
||||||
@@ -656,7 +665,7 @@ modes:
|
|||||||
|
|
||||||
=item B<CUx>
|
=item B<CUx>
|
||||||
|
|
||||||
- transition to subprofile on execute with fallback to unconfined -- scrub the environment
|
- transition to subprofile on execute with fallback to unconfined -- use ld.so(8) secure-execution mode
|
||||||
|
|
||||||
=item B<deny x>
|
=item B<deny x>
|
||||||
|
|
||||||
@@ -715,20 +724,20 @@ constrained, see the apparmor(7) man page.
|
|||||||
|
|
||||||
B<WARNING> 'ux' should only be used in very special cases. It enables the
|
B<WARNING> 'ux' should only be used in very special cases. It enables the
|
||||||
designated child processes to be run without any AppArmor protection.
|
designated child processes to be run without any AppArmor protection.
|
||||||
'ux' does not scrub the environment of variables such as LD_PRELOAD;
|
'ux' does not use ld.so(8) secure-execution mode to clear variables such as
|
||||||
as a result, the calling domain may have an undue amount of influence
|
LD_PRELOAD; as a result, the calling domain may have an undue amount of
|
||||||
over the callee. Use this mode only if the child absolutely must be
|
influence over the callee. Use this mode only if the child absolutely must be
|
||||||
run unconfined and LD_PRELOAD must be used. Any profile using this mode
|
run unconfined and LD_PRELOAD must be used. Any profile using this mode
|
||||||
provides negligible security. Use at your own risk.
|
provides negligible security. Use at your own risk.
|
||||||
|
|
||||||
Incompatible with other exec transition modes and the deny qualifier.
|
Incompatible with other exec transition modes and the deny qualifier.
|
||||||
|
|
||||||
=item B<Ux - unconfined execute -- scrub the environment>
|
=item B<Ux - unconfined execute -- use ld.so(8) secure-execution mode>
|
||||||
|
|
||||||
'Ux' allows the named program to run in 'ux' mode, but AppArmor
|
'Ux' allows the named program to run in 'ux' mode, but AppArmor
|
||||||
will invoke the Linux Kernel's B<unsafe_exec> routines to scrub
|
will invoke the Linux Kernel's B<unsafe_exec> routines to set ld.so(8)
|
||||||
the environment, similar to setuid programs. (See ld.so(8) for some
|
secure-execution mode and clear environment variables such as LD_PRELOAD,
|
||||||
information on setuid/setgid environment scrubbing.)
|
similar to setuid programs. (See ld.so(8) for more information.)
|
||||||
|
|
||||||
B<WARNING> 'Ux' should only be used in very special cases. It enables the
|
B<WARNING> 'Ux' should only be used in very special cases. It enables the
|
||||||
designated child processes to be run without any AppArmor protection.
|
designated child processes to be run without any AppArmor protection.
|
||||||
@@ -743,18 +752,18 @@ This mode requires that a discrete security profile is defined for a
|
|||||||
program executed and forces an AppArmor domain transition. If there is
|
program executed and forces an AppArmor domain transition. If there is
|
||||||
no profile defined then the access will be denied.
|
no profile defined then the access will be denied.
|
||||||
|
|
||||||
B<WARNING> 'px' does not scrub the environment of variables such as
|
B<WARNING> 'px' does not use ld.so(8) secure-execution mode to clear variables
|
||||||
LD_PRELOAD; as a result, the calling domain may have an undue amount of
|
such as LD_PRELOAD; as a result, the calling domain may have an undue amount of
|
||||||
influence over the callee.
|
influence over the callee.
|
||||||
|
|
||||||
Incompatible with other exec transition modes and the deny qualifier.
|
Incompatible with other exec transition modes and the deny qualifier.
|
||||||
|
|
||||||
=item B<Px - Discrete Profile execute mode -- scrub the environment>
|
=item B<Px - Discrete Profile execute mode -- use ld.so(8) secure-execution mode>
|
||||||
|
|
||||||
'Px' allows the named program to run in 'px' mode, but AppArmor
|
'Px' allows the named program to run in 'px' mode, but AppArmor
|
||||||
will invoke the Linux Kernel's B<unsafe_exec> routines to scrub
|
will invoke the Linux Kernel's B<unsafe_exec> routines to set ld.so(8)
|
||||||
the environment, similar to setuid programs. (See ld.so(8) for some
|
secure-execution mode and clear environment variables such as LD_PRELOAD,
|
||||||
information on setuid/setgid environment scrubbing.)
|
similar to setuid programs. (See ld.so(8) for more information.)
|
||||||
|
|
||||||
Incompatible with other exec transition modes and the deny qualifier.
|
Incompatible with other exec transition modes and the deny qualifier.
|
||||||
|
|
||||||
@@ -764,18 +773,18 @@ This mode requires that a local security profile is defined and forces an
|
|||||||
AppArmor domain transition to the named profile. If there is no profile
|
AppArmor domain transition to the named profile. If there is no profile
|
||||||
defined then the access will be denied.
|
defined then the access will be denied.
|
||||||
|
|
||||||
B<WARNING> 'cx' does not scrub the environment of variables such as
|
B<WARNING> 'cx' does not use ld.so(8) secure-execution mode to clear variables
|
||||||
LD_PRELOAD; as a result, the calling domain may have an undue amount of
|
such as LD_PRELOAD; as a result, the calling domain may have an undue amount of
|
||||||
influence over the callee.
|
influence over the callee.
|
||||||
|
|
||||||
Incompatible with other exec transition modes and the deny qualifier.
|
Incompatible with other exec transition modes and the deny qualifier.
|
||||||
|
|
||||||
=item B<Cx - Transition to Subprofile execute mode -- scrub the environment>
|
=item B<Cx - Transition to Subprofile execute mode -- use ld.so(8) secure-execution mode>
|
||||||
|
|
||||||
'Cx' allows the named program to run in 'cx' mode, but AppArmor
|
'Cx' allows the named program to run in 'cx' mode, but AppArmor
|
||||||
will invoke the Linux Kernel's B<unsafe_exec> routines to scrub
|
will invoke the Linux Kernel's B<unsafe_exec> routines to set ld.so(8)
|
||||||
the environment, similar to setuid programs. (See ld.so(8) for some
|
secure-execution mode and clear environment variables such as LD_PRELOAD,
|
||||||
information on setuid/setgid environment scrubbing.)
|
similar to setuid programs. (See ld.so(8) for more information.)
|
||||||
|
|
||||||
Incompatible with other exec transition modes and the deny qualifier.
|
Incompatible with other exec transition modes and the deny qualifier.
|
||||||
|
|
||||||
@@ -788,7 +797,7 @@ will inherit the current profile.
|
|||||||
This mode is useful when a confined program needs to call another
|
This mode is useful when a confined program needs to call another
|
||||||
confined program without gaining the permissions of the target's
|
confined program without gaining the permissions of the target's
|
||||||
profile, or losing the permissions of the current profile. There is no
|
profile, or losing the permissions of the current profile. There is no
|
||||||
version to scrub the environment because 'ix' executions don't change
|
version to set secure-execution mode because 'ix' executions don't change
|
||||||
privileges.
|
privileges.
|
||||||
|
|
||||||
Incompatible with other exec transition modes and the deny qualifier.
|
Incompatible with other exec transition modes and the deny qualifier.
|
||||||
@@ -996,13 +1005,14 @@ can be represented by:
|
|||||||
network ip=0.0.0.0; #allow INADDR_ANY
|
network ip=0.0.0.0; #allow INADDR_ANY
|
||||||
|
|
||||||
The network rules support the specification of local and remote IP
|
The network rules support the specification of local and remote IP
|
||||||
addresses and ports.
|
addresses, ports, and port ranges.
|
||||||
|
|
||||||
network ip=127.0.0.1 port=8080,
|
network ip=127.0.0.1 port=8080,
|
||||||
network peer=(ip=10.139.15.23 port=8081),
|
network peer=(ip=10.139.15.23 port=8081),
|
||||||
network ip=fd74:1820:b03a:b361::cf32 peer=(ip=fd74:1820:b03a:b361::a0f9),
|
network ip=fd74:1820:b03a:b361::cf32 peer=(ip=fd74:1820:b03a:b361::a0f9),
|
||||||
network port=8080 peer=(port=8081),
|
network port=8080 peer=(port=8081),
|
||||||
network ip=127.0.0.1 port=8080 peer=(ip=10.139.15.23 port=8081),
|
network ip=127.0.0.1 port=8080 peer=(ip=10.139.15.23 port=8081),
|
||||||
|
network ip=127.0.0.1 port=8080-8084,
|
||||||
|
|
||||||
=head2 Mount Rules
|
=head2 Mount Rules
|
||||||
|
|
||||||
@@ -1023,7 +1033,7 @@ If a conditional is specified using '=', then the rule only grants permission
|
|||||||
for mounts matching the exactly specified options. For example, an AppArmor
|
for mounts matching the exactly specified options. For example, an AppArmor
|
||||||
policy with the following rule:
|
policy with the following rule:
|
||||||
|
|
||||||
mount options=ro /dev/foo -E<gt> /mnt/,
|
mount options=ro /dev/foo -> /mnt/,
|
||||||
|
|
||||||
Would match:
|
Would match:
|
||||||
|
|
||||||
@@ -1070,7 +1080,7 @@ grants permission for each set of options. This provides a shorthand when
|
|||||||
writing mount rules which might help to logically break up a conditional. For
|
writing mount rules which might help to logically break up a conditional. For
|
||||||
example, if an AppArmor policy has the following rule:
|
example, if an AppArmor policy has the following rule:
|
||||||
|
|
||||||
mount options=ro options=atime
|
mount options=ro options=atime,
|
||||||
|
|
||||||
both of these mount commands will match:
|
both of these mount commands will match:
|
||||||
|
|
||||||
@@ -1186,17 +1196,17 @@ using inode access times. Matches only:
|
|||||||
|
|
||||||
=item B<< mount options=(ro, atime) options in (nodev, user) /dev/foo -E<gt> /mnt/, >>
|
=item B<< mount options=(ro, atime) options in (nodev, user) /dev/foo -E<gt> /mnt/, >>
|
||||||
|
|
||||||
allow mounting /dev/foo on /mmt/ read only and using inode access times or
|
allow mounting /dev/foo on /mnt/ read only and using inode access times, in
|
||||||
allow mounting /dev/foo on /mnt/ with some combination of 'nodev' and 'user'.
|
addition to allowing some combination of 'nodev' and 'user' to be added on top.
|
||||||
Matches only:
|
Matches only:
|
||||||
|
|
||||||
$ mount -o ro,atime /dev/foo /mnt
|
$ mount -o ro,atime /dev/foo /mnt
|
||||||
|
|
||||||
$ mount -o nodev /dev/foo /mnt
|
$ mount -o ro,atime,nodev /dev/foo /mnt
|
||||||
|
|
||||||
$ mount -o user /dev/foo /mnt
|
$ mount -o ro,atime,user /dev/foo /mnt
|
||||||
|
|
||||||
$ mount -o nodev,user /dev/foo /mnt
|
$ mount -o ro,atime,nodev,user /dev/foo /mnt
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
@@ -1318,7 +1328,7 @@ Example IO_URING rules:
|
|||||||
=over 4
|
=over 4
|
||||||
|
|
||||||
# Allow io_uring operations
|
# Allow io_uring operations
|
||||||
io_ring,
|
io_uring,
|
||||||
|
|
||||||
# Allow creation of a polling thread
|
# Allow creation of a polling thread
|
||||||
io_uring sqpoll,
|
io_uring sqpoll,
|
||||||
@@ -1338,8 +1348,9 @@ pivot_root(2) is optionally specified in the 'pivot_root' rule using the
|
|||||||
'oldroot=' prefix.
|
'oldroot=' prefix.
|
||||||
|
|
||||||
AppArmor 'pivot_root' rules can specify a profile transition to occur during
|
AppArmor 'pivot_root' rules can specify a profile transition to occur during
|
||||||
the pivot_root(2) system call. Note that AppArmor will only transition the
|
the pivot_root(2) system call. Note that currently, this feature is not
|
||||||
process calling pivot_root(2) to the new profile.
|
supported by any kernel. When this feature will be supported, AppArmor will
|
||||||
|
only transition the process calling pivot_root(2) to the new profile.
|
||||||
|
|
||||||
The paths specified in 'pivot_root' rules must end with '/' since they are
|
The paths specified in 'pivot_root' rules must end with '/' since they are
|
||||||
directories.
|
directories.
|
||||||
@@ -1688,11 +1699,11 @@ rule set. Eg.
|
|||||||
change_profile /bin/bash -> {new_profile1,new_profile2,new_profile3},
|
change_profile /bin/bash -> {new_profile1,new_profile2,new_profile3},
|
||||||
|
|
||||||
The exec mode dictates whether or not the Linux Kernel's B<unsafe_exec>
|
The exec mode dictates whether or not the Linux Kernel's B<unsafe_exec>
|
||||||
routines should be used to scrub the environment, similar to setuid programs.
|
routines should be used to set ld.so(8) secure-execution mode and clear
|
||||||
(See ld.so(8) for some information on setuid/setgid environment scrubbing.) The
|
environment variables such as LD_PRELOAD, similar to setuid programs.
|
||||||
B<safe> mode sets up environment scrubbing to occur when the new application is
|
(See ld.so(8) for more information.) The B<safe> mode sets up secure-execution
|
||||||
executed and B<unsafe> mode disables AppArmor's requirement for environment
|
mode for the new application, and B<unsafe> mode disables AppArmor's
|
||||||
scrubbing (the kernel and/or libc may still require environment scrubbing). An
|
requirement for it (the kernel and/or libc may still turn it on). An
|
||||||
exec mode can only be specified when an exec condition is present.
|
exec mode can only be specified when an exec condition is present.
|
||||||
|
|
||||||
change_profile safe /bin/bash -> new_profile,
|
change_profile safe /bin/bash -> new_profile,
|
||||||
@@ -1791,8 +1802,84 @@ site-specific customization of B<@{HOMEDIRS}>,
|
|||||||
F</etc/apparmor.d/tunables/multiarch.d> for B<@{multiarch}> and
|
F</etc/apparmor.d/tunables/multiarch.d> for B<@{multiarch}> and
|
||||||
F</etc/apparmor.d/tunables/xdg-user-dirs.d> for B<@{XDG_*}>.
|
F</etc/apparmor.d/tunables/xdg-user-dirs.d> for B<@{XDG_*}>.
|
||||||
|
|
||||||
The special B<@{profile_name}> variable is set to the profile name and may be
|
=head3 Special builtin variables
|
||||||
used in all policy.
|
|
||||||
|
AppArmor has some builtin variables that are not declared in policy
|
||||||
|
but are available to be used in policy.
|
||||||
|
|
||||||
|
@{profile_name} - the profile name
|
||||||
|
@{attach_path} - the profile exec attachment path - if one has been defined
|
||||||
|
@{exec_path} - the executables path
|
||||||
|
|
||||||
|
|
||||||
|
The B<@{profile_name}> variable is set to the profile name and may be
|
||||||
|
used in all policy. It is only defined when used inside of a profile.
|
||||||
|
|
||||||
|
The B<@{attach_path}> variable is only defined if the profile will attach
|
||||||
|
to an executable. It will be the path attachment specification or
|
||||||
|
if that is not defined it may be the profile's name if the profile name
|
||||||
|
is a path.
|
||||||
|
|
||||||
|
The B<@{exec_path}> variable like B<@{attach_path}> is only defined if
|
||||||
|
the profile attaches to an executable. If the kernel supports it as a
|
||||||
|
kernel variable, it will be set to the specific path that matches the
|
||||||
|
executable at run time. If the kernel does not support kernel variables
|
||||||
|
it will have the same value as B<@{attach_path}>.
|
||||||
|
|
||||||
|
=head3 Notes on variable expansion and the / character
|
||||||
|
|
||||||
|
It is important to note that how AppArmor performs variable expansion
|
||||||
|
depends on the context where a variable is used. When a variable is
|
||||||
|
expanded it can result in a string with multiple path characters
|
||||||
|
next to each other, in a way that is not evident when looking at
|
||||||
|
policy.
|
||||||
|
|
||||||
|
Eg.
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
Given the following variable definition and rule
|
||||||
|
|
||||||
|
@{HOME}=/home/*/
|
||||||
|
file rw @{HOME}/*,
|
||||||
|
|
||||||
|
The variable expansion results in a rule of
|
||||||
|
|
||||||
|
file rw /home/*//*.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
When this occurs in a context where a path is expected, AppArmor will
|
||||||
|
canonicalize the path by collapsing consecutive / characters into
|
||||||
|
a single character. For the above example, this would be
|
||||||
|
|
||||||
|
file rw /home/*/*,
|
||||||
|
|
||||||
|
There is one exception to this rule, when the consecutive / characters
|
||||||
|
are at the beginning of a path, this indicates a posix namespace
|
||||||
|
and the characters will not be collapsed.
|
||||||
|
|
||||||
|
Eg.
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
@{HOME}=/home/*/
|
||||||
|
file rw /@{HOME}/*,
|
||||||
|
|
||||||
|
will result in an expansion of
|
||||||
|
|
||||||
|
file rw //home/*//*,
|
||||||
|
|
||||||
|
which is collapsed to
|
||||||
|
|
||||||
|
file rw //home/*/*,
|
||||||
|
|
||||||
|
Note: that the leading // in the above example is not collapsed to a
|
||||||
|
single /. However the second // (that was also seen in the first
|
||||||
|
example) is collapsed.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
|
||||||
=head2 Alias rules
|
=head2 Alias rules
|
||||||
|
|
||||||
@@ -2061,6 +2148,8 @@ If the policy abi is specified as B<kernel> then the running kernel's
|
|||||||
abi will be used. This should never be used in shipped policy as it
|
abi will be used. This should never be used in shipped policy as it
|
||||||
can cause system breakage when a new kernel is installed.
|
can cause system breakage when a new kernel is installed.
|
||||||
|
|
||||||
|
The special abi B<default> is equivalent to not specifying an ABI.
|
||||||
|
|
||||||
=head3 ABI compatibility with AppArmor 2.x
|
=head3 ABI compatibility with AppArmor 2.x
|
||||||
|
|
||||||
AppArmor 3 remains compatible with AppArmor 2.x by detecting when a
|
AppArmor 3 remains compatible with AppArmor 2.x by detecting when a
|
||||||
@@ -2093,9 +2182,8 @@ An example AppArmor profile:
|
|||||||
/lib/lib*.so* r,
|
/lib/lib*.so* r,
|
||||||
/proc/[0-9]** r,
|
/proc/[0-9]** r,
|
||||||
/usr/lib/** r,
|
/usr/lib/** r,
|
||||||
/tmp/foo.pid wr,
|
|
||||||
/tmp/foo.* lrw,
|
/tmp/foo.* lrw,
|
||||||
/@{HOME}/.foo_file rw,
|
@{HOME}/.foo_file rw,
|
||||||
/usr/bin/baz Cx -> baz,
|
/usr/bin/baz Cx -> baz,
|
||||||
|
|
||||||
# a comment about foo's hat (subprofile), bar.
|
# a comment about foo's hat (subprofile), bar.
|
||||||
@@ -2157,7 +2245,7 @@ negative values match when specifying one or the other. Eg, 'rw' matches when
|
|||||||
=head1 SEE ALSO
|
=head1 SEE ALSO
|
||||||
|
|
||||||
apparmor(7), apparmor_parser(8), apparmor_xattrs(7), aa-complain(1),
|
apparmor(7), apparmor_parser(8), apparmor_xattrs(7), aa-complain(1),
|
||||||
aa-enforce(1), aa_change_hat(2), mod_apparmor(5), and
|
aa-enforce(1), aa_change_hat(2), aa_change_profile(2), mod_apparmor(5), and
|
||||||
L<https://wiki.apparmor.net>.
|
L<https://wiki.apparmor.net>.
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
@@ -206,8 +206,8 @@ which can help debugging profiles.
|
|||||||
=head2 Enable debug mode
|
=head2 Enable debug mode
|
||||||
|
|
||||||
When debug mode is enabled, AppArmor will log a few extra messages to
|
When debug mode is enabled, AppArmor will log a few extra messages to
|
||||||
dmesg (not via the audit subsystem). For example, the logs will tell
|
dmesg (not via the audit subsystem). For example, the logs will state when
|
||||||
whether environment scrubbing has been applied.
|
ld.so(8) secure-execution mode has been applied in a profile transition.
|
||||||
|
|
||||||
To enable debug mode, run:
|
To enable debug mode, run:
|
||||||
|
|
||||||
|
@@ -63,7 +63,6 @@ typedef enum capability_flags {
|
|||||||
} capability_flags;
|
} capability_flags;
|
||||||
|
|
||||||
int name_to_capability(const char *keyword);
|
int name_to_capability(const char *keyword);
|
||||||
void capabilities_init(void);
|
|
||||||
void __debug_capabilities(uint64_t capset, const char *name);
|
void __debug_capabilities(uint64_t capset, const char *name);
|
||||||
bool add_cap_feature_mask(struct aa_features *features, capability_flags flags);
|
bool add_cap_feature_mask(struct aa_features *features, capability_flags flags);
|
||||||
void clear_cap_flag(capability_flags flags);
|
void clear_cap_flag(capability_flags flags);
|
||||||
|
@@ -43,7 +43,13 @@ optflag_table_t dumpflag_table[] = {
|
|||||||
{ 1, "dfa-progress", "Dump dfa creation as in progress",
|
{ 1, "dfa-progress", "Dump dfa creation as in progress",
|
||||||
DUMP_DFA_PROGRESS | DUMP_DFA_STATS },
|
DUMP_DFA_PROGRESS | DUMP_DFA_STATS },
|
||||||
{ 1, "dfa-stats", "Dump dfa creation stats", DUMP_DFA_STATS },
|
{ 1, "dfa-stats", "Dump dfa creation stats", DUMP_DFA_STATS },
|
||||||
{ 1, "dfa-states", "Dump dfa state diagram", DUMP_DFA_STATES },
|
{ 1, "dfa-states", "Dump final dfa state information", DUMP_DFA_STATES },
|
||||||
|
{ 1, "dfa-compressed-states", "Dump compressed dfa state information", DUMP_DFA_COMPTRESSED_STATES },
|
||||||
|
{ 1, "dfa-states-initial", "Dump dfa state immediately after initial build", DUMP_DFA_STATES_INIT },
|
||||||
|
{ 1, "dfa-states-post-filter", "Dump dfa state immediately after filtering deny", DUMP_DFA_STATES_POST_FILTER },
|
||||||
|
{ 1, "dfa-states-post-minimize", "Dump dfa state immediately after initial build", DUMP_DFA_STATES_POST_MINIMIZE },
|
||||||
|
{ 1, "dfa-states-post-unreachable", "Dump dfa state immediately after filtering deny", DUMP_DFA_STATES_POST_UNREACHABLE },
|
||||||
|
{ 1, "dfa-perms-build", "Dump permission being built from accept node", DUMP_DFA_PERMS },
|
||||||
{ 1, "dfa-graph", "Dump dfa dot (graphviz) graph", DUMP_DFA_GRAPH },
|
{ 1, "dfa-graph", "Dump dfa dot (graphviz) graph", DUMP_DFA_GRAPH },
|
||||||
{ 1, "dfa-minimize", "Dump dfa minimization", DUMP_DFA_MINIMIZE },
|
{ 1, "dfa-minimize", "Dump dfa minimization", DUMP_DFA_MINIMIZE },
|
||||||
{ 1, "dfa-unreachable", "Dump dfa unreachable states",
|
{ 1, "dfa-unreachable", "Dump dfa unreachable states",
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "cond_expr.h"
|
#include "cond_expr.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
#include "symtab.h"
|
||||||
|
|
||||||
cond_expr::cond_expr(bool result):
|
cond_expr::cond_expr(bool result):
|
||||||
result(result)
|
result(result)
|
||||||
@@ -26,20 +27,21 @@ cond_expr::cond_expr(bool result):
|
|||||||
|
|
||||||
cond_expr::cond_expr(const char *var, bool defined)
|
cond_expr::cond_expr(const char *var, bool defined)
|
||||||
{
|
{
|
||||||
char *var_name = process_var(var);
|
variable *ref;
|
||||||
|
|
||||||
if (!defined) {
|
if (!defined) {
|
||||||
int ret = get_boolean_var(var_name);
|
ref = symtab::get_boolean_var(var);
|
||||||
if (ret < 0) {
|
if (!ref) {
|
||||||
/* FIXME check for set var */
|
/* FIXME check for set var */
|
||||||
free(var_name);
|
|
||||||
yyerror(_("Unset boolean variable %s used in if-expression"), var);
|
yyerror(_("Unset boolean variable %s used in if-expression"), var);
|
||||||
}
|
}
|
||||||
result = ret;
|
result = ref->boolean;
|
||||||
} else {
|
} else {
|
||||||
void *set_value = get_set_var(var_name);
|
ref = symtab::get_set_var(var);
|
||||||
PDEBUG("Matched: defined set expr %s value %lx\n", var_name, (long) set_value);
|
if (!ref) {
|
||||||
result = !! (long) set_value;
|
result = false;
|
||||||
|
} else {
|
||||||
|
PDEBUG("Matched: defined set expr %s value %s\n", var, ref->expanded.begin()->c_str());
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(var_name);
|
|
||||||
}
|
}
|
||||||
|
@@ -42,7 +42,7 @@ public:
|
|||||||
|
|
||||||
dbus_rule(perm32_t perms_p, struct cond_entry *conds,
|
dbus_rule(perm32_t perms_p, struct cond_entry *conds,
|
||||||
struct cond_entry *peer_conds);
|
struct cond_entry *peer_conds);
|
||||||
virtual ~dbus_rule() {
|
~dbus_rule() override {
|
||||||
free(bus);
|
free(bus);
|
||||||
free(name);
|
free(name);
|
||||||
free(peer_label);
|
free(peer_label);
|
||||||
@@ -50,7 +50,7 @@ public:
|
|||||||
free(interface);
|
free(interface);
|
||||||
free(member);
|
free(member);
|
||||||
};
|
};
|
||||||
virtual bool valid_prefix(const prefixes &p, const char *&error) {
|
bool valid_prefix(const prefixes &p, const char *&error) override {
|
||||||
if (p.owner != OWNER_UNSPECIFIED) {
|
if (p.owner != OWNER_UNSPECIFIED) {
|
||||||
error = "owner prefix not allowed on dbus rules";
|
error = "owner prefix not allowed on dbus rules";
|
||||||
return false;
|
return false;
|
||||||
@@ -58,12 +58,12 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ostream &dump(ostream &os);
|
ostream &dump(ostream &os) override;
|
||||||
virtual int expand_variables(void);
|
int expand_variables(void) override;
|
||||||
virtual int gen_policy_re(Profile &prof);
|
int gen_policy_re(Profile &prof) override;
|
||||||
|
|
||||||
virtual bool is_mergeable(void) { return true; }
|
bool is_mergeable(void) override { return true; }
|
||||||
virtual int cmp(rule_t const &rhs) const
|
int cmp(rule_t const &rhs) const override
|
||||||
{
|
{
|
||||||
int res = perms_rule_t::cmp(rhs);
|
int res = perms_rule_t::cmp(rhs);
|
||||||
if (res)
|
if (res)
|
||||||
@@ -89,7 +89,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void warn_once(const char *name) override;
|
void warn_once(const char *name) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __AA_DBUS_H */
|
#endif /* __AA_DBUS_H */
|
||||||
|
@@ -21,14 +21,12 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
/* TODO: have includecache be a frontend for file cache, don't just
|
/* TODO: have includecache be a frontend for file cache, don't just
|
||||||
* store name.
|
* store name.
|
||||||
*/
|
*/
|
||||||
class IncludeCache_t {
|
class IncludeCache_t {
|
||||||
public:
|
public:
|
||||||
set<string> cache;
|
std::set<std::string> cache;
|
||||||
|
|
||||||
IncludeCache_t() = default;
|
IncludeCache_t() = default;
|
||||||
virtual ~IncludeCache_t() = default;
|
virtual ~IncludeCache_t() = default;
|
||||||
@@ -39,7 +37,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool insert(const char *name) {
|
bool insert(const char *name) {
|
||||||
pair<set<string>::iterator,bool> res = cache.insert(name);
|
std::pair<std::set<std::string>::iterator,bool> res = cache.insert(name);
|
||||||
if (res.second == false) {
|
if (res.second == false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -95,6 +95,12 @@
|
|||||||
#define ALL_USER_EXEC (AA_USER_EXEC | AA_USER_EXEC_TYPE)
|
#define ALL_USER_EXEC (AA_USER_EXEC | AA_USER_EXEC_TYPE)
|
||||||
#define ALL_OTHER_EXEC (AA_OTHER_EXEC | AA_OTHER_EXEC_TYPE)
|
#define ALL_OTHER_EXEC (AA_OTHER_EXEC | AA_OTHER_EXEC_TYPE)
|
||||||
|
|
||||||
|
#define AA_USER_EXEC_INHERIT (AA_EXEC_INHERIT << AA_USER_SHIFT)
|
||||||
|
#define AA_OTHER_EXEC_INHERIT (AA_EXEC_INHERIT << AA_OTHER_SHIFT)
|
||||||
|
|
||||||
|
#define AA_USER_EXEC_MMAP (AA_OLD_EXEC_MMAP << AA_USER_SHIFT)
|
||||||
|
#define AA_OTHER_EXEC_MMAP (AA_OLD_EXEC_MMAP << AA_OTHER_SHIFT)
|
||||||
|
|
||||||
#define AA_LINK_BITS ((AA_OLD_MAY_LINK << AA_USER_SHIFT) | \
|
#define AA_LINK_BITS ((AA_OLD_MAY_LINK << AA_USER_SHIFT) | \
|
||||||
(AA_OLD_MAY_LINK << AA_OTHER_SHIFT))
|
(AA_OLD_MAY_LINK << AA_OTHER_SHIFT))
|
||||||
|
|
||||||
@@ -175,6 +181,28 @@ static inline int is_merged_x_consistent(int a, int b)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Arbitrary max and minimum priority that userspace can specify,
|
||||||
|
* internally we handle up to MAX_INTERNAL_PRIORITY and
|
||||||
|
* MIN_INTERNAL_PRIORITY. Do not ever allow INT_MAX, or INT_MIN
|
||||||
|
* because cmp uses subtraction and it can cause overflow. Ensure we
|
||||||
|
* don't over/underflow make internal max/min one more than allowed on
|
||||||
|
* rules.
|
||||||
|
*
|
||||||
|
* see
|
||||||
|
* note on mediates_priority
|
||||||
|
*/
|
||||||
|
#define MIN_POLICY_PRIORITY (-1000)
|
||||||
|
#define MAX_POLICY_PRIORITY (1000)
|
||||||
|
|
||||||
|
/* internally we need a priority that any policy based rule can override
|
||||||
|
* and a priority that no policy based rule can override. These are
|
||||||
|
* used on rules encoding what abi/classes are supported by the
|
||||||
|
* compiled policy.
|
||||||
|
*/
|
||||||
|
#define MIN_INTERNAL_PRIORITY (MIN_POLICY_PRIORITY - 1)
|
||||||
|
#define MAX_INTERNAL_PRIORITY (MAX_POLICY_PRIORITY + 1)
|
||||||
|
|
||||||
|
|
||||||
#endif /* ! _IMMUNIX_H */
|
#endif /* ! _IMMUNIX_H */
|
||||||
|
|
||||||
/* LocalWords: MMAP
|
/* LocalWords: MMAP
|
||||||
|
@@ -127,6 +127,13 @@ int io_uring_rule::gen_policy_re(Profile &prof)
|
|||||||
audit == AUDIT_FORCE ? perms : 0,
|
audit == AUDIT_FORCE ? perms : 0,
|
||||||
parseopts))
|
parseopts))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
/* add a mediates_io_uring rule for every rule added. It
|
||||||
|
* needs to be the same priority
|
||||||
|
*/
|
||||||
|
if (!prof.policy.rules->add_rule(buf.c_str(), priority,
|
||||||
|
RULE_ALLOW, AA_MAY_READ, 0,
|
||||||
|
parseopts))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
if (perms & AA_IO_URING_OVERRIDE_CREDS) {
|
if (perms & AA_IO_URING_OVERRIDE_CREDS) {
|
||||||
buf = buffer.str(); /* update buf to have label */
|
buf = buffer.str(); /* update buf to have label */
|
||||||
|
@@ -32,12 +32,12 @@ public:
|
|||||||
char *label;
|
char *label;
|
||||||
|
|
||||||
io_uring_rule(perm32_t perms, struct cond_entry *conds, struct cond_entry *ring_conds);
|
io_uring_rule(perm32_t perms, struct cond_entry *conds, struct cond_entry *ring_conds);
|
||||||
virtual ~io_uring_rule()
|
~io_uring_rule() override
|
||||||
{
|
{
|
||||||
free(label);
|
free(label);
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual bool valid_prefix(const prefixes &p, const char *&error) {
|
bool valid_prefix(const prefixes &p, const char *&error) override {
|
||||||
if (p.owner) {
|
if (p.owner) {
|
||||||
error = _("owner prefix not allowed on io_uring rules");
|
error = _("owner prefix not allowed on io_uring rules");
|
||||||
return false;
|
return false;
|
||||||
@@ -45,12 +45,12 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ostream &dump(ostream &os);
|
ostream &dump(ostream &os) override;
|
||||||
virtual int expand_variables(void);
|
int expand_variables(void) override;
|
||||||
virtual int gen_policy_re(Profile &prof);
|
int gen_policy_re(Profile &prof) override;
|
||||||
|
|
||||||
virtual bool is_mergeable(void) { return true; }
|
bool is_mergeable(void) override { return true; }
|
||||||
virtual int cmp(rule_t const &rhs) const
|
int cmp(rule_t const &rhs) const override
|
||||||
{
|
{
|
||||||
int res = perms_rule_t::cmp(rhs);
|
int res = perms_rule_t::cmp(rhs);
|
||||||
if (res)
|
if (res)
|
||||||
@@ -60,7 +60,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void warn_once(const char *name) override;
|
void warn_once(const char *name) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __AA_IO_URING_H */
|
#endif /* __AA_IO_URING_H */
|
||||||
|
@@ -28,6 +28,8 @@
|
|||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
int dirat_for_each(int dirfd, const char *name, void *data,
|
int dirat_for_each(int dirfd, const char *name, void *data,
|
||||||
int (* cb)(int, const char *, struct stat *, void *))
|
int (* cb)(int, const char *, struct stat *, void *))
|
||||||
{
|
{
|
||||||
|
@@ -14,6 +14,14 @@ AR ?= ar
|
|||||||
CFLAGS ?= -g -Wall -O2 ${EXTRA_CFLAGS} -std=gnu++0x
|
CFLAGS ?= -g -Wall -O2 ${EXTRA_CFLAGS} -std=gnu++0x
|
||||||
CXXFLAGS := ${CFLAGS} ${INCLUDE_APPARMOR}
|
CXXFLAGS := ${CFLAGS} ${INCLUDE_APPARMOR}
|
||||||
|
|
||||||
|
LIB_HDRS = aare_rules.h flex-tables.h apparmor_re.h hfa.h chfa.h parse.h \
|
||||||
|
expr-tree.h policy_compat.h
|
||||||
|
|
||||||
|
OTHER_HDRS = ../common_optarg.h ../common_flags.h ../immunix.h \
|
||||||
|
../policydb.h ../perms.h ../rule.h
|
||||||
|
|
||||||
|
HDRS = ${LIB_HDRS} ${OTHER_HDRS}
|
||||||
|
|
||||||
ARFLAGS=-rcs
|
ARFLAGS=-rcs
|
||||||
|
|
||||||
BISON := bison
|
BISON := bison
|
||||||
@@ -27,17 +35,17 @@ libapparmor_re.a: parse.o expr-tree.o hfa.o chfa.o aare_rules.o policy_compat.o
|
|||||||
|
|
||||||
expr-tree.o: expr-tree.cc expr-tree.h
|
expr-tree.o: expr-tree.cc expr-tree.h
|
||||||
|
|
||||||
hfa.o: hfa.cc apparmor_re.h hfa.h ../immunix.h policy_compat.h
|
hfa.o: hfa.cc ${HDRS}
|
||||||
|
|
||||||
aare_rules.o: aare_rules.cc aare_rules.h apparmor_re.h expr-tree.h hfa.h chfa.h parse.h ../immunix.h
|
aare_rules.o: aare_rules.cc ${HDRS}
|
||||||
|
|
||||||
chfa.o: chfa.cc chfa.h ../immunix.h
|
chfa.o: chfa.cc ${HDRS}
|
||||||
|
|
||||||
policy_compat.o: policy_compat.cc policy_compat.h ../perms.h ../immunix.h
|
policy_compat.o: policy_compat.cc ${HDRS}
|
||||||
|
|
||||||
parse.o : parse.cc apparmor_re.h expr-tree.h
|
parse.o : parse.cc ${HDRS}
|
||||||
|
|
||||||
parse.cc : parse.y parse.h flex-tables.h ../immunix.h
|
parse.cc : parse.y ${HDRS}
|
||||||
${BISON} -o $@ $<
|
${BISON} -o $@ $<
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
@@ -10,6 +10,199 @@ aare_rules.{h,cc} - code to that binds parse -> expr-tree -> hfa generation
|
|||||||
-> chfa generation into a basic interface for converting
|
-> chfa generation into a basic interface for converting
|
||||||
rules to a runtime ready state machine.
|
rules to a runtime ready state machine.
|
||||||
|
|
||||||
|
Notes on the compiler pipeline order
|
||||||
|
============================================
|
||||||
|
|
||||||
|
Front End: Program driver logic and policy text parsing into an
|
||||||
|
abstract syntax tree.
|
||||||
|
Middle Layer: Transforms and operations on the abstract syntax tree.
|
||||||
|
Converts syntax tree into expression tree for back end.
|
||||||
|
Back End: transforms of syntax tree, and creation of policy HFA from
|
||||||
|
expression trees and HFAs.
|
||||||
|
|
||||||
|
|
||||||
|
Basic order of the backend of the compiler pipe line and where the
|
||||||
|
dump information occurs in the pipeline.
|
||||||
|
|
||||||
|
===== Front End (parse -> AST ================
|
||||||
|
|
|
||||||
|
v
|
||||||
|
yyparse
|
||||||
|
|
|
||||||
|
+--->--+-->-+
|
||||||
|
| |
|
||||||
|
| +-->---- +---------------------------<-----------------------+
|
||||||
|
| | | |
|
||||||
|
| | v |
|
||||||
|
| | yylex |
|
||||||
|
| | | |
|
||||||
|
| ^ token match |
|
||||||
|
| | | |
|
||||||
|
| | +----------------------------+ |
|
||||||
|
| | | | ^
|
||||||
|
| | v v |
|
||||||
|
| +-<- rule match? preprocess |
|
||||||
|
| | | |
|
||||||
|
| early var expansion +----------+-----------+ |
|
||||||
|
| | | | | |
|
||||||
|
^ v v v v |
|
||||||
|
| new rule() / new ent include variable conditional |
|
||||||
|
| | | | | |
|
||||||
|
| v +---->-----+----->-----+----->----+
|
||||||
|
| new rule semantic check
|
||||||
|
| |
|
||||||
|
+-----<-----+
|
||||||
|
|
|
||||||
|
----------- | ------ End of Parse --------------------
|
||||||
|
|
|
||||||
|
v
|
||||||
|
post_parse_profile semantic check
|
||||||
|
|
|
||||||
|
v
|
||||||
|
post_process
|
||||||
|
|
|
||||||
|
v
|
||||||
|
add implied rules()
|
||||||
|
|
|
||||||
|
v
|
||||||
|
process_profile_variables()
|
||||||
|
|
|
||||||
|
v
|
||||||
|
rule->expand_variables()
|
||||||
|
|
|
||||||
|
+--------+
|
||||||
|
|
|
||||||
|
v
|
||||||
|
replace aliases (to be moved to backend rewrite)
|
||||||
|
|
|
||||||
|
v
|
||||||
|
merge rules
|
||||||
|
|
|
||||||
|
v
|
||||||
|
profile->merge_rules()
|
||||||
|
|
|
||||||
|
v
|
||||||
|
+-->--rule->is_mergeable()
|
||||||
|
| |
|
||||||
|
^ v
|
||||||
|
| add to table
|
||||||
|
| |
|
||||||
|
+-------+--------+
|
||||||
|
|
|
||||||
|
v
|
||||||
|
sort->cmp()/oper<()
|
||||||
|
|
|
||||||
|
rule->merge()
|
||||||
|
|
|
||||||
|
+------------+
|
||||||
|
|
|
||||||
|
v
|
||||||
|
process_profile_rules
|
||||||
|
|
|
||||||
|
v
|
||||||
|
rule->gen_policy_re()
|
||||||
|
|
|
||||||
|
v
|
||||||
|
===== Mid layer (AST -> expr tree) =================
|
||||||
|
|
|
||||||
|
+-> add_rule() (aare_rules.{h,cc})
|
||||||
|
| |
|
||||||
|
| v
|
||||||
|
| rule parse (parse.y)
|
||||||
|
| | |
|
||||||
|
| | v
|
||||||
|
| | expr tree (expr-tree.{h,cc})
|
||||||
|
| | |
|
||||||
|
| v |
|
||||||
|
| unique perms | (aare_rules.{h,cc})
|
||||||
|
| | |
|
||||||
|
| +------ +
|
||||||
|
| |
|
||||||
|
| v
|
||||||
|
| add to rules expr tree (aare_rules.{h,c})
|
||||||
|
| |
|
||||||
|
+------+
|
||||||
|
|
|
||||||
|
+------------------+
|
||||||
|
|
|
||||||
|
v
|
||||||
|
create_dfablob()
|
||||||
|
|
|
||||||
|
v
|
||||||
|
expr tree
|
||||||
|
|
|
||||||
|
v
|
||||||
|
create_chfa() (aare_rules.cc)
|
||||||
|
|
|
||||||
|
v
|
||||||
|
expr normalization (expr-tree.{h,cc})
|
||||||
|
|
|
||||||
|
v
|
||||||
|
expr simplification (expr-tree.{h,c})
|
||||||
|
|
|
||||||
|
+- D expr-tree
|
||||||
|
|
|
||||||
|
+- D expr-simplified
|
||||||
|
|
|
||||||
|
==== Back End - Create cHFA out of expr tree and other HFAs ====
|
||||||
|
v
|
||||||
|
hfa creation (hfa.{h,cc})
|
||||||
|
|
|
||||||
|
+- D dfa-node-map
|
||||||
|
|
|
||||||
|
+- D dfa-uniq-perms
|
||||||
|
|
|
||||||
|
+- D dfa-states-initial
|
||||||
|
|
|
||||||
|
v
|
||||||
|
hfa rewrite (not yet implemented)
|
||||||
|
|
|
||||||
|
v
|
||||||
|
filter deny (hfa.{h,cc})
|
||||||
|
|
|
||||||
|
+- D dfa-states-post-filter
|
||||||
|
|
|
||||||
|
v
|
||||||
|
minimization (hfa.{h,cc})
|
||||||
|
|
|
||||||
|
+- D dfa-minimize-partitions
|
||||||
|
|
|
||||||
|
+- D dfa-minimize-uniq-perms
|
||||||
|
|
|
||||||
|
+- D dfa-states-post-minimize
|
||||||
|
|
|
||||||
|
v
|
||||||
|
unreachable state removal (hfa.{h,cc})
|
||||||
|
|
|
||||||
|
+- D dfa-states-post-unreachable
|
||||||
|
|
|
||||||
|
+- D dfa-states constructed hfa
|
||||||
|
|
|
||||||
|
+- D dfa-graph
|
||||||
|
|
|
||||||
|
v
|
||||||
|
equivalence class construction
|
||||||
|
|
|
||||||
|
+- D equiv
|
||||||
|
|
|
||||||
|
diff encode (hfa.{h,cc})
|
||||||
|
|
|
||||||
|
+- D diff-encode
|
||||||
|
|
|
||||||
|
compute perms table
|
||||||
|
|
|
||||||
|
+- D compressed-dfa == perm table dump
|
||||||
|
|
|
||||||
|
compressed hfa (chfa.{h,cc}
|
||||||
|
|
|
||||||
|
+- D compressed-dfa == transition tables
|
||||||
|
|
|
||||||
|
+- D dfa-compressed-states - compress HFA in state form
|
||||||
|
|
|
||||||
|
v
|
||||||
|
Return to Mid Layer
|
||||||
|
|
||||||
|
|
||||||
Notes on the compress hfa file format (chfa)
|
Notes on the compress hfa file format (chfa)
|
||||||
==============================================
|
==============================================
|
||||||
|
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
#include "chfa.h"
|
#include "chfa.h"
|
||||||
#include "../immunix.h"
|
#include "../immunix.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
aare_rules::~aare_rules(void)
|
aare_rules::~aare_rules(void)
|
||||||
{
|
{
|
||||||
@@ -202,7 +203,7 @@ bool aare_rules::append_rule(const char *rule, bool oob, bool with_perm,
|
|||||||
CHFA *aare_rules::create_chfa(int *min_match_len,
|
CHFA *aare_rules::create_chfa(int *min_match_len,
|
||||||
vector <aa_perms> &perms_table,
|
vector <aa_perms> &perms_table,
|
||||||
optflags const &opts, bool filedfa,
|
optflags const &opts, bool filedfa,
|
||||||
bool extended_perms, bool prompt)
|
bool extended_perms)
|
||||||
{
|
{
|
||||||
/* finish constructing the expr tree from the different permission
|
/* finish constructing the expr tree from the different permission
|
||||||
* set nodes */
|
* set nodes */
|
||||||
@@ -258,6 +259,9 @@ CHFA *aare_rules::create_chfa(int *min_match_len,
|
|||||||
if (opts.dump & DUMP_DFA_UNIQ_PERMS)
|
if (opts.dump & DUMP_DFA_UNIQ_PERMS)
|
||||||
dfa.dump_uniq_perms("dfa");
|
dfa.dump_uniq_perms("dfa");
|
||||||
|
|
||||||
|
if (opts.dump & DUMP_DFA_STATES_INIT)
|
||||||
|
dfa.dump(cerr, NULL);
|
||||||
|
|
||||||
/* since we are building a chfa, use the info about
|
/* since we are building a chfa, use the info about
|
||||||
* whether the chfa supports extended perms to help
|
* whether the chfa supports extended perms to help
|
||||||
* determine whether we clear the deny info.
|
* determine whether we clear the deny info.
|
||||||
@@ -265,25 +269,26 @@ CHFA *aare_rules::create_chfa(int *min_match_len,
|
|||||||
* information supported by the backed
|
* information supported by the backed
|
||||||
*/
|
*/
|
||||||
if (!extended_perms ||
|
if (!extended_perms ||
|
||||||
// TODO: we should drop DFA_MINIMIZE check here but doing
|
((opts.control & CONTROL_DFA_FILTER_DENY))) {
|
||||||
// so changes behavior. Do as a separate patch and fixup
|
|
||||||
// tests, etc.
|
|
||||||
((opts.control & CONTROL_DFA_FILTER_DENY) &&
|
|
||||||
(opts.control & CONTROL_DFA_MINIMIZE)))
|
|
||||||
dfa.apply_and_clear_deny();
|
dfa.apply_and_clear_deny();
|
||||||
|
if (opts.dump & DUMP_DFA_STATES_POST_FILTER)
|
||||||
|
dfa.dump(cerr, NULL);
|
||||||
|
}
|
||||||
if (opts.control & CONTROL_DFA_MINIMIZE) {
|
if (opts.control & CONTROL_DFA_MINIMIZE) {
|
||||||
dfa.minimize(opts);
|
dfa.minimize(opts);
|
||||||
|
|
||||||
if (opts.dump & DUMP_DFA_MIN_UNIQ_PERMS)
|
if (opts.dump & DUMP_DFA_MIN_UNIQ_PERMS)
|
||||||
dfa.dump_uniq_perms("minimized dfa");
|
dfa.dump_uniq_perms("minimized dfa");
|
||||||
|
if (opts.dump & DUMP_DFA_STATES_POST_MINIMIZE)
|
||||||
|
dfa.dump(cerr, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.control & CONTROL_DFA_REMOVE_UNREACHABLE)
|
if (opts.control & CONTROL_DFA_REMOVE_UNREACHABLE) {
|
||||||
dfa.remove_unreachable(opts);
|
dfa.remove_unreachable(opts);
|
||||||
|
if (opts.dump & DUMP_DFA_STATES_POST_UNREACHABLE)
|
||||||
|
dfa.dump(cerr, NULL);
|
||||||
|
}
|
||||||
if (opts.dump & DUMP_DFA_STATES)
|
if (opts.dump & DUMP_DFA_STATES)
|
||||||
dfa.dump(cerr);
|
dfa.dump(cerr, NULL);
|
||||||
|
|
||||||
if (opts.dump & DUMP_DFA_GRAPH)
|
if (opts.dump & DUMP_DFA_GRAPH)
|
||||||
dfa.dump_dot_graph(cerr);
|
dfa.dump_dot_graph(cerr);
|
||||||
@@ -310,11 +315,25 @@ CHFA *aare_rules::create_chfa(int *min_match_len,
|
|||||||
//cerr << "Checking extended perms " << extended_perms << "\n";
|
//cerr << "Checking extended perms " << extended_perms << "\n";
|
||||||
if (extended_perms) {
|
if (extended_perms) {
|
||||||
//cerr << "creating permstable\n";
|
//cerr << "creating permstable\n";
|
||||||
dfa.compute_perms_table(perms_table, prompt);
|
dfa.compute_perms_table(perms_table);
|
||||||
|
// TODO: move perms table to a class
|
||||||
|
if (opts.dump & DUMP_DFA_TRANS_TABLE && perms_table.size()) {
|
||||||
|
cerr << "Perms Table size: " << perms_table.size() << "\n";
|
||||||
|
perms_table[0].dump_header(cerr);
|
||||||
|
for (size_t i = 0; i < perms_table.size(); i++) {
|
||||||
|
perms_table[i].dump(cerr);
|
||||||
|
cerr << "accept1: 0x";
|
||||||
|
cerr << ", accept2: 0x";
|
||||||
|
cerr << "\n";
|
||||||
}
|
}
|
||||||
chfa = new CHFA(dfa, eq, opts, extended_perms, prompt);
|
cerr << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chfa = new CHFA(dfa, eq, opts, extended_perms);
|
||||||
if (opts.dump & DUMP_DFA_TRANS_TABLE)
|
if (opts.dump & DUMP_DFA_TRANS_TABLE)
|
||||||
chfa->dump(cerr);
|
chfa->dump(cerr);
|
||||||
|
if (opts.dump & DUMP_DFA_COMPTRESSED_STATES)
|
||||||
|
dfa.dump(cerr, &chfa->num);
|
||||||
}
|
}
|
||||||
catch(int error) {
|
catch(int error) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -331,15 +350,14 @@ CHFA *aare_rules::create_chfa(int *min_match_len,
|
|||||||
void *aare_rules::create_dfablob(size_t *size, int *min_match_len,
|
void *aare_rules::create_dfablob(size_t *size, int *min_match_len,
|
||||||
vector <aa_perms> &perms_table,
|
vector <aa_perms> &perms_table,
|
||||||
optflags const &opts, bool filedfa,
|
optflags const &opts, bool filedfa,
|
||||||
bool extended_perms, bool prompt)
|
bool extended_perms)
|
||||||
{
|
{
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
stringstream stream;
|
stringstream stream;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CHFA *chfa = create_chfa(min_match_len, perms_table,
|
CHFA *chfa = create_chfa(min_match_len, perms_table,
|
||||||
opts, filedfa, extended_perms,
|
opts, filedfa, extended_perms);
|
||||||
prompt);
|
|
||||||
if (!chfa) {
|
if (!chfa) {
|
||||||
*size = 0;
|
*size = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -364,82 +382,3 @@ void *aare_rules::create_dfablob(size_t *size, int *min_match_len,
|
|||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* create a dfa from the ruleset
|
|
||||||
* returns: buffer contain dfa tables, @size set to the size of the tables
|
|
||||||
* else NULL on failure, @min_match_len set to the shortest string
|
|
||||||
* that can match the dfa for determining xmatch priority.
|
|
||||||
*/
|
|
||||||
void *aare_rules::create_welded_dfablob(aare_rules *file_rules,
|
|
||||||
size_t *size, int *min_match_len,
|
|
||||||
size_t *new_start,
|
|
||||||
vector <aa_perms> &perms_table,
|
|
||||||
optflags const &opts,
|
|
||||||
bool extended_perms, bool prompt)
|
|
||||||
{
|
|
||||||
int file_min_len;
|
|
||||||
vector <aa_perms> file_perms;
|
|
||||||
CHFA *file_chfa;
|
|
||||||
try {
|
|
||||||
file_chfa = file_rules->create_chfa(&file_min_len,
|
|
||||||
file_perms, opts,
|
|
||||||
true, extended_perms, prompt);
|
|
||||||
if (!file_chfa) {
|
|
||||||
*size = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(int error) {
|
|
||||||
*size = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CHFA *policy_chfa;
|
|
||||||
try {
|
|
||||||
policy_chfa = create_chfa(min_match_len,
|
|
||||||
perms_table, opts,
|
|
||||||
false, extended_perms, prompt);
|
|
||||||
if (!policy_chfa) {
|
|
||||||
delete file_chfa;
|
|
||||||
*size = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(int error) {
|
|
||||||
delete file_chfa;
|
|
||||||
*size = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
stringstream stream;
|
|
||||||
try {
|
|
||||||
policy_chfa->weld_file_to_policy(*file_chfa, *new_start,
|
|
||||||
extended_perms, prompt,
|
|
||||||
perms_table, file_perms);
|
|
||||||
policy_chfa->flex_table(stream, opts);
|
|
||||||
}
|
|
||||||
catch(int error) {
|
|
||||||
delete (file_chfa);
|
|
||||||
delete (policy_chfa);
|
|
||||||
*size = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
delete file_chfa;
|
|
||||||
delete policy_chfa;
|
|
||||||
|
|
||||||
/* write blob to buffer */
|
|
||||||
stringbuf *buf = stream.rdbuf();
|
|
||||||
|
|
||||||
buf->pubseekpos(0);
|
|
||||||
*size = buf->in_avail();
|
|
||||||
if (file_min_len < *min_match_len)
|
|
||||||
*min_match_len = file_min_len;
|
|
||||||
|
|
||||||
char *buffer = (char *)malloc(*size);
|
|
||||||
if (!buffer)
|
|
||||||
return NULL;
|
|
||||||
buf->sgetn(buffer, *size);
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
@@ -59,7 +59,7 @@ public:
|
|||||||
|
|
||||||
class UniquePermsCache {
|
class UniquePermsCache {
|
||||||
public:
|
public:
|
||||||
typedef map<UniquePerm, Node*> UniquePermMap;
|
typedef std::map<UniquePerm, Node*> UniquePermMap;
|
||||||
typedef UniquePermMap::iterator iterator;
|
typedef UniquePermMap::iterator iterator;
|
||||||
UniquePermMap nodes;
|
UniquePermMap nodes;
|
||||||
|
|
||||||
@@ -89,9 +89,11 @@ public:
|
|||||||
node = new ExactMatchFlag(priority, perms, audit);
|
node = new ExactMatchFlag(priority, perms, audit);
|
||||||
else
|
else
|
||||||
node = new MatchFlag(priority, perms, audit);
|
node = new MatchFlag(priority, perms, audit);
|
||||||
pair<iterator, bool> val = nodes.insert(make_pair(tmp, node));
|
std::pair<iterator, bool> val = nodes.insert(std::make_pair(tmp, node));
|
||||||
if (val.second == false)
|
if (val.second == false) {
|
||||||
|
delete node;
|
||||||
return val.first->second;
|
return val.first->second;
|
||||||
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
return res->second;
|
return res->second;
|
||||||
@@ -119,19 +121,13 @@ class aare_rules {
|
|||||||
optflags const &opts, bool oob);
|
optflags const &opts, bool oob);
|
||||||
bool append_rule(const char *rule, bool oob, bool with_perm, optflags const &opts);
|
bool append_rule(const char *rule, bool oob, bool with_perm, optflags const &opts);
|
||||||
CHFA *create_chfa(int *min_match_len,
|
CHFA *create_chfa(int *min_match_len,
|
||||||
vector <aa_perms> &perms_table,
|
std::vector <aa_perms> &perms_table,
|
||||||
optflags const &opts, bool filedfa,
|
optflags const &opts, bool filedfa,
|
||||||
bool extended_perms, bool prompt);
|
bool extended_perms);
|
||||||
void *create_dfablob(size_t *size, int *min_match_len,
|
void *create_dfablob(size_t *size, int *min_match_len,
|
||||||
vector <aa_perms> &perms_table,
|
std::vector <aa_perms> &perms_table,
|
||||||
optflags const &opts,
|
optflags const &opts,
|
||||||
bool filedfa, bool extended_perms, bool prompt);
|
bool filedfa, bool extended_perms);
|
||||||
void *create_welded_dfablob(aare_rules *file_rules,
|
|
||||||
size_t *size, int *min_match_len,
|
|
||||||
size_t *new_start,
|
|
||||||
vector <aa_perms> &perms_table,
|
|
||||||
optflags const &opts,
|
|
||||||
bool extended_perms, bool prompt);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __LIBAA_RE_RULES_H */
|
#endif /* __LIBAA_RE_RULES_H */
|
||||||
|
@@ -60,5 +60,11 @@
|
|||||||
#define DUMP_RULE_MERGE (1 << 22)
|
#define DUMP_RULE_MERGE (1 << 22)
|
||||||
#define DUMP_DFA_STATE32 (1 << 23)
|
#define DUMP_DFA_STATE32 (1 << 23)
|
||||||
#define DUMP_DFA_FLAGS_TABLE (1 << 24)
|
#define DUMP_DFA_FLAGS_TABLE (1 << 24)
|
||||||
|
#define DUMP_DFA_STATES_INIT (1 << 25)
|
||||||
|
#define DUMP_DFA_STATES_POST_FILTER (1 << 26)
|
||||||
|
#define DUMP_DFA_STATES_POST_MINIMIZE (1 << 27)
|
||||||
|
#define DUMP_DFA_STATES_POST_UNREACHABLE (1 << 28)
|
||||||
|
#define DUMP_DFA_COMPTRESSED_STATES (1 << 29)
|
||||||
|
#define DUMP_DFA_PERMS (1 << 30)
|
||||||
|
|
||||||
#endif /* APPARMOR_RE_H */
|
#endif /* APPARMOR_RE_H */
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user