mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-05 00:35:13 +00:00
Compare commits
2083 Commits
apparmor-2
...
v2.9-beta3
Author | SHA1 | Date | |
---|---|---|---|
|
a44b6ce0a2 | ||
|
ce70c84f5c | ||
|
655b1534e7 | ||
|
95994ed64a | ||
|
bcb1cd750e | ||
|
7bf0c15ef8 | ||
|
85db44b586 | ||
|
84b6f98007 | ||
|
0262f44eb7 | ||
|
2b22c70e74 | ||
|
3368c9bc40 | ||
|
48a755d471 | ||
|
12b09ecd9e | ||
|
f31b44ff2d | ||
|
deaa692aa2 | ||
|
ce2abf01d5 | ||
|
1d867ae7ba | ||
|
3d902d57fc | ||
|
1842767cf3 | ||
|
9e93e6eaf5 | ||
|
8fb91c8e9d | ||
|
8b030e8877 | ||
|
297716d7e7 | ||
|
862bbb91eb | ||
|
9e385d86c9 | ||
|
5153701317 | ||
|
3fb09b20f2 | ||
|
eea15ce54b | ||
|
0daaaca946 | ||
|
bd681b8977 | ||
|
a154d14f5a | ||
|
ffa2f682ea | ||
|
0a01abf370 | ||
|
c32681a236 | ||
|
01b754b24d | ||
|
1519d46325 | ||
|
f22496cdac | ||
|
5def2f5693 | ||
|
08bc0441d4 | ||
|
c48d7dc71f | ||
|
f4b5811109 | ||
|
b7ff639d73 | ||
|
bc06f9f23a | ||
|
b6d33f2c16 | ||
|
68b3af026c | ||
|
503fcc1ad9 | ||
|
79fe4cbfb5 | ||
|
ff1ae04853 | ||
|
3ca8bbe6a7 | ||
|
b80559ab20 | ||
|
8418703863 | ||
|
b421cf7c1a | ||
|
e67f6561c4 | ||
|
cd539e0a21 | ||
|
b099168e6b | ||
|
298df16292 | ||
|
4d93599568 | ||
|
0371afa3fc | ||
|
2f85b775d3 | ||
|
f2e4a44191 | ||
|
47ec6707e5 | ||
|
d3bf71c20a | ||
|
c9bf33e17f | ||
|
40a829ef6b | ||
|
525451de43 | ||
|
251a8a9650 | ||
|
2f54f0d97a | ||
|
70119a81d8 | ||
|
0e7c2e4296 | ||
|
4e7dbabd61 | ||
|
63976b49d4 | ||
|
575d75eca8 | ||
|
e9fbdbf74b | ||
|
3035660716 | ||
|
4985e50a41 | ||
|
f63f08d79a | ||
|
e5528ff87b | ||
|
ce8fbf63fd | ||
|
6bc1b6ef43 | ||
|
bafb5ff2b4 | ||
|
79698cdbfe | ||
|
cdd23798bb | ||
|
2259857281 | ||
|
c2f7e5ff80 | ||
|
5bd93faf73 | ||
|
d99222b1b9 | ||
|
4dd76b704e | ||
|
049cb96106 | ||
|
826e9d998b | ||
|
3a5106527c | ||
|
b05cc0f36f | ||
|
e8d7dcd321 | ||
|
37adff769c | ||
|
59b5b8bab6 | ||
|
365b6d603c | ||
|
74da13e7a3 | ||
|
b86d83759a | ||
|
6d34893d4d | ||
|
9e4c01f8d3 | ||
|
29c776e4fc | ||
|
e119901e3a | ||
|
4a616e3545 | ||
|
4f80b4d5ca | ||
|
0005895e3d | ||
|
b5c3ce638d | ||
|
4ed3dd090d | ||
|
ab93c858d3 | ||
|
e811d8f2bf | ||
|
19c942e5c2 | ||
|
fb53ec793b | ||
|
df961a3e02 | ||
|
e86f850d59 | ||
|
ee7bf1dc28 | ||
|
73c74d044d | ||
|
831db5985f | ||
|
ade71dc171 | ||
|
e85777a57c | ||
|
5b46e3b334 | ||
|
019de74059 | ||
|
dd44858e60 | ||
|
0d4f802572 | ||
|
0b355ebaac | ||
|
72cde9a4f4 | ||
|
288fc40d1a | ||
|
95c393ae29 | ||
|
e1ef7e5582 | ||
|
9dfa9611ea | ||
|
8566ed0a0a | ||
|
1f003c0120 | ||
|
1245d9c287 | ||
|
c4d40cede0 | ||
|
659e5ff11d | ||
|
9e37c3278e | ||
|
a620f18cf0 | ||
|
4608322da9 | ||
|
1930675a9b | ||
|
bccca11bf6 | ||
|
f5704761b5 | ||
|
54655cf9a4 | ||
|
d3c229fc48 | ||
|
9fe1e72c44 | ||
|
0465bdbf81 | ||
|
ac481f142e | ||
|
6db2f7d4eb | ||
|
502e992c42 | ||
|
5006abbbb2 | ||
|
427258d07a | ||
|
784837301b | ||
|
51eb1bd69c | ||
|
ddd78f97d9 | ||
|
0ba4c8cd7e | ||
|
74f82b022f | ||
|
e46fa6d92f | ||
|
a2d0cc1a97 | ||
|
f7465573b7 | ||
|
1cd336386e | ||
|
fc8c936361 | ||
|
0c904eb476 | ||
|
61ac0a0ac4 | ||
|
d5e6058370 | ||
|
c814443a83 | ||
|
356e7cb199 | ||
|
265270b83c | ||
|
c7f7b8d7e0 | ||
|
d6f1895465 | ||
|
241544ad8a | ||
|
37ca3dd556 | ||
|
be6cb6724d | ||
|
ab2ac92ecf | ||
|
3ec7f81dcc | ||
|
dd3b6a8d4a | ||
|
95ef7cabcb | ||
|
aeebd69555 | ||
|
a04a6bfdaf | ||
|
5f8b035a71 | ||
|
9106aa7e59 | ||
|
0c64863c97 | ||
|
1619144323 | ||
|
43b128473d | ||
|
abf92ecf67 | ||
|
faff4b97c4 | ||
|
c71af8b926 | ||
|
16d7e971c3 | ||
|
dd41f0ff87 | ||
|
dd3df80f01 | ||
|
c42bc173ac | ||
|
495b4c2c36 | ||
|
8b79c9beb1 | ||
|
372764355a | ||
|
0f6be43d8e | ||
|
b3c7f00669 | ||
|
70926b5d55 | ||
|
1b29c35db8 | ||
|
8f60678946 | ||
|
2edbaca0bf | ||
|
999cb6e4f5 | ||
|
f9ea3d47a6 | ||
|
f77d5666d4 | ||
|
7c14d01d7a | ||
|
3bd3573dbb | ||
|
f3fd90ea57 | ||
|
7f29e7edee | ||
|
80cb9dd67b | ||
|
b917e30c35 | ||
|
d2d6cdb1c2 | ||
|
4a753029bb | ||
|
84082805e0 | ||
|
c1e06843eb | ||
|
6e127a5deb | ||
|
2a8c44ad83 | ||
|
092ac30ee5 | ||
|
da7c856f5d | ||
|
f32daf1e34 | ||
|
a79453fb1f | ||
|
0d4257462d | ||
|
f8ed2e1d0d | ||
|
f6f4ef7ee9 | ||
|
cf9a7287fe | ||
|
8eebcf28ac | ||
|
d2b62fff47 | ||
|
4bff5778e0 | ||
|
29469c6e2a | ||
|
0cf50140a5 | ||
|
5ffb6eb26b | ||
|
5fee376411 | ||
|
5cde820d4c | ||
|
b2c4934bc1 | ||
|
8c28481311 | ||
|
24210c084d | ||
|
fdc55ff203 | ||
|
e08eaa39e2 | ||
|
ea4cbd68e7 | ||
|
46586a6334 | ||
|
e7001e0d94 | ||
|
cb5306e2c5 | ||
|
f4c0353061 | ||
|
62fdd3bd3a | ||
|
e83d05e521 | ||
|
6aab291185 | ||
|
17fa550665 | ||
|
236c7db4b3 | ||
|
c7d180c43b | ||
|
d3030f8627 | ||
|
b3863c8af7 | ||
|
0033f683fd | ||
|
55fe4c4a4e | ||
|
a67d9be5a2 | ||
|
e9019eb650 | ||
|
876e30a3c5 | ||
|
f8f3d16d4c | ||
|
bd129145ad | ||
|
6b85a158e9 | ||
|
ddf977faf5 | ||
|
432bf597ae | ||
|
496502b150 | ||
|
81c6fc9ff1 | ||
|
5cf1c6973d | ||
|
49b51e8070 | ||
|
071e956981 | ||
|
288faefae3 | ||
|
844b5cbd42 | ||
|
0cc659cdb4 | ||
|
a1a7c78755 | ||
|
559f0a72fa | ||
|
f19c9f9511 | ||
|
b222731c4f | ||
|
b10965b78e | ||
|
2e01c945aa | ||
|
f5494f0331 | ||
|
7907132269 | ||
|
77cd2e34a0 | ||
|
746cecf4b7 | ||
|
564ffd3c8d | ||
|
727489fffd | ||
|
2097398232 | ||
|
6ecf828a13 | ||
|
d05313f555 | ||
|
b9b99508e8 | ||
|
f7e12a9bc5 | ||
|
873ae31d29 | ||
|
0d42a832c1 | ||
|
30b5eef230 | ||
|
53216edd1d | ||
|
e4cc8d1396 | ||
|
c9ed990016 | ||
|
6eeaabb33c | ||
|
94632cdca5 | ||
|
d44a16e1f0 | ||
|
1f01ade154 | ||
|
0f4ad98321 | ||
|
01b8e1c609 | ||
|
79f80314ed | ||
|
ac540cff74 | ||
|
86ce4ba305 | ||
|
a066f80372 | ||
|
54a24c2b6a | ||
|
a26b7a5a79 | ||
|
40c2d811f9 | ||
|
29208310a9 | ||
|
74b523f248 | ||
|
01ecdee3b2 | ||
|
5a826d8a5c | ||
|
731358f3bc | ||
|
cbf8a59ef1 | ||
|
52955d1e98 | ||
|
3ecb969a12 | ||
|
62ea36073b | ||
|
e5d9d541f6 | ||
|
5dce40c97f | ||
|
87d1c1e9f4 | ||
|
13af2c37f0 | ||
|
ea79ad206c | ||
|
d0edb879b8 | ||
|
5f3fc904b5 | ||
|
6557090ac3 | ||
|
ad2973e89f | ||
|
19cf0fd89d | ||
|
12d13a4a33 | ||
|
d9deb90953 | ||
|
05ef0c51a0 | ||
|
fa1a5f8a61 | ||
|
61fb0e9cea | ||
|
212586fceb | ||
|
7d96d41f8e | ||
|
757cc25163 | ||
|
579aa7cb3e | ||
|
0e33e27401 | ||
|
2eb307661f | ||
|
d37de1fd46 | ||
|
0f32b02deb | ||
|
a18b499552 | ||
|
eb76275cea | ||
|
bea00cf66b | ||
|
daf437f4e3 | ||
|
390cfb2cd5 | ||
|
7580a02c6c | ||
|
07bcb79b1d | ||
|
6ceb2030f9 | ||
|
c4ef115e3d | ||
|
2a5587439f | ||
|
6cf4cbea21 | ||
|
3575ca4ac9 | ||
|
4f8dea0db8 | ||
|
fc24ae63ef | ||
|
9bfb0d911e | ||
|
09af9efd5c | ||
|
6a44e0eef5 | ||
|
781d237798 | ||
|
5045d74716 | ||
|
20f26a0680 | ||
|
0dede73da8 | ||
|
fc7a7004da | ||
|
6744feeb76 | ||
|
429f077679 | ||
|
7e60928b34 | ||
|
7b9d8a1f9d | ||
|
410e1eb132 | ||
|
361f08bad8 | ||
|
33857562af | ||
|
a5d003f90d | ||
|
ce8429523d | ||
|
2e3d542c28 | ||
|
295a836324 | ||
|
1c731c92fd | ||
|
72fa616362 | ||
|
00ca3bf967 | ||
|
e4c534fc99 | ||
|
192ca1dc57 | ||
|
59e97687b1 | ||
|
96fd3f8bd0 | ||
|
2eb7390aa2 | ||
|
ff2be24203 | ||
|
ea8e02412e | ||
|
c77143b542 | ||
|
20e0063dfc | ||
|
c3b258f602 | ||
|
b98c40181c | ||
|
7fab3a7a69 | ||
|
ec7676bdec | ||
|
503d951673 | ||
|
6812e5e550 | ||
|
8a0951be18 | ||
|
e9c30a9361 | ||
|
a482139616 | ||
|
3cbbeac60d | ||
|
edb874a2de | ||
|
4d2b9b5c5d | ||
|
35e79ef66d | ||
|
0aefb378f9 | ||
|
b432cf45c9 | ||
|
3ee30ca14c | ||
|
b70d3fe48e | ||
|
8e5f15c603 | ||
|
f88539d230 | ||
|
37ecdcfce5 | ||
|
841c0e767c | ||
|
311163203a | ||
|
e61d8bda60 | ||
|
f54a574ee4 | ||
|
56b01b6eaa | ||
|
3b726b996d | ||
|
2db3a226dc | ||
|
be2296edf1 | ||
|
81b3db3dbf | ||
|
f652178a02 | ||
|
d318ff6100 | ||
|
15a95e3b36 | ||
|
bf655b530f | ||
|
e9db24ac23 | ||
|
32e0931588 | ||
|
f989dd0132 | ||
|
b3b4fd448e | ||
|
c1c0eab113 | ||
|
46f5f51909 | ||
|
975e389f1d | ||
|
c43d4eaa93 | ||
|
d27752350a | ||
|
4987e5b158 | ||
|
0525932561 | ||
|
35e1936202 | ||
|
395c429cb1 | ||
|
4b01cb2544 | ||
|
0c5d6f4660 | ||
|
4b950117f9 | ||
|
0d613279ba | ||
|
2001fb6f81 | ||
|
5df1ac3610 | ||
|
0a8e97098d | ||
|
572fe066da | ||
|
19038d063b | ||
|
a38ce71813 | ||
|
8b802b3fe6 | ||
|
1126e1f8d7 | ||
|
21d1c4572d | ||
|
c82fda86b6 | ||
|
bdaf2592e8 | ||
|
0fa4676d30 | ||
|
df94a355fc | ||
|
86ed060f25 | ||
|
6733da5fcd | ||
|
cb679f3206 | ||
|
9bb81e1ed3 | ||
|
f65368068f | ||
|
1fd3b5ed5a | ||
|
fb3baeaf23 | ||
|
8237c6fb28 | ||
|
d4c8971b65 | ||
|
78fe398a2f | ||
|
39564bbdf5 | ||
|
6e701f798f | ||
|
5f18a7c237 | ||
|
fdd89f1da5 | ||
|
52b3458972 | ||
|
016e1f1b19 | ||
|
6fd2f36bd8 | ||
|
c98f54ecdc | ||
|
8250e061d4 | ||
|
1a008da295 | ||
|
124f598090 | ||
|
3d155a3016 | ||
|
eff2a32082 | ||
|
087ec5e1ce | ||
|
637a6bfe9f | ||
|
2d504e3c71 | ||
|
960a8aee87 | ||
|
32eb900317 | ||
|
1886ab9f35 | ||
|
b3c9d8b86b | ||
|
2edb7d57be | ||
|
f6af922088 | ||
|
5bae654061 | ||
|
68fbe714a4 | ||
|
6e2733a945 | ||
|
bae37248f5 | ||
|
cb7e717a7e | ||
|
f9d1005b9d | ||
|
62d636f125 | ||
|
49ec571bd0 | ||
|
831870b122 | ||
|
aae194cc54 | ||
|
a5a9e6c7a8 | ||
|
252829aee0 | ||
|
58f96365d9 | ||
|
9c1890fe13 | ||
|
b9b1f7efe7 | ||
|
f6f8232b6c | ||
|
2559b9cfd8 | ||
|
46685a5637 | ||
|
38aae1d1f0 | ||
|
9fcbd8af1c | ||
|
b6cb988ed7 | ||
|
92eae9d2d9 | ||
|
35f89fc3d6 | ||
|
7ba571395e | ||
|
3fb0689b84 | ||
|
f0b154528d | ||
|
22855508e8 | ||
|
c6f1034177 | ||
|
598f7a0b5b | ||
|
11301681aa | ||
|
c478f8f0e1 | ||
|
260d73f752 | ||
|
a72f0693f3 | ||
|
6552d192a6 | ||
|
c37643e8a0 | ||
|
3edc4d16ac | ||
|
aa6b86a1c3 | ||
|
d64797e4c3 | ||
|
9b82f1286f | ||
|
28964ebe24 | ||
|
42ea5f4f67 | ||
|
4146495b05 | ||
|
68a9f24fb5 | ||
|
513d507423 | ||
|
cc1a6f0e55 | ||
|
62c13f66b0 | ||
|
d60f1a19da | ||
|
f0cfec62cd | ||
|
b62f6d3982 | ||
|
d3bc4e43a5 | ||
|
690f35f61c | ||
|
2e8f7fff7c | ||
|
d50169fc06 | ||
|
30a215009d | ||
|
9a4b1c6493 | ||
|
500c5cca68 | ||
|
de13aa5126 | ||
|
b83810af84 | ||
|
98f0202c99 | ||
|
d5ee5d0c65 | ||
|
99e509065f | ||
|
1580ba5ac1 | ||
|
b7e9efdc98 | ||
|
738427a151 | ||
|
fa9c9f14a6 | ||
|
7a42de3eae | ||
|
dfb4d9a48b | ||
|
8bda1488dc | ||
|
73a5f13175 | ||
|
7e71162ed5 | ||
|
8498f129d3 | ||
|
26498aac58 | ||
|
5a15953a76 | ||
|
0e09546391 | ||
|
fb33689ec3 | ||
|
cfd8478ba4 | ||
|
dd8c646920 | ||
|
c7019d4d14 | ||
|
7694eae167 | ||
|
4e82541ead | ||
|
010f3c9575 | ||
|
067a87dc30 | ||
|
208cf752a1 | ||
|
151fb20972 | ||
|
49ba23dc1a | ||
|
8d21d1e1fe | ||
|
f4fd695853 | ||
|
b235dea47b | ||
|
b5b42f3de1 | ||
|
61aebaeb4c | ||
|
055b68289c | ||
|
1c86517e79 | ||
|
36704d4224 | ||
|
71b441020e | ||
|
b566174cc5 | ||
|
a80c27ece3 | ||
|
89bae9e64b | ||
|
218e727163 | ||
|
98d57db313 | ||
|
5593678542 | ||
|
1303ad0d16 | ||
|
1d1ccf7488 | ||
|
825f5864d3 | ||
|
7237146ea5 | ||
|
7adcc25aa4 | ||
|
fa8fecd610 | ||
|
38934d74ae | ||
|
859774482f | ||
|
037924384f | ||
|
744f434a32 | ||
|
7841b26c18 | ||
|
ca01679379 | ||
|
fb712c3987 | ||
|
eb61520753 | ||
|
aa0a24a0f1 | ||
|
a69f5655d8 | ||
|
b3bf36175d | ||
|
5c2bea1b4f | ||
|
2aad74d8cc | ||
|
b216d488f9 | ||
|
99a58c93d3 | ||
|
aa53ef66e2 | ||
|
8aa976458c | ||
|
2542705390 | ||
|
c3e2e9cf26 | ||
|
b2d8e25f41 | ||
|
9c50ff9fb3 | ||
|
3d26d2431c | ||
|
a5bf039819 | ||
|
5161dca58a | ||
|
cd3a23e7bf | ||
|
0c4d2a0fc5 | ||
|
a32c85c1c2 | ||
|
3093465dc7 | ||
|
cf57476d6b | ||
|
9bbf089634 | ||
|
f85bf5fa68 | ||
|
d22b985e3f | ||
|
3bbf269afb | ||
|
9d375934dd | ||
|
f1a566ec6b | ||
|
f3e549e772 | ||
|
4f8c524839 | ||
|
5b908d7502 | ||
|
c70710d4c7 | ||
|
ef8a468f1f | ||
|
6d2b2ef2b9 | ||
|
a28e66c5fe | ||
|
dc76404590 | ||
|
59dc00bc30 | ||
|
a34059b1e5 | ||
|
b0a1488820 | ||
|
173d8fca00 | ||
|
7cccd1fae5 | ||
|
be63388638 | ||
|
72e0aac551 | ||
|
63efd5d96a | ||
|
a8a19da607 | ||
|
24f3b67b56 | ||
|
6f46a777ca | ||
|
37529a4cd1 | ||
|
381ff97efa | ||
|
0b0aeeda29 | ||
|
93d59eb6eb | ||
|
4debd1ea79 | ||
|
86e7c22196 | ||
|
2c19d7f3da | ||
|
61ed67f27b | ||
|
e44863e908 | ||
|
72f9a80c76 | ||
|
1d3c2be0be | ||
|
877f8253c3 | ||
|
0b73862cfe | ||
|
17f0565afc | ||
|
ec7381483a | ||
|
198f660ee8 | ||
|
b512123303 | ||
|
3d0307a5a9 | ||
|
e41a8aec0e | ||
|
3f9526c1ac | ||
|
a8a1878281 | ||
|
9482ccdb74 | ||
|
1eddb70396 | ||
|
49c51368eb | ||
|
3d989e822d | ||
|
398ed04958 | ||
|
74d72d6028 | ||
|
f6c192f584 | ||
|
53d6e4bff3 | ||
|
2763f0c064 | ||
|
6c64b35f4d | ||
|
3ce3adf3fe | ||
|
98ee5a5741 | ||
|
eb0d2d9851 | ||
|
46ae49a305 | ||
|
93198cc7dd | ||
|
a1bf63dbe9 | ||
|
fce987ffc8 | ||
|
6047bca2c3 | ||
|
2c7ba24977 | ||
|
a76b0d8d74 | ||
|
a41e4696a0 | ||
|
994d1ddbba | ||
|
c0ef28186e | ||
|
54b6b527c7 | ||
|
e5ce6f92ac | ||
|
d68f67bf5c | ||
|
dd5145131e | ||
|
ebabb30abd | ||
|
54382a9bf5 | ||
|
2ce5fd6267 | ||
|
bdc2677f7b | ||
|
c7a74802ab | ||
|
27efe62a92 | ||
|
05029cb9b7 | ||
|
2420c573d0 | ||
|
a5213b572c | ||
|
781ff9c3d9 | ||
|
41b9aa112d | ||
|
9af7906180 | ||
|
5490dddbda | ||
|
8801abf380 | ||
|
f2dfd613f8 | ||
|
1fb521418d | ||
|
ed28caeba6 | ||
|
457604014f | ||
|
d1791ff286 | ||
|
6ce67f3cbe | ||
|
2a1e419bf8 | ||
|
396b504b5f | ||
|
f12667c011 | ||
|
5886faf63b | ||
|
4f4a8f6163 | ||
|
05e695c7d3 | ||
|
3212422921 | ||
|
cbedbdde81 | ||
|
eacdddaf12 | ||
|
fe3ccea370 | ||
|
5aa58bef7c | ||
|
a9c594d5bc | ||
|
5bddcaa84d | ||
|
de69b2242c | ||
|
2d9f37be87 | ||
|
da49e6a3ee | ||
|
d48c88428e | ||
|
bb4c83d404 | ||
|
68afe0f0e9 | ||
|
d680eb7b6d | ||
|
2fbea1ceea | ||
|
e78dd6e9bc | ||
|
553d0d9eaf | ||
|
7c817bde70 | ||
|
670a1815ed | ||
|
ab84444d3a | ||
|
1aba3394a3 | ||
|
8f378e3ce2 | ||
|
928e4503c6 | ||
|
1af5f1f03f | ||
|
375fc3b5bb | ||
|
bcceaa9c28 | ||
|
5abbc86d37 | ||
|
8e47307fed | ||
|
60def06040 | ||
|
d97f0c6b7d | ||
|
e727c62e76 | ||
|
211b404195 | ||
|
af034537fc | ||
|
da9cd60ec4 | ||
|
f5b43cc7b4 | ||
|
f4b89ce45b | ||
|
a33c95f8b1 | ||
|
2ba755318f | ||
|
f745f7df33 | ||
|
ddcf88b827 | ||
|
bf0674c40b | ||
|
ccee5cd5e0 | ||
|
38b8d4527c | ||
|
58f48db381 | ||
|
03908feacc | ||
|
48fdbda9cd | ||
|
b3767766ef | ||
|
7b50892339 | ||
|
5b8abaee50 | ||
|
6753f46bf5 | ||
|
e03a9ba22f | ||
|
54a5c2a5c4 | ||
|
1974c22e54 | ||
|
9b7a7d797e | ||
|
80f5a9a448 | ||
|
4eb5fa017d | ||
|
1423e8f8ff | ||
|
7d81fbcd05 | ||
|
43f29bbc58 | ||
|
063095bcaa | ||
|
0d86e64114 | ||
|
b6c9a7623a | ||
|
887c0a9a44 | ||
|
e4ad1bde21 | ||
|
1c10749be2 | ||
|
c70af14af3 | ||
|
9692fbfd89 | ||
|
47679582aa | ||
|
758d1c6e7d | ||
|
a3a3624c57 | ||
|
b6c9f6cc53 | ||
|
c832f82027 | ||
|
6f38bb5c0e | ||
|
80ce4c557b | ||
|
adb9936959 | ||
|
6d32f3cb94 | ||
|
e40445dea7 | ||
|
647d7c1585 | ||
|
58f5df11e6 | ||
|
e3c0425857 | ||
|
b643a42dfd | ||
|
c0123646f6 | ||
|
5d220486e9 | ||
|
8a2efb0dec | ||
|
ae2cdf0fad | ||
|
5f871cfad2 | ||
|
7679ac49b1 | ||
|
7e9c7c37be | ||
|
53f9cd79f5 | ||
|
0c3899065b | ||
|
8f931d8fd6 | ||
|
f4716805aa | ||
|
3c41028cd5 | ||
|
e91ac70739 | ||
|
52d8345a55 | ||
|
c4947a5a1c | ||
|
f86e2858a2 | ||
|
a9e0ae35ba | ||
|
4962992516 | ||
|
cc2beb996e | ||
|
902c48d748 | ||
|
e80eeb3296 | ||
|
e3e47a7b61 | ||
|
33bfedb95a | ||
|
fd26b2c044 | ||
|
ce8bb0863b | ||
|
1cc0885890 | ||
|
3810ecb08b | ||
|
39b1aa98eb | ||
|
f536c8c50d | ||
|
fb510f8d5b | ||
|
d19097c5e1 | ||
|
f9b9212100 | ||
|
5a053dc580 | ||
|
3690a2e1c0 | ||
|
039e8d285b | ||
|
66717a2aec | ||
|
40d4e22249 | ||
|
3298ac489c | ||
|
7baf9a4d36 | ||
|
826a84aca1 | ||
|
6a8e98d4b7 | ||
|
7d5f45d9e3 | ||
|
d633495817 | ||
|
4ede12c5c0 | ||
|
849a8bd4d2 | ||
|
b9043f2785 | ||
|
0857616d9f | ||
|
fab491b44c | ||
|
8e70fdcdfd | ||
|
8c7c5a6a80 | ||
|
4791fb1bc8 | ||
|
702a6edcb9 | ||
|
0e88c3ac70 | ||
|
6fe8e80388 | ||
|
50d89bc579 | ||
|
528d7c463a | ||
|
3a9cb05d58 | ||
|
5ae05cc2f4 | ||
|
0742f72f4f | ||
|
a8f5562bde | ||
|
aa6407d07b | ||
|
457d19beaf | ||
|
a324724cf3 | ||
|
08d91ef714 | ||
|
7eeaa74dd9 | ||
|
0cd5965fcc | ||
|
06cc33166d | ||
|
f2050ec13a | ||
|
c92491621b | ||
|
091bcd72fd | ||
|
981188e17a | ||
|
72995c5bcb | ||
|
cb3d73424b | ||
|
392b5e07c0 | ||
|
ea6b1568b4 | ||
|
3ad2820ebd | ||
|
fd4986e726 | ||
|
bb58f40ae3 | ||
|
ec5973a3e6 | ||
|
72dbf597cc | ||
|
c062a8a841 | ||
|
056e642d2b | ||
|
3fe45e4a9b | ||
|
064887dfbd | ||
|
a13efcfe0a | ||
|
cf24f21a77 | ||
|
5ce539c432 | ||
|
7756e48197 | ||
|
ed0f41c650 | ||
|
80a59da4b8 | ||
|
cafd8c9b3e | ||
|
d7b2cb6a50 | ||
|
c0821032fb | ||
|
51256d8fe7 | ||
|
1fdc3a5e99 | ||
|
7157a62d2b | ||
|
354486e326 | ||
|
f826be087d | ||
|
a995c08356 | ||
|
1e80b85296 | ||
|
5a026afd9f | ||
|
c0b5035b1a | ||
|
175120fdd7 | ||
|
1b2aaaa440 | ||
|
bf2eebd54d | ||
|
19a6b9673e | ||
|
9c42360b34 | ||
|
8eb069cce5 | ||
|
55d6f869fc | ||
|
aa4f2813e4 | ||
|
ee71bf3b71 | ||
|
d64d860c93 | ||
|
83a48dd395 | ||
|
58646ebf20 | ||
|
f7d1df0aab | ||
|
e7da3d81d1 | ||
|
3d4a98bed9 | ||
|
a465a211c2 | ||
|
09ab5e4d65 | ||
|
87d912e4db | ||
|
18ea588e5c | ||
|
3418d895f2 | ||
|
5fcbcf3ddc | ||
|
9f19fb7b53 | ||
|
00505ab2dc | ||
|
dac3c00862 | ||
|
5b6b2bbc01 | ||
|
ad7fecf48e | ||
|
cc06a43142 | ||
|
79aa2d1138 | ||
|
1fd88819be | ||
|
7b98d8a227 | ||
|
b0443467aa | ||
|
41b454f2e5 | ||
|
2347b6628d | ||
|
64a8698a5f | ||
|
cc1c57727d | ||
|
af26d11dd2 | ||
|
ac3628c1fd | ||
|
41a960ecc7 | ||
|
89933a4cb0 | ||
|
352542d12b | ||
|
d418a16703 | ||
|
440e9c3d5d | ||
|
1db463f4de | ||
|
279b5945cb | ||
|
d2bcf440e8 | ||
|
33557e22ed | ||
|
67ce4c3bd9 | ||
|
dd91c7791b | ||
|
fc6b59e8b1 | ||
|
ebe8803e80 | ||
|
a078c1feb5 | ||
|
b6c08d74a6 | ||
|
68297d9398 | ||
|
6f27ba3abb | ||
|
7afa066be3 | ||
|
562eb63964 | ||
|
852907e1cc | ||
|
50aa2335eb | ||
|
3ff29d2e4b | ||
|
24e46508d5 | ||
|
f7ce93b27c | ||
|
f67168cf2d | ||
|
c80254eb3f | ||
|
01fe7f42a0 | ||
|
f37f59f47b | ||
|
521b237e8b | ||
|
daa5b9f496 | ||
|
18ddf78dbe | ||
|
3356dc4edd | ||
|
c1722cdfdb | ||
|
5c09f44f8b | ||
|
40588d182a | ||
|
83ead1217f | ||
|
4a89f974f6 | ||
|
93308e4a29 | ||
|
593cb59d38 | ||
|
1439d006cd | ||
|
b4feb99841 | ||
|
63c43ae9f5 | ||
|
a31e1349ce | ||
|
f4240fcc74 | ||
|
8eaeb44f56 | ||
|
bfc1032fc1 | ||
|
65f90c0942 | ||
|
4fcd1f33dc | ||
|
86527a2f4c | ||
|
648166ecca | ||
|
2e3b5ff134 | ||
|
3c9cdfb841 | ||
|
e7f6e0f9f1 | ||
|
7fcbd543d7 | ||
|
2f603cc73e | ||
|
69dc13efdf | ||
|
456220db56 | ||
|
c50858a877 | ||
|
a11efe838a | ||
|
d6dc04d737 | ||
|
feeea88a58 | ||
|
36d44a3b25 | ||
|
fc5f4dc86f | ||
|
59c0bb0f46 | ||
|
fae11e12cf | ||
|
e0a74881bf | ||
|
ce38857061 | ||
|
c8e134930f | ||
|
3876299fa0 | ||
|
b0b2bde160 | ||
|
3a1b7bb54c | ||
|
04ef92ca94 | ||
|
d7a6860a23 | ||
|
5e361a4a05 | ||
|
cf5f7ef9c2 | ||
|
811d8aefa3 | ||
|
37f446dd79 | ||
|
1a01b5c296 | ||
|
b47197b881 | ||
|
3e5ae57164 | ||
|
a0048ec064 | ||
|
c35e10f875 | ||
|
46d9aae952 | ||
|
bd67bb909a | ||
|
c454964e5b | ||
|
e61b7b9241 | ||
|
954dc6f694 | ||
|
c9e31b7fbd | ||
|
df46234c55 | ||
|
662ad60cd7 | ||
|
a5640ec89c | ||
|
93cd01d7e6 | ||
|
ca9b813aea | ||
|
cbe3f33daf | ||
|
b8f36df713 | ||
|
e087db57b2 | ||
|
dd7427d1eb | ||
|
4a4ec1c54a | ||
|
18c87e98bf | ||
|
8a3edd677c | ||
|
def8c20168 | ||
|
613997fd7e | ||
|
eabeb4f7b3 | ||
|
ac6c7dd37f | ||
|
e7c550243c | ||
|
6f95ff5637 | ||
|
82a20d9bb8 | ||
|
fb55e9cddc | ||
|
4d406621ee | ||
|
e074def743 | ||
|
13e959f8c0 | ||
|
5151168071 | ||
|
77f37e84eb | ||
|
8e3b75c40a | ||
|
4037c3ae65 | ||
|
c817e01774 | ||
|
8d1e8c9c2e | ||
|
b0ad1303ac | ||
|
e4e173233c | ||
|
dd1756ba9e | ||
|
cec0d50cfd | ||
|
1ef2d7e757 | ||
|
03976a038e | ||
|
83a3de91f8 | ||
|
e7cc3e2094 | ||
|
4fa434a3d0 | ||
|
44ca1c0f11 | ||
|
a0fbc1f26c | ||
|
62a7934ea6 | ||
|
5fdf33c689 | ||
|
7031a91aec | ||
|
39a3f5b08d | ||
|
7eee94290b | ||
|
45e7265c82 | ||
|
3c2684b674 | ||
|
b1a8e7cf44 | ||
|
7887d5906d | ||
|
b0ef4d2b6a | ||
|
c626e62da6 | ||
|
b93c49974c | ||
|
d045d609be | ||
|
333cd41d33 | ||
|
2526933747 | ||
|
a33c5822a9 | ||
|
d6c4f56da8 | ||
|
25f800ac7d | ||
|
ad0f942bb5 | ||
|
1ff5a08f60 | ||
|
8a223ce3d5 | ||
|
2f85e0b7d2 | ||
|
6d55882b4a | ||
|
c5ccbb50d2 | ||
|
572bab7e84 | ||
|
f561b8cdfe | ||
|
3ff8b4d19a | ||
|
47280bb483 | ||
|
2b4e235ffd | ||
|
27dacf2eca | ||
|
15e4f8a05f | ||
|
0cb4e48344 | ||
|
f29c0cc377 | ||
|
960d19b6cb | ||
|
4b34c77a39 | ||
|
61b614543c | ||
|
30c8dfe12c | ||
|
3d42221ba8 | ||
|
bd56500d03 | ||
|
401363854a | ||
|
a6d274dcb0 | ||
|
9d20afa95c | ||
|
32362d2f79 | ||
|
3a201bf72b | ||
|
d15fcb69ab | ||
|
c1850f9855 | ||
|
b9bbcdc45c | ||
|
ff98d79963 | ||
|
6ef6f605b0 | ||
|
7f9c79e345 | ||
|
37e2975d4d | ||
|
49142c74a5 | ||
|
98f196506a | ||
|
c52f417406 | ||
|
ec68828a30 | ||
|
c259deb5b2 | ||
|
f0f520eeff | ||
|
a9697cec28 | ||
|
9e6a13fa78 | ||
|
95015dae9f | ||
|
cba77b26a5 | ||
|
0069bf82a6 | ||
|
9e9a7ff572 | ||
|
18821b079b | ||
|
2674a8b708 | ||
|
8bc30c8851 | ||
|
bd10235397 | ||
|
35b7ee91eb | ||
|
d452f53576 | ||
|
9d374d4726 | ||
|
4beee46c52 | ||
|
319cd6c038 | ||
|
bd66fba55f | ||
|
3c11c66ff2 | ||
|
c52cf4d537 | ||
|
1e8dc4f375 | ||
|
7988124de5 | ||
|
f0aa65c832 | ||
|
1c96c09ec9 | ||
|
9685aae967 | ||
|
c7a6608777 | ||
|
bca67d3d27 | ||
|
9c39909a9c | ||
|
f278505db2 | ||
|
e91cc118df | ||
|
e1763ba13c | ||
|
cad0c3c8a9 | ||
|
49103b30f2 | ||
|
df47a59ecb | ||
|
091ec763f9 | ||
|
33b7c5316f | ||
|
986093cf8d | ||
|
33c62acc5c | ||
|
8b671f013a | ||
|
5789ab84a6 | ||
|
6d6e04dc12 | ||
|
7a7c99f3a1 | ||
|
9896f5edbd | ||
|
12a98135bf | ||
|
a30dfb6b19 | ||
|
a4d4eddd92 | ||
|
b393893c7a | ||
|
572fb7e943 | ||
|
7173d7a6a5 | ||
|
7b577d72b5 | ||
|
5a140c2e5c | ||
|
e922cdb113 | ||
|
189da8236c | ||
|
2c62d802b6 | ||
|
23df761b70 | ||
|
6a80641ee2 | ||
|
02e1e94ab9 | ||
|
f28b91b8cf | ||
|
6849615de6 | ||
|
743f84099d | ||
|
a041b1738c | ||
|
1056ef8418 | ||
|
ac77e10a0f | ||
|
eae6f0525c | ||
|
341b7e61da | ||
|
eb6d2224bd | ||
|
bb1b5f986b | ||
|
1c1cc65cbd | ||
|
5dedd16bf5 | ||
|
66d51b575d | ||
|
f26df713c0 | ||
|
b8f486dee9 | ||
|
ac7e66684c | ||
|
be3d2bc1a4 | ||
|
8f28eebe5a | ||
|
d17a87bd28 | ||
|
59eb0af705 | ||
|
7d5840d449 | ||
|
fb7f0ddaaa | ||
|
4bdc7ea51a | ||
|
3ac9f7e676 | ||
|
843ef93202 | ||
|
00726ed51a | ||
|
0cbad5b99b | ||
|
d180252c52 | ||
|
ca5cd28d48 | ||
|
12e0d064cd | ||
|
386a5abc7d | ||
|
084233a207 | ||
|
94e665b3fa | ||
|
0a5c4fa159 | ||
|
9fddd7a716 | ||
|
92473dfc46 | ||
|
8ee0292d8e | ||
|
174105b9fa | ||
|
7f45708c86 | ||
|
015229d551 | ||
|
267e9610c7 | ||
|
32797f5780 | ||
|
ce85512673 | ||
|
5f630f2c5d | ||
|
4fc9106d37 | ||
|
614c051a71 | ||
|
94f06d23c0 | ||
|
a8e0b0d0a3 | ||
|
0f3263f710 | ||
|
2a81cadd27 | ||
|
f69822107f | ||
|
4dec6cab65 | ||
|
0287ce0c9d | ||
|
aae597bfde | ||
|
8347fb69c2 | ||
|
685632db0c | ||
|
5169b4556a | ||
|
3f099da257 | ||
|
d4c4cbe62b | ||
|
c66975ffc5 | ||
|
c35ac067b2 | ||
|
851a8c8b3a | ||
|
d081f7cb85 | ||
|
2c5534ca18 | ||
|
08fb58e10d | ||
|
13c3e40044 | ||
|
b5e525b251 | ||
|
663698c7a6 | ||
|
957f1ae00f | ||
|
763855fe9e | ||
|
e6880f9584 | ||
|
786f592d7e | ||
|
38d83c3c76 | ||
|
7897ba2293 | ||
|
a43931e987 | ||
|
2fec4eb2b4 | ||
|
3f59259dec | ||
|
2c110ed3d5 | ||
|
0d9a39bd26 | ||
|
5e273b0892 | ||
|
e91c83964a | ||
|
35acee98d5 | ||
|
8434463621 | ||
|
20f117500f | ||
|
850bce2754 | ||
|
7c05b9ed91 | ||
|
5abb79d5be | ||
|
70a06835b8 | ||
|
2e73225586 | ||
|
65c7473407 | ||
|
901e67a83f | ||
|
33c615e5f9 | ||
|
fdae9784f4 | ||
|
25f7aa6621 | ||
|
156a980c30 | ||
|
e9d5d491b8 | ||
|
b9bfc10d0f | ||
|
12876afa07 | ||
|
e66e56b020 | ||
|
6a7a20da88 | ||
|
35cdeebe19 | ||
|
c2fdcf7d39 | ||
|
627638a6cf | ||
|
414e5bf560 | ||
|
343749dc26 | ||
|
6a68aa2ecb | ||
|
70bb296a70 | ||
|
a25a2ec0d9 | ||
|
1644ce31e7 | ||
|
abcf66292d | ||
|
42a5483ba9 | ||
|
83282f8700 | ||
|
8485c8e417 | ||
|
4670afee7c | ||
|
e946b88d82 | ||
|
780ae4663d | ||
|
34676334b6 | ||
|
d799edbcc6 | ||
|
00f32d555d | ||
|
b7a8a01ac7 | ||
|
3a8546732a | ||
|
d656afa1d5 | ||
|
5b3190d39c | ||
|
c5dca95504 | ||
|
dce1d5d5e6 | ||
|
bb31faff1b | ||
|
162b49b417 | ||
|
f8b43d5ba9 | ||
|
e8f297db5a | ||
|
4d332ff241 | ||
|
83007d7600 | ||
|
5f72ae98eb | ||
|
940ead1fb8 | ||
|
bb28ca5371 | ||
|
0edae73a9a | ||
|
19a2d6d169 | ||
|
f3b847c4b0 | ||
|
1a2484e5bc | ||
|
6ed55cb1d5 | ||
|
099f19f99c | ||
|
7d2a6b53d4 | ||
|
6f0c68a4d4 | ||
|
9a377bb9da | ||
|
3cfe47d3f0 | ||
|
84c0bba1ef | ||
|
6aad970d1c | ||
|
298a36bffb | ||
|
846cee5066 | ||
|
50760ef05b | ||
|
0b383ad769 | ||
|
55bad42088 | ||
|
258c39d4a5 | ||
|
9819bf5df0 | ||
|
174c89f772 | ||
|
52e14b5c93 | ||
|
83ef426514 | ||
|
e14c6c39f1 | ||
|
d1789d1469 | ||
|
2fed7cdb61 | ||
|
cd97402779 | ||
|
ca4906c0a3 | ||
|
a28e39cd06 | ||
|
3768096308 | ||
|
3dde3d5322 | ||
|
9df0a29e9e | ||
|
da1e958eb9 | ||
|
52ca88141a | ||
|
4cd73b7a93 | ||
|
fb188972dc | ||
|
6e6b57fbd1 | ||
|
ee0d5b7d50 | ||
|
6d62a3634e | ||
|
54fd453d35 | ||
|
18537e6c38 | ||
|
7e78ee6363 | ||
|
d788969c25 | ||
|
db70a37621 | ||
|
b8be715227 | ||
|
24a47e2faa | ||
|
c56ec9eea7 | ||
|
a39d6e36e8 | ||
|
4e01f55a81 | ||
|
6c7492af89 | ||
|
4c8d4490cb | ||
|
5a56604f99 | ||
|
f471bc4018 | ||
|
596cba37e8 | ||
|
3c8538c0c6 | ||
|
4df8c4c09c | ||
|
bf9a559dcc | ||
|
974d0a33b0 | ||
|
b5cd93aa2f | ||
|
ef2fa2c895 | ||
|
4ff5b80ee8 | ||
|
fb8d5d05dc | ||
|
cef7289d75 | ||
|
94dfe15b28 | ||
|
788bdcafb9 | ||
|
0cfa2b2cf8 | ||
|
37ac8ede4f | ||
|
09edd269aa | ||
|
61e7aac455 | ||
|
bf02536fa3 | ||
|
74b2fdc52c | ||
|
1459c9eb20 | ||
|
1005bfdf7e | ||
|
52453313c1 | ||
|
6f620e9247 | ||
|
1c2591de1e | ||
|
93ae7808cb | ||
|
14d8bac7b2 | ||
|
dd3a964249 | ||
|
d088727bdf | ||
|
0807a74490 | ||
|
b12d93a739 | ||
|
2796c58eca | ||
|
22f912b9f1 | ||
|
0e87acb318 | ||
|
f7c6a848bb | ||
|
cb96345f21 | ||
|
d03c2e681f | ||
|
73c1283e98 | ||
|
e400b296d8 | ||
|
8180aa0bd3 | ||
|
e356c4b19e | ||
|
5c040c6149 | ||
|
d097df8226 | ||
|
add5d47fc3 | ||
|
2227de709b | ||
|
84b5f6e441 | ||
|
1f2b4a5a19 | ||
|
1b78752db6 | ||
|
ca30e18692 | ||
|
36f6da62aa | ||
|
046cfe305f | ||
|
5272c9ef0a | ||
|
aa7304f01e | ||
|
acfcdfe750 | ||
|
39b5240966 | ||
|
b11fd82d96 | ||
|
3973387295 | ||
|
a6dc414f57 | ||
|
723a20ba7d | ||
|
46e96476d8 | ||
|
b3c6ec3ded | ||
|
319777962b | ||
|
283abda83c | ||
|
77be2c450f | ||
|
4eea3ae073 | ||
|
c059224811 | ||
|
a29078ac04 | ||
|
851b7655c1 | ||
|
bdea9e5678 | ||
|
6d6df2a16b | ||
|
240c4e3674 | ||
|
fb61ea7635 | ||
|
d4ca9f3ba0 | ||
|
49f27414e0 | ||
|
77b864527a | ||
|
e5f4aa4140 | ||
|
289dcfb492 | ||
|
79828d1f10 | ||
|
7296af3f39 | ||
|
2ade2782d4 | ||
|
34c78d34b1 | ||
|
7c1f5fd932 | ||
|
810f54ffdd | ||
|
8740fd517d | ||
|
7ef28d9fdc | ||
|
83c4a5132e | ||
|
85c133cd84 | ||
|
d551a1a9ab | ||
|
e87e45c0a2 | ||
|
72aa490e49 | ||
|
35d55fce81 | ||
|
5578299445 | ||
|
99a7991664 | ||
|
15567a55dc | ||
|
5b68e0f7c4 | ||
|
eaa6a3c297 | ||
|
d53bb7f811 | ||
|
29c6f7e3ac | ||
|
14e7d94701 | ||
|
318351376c | ||
|
af8b3b84ef | ||
|
b64921a5ec | ||
|
f1a3f66515 | ||
|
6b4dff4bee | ||
|
de2dec2bec | ||
|
fae7cac15c | ||
|
8972e4f577 | ||
|
0ad84d93f9 | ||
|
ac9553de19 | ||
|
6801346b81 | ||
|
04d6c727e1 | ||
|
aec77cecde | ||
|
0f26d8f097 | ||
|
cb2ebc3102 | ||
|
d2581332db | ||
|
adb0973d61 | ||
|
7f987f93d1 | ||
|
c5fa0e98b3 | ||
|
a84844cea5 | ||
|
51f443c7b6 | ||
|
c2601dbd30 | ||
|
2fb64fa85e | ||
|
4e80416a4f | ||
|
a949b075b4 | ||
|
36e99af7fb | ||
|
9b99039fdb | ||
|
344e11a539 | ||
|
ca1d891799 | ||
|
485df894ab | ||
|
38cefc358a | ||
|
6d2d55057c | ||
|
4b9a2683ed | ||
|
06b4d7db0d | ||
|
225c779225 | ||
|
6717e29909 | ||
|
7f1b117675 | ||
|
632b6aaf1f | ||
|
3e8a61d626 | ||
|
fb418015e3 | ||
|
db30c2bc19 | ||
|
f6b043b434 | ||
|
abcd1f2975 | ||
|
5849c7ab78 | ||
|
19fa8a3ed9 | ||
|
875a06b9d7 | ||
|
c90b199488 | ||
|
0e1158c71d | ||
|
b19f77d5c7 | ||
|
7e0969bf82 | ||
|
8e51a7b31e | ||
|
317197a6b5 | ||
|
39902eff28 | ||
|
2cb3463cc8 | ||
|
60b014667a | ||
|
d7fde9d109 | ||
|
72701bd2a0 | ||
|
6b81b50d36 | ||
|
862836548d | ||
|
feb70284bc | ||
|
3a1fbb49f4 | ||
|
02e86864da | ||
|
b465b91ec9 | ||
|
7aac7a23a3 | ||
|
8fd1f15ae7 | ||
|
5c43890b31 | ||
|
073064bdb0 | ||
|
59597775e5 | ||
|
4c666b4d2f | ||
|
1e098b5928 | ||
|
4fcd7e94f5 | ||
|
513611ff92 | ||
|
fe3cce7828 | ||
|
edb1ae1798 | ||
|
85c20fb564 | ||
|
834efc7b2c | ||
|
d2c61794ea | ||
|
b56e654f26 | ||
|
d256e1f9c0 | ||
|
8762c1dcfb | ||
|
1f1a303457 | ||
|
046e1fb215 | ||
|
341877416e | ||
|
6c31d0d894 | ||
|
40751c2ed3 | ||
|
d72422b369 | ||
|
291066dcbd | ||
|
c96c8a391f | ||
|
7536899894 | ||
|
44f2e73d1b | ||
|
9e99dfc8b2 | ||
|
42cd946ff2 | ||
|
cbbf3ea75e | ||
|
23a77d70e8 | ||
|
e1e85f285c | ||
|
6988cd07a0 | ||
|
1bdb6069da | ||
|
0978a1ad8a | ||
|
350520a650 | ||
|
2a3aae6d57 | ||
|
d472cf13b1 | ||
|
eace04e2e7 | ||
|
f9187ac661 | ||
|
9c3fb960e8 | ||
|
b550fa291c | ||
|
6fb3f5c4a6 | ||
|
f25949cf84 | ||
|
cc434a1c7f | ||
|
5c8581a345 | ||
|
6259edac38 | ||
|
f0220611aa | ||
|
5c8051994b | ||
|
62f2e7f06e | ||
|
24e3b5296e | ||
|
9533ac3405 | ||
|
b5c780d2a1 | ||
|
06ebb0b6d6 | ||
|
5f76ba2ae3 | ||
|
32d899eb6d | ||
|
b30b4c1877 | ||
|
0d357a892b | ||
|
e180ed4ccb | ||
|
27ce962708 | ||
|
084f975d5e | ||
|
624aee531a | ||
|
a92f9e67b3 | ||
|
5649f5237b | ||
|
24a05b0bf5 | ||
|
359514432f | ||
|
cf706a37f0 | ||
|
4be07c3265 | ||
|
837f47c921 | ||
|
bfb96638f6 | ||
|
6453a41a28 | ||
|
1d9ca54cec | ||
|
1cc6ef54d0 | ||
|
af3476afb9 | ||
|
4f8e01ff36 | ||
|
d0dcab10f1 | ||
|
1004f039ec | ||
|
da6df9fdc5 | ||
|
a30ecbfe3c | ||
|
49530d5fe5 | ||
|
2d2897f426 | ||
|
d744377f4a | ||
|
23bc2980c6 | ||
|
f8c7cee59c | ||
|
6737031eb9 | ||
|
7cfc7e1133 | ||
|
67bd489ba8 | ||
|
34f5510faf | ||
|
0e07298340 | ||
|
a7fd5abe37 | ||
|
a029b16066 | ||
|
ea4756a802 | ||
|
7d76eea05a | ||
|
7d22b5bdce | ||
|
8e97e4a405 | ||
|
d6713e49cd | ||
|
369e18202f | ||
|
96b1328967 | ||
|
0254d63fdc | ||
|
b0a9f46bb7 | ||
|
d295e3b444 | ||
|
6186118aa0 | ||
|
98d20bf257 | ||
|
c38f0f22bc | ||
|
24446dd1d0 | ||
|
cd90674f37 | ||
|
4cfe8e9d48 | ||
|
5ceb1fa1c9 | ||
|
4fb9a702f0 | ||
|
daffe30e47 | ||
|
f0b380fe5e | ||
|
4e039d07f3 | ||
|
b403bbdf82 | ||
|
8c7fea39d4 | ||
|
9efd526f6f | ||
|
4ab92b62f5 | ||
|
bd1b72ad42 | ||
|
bccd45a22e | ||
|
3b9b2158c1 | ||
|
2a0df39961 | ||
|
21875a520d | ||
|
6c23d48649 | ||
|
4094043011 | ||
|
970807f01a | ||
|
66286494a2 | ||
|
140495fe64 | ||
|
04a872f927 | ||
|
60f6153446 | ||
|
e2737566ff | ||
|
dd3a979827 | ||
|
69d59f80ed | ||
|
ebe59ca483 | ||
|
fc669861fe | ||
|
61c61f9aab | ||
|
fd3baa930e | ||
|
df05261cd3 | ||
|
75d858a764 | ||
|
5709d94710 | ||
|
4f5686901b | ||
|
725328c209 | ||
|
ee00b0cea2 | ||
|
eafddd3cea | ||
|
94b2a345f2 | ||
|
e0ca522633 | ||
|
a58c1b5119 | ||
|
7d940743cb | ||
|
f999b49843 | ||
|
7592c80db5 | ||
|
60fb075419 | ||
|
91f0f0053f | ||
|
56d1be6ca6 | ||
|
516e3f60e4 | ||
|
db796ef3f1 | ||
|
335b088dd0 | ||
|
98ea04e7c6 | ||
|
737cd15707 | ||
|
3d899affcf | ||
|
858d535389 | ||
|
767bf6d1d7 | ||
|
29a95e10de | ||
|
8dd795dec1 | ||
|
8bcfa1a32f | ||
|
e984b6ff74 | ||
|
1179c1a42c | ||
|
69ebfc4cda | ||
|
26499f965b | ||
|
75b07641fd | ||
|
80c7ee74a2 | ||
|
f9906a9584 | ||
|
91dd7527d9 | ||
|
d4d9dda5cb | ||
|
e8b3312f2e | ||
|
3fd950e823 | ||
|
d98c8ae8b5 | ||
|
b8b2b48949 | ||
|
636ee4a11a | ||
|
fe08d62e91 | ||
|
d87145ad23 | ||
|
dce395e7ad | ||
|
926b0c72e8 | ||
|
4f044e753c | ||
|
b69c5e9972 | ||
|
fc597b736b | ||
|
56a9fded36 | ||
|
17a67d7227 | ||
|
09ced81ee5 | ||
|
8304b7db87 | ||
|
2f9259a215 | ||
|
fd07a7b17a | ||
|
369a280f64 | ||
|
8d760811b8 | ||
|
8b54df93dd | ||
|
2d8246668c | ||
|
ebedab89e5 | ||
|
a0e8bf9661 | ||
|
938385db40 | ||
|
45dc9d4d08 | ||
|
b2952da4bd | ||
|
d6a2f8258f | ||
|
92b9063527 | ||
|
40e8c9f6e6 | ||
|
3c43ce869c | ||
|
190329745d | ||
|
b4c355e17e | ||
|
4173f0a558 | ||
|
0d2518551f | ||
|
6fa3406b0e | ||
|
da6c9246f5 | ||
|
84565d5407 | ||
|
b0ae3243d5 | ||
|
6e42e18191 | ||
|
694c9916b9 | ||
|
4265cecdfa | ||
|
317a3a0ad2 | ||
|
0018491c1e | ||
|
aced280818 | ||
|
0320e0e849 | ||
|
e43065cfe0 | ||
|
6998f6fc3d | ||
|
747d7da402 | ||
|
c80b2c9766 | ||
|
ed8530d9b6 | ||
|
7e962a409c | ||
|
bf7c9c8567 | ||
|
07d3b17eb4 | ||
|
9e27a95b8e | ||
|
4f3e6daae9 | ||
|
9c532c444b | ||
|
22d883b4d3 | ||
|
c8fa7815a6 | ||
|
b8cde97ab7 | ||
|
098598c98d | ||
|
f9c5756b4d | ||
|
1b069745b3 | ||
|
5a8a692628 | ||
|
da52731c75 | ||
|
ed86641695 | ||
|
f579d5efe6 | ||
|
a7a1cb3827 | ||
|
ab3d7edcdc | ||
|
33d01a980a | ||
|
af902dddf1 | ||
|
1fd75ff4f4 | ||
|
c4c430dcd0 | ||
|
627c044e4d | ||
|
0137b992b4 | ||
|
397ead10af | ||
|
6afe6185be | ||
|
298b32e82e | ||
|
f67f92652a | ||
|
8a780d6f6d | ||
|
a03d354ee5 | ||
|
a08658b46d | ||
|
100d791e84 | ||
|
3850ede5cf | ||
|
5a2b875b81 | ||
|
54037862e6 | ||
|
5998357682 | ||
|
b240be37cc | ||
|
5d38632153 | ||
|
719bfd2011 | ||
|
c3f9d75abe | ||
|
b02e3ff0cd | ||
|
be5ddfa59b | ||
|
b1fab26057 | ||
|
19ddb3bfa4 | ||
|
0208c5b5d6 | ||
|
62372fe628 | ||
|
a9ff89cd5d | ||
|
1acfd92d8a | ||
|
947a77bcde | ||
|
24ddc6f081 | ||
|
27b8275d5a | ||
|
ff1dc201b1 | ||
|
13f73b626b | ||
|
087182be9a | ||
|
01519b3ae0 | ||
|
59f0d08417 | ||
|
4fc0bd5881 | ||
|
262075ca80 | ||
|
1def78f1c4 | ||
|
9574478aaa | ||
|
458a6c0418 | ||
|
1910575215 | ||
|
28ba83a313 | ||
|
9d87470a60 | ||
|
5148942b90 | ||
|
037d7b5a57 | ||
|
c4a2786ff7 | ||
|
a4c3f33245 | ||
|
72bdec2f76 | ||
|
e18d431b0e | ||
|
edfa025814 | ||
|
2e5807b6c4 | ||
|
9bf970a4c1 | ||
|
e9e58b9887 | ||
|
7fdf8d9925 | ||
|
4c3df3ae53 | ||
|
39343c8675 | ||
|
77caea2cc7 | ||
|
07ded00bd3 | ||
|
f1348fb693 | ||
|
1e3e427263 | ||
|
a64d8142c9 | ||
|
e1a2c27cfd | ||
|
de3ed997a7 | ||
|
a8fea9babc | ||
|
b017899f12 | ||
|
0491e8d707 | ||
|
c0533b390b | ||
|
1855fde331 | ||
|
91eb71e9fa | ||
|
77eb67b5a0 | ||
|
6cfcb1a823 | ||
|
aed481debe | ||
|
96e124bf8d | ||
|
cc923edf3c | ||
|
6b793b1a8b | ||
|
b07ec7d81b | ||
|
052c58403d | ||
|
5b97455878 | ||
|
8db35802f9 | ||
|
6c39288cec | ||
|
528b1435da | ||
|
4f2821bce0 | ||
|
ecf9412623 | ||
|
f6d502017d | ||
|
7d6b94b4c2 | ||
|
6911dfd7d6 | ||
|
42c43bb520 | ||
|
6b6c57887c | ||
|
1b0dd32cca | ||
|
32696e32bc | ||
|
7d8f597c86 | ||
|
a77734a600 | ||
|
7e49a0004b | ||
|
aab94f31c0 | ||
|
434bbfc409 | ||
|
148ed13b5e | ||
|
f772109c4d | ||
|
288aed8886 | ||
|
e56ed9a68a | ||
|
e6e3447c19 | ||
|
023fe19c6d | ||
|
449abea6b5 | ||
|
f1de0575d1 | ||
|
5c9177fa81 | ||
|
6c526f081f | ||
|
0ebee05092 | ||
|
93f22b7fd6 | ||
|
2873f3effd | ||
|
b3a1923a8f | ||
|
fe07cb1e6c | ||
|
c149ae6097 | ||
|
ac88f71c63 | ||
|
f2dec0e337 | ||
|
4fb77c6f5d | ||
|
ddfb6fb978 | ||
|
6a3e6c68be | ||
|
748e398c21 | ||
|
e663e7c0b0 | ||
|
2781d88abc | ||
|
58b8a58e86 | ||
|
f670eaf464 | ||
|
100ff7cabb | ||
|
d8df8830f1 | ||
|
8420935617 | ||
|
5655293cf8 | ||
|
303721fca2 | ||
|
8f13e0d60d | ||
|
0c95606e03 | ||
|
3b11aa9050 | ||
|
b2f4863231 | ||
|
aa0b2030c7 | ||
|
be495f2125 | ||
|
3897c52414 | ||
|
9e8c5e9914 | ||
|
cb9f84a61e | ||
|
838d22220a | ||
|
9a1f1a5689 | ||
|
8d3ff10db1 | ||
|
787cb39f81 | ||
|
934e00a1de | ||
|
8c47189e19 | ||
|
c82947b8b7 | ||
|
b4edea623b | ||
|
1b60c9bf8e | ||
|
613471f84c | ||
|
4be9cf08e7 | ||
|
84cd045d53 | ||
|
516fb55d1d | ||
|
4dd8db05b8 | ||
|
0bd0e19f05 | ||
|
62888cfec7 | ||
|
44e22c56f9 | ||
|
c207df96bb | ||
|
39f20fd3b1 | ||
|
02235cc3cb | ||
|
7d30be5087 | ||
|
332c5f908a | ||
|
4c3f1268aa | ||
|
ddf2704a42 | ||
|
f6824704c5 | ||
|
5eb6218708 | ||
|
10a2b621f4 | ||
|
51558b0b19 | ||
|
fe9ae3968b | ||
|
cbdea9c7c2 | ||
|
d4856f9680 | ||
|
8c5f77c4bd | ||
|
d85344df63 | ||
|
3db6bd6c54 | ||
|
fe5a2b35ee | ||
|
e06d1bf84b | ||
|
ad996cec9c | ||
|
94c795aa52 | ||
|
ac273b33f8 | ||
|
9b7912c39f | ||
|
36e0d38fc4 | ||
|
8d715ce9d6 | ||
|
6e87b3f004 | ||
|
bc652326a7 | ||
|
1c8b9a51e4 | ||
|
83a35b57c2 | ||
|
e43a4769be | ||
|
f213706f17 | ||
|
5a088a1a47 | ||
|
0cbaee9902 | ||
|
a67cfbbb30 | ||
|
2a0dc5aae9 | ||
|
d07689e2a7 | ||
|
5d1d6d31c3 | ||
|
03728a0155 | ||
|
715952ce0d | ||
|
de95e8b6ef | ||
|
cda1e94f8a | ||
|
7ec531f4e8 | ||
|
e48fccb6d0 | ||
|
e25c4dad06 | ||
|
89b9ef516a | ||
|
3efb4ea353 | ||
|
7a751a53f6 | ||
|
c0275d06eb | ||
|
e41a326ef5 | ||
|
ee03760c1d | ||
|
11f925abba | ||
|
015df061e3 | ||
|
db34aac811 | ||
|
051a3f8c01 | ||
|
666a8ec51b | ||
|
3092aaa821 | ||
|
c6666773d9 | ||
|
9961c4b895 | ||
|
e59f8bfd29 | ||
|
6850b933dc | ||
|
16b5a26306 | ||
|
4dd0e8ead8 | ||
|
78590d1823 | ||
|
b742da7751 | ||
|
add2b93657 | ||
|
4016ae5fb3 | ||
|
26e1f20262 | ||
|
2ed2bc67f0 | ||
|
1daeaa9308 | ||
|
d3eb6500f5 | ||
|
aef0eb93dd | ||
|
aba82ff427 | ||
|
831f2e252c | ||
|
ecf6b55baf | ||
|
34f2c96700 | ||
|
13e04a9f02 | ||
|
d4c9f0ad0c | ||
|
c460dcc52f | ||
|
6f65e6e8f5 | ||
|
5f5aeee472 | ||
|
bbd31c70a1 | ||
|
74152bbd9d | ||
|
81d40bd281 | ||
|
ec08477129 | ||
|
3bbca91391 | ||
|
6b6c045fbf | ||
|
e103873eb2 | ||
|
a3c0753b89 | ||
|
36ad7de2c5 | ||
|
d2eeef8291 | ||
|
814773b2e1 | ||
|
923fc92c7a | ||
|
d870116ae5 | ||
|
6eb48919ee | ||
|
aed6f06800 | ||
|
fe2502ed2d | ||
|
db7fe20a54 | ||
|
ed4e639d7e | ||
|
7e69d3c91c | ||
|
aec1d504fe | ||
|
a0cafba8c5 | ||
|
932df992e1 | ||
|
ba6606460d | ||
|
28860a8386 | ||
|
010fc621ca | ||
|
0562961d71 | ||
|
dfe2b6d3db | ||
|
1f8ac9108b | ||
|
7140ac64a3 | ||
|
1421b0b366 | ||
|
777ff460f8 | ||
|
04acbd2bfb | ||
|
486bb79ef7 | ||
|
92977daf75 | ||
|
66276373cd | ||
|
599e624b3a | ||
|
451deea533 | ||
|
7ef32ce6f0 | ||
|
5a666b5d29 | ||
|
46fefd63a1 | ||
|
fb62cb15b2 | ||
|
482b8741b7 | ||
|
e9fd1d8fc1 | ||
|
bad1c12112 | ||
|
781e6d1882 | ||
|
5d51c46fd6 | ||
|
7742386a84 | ||
|
ee47e61713 | ||
|
477e460858 | ||
|
2c7d194499 | ||
|
a75127d9aa | ||
|
fb036e3296 | ||
|
d447b3b4e4 | ||
|
77dc3a81f6 | ||
|
b5d54384f0 | ||
|
247a887a95 | ||
|
25c06ea4fb | ||
|
7cb38c90aa | ||
|
355b968257 | ||
|
7be938573e | ||
|
5fb7c2cac6 | ||
|
93d88ebfd4 | ||
|
5b61f80b97 | ||
|
c843dbc392 | ||
|
d54462a550 | ||
|
98ce614c3b | ||
|
5b758f9dad | ||
|
edda8c2604 | ||
|
ace86e6d01 | ||
|
65e2c09be1 | ||
|
e0a1668ffd | ||
|
97dbaa02cb | ||
|
55abf6aa0b | ||
|
1d3697e07e | ||
|
33e0151579 | ||
|
3370223f9f | ||
|
7cb2653a85 | ||
|
4ce25448af | ||
|
398102afa8 | ||
|
0e5484ce77 | ||
|
638535d650 | ||
|
ec639bc82c | ||
|
e601767e03 | ||
|
40c3686041 | ||
|
50284e8aad | ||
|
c841a140b3 | ||
|
999e291acc | ||
|
20d5d20855 | ||
|
230b04231c | ||
|
92a569fdb3 | ||
|
a4721bd02d | ||
|
11d8181d0d | ||
|
a2de30e4ce | ||
|
67f130c66c | ||
|
472a1d333a | ||
|
c074a19f24 | ||
|
63a7fa4aed | ||
|
57f1e839b7 |
168
.bzrignore
Normal file
168
.bzrignore
Normal file
@@ -0,0 +1,168 @@
|
||||
apparmor-*
|
||||
parser/po/*.mo
|
||||
parser/af_names.h
|
||||
parser/cap_names.h
|
||||
parser/tst_misc
|
||||
parser/tst_regex
|
||||
parser/tst_symtab
|
||||
parser/tst_variable
|
||||
parser/tst/simple_tests/generated_*/*
|
||||
parser/parser_lex.c
|
||||
parser/parser_version.h
|
||||
parser/parser_yacc.c
|
||||
parser/parser_yacc.h
|
||||
parser/pod2htm*.tmp
|
||||
parser/*.7
|
||||
parser/*.5
|
||||
parser/*.8
|
||||
parser/*.7.html
|
||||
parser/*.5.html
|
||||
parser/*.8.html
|
||||
parser/common
|
||||
parser/apparmor_parser
|
||||
parser/libapparmor_re/regexp.cc
|
||||
parser/techdoc.aux
|
||||
parser/techdoc.log
|
||||
parser/techdoc.pdf
|
||||
parser/techdoc.toc
|
||||
libraries/libapparmor/Makefile
|
||||
libraries/libapparmor/Makefile.in
|
||||
libraries/libapparmor/aclocal.m4
|
||||
libraries/libapparmor/audit.log
|
||||
libraries/libapparmor/autom4te.cache
|
||||
libraries/libapparmor/compile
|
||||
libraries/libapparmor/config.guess
|
||||
libraries/libapparmor/config.log
|
||||
libraries/libapparmor/config.status
|
||||
libraries/libapparmor/config.sub
|
||||
libraries/libapparmor/configure
|
||||
libraries/libapparmor/depcomp
|
||||
libraries/libapparmor/install-sh
|
||||
libraries/libapparmor/libtool
|
||||
libraries/libapparmor/ltmain.sh
|
||||
libraries/libapparmor/missing
|
||||
libraries/libapparmor/ylwrap
|
||||
libraries/libapparmor/doc/Makefile
|
||||
libraries/libapparmor/doc/Makefile.in
|
||||
libraries/libapparmor/doc/*.2
|
||||
libraries/libapparmor/src/.deps
|
||||
libraries/libapparmor/src/.libs
|
||||
libraries/libapparmor/src/Makefile
|
||||
libraries/libapparmor/src/Makefile.in
|
||||
libraries/libapparmor/src/af_protos.h
|
||||
libraries/libapparmor/src/change_hat.lo
|
||||
libraries/libapparmor/src/grammar.lo
|
||||
libraries/libapparmor/src/libaalogparse.lo
|
||||
libraries/libapparmor/src/libimmunix_warning.lo
|
||||
libraries/libapparmor/src/scanner.lo
|
||||
libraries/libapparmor/src/libapparmor.la
|
||||
libraries/libapparmor/src/libimmunix.la
|
||||
libraries/libapparmor/src/grammar.c
|
||||
libraries/libapparmor/src/grammar.h
|
||||
libraries/libapparmor/src/scanner.c
|
||||
libraries/libapparmor/src/scanner.h
|
||||
libraries/libapparmor/src/tst_aalogmisc
|
||||
libraries/libapparmor/swig/Makefile
|
||||
libraries/libapparmor/swig/Makefile.in
|
||||
libraries/libapparmor/swig/perl/LibAppArmor.bs
|
||||
libraries/libapparmor/swig/perl/LibAppArmor.pm
|
||||
libraries/libapparmor/swig/perl/Makefile
|
||||
libraries/libapparmor/swig/perl/Makefile.PL
|
||||
libraries/libapparmor/swig/perl/Makefile.in
|
||||
libraries/libapparmor/swig/perl/Makefile.perl
|
||||
libraries/libapparmor/swig/perl/blib
|
||||
libraries/libapparmor/swig/perl/libapparmor_wrap.c
|
||||
libraries/libapparmor/swig/perl/pm_to_blib
|
||||
libraries/libapparmor/swig/python/Makefile
|
||||
libraries/libapparmor/swig/python/Makefile.in
|
||||
libraries/libapparmor/swig/python/setup.py
|
||||
libraries/libapparmor/swig/ruby/Makefile
|
||||
libraries/libapparmor/swig/ruby/Makefile.in
|
||||
libraries/libapparmor/testsuite/.deps
|
||||
libraries/libapparmor/testsuite/.libs
|
||||
libraries/libapparmor/testsuite/Makefile
|
||||
libraries/libapparmor/testsuite/Makefile.in
|
||||
libraries/libapparmor/testsuite/libaalogparse.log
|
||||
libraries/libapparmor/testsuite/libaalogparse.sum
|
||||
libraries/libapparmor/testsuite/site.exp
|
||||
libraries/libapparmor/testsuite/test_multi.multi
|
||||
libraries/libapparmor/testsuite/config/Makefile
|
||||
libraries/libapparmor/testsuite/config/Makefile.in
|
||||
libraries/libapparmor/testsuite/lib/Makefile
|
||||
libraries/libapparmor/testsuite/lib/Makefile.in
|
||||
libraries/libapparmor/testsuite/libaalogparse.test/Makefile
|
||||
libraries/libapparmor/testsuite/libaalogparse.test/Makefile.in
|
||||
libraries/libapparmor/testsuite/test_multi/out
|
||||
changehat/mod_apparmor/.libs
|
||||
changehat/mod_apparmor/common
|
||||
changehat/pam_apparmor/common
|
||||
changehat/tomcat_apparmor/common
|
||||
utils/common
|
||||
utils/*.8
|
||||
utils/*.8.html
|
||||
utils/*.5
|
||||
utils/*.5.html
|
||||
utils/*.tmp
|
||||
utils/po/*.mo
|
||||
tests/regression/apparmor/access
|
||||
tests/regression/apparmor/changehat
|
||||
tests/regression/apparmor/changehat_fail
|
||||
tests/regression/apparmor/changehat_fork
|
||||
tests/regression/apparmor/changehat_misc
|
||||
tests/regression/apparmor/changehat_misc2
|
||||
tests/regression/apparmor/changehat_pthread
|
||||
tests/regression/apparmor/changehat_twice
|
||||
tests/regression/apparmor/changehat_wrapper
|
||||
tests/regression/apparmor/changeprofile
|
||||
tests/regression/apparmor/chdir
|
||||
tests/regression/apparmor/chgrp
|
||||
tests/regression/apparmor/chmod
|
||||
tests/regression/apparmor/chown
|
||||
tests/regression/apparmor/clone
|
||||
tests/regression/apparmor/deleted
|
||||
tests/regression/apparmor/env_check
|
||||
tests/regression/apparmor/environ
|
||||
tests/regression/apparmor/exec
|
||||
tests/regression/apparmor/exec_qual
|
||||
tests/regression/apparmor/exec_qual2
|
||||
tests/regression/apparmor/fchdir
|
||||
tests/regression/apparmor/fchgrp
|
||||
tests/regression/apparmor/fchmod
|
||||
tests/regression/apparmor/fchown
|
||||
tests/regression/apparmor/fork
|
||||
tests/regression/apparmor/link
|
||||
tests/regression/apparmor/link_subset
|
||||
tests/regression/apparmor/mkdir
|
||||
tests/regression/apparmor/mmap
|
||||
tests/regression/apparmor/mount
|
||||
tests/regression/apparmor/named_pipe
|
||||
tests/regression/apparmor/net_raw
|
||||
tests/regression/apparmor/open
|
||||
tests/regression/apparmor/openat
|
||||
tests/regression/apparmor/pipe
|
||||
tests/regression/apparmor/ptrace
|
||||
tests/regression/apparmor/ptrace_helper
|
||||
tests/regression/apparmor/pwrite
|
||||
tests/regression/apparmor/readdir
|
||||
tests/regression/apparmor/rename
|
||||
tests/regression/apparmor/rw
|
||||
tests/regression/apparmor/swap
|
||||
tests/regression/apparmor/symlink
|
||||
tests/regression/apparmor/syscall_chroot
|
||||
tests/regression/apparmor/syscall_mknod
|
||||
tests/regression/apparmor/syscall_mlockall
|
||||
tests/regression/apparmor/syscall_ptrace
|
||||
tests/regression/apparmor/syscall_reboot
|
||||
tests/regression/apparmor/syscall_setdomainname
|
||||
tests/regression/apparmor/syscall_sethostname
|
||||
tests/regression/apparmor/syscall_setpriority
|
||||
tests/regression/apparmor/syscall_setscheduler
|
||||
tests/regression/apparmor/syscall_sysctl
|
||||
tests/regression/apparmor/sysctl_proc
|
||||
tests/regression/apparmor/tcp
|
||||
tests/regression/apparmor/unix_fd_client
|
||||
tests/regression/apparmor/unix_fd_server
|
||||
tests/regression/apparmor/unlink
|
||||
tests/regression/apparmor/xattrs
|
||||
tests/regression/apparmor/coredump
|
||||
./utils/apparmor/__pycache__
|
68
Makefile
68
Makefile
@@ -1,5 +1,4 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
OVERRIDE_TARBALL=yes
|
||||
|
||||
@@ -8,31 +7,64 @@ include common/Make.rules
|
||||
DIRS=parser \
|
||||
profiles \
|
||||
utils \
|
||||
changehat/libapparmor \
|
||||
libraries/libapparmor \
|
||||
changehat/mod_apparmor \
|
||||
changehat/pam_apparmor \
|
||||
management/apparmor-dbus \
|
||||
management/applets/apparmorapplet-gnome \
|
||||
management/yastui \
|
||||
common \
|
||||
tests
|
||||
|
||||
RELEASE_DIR=apparmor-${VERSION}-${REPO_VERSION}
|
||||
#REPO_URL?=lp:apparmor
|
||||
# --per-file-timestamps is failing over SSH, https://bugs.launchpad.net/bzr/+bug/1257078
|
||||
REPO_URL?=https://code.launchpad.net/~apparmor-dev/apparmor/master
|
||||
# alternate possibilities to export from
|
||||
#REPO_URL=.
|
||||
#REPO_URL="bzr+ssh://bazaar.launchpad.net/~sbeattie/+junk/apparmor-dev/"
|
||||
|
||||
RELEASE_DIR=apparmor-${VERSION}
|
||||
__SETUP_DIR?=.
|
||||
|
||||
# We create a separate version for tags because git can't handle tags
|
||||
# with embedded ~s in them. No spaces around '-' or they'll get
|
||||
# embedded in ${VERSION}
|
||||
TAG_VERSION=$(subst ~,-,${VERSION})
|
||||
|
||||
# Add exclusion entries arguments for tar here, of the form:
|
||||
# --exclude dir_to_exclude --exclude other_dir
|
||||
TAR_EXCLUSIONS=
|
||||
|
||||
.PHONY: tarball
|
||||
tarball: _dist
|
||||
tar cvzf ${RELEASE_DIR}.tar.gz ${RELEASE_DIR}
|
||||
tarball: clean
|
||||
REPO_VERSION=`$(value REPO_VERSION_CMD)` ; \
|
||||
make export_dir __EXPORT_DIR=${RELEASE_DIR} __REPO_VERSION=$${REPO_VERSION} ; \
|
||||
make setup __SETUP_DIR=${RELEASE_DIR} ; \
|
||||
tar ${TAR_EXCLUSIONS} -cvzf ${RELEASE_DIR}.tar.gz ${RELEASE_DIR}
|
||||
|
||||
${RELEASE_DIR}:
|
||||
mkdir ${RELEASE_DIR}
|
||||
.PHONY: snapshot
|
||||
snapshot: clean
|
||||
REPO_VERSION=`$(value REPO_VERSION_CMD)` ; \
|
||||
SNAPSHOT_DIR=apparmor-${VERSION}~$${REPO_VERSION} ;\
|
||||
make export_dir __EXPORT_DIR=$${SNAPSHOT_DIR} __REPO_VERSION=$${REPO_VERSION} ; \
|
||||
make setup __SETUP_DIR=$${SNAPSHOT_DIR} ; \
|
||||
tar ${TAR_EXCLUSIONS} -cvzf $${SNAPSHOT_DIR}.tar.gz $${SNAPSHOT_DIR} ;
|
||||
|
||||
.PHONY: _dist
|
||||
.PHONY: ${DIRS}
|
||||
|
||||
_dist: clean ${DIRS}
|
||||
|
||||
${DIRS}: ${RELEASE_DIR}
|
||||
svn export -r $(REPO_VERSION) $(REPO_URL)/$@ $(RELEASE_DIR)/$@ ; \
|
||||
.PHONY: export_dir
|
||||
export_dir:
|
||||
mkdir $(__EXPORT_DIR)
|
||||
/usr/bin/bzr export --per-file-timestamps -r $(__REPO_VERSION) $(__EXPORT_DIR) $(REPO_URL)
|
||||
echo "$(REPO_URL) $(__REPO_VERSION)" > $(__EXPORT_DIR)/common/.stamp_rev
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
-rm -rf ${RELEASE_DIR}
|
||||
-rm -rf ${RELEASE_DIR} ./apparmor-${VERSION}~*
|
||||
for dir in $(DIRS); do \
|
||||
make -C $$dir clean; \
|
||||
done
|
||||
|
||||
.PHONY: setup
|
||||
setup:
|
||||
cd $(__SETUP_DIR)/libraries/libapparmor && ./autogen.sh
|
||||
|
||||
.PHONY: tag
|
||||
tag:
|
||||
bzr tag apparmor_${TAG_VERSION}
|
||||
|
||||
|
219
README
Normal file
219
README
Normal file
@@ -0,0 +1,219 @@
|
||||
------------
|
||||
Introduction
|
||||
------------
|
||||
AppArmor protects systems from insecure or untrusted processes by
|
||||
running them in restricted confinement, while still allowing processes
|
||||
to share files, exercise privilege and communicate with other processes.
|
||||
AppArmor is a Mandatory Access Control (MAC) mechanism which uses the
|
||||
Linux Security Module (LSM) framework. The confinement's restrictions
|
||||
are mandatory and are not bound to identity, group membership, or object
|
||||
ownership. The protections provided are in addition to the kernel's
|
||||
regular access control mechanisms (including DAC) and can be used to
|
||||
restrict the superuser.
|
||||
|
||||
The AppArmor kernel module and accompanying user-space tools are
|
||||
available under the GPL license (the exception is the libapparmor
|
||||
library, available under the LGPL license, which allows change_hat(2)
|
||||
and change_profile(2) to be used by non-GPL binaries).
|
||||
|
||||
For more information, you can read the techdoc.pdf (available after
|
||||
building the parser) and by visiting the http://apparmor.net/ web
|
||||
site.
|
||||
|
||||
|
||||
-------------
|
||||
Source Layout
|
||||
-------------
|
||||
|
||||
AppArmor consists of several different parts:
|
||||
|
||||
changehat/ source for using changehat with Apache, PAM and Tomcat
|
||||
common/ common makefile rules
|
||||
desktop/ empty
|
||||
kernel-patches/ compatibility patches for various kernel versions
|
||||
libraries/ libapparmor source and language bindings
|
||||
parser/ source for parser/loader and corresponding documentation
|
||||
profiles/ configuration files, reference profiles and abstractions
|
||||
tests/ regression and stress testsuites
|
||||
utils/ high-level utilities for working with AppArmor
|
||||
|
||||
--------------------------------------
|
||||
Important note on AppArmor kernel code
|
||||
--------------------------------------
|
||||
|
||||
While most of the kernel AppArmor code has been accepted in the
|
||||
upstream Linux kernel, a few important pieces were not included. These
|
||||
missing pieces unfortunately are important bits for AppArmor userspace
|
||||
and kernel interaction; therefore we have included compatibility
|
||||
patches in the kernel-patches/ subdirectory, versioned by upstream
|
||||
kernel (2.6.37 patches should apply cleanly to 2.6.38 source).
|
||||
|
||||
Without these patches applied to the kernel, the AppArmor userspace
|
||||
will not function correctly.
|
||||
|
||||
------------------------------------------
|
||||
Building and Installing AppArmor Userspace
|
||||
------------------------------------------
|
||||
|
||||
To build and install AppArmor userspace on your system, build and install in
|
||||
the following order.
|
||||
|
||||
|
||||
libapparmor:
|
||||
$ cd ./libraries/libapparmor
|
||||
$ sh ./autogen.sh
|
||||
$ sh ./configure --prefix=/usr --with-perl # see below
|
||||
$ make
|
||||
$ make check
|
||||
$ make install
|
||||
|
||||
[optional arguments to libapparmor's configure include --with-python
|
||||
and --with-ruby, to generate python and ruby bindings to libapparmor,
|
||||
respectively.]
|
||||
|
||||
|
||||
Utilities:
|
||||
$ cd utils
|
||||
$ make
|
||||
$ make check
|
||||
$ make install
|
||||
|
||||
|
||||
parser:
|
||||
$ cd parser
|
||||
$ make # depends on libapparmor having been built first
|
||||
$ make check
|
||||
$ make install
|
||||
|
||||
|
||||
Apache mod_apparmor:
|
||||
$ cd changehat/mod_apparmor
|
||||
$ make # depends on libapparmor having been built first
|
||||
$ make install
|
||||
|
||||
|
||||
PAM AppArmor:
|
||||
$ cd changehat/pam_apparmor
|
||||
$ make # depends on libapparmor having been built first
|
||||
$ make install
|
||||
|
||||
|
||||
Profiles:
|
||||
$ cd profiles
|
||||
$ make
|
||||
$ make check # depends on the parser having been built first
|
||||
$ make install
|
||||
|
||||
|
||||
[Note that for the parser and the utils, if you only with to build/use
|
||||
some of the locale languages, you can override the default by passing
|
||||
the LANGS arguments to make; e.g. make all install "LANGS=en_US fr".]
|
||||
|
||||
-------------------
|
||||
AppArmor Testsuites
|
||||
-------------------
|
||||
|
||||
A number of testsuites are in the AppArmor sources. Most have documentation on
|
||||
usage and how to update and add tests. Below is a quick overview of their
|
||||
location and how to run them.
|
||||
|
||||
|
||||
Regression tests
|
||||
----------------
|
||||
For details on structure and adding tests, see
|
||||
tests/regression/apparmor/README.
|
||||
|
||||
To run:
|
||||
$ cd tests/regression/apparmor (requires root)
|
||||
$ make
|
||||
$ sudo make tests
|
||||
$ sudo bash open.sh -r # runs and saves the last testcase from open.sh
|
||||
|
||||
|
||||
Parser tests
|
||||
------------
|
||||
For details on structure and adding tests, see parser/tst/README.
|
||||
|
||||
To run:
|
||||
$ cd parser/tst
|
||||
$ make
|
||||
$ make tests
|
||||
|
||||
|
||||
Libapparmor
|
||||
-----------
|
||||
For details on structure and adding tests, see libraries/libapparmor/README.
|
||||
$ cd libraries/libapparmor
|
||||
$ make check
|
||||
|
||||
Utils
|
||||
-----
|
||||
There are some simple tests available, including basic perl syntax
|
||||
checks for the perl modules and executables. There are also minimal
|
||||
checks on the python utilities and python-based tests in the test/
|
||||
subdirectory.
|
||||
$ cd utils
|
||||
$ make check
|
||||
|
||||
The aa-decode utility to be tested can be overridden by
|
||||
setting up environment variable APPARMOR_DECODE; e.g.:
|
||||
|
||||
$ APPARMOR_DECODE=/usr/bin/aa-decode make check
|
||||
|
||||
Profile checks
|
||||
--------------
|
||||
A basic consistency check to ensure that the parser and aa-logprof parse
|
||||
successfully the current set of shipped profiles. The system or other
|
||||
parser and logprof can be passed in by overriding the PARSER and LOGPROF
|
||||
variables.
|
||||
$ cd profiles
|
||||
$ make && make check
|
||||
|
||||
Stress Tests
|
||||
------------
|
||||
To run AppArmor stress tests:
|
||||
$ make all
|
||||
|
||||
Use these:
|
||||
$ ./change_hat
|
||||
$ ./child
|
||||
$ ./kill.sh
|
||||
$ ./open
|
||||
$ ./s.sh
|
||||
|
||||
Or run all at once:
|
||||
$ ./stress.sh
|
||||
|
||||
Please note that the above will stress the system so much it may end up
|
||||
invoking the OOM killer.
|
||||
|
||||
To run parser stress tests (requires /usr/bin/ruby):
|
||||
$ ./stress.sh
|
||||
|
||||
(see stress.sh -h for options)
|
||||
|
||||
-----------------------------------------------
|
||||
Building and Installing AppArmor Kernel Patches
|
||||
-----------------------------------------------
|
||||
|
||||
TODO
|
||||
|
||||
|
||||
-----------------
|
||||
Required versions
|
||||
-----------------
|
||||
|
||||
The AppArmor userspace utilities are written with some assumptions about
|
||||
installed and available versions of other tools. This is a (possibly
|
||||
incomplete) list of known version dependencies:
|
||||
|
||||
AppArmor.pm (used by aa-audit, aa-autodep, aa-complain, aa-disable,
|
||||
aa-enforce, aa-genprof, aa-logprof, aa-unconfined) requires minimum
|
||||
Perl 5.10.1.
|
||||
|
||||
Python scripts require a minimum of Python 2.7. Some utilities as well
|
||||
as some of the parser test scripts may require Python 3.3. Python 3.0,
|
||||
3.1, and 3.2 are largely untested.
|
||||
|
||||
Most shell scripts are written for POSIX-compatible sh. aa-decode expects
|
||||
bash, probably version 3.2 and higher.
|
@@ -1 +0,0 @@
|
||||
What little documentation exists is in src/aalogparse.h. Please file bugs using http://bugzilla.novell.com under the AppArmor product.
|
@@ -1,42 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
DIE=0
|
||||
|
||||
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "You must have autoconf installed to compile $package."
|
||||
echo "Download the appropriate package for your distribution,"
|
||||
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
|
||||
DIE=1
|
||||
}
|
||||
|
||||
(automake --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "You must have automake installed to compile $package."
|
||||
echo "Download the appropriate package for your system,"
|
||||
echo "or get the source from one of the GNU ftp sites"
|
||||
echo "listed in http://www.gnu.org/order/ftp.html"
|
||||
DIE=1
|
||||
}
|
||||
|
||||
(libtool --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "You must have libtool installed to compile $package."
|
||||
echo "Download the appropriate package for your system,"
|
||||
echo "or get the source from one of the GNU ftp sites"
|
||||
echo "listed in http://www.gnu.org/order/ftp.html"
|
||||
DIE=1
|
||||
}
|
||||
|
||||
if test "$DIE" -eq 1; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Running aclocal"
|
||||
aclocal
|
||||
echo "Running autoconf"
|
||||
autoconf --force
|
||||
echo "Running libtoolize"
|
||||
libtoolize --automake
|
||||
echo "Running automake -ac"
|
||||
automake -ac
|
@@ -1,77 +0,0 @@
|
||||
AC_INIT(configure.in)
|
||||
|
||||
AM_INIT_AUTOMAKE(libapparmor1, 2.2)
|
||||
|
||||
AM_PROG_LEX
|
||||
AC_PROG_YACC
|
||||
|
||||
AC_PATH_PROG([SWIG], [swig])
|
||||
|
||||
PROG_POD2MAN
|
||||
|
||||
AC_MSG_CHECKING(Checking for Python)
|
||||
AC_ARG_WITH(python,
|
||||
[ --with-python enable the python wrapper [[default=no]]],
|
||||
[AC_MSG_RESULT($withval)], [AC_MSG_RESULT(no)])
|
||||
if test "$with_python" = "yes"; then
|
||||
AC_PATH_PROG(PYTHON, python, no)
|
||||
if test x$PYTHON = xno; then
|
||||
enable_python = no
|
||||
else
|
||||
sinclude(m4/ac_python_devel.m4)
|
||||
AC_PYTHON_DEVEL
|
||||
AM_PATH_PYTHON
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(Checking for perl)
|
||||
AC_ARG_WITH(perl,
|
||||
[ --with-perl enable the perl wrapper [[default=no]]],
|
||||
[AC_MSG_RESULT($withval)], [AC_MSG_RESULT(no)])
|
||||
if test "$with_perl" = "yes"; then
|
||||
AC_PATH_PROG(PERL, perl, no)
|
||||
if test x$PERL = xno; then
|
||||
enable_perl=no
|
||||
else
|
||||
perl_includedir="`$PERL -e 'use Config; print $Config{archlib}'`/CORE"
|
||||
AC_CHECK_FILE($perl_includedir/perl.h, enable_perl=yes, enable_perl=no)
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
AC_MSG_CHECKING(Checking for ruby)
|
||||
AC_ARG_WITH(ruby,
|
||||
[ --with-ruby enable the ruby wrapper [[default=no]]],
|
||||
[AC_MSG_RESULT($withval)], [AC_MSG_RESULT(no)])
|
||||
if test "$with_ruby" = "yes"; then
|
||||
AC_PATH_PROG([RUBY], [ruby])
|
||||
fi
|
||||
|
||||
|
||||
AM_CONDITIONAL(HAVE_PYTHON, test x$with_python = xyes)
|
||||
AM_CONDITIONAL(HAVE_PERL, test x$with_perl = xyes)
|
||||
AM_CONDITIONAL(HAVE_RUBY, test x$with_ruby = xyes)
|
||||
AM_CONDITIONAL(BUILD_ROOTLIB, test x$enable_rootlib = xyes)
|
||||
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS(unistd.h stdint.h)
|
||||
|
||||
AC_CHECK_FUNCS(asprintf)
|
||||
|
||||
AM_PROG_CC_C_O
|
||||
AC_C_CONST
|
||||
AM_PROG_LIBTOOL
|
||||
|
||||
AC_OUTPUT(
|
||||
Makefile
|
||||
doc/Makefile
|
||||
src/Makefile
|
||||
swig/Makefile
|
||||
swig/perl/Makefile
|
||||
swig/python/Makefile
|
||||
swig/ruby/Makefile
|
||||
testsuite/Makefile
|
||||
testsuite/config/Makefile
|
||||
testsuite/libaalogparse.test/Makefile
|
||||
testsuite/lib/Makefile
|
||||
)
|
@@ -1,33 +0,0 @@
|
||||
INCLUDES = $(all_includes)
|
||||
|
||||
BUILT_SOURCES = grammar.h scanner.h
|
||||
AM_LFLAGS = -v
|
||||
AM_YFLAGS = -d -p aalogparse_
|
||||
AM_CFLAGS = @CFLAGS@ -D_GNU_SOURCE -Wall
|
||||
scanner.h: scanner.l
|
||||
$(LEX) -v $<
|
||||
|
||||
scanner.c: scanner.l
|
||||
|
||||
changehatdir = $(includedir)/sys
|
||||
changehat_HEADERS = apparmor.h
|
||||
|
||||
aalogparsedir = $(includedir)/aalogparse
|
||||
aalogparse_HEADERS = aalogparse.h
|
||||
|
||||
lib_LTLIBRARIES = libapparmor.la libimmunix.la
|
||||
noinst_HEADERS = grammar.h parser.h scanner.h
|
||||
|
||||
libapparmor_la_SOURCES = grammar.y libaalogparse.c change_hat.c scanner.c
|
||||
libapparmor_la_LDFLAGS = -version-info 1:2:0 -XCClinker -dynamic \
|
||||
-Wl,--version-script=libapparmor.map -Wl,-soname=libapparmor.so.1
|
||||
|
||||
libimmunix_la_SOURCES = change_hat.c libimmunix_warning.c
|
||||
libimmunix_la_LDFLAGS = -version-info 1:2:0 -Wl,--version-script=libapparmor.map -Wl,-soname=libimmunix.so.1
|
||||
|
||||
tst_aalogmisc_SOURCES = tst_aalogmisc.c
|
||||
tst_aalogmisc_LDADD = .libs/libapparmor.a
|
||||
check_PROGRAMS = tst_aalogmisc
|
||||
TESTS = $(check_PROGRAMS)
|
||||
|
||||
EXTRA_DIST = grammar.y scanner.l libapparmor.map
|
@@ -1,27 +0,0 @@
|
||||
/* $Id: apparmor.h 132 2006-09-28 07:45:55Z steve-beattie $
|
||||
|
||||
Copyright (c) 2003-2007 Novell, Inc. (All rights reserved)
|
||||
|
||||
The libapparmor library is licensed under the terms of the GNU
|
||||
Lesser General Public License, version 2.1. Please see the file
|
||||
COPYING.LGPL.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_APPARMOR_H_
|
||||
#define _SYS_APPARMOR_H 1
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* Prototype for change_hat as defined by the AppArmor project
|
||||
<http://forge.novell.com/modules/xfmod/project/?apparmor>
|
||||
Please see the change_hat(2) manpage for information. */
|
||||
|
||||
extern int (change_hat)(const char *subprofile, unsigned int magic_token);
|
||||
extern int aa_change_hat(const char *subprofile, unsigned long magic_token);
|
||||
extern int aa_change_profile(const char *profile);
|
||||
|
||||
#define change_hat(X, Y) aa_change_hat((X), (Y))
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* sys/apparmor.h */
|
@@ -1,134 +0,0 @@
|
||||
/* $Id: change_hat.c 13 2006-04-12 21:43:34Z steve-beattie $
|
||||
|
||||
Copyright (c) 2003-2007 Novell, Inc. (All rights reserved)
|
||||
|
||||
The libapparmor library is licensed under the terms of the GNU
|
||||
Lesser General Public License, version 2.1. Please see the file
|
||||
COPYING.LGPL.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define symbol_version(real, name, version) \
|
||||
__asm__ (".symver " #real "," #name "@" #version)
|
||||
#define default_symbol_version(real, name, version) \
|
||||
__asm__ (".symver " #real "," #name "@@" #version)
|
||||
|
||||
static int setprocattr(const char *buf, int len)
|
||||
{
|
||||
int rc = -1;
|
||||
int fd, ret, ctlerr = 0;
|
||||
char *ctl = NULL;
|
||||
pid_t tid = syscall(SYS_gettid);
|
||||
|
||||
if (!buf) {
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctlerr = asprintf(&ctl, "/proc/%d/attr/current", tid);
|
||||
if (ctlerr < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd = open(ctl, O_WRONLY);
|
||||
if (fd == -1) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = write(fd, buf, len);
|
||||
if (ret != len) {
|
||||
int saved;
|
||||
if (ret != -1) {
|
||||
errno = EPROTO;
|
||||
}
|
||||
saved = errno;
|
||||
(void)close(fd);
|
||||
errno = saved;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
(void)close(fd);
|
||||
|
||||
out:
|
||||
if (ctl) {
|
||||
free(ctl);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int aa_change_hat(const char *subprofile, unsigned long token)
|
||||
{
|
||||
int rc = -1;
|
||||
int len = 0;
|
||||
char *buf = NULL;
|
||||
const char *fmt = "changehat %016x^%s";
|
||||
|
||||
/* both may not be null */
|
||||
if (!(token || subprofile)) {
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (subprofile && strnlen(subprofile, PATH_MAX + 1) > PATH_MAX) {
|
||||
errno = EPROTO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = asprintf(&buf, fmt, token, subprofile ? subprofile : "");
|
||||
if (len < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = setprocattr(buf, len);
|
||||
out:
|
||||
if (buf) {
|
||||
/* clear local copy of magic token before freeing */
|
||||
memset(buf, '\0', len);
|
||||
free(buf);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* original change_hat interface */
|
||||
int __change_hat(char *subprofile, unsigned int token)
|
||||
{
|
||||
return aa_change_hat(subprofile, (unsigned long) token);
|
||||
}
|
||||
|
||||
int aa_change_profile(const char *profile)
|
||||
{
|
||||
char *buf = NULL;
|
||||
int len;
|
||||
int rc;
|
||||
|
||||
if (!profile) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = asprintf(&buf, "changeprofile %s", profile);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
rc = setprocattr(buf, len);
|
||||
|
||||
free(buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* create an alias for the old change_hat@IMMUNIX_1.0 symbol */
|
||||
extern typeof((__change_hat)) __old_change_hat __attribute__((alias ("__change_hat")));
|
||||
symbol_version(__old_change_hat, change_hat, IMMUNIX_1.0);
|
||||
default_symbol_version(__change_hat, change_hat, APPARMOR_1.0);
|
@@ -1,438 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
* NOVELL (All rights reserved)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact Novell, Inc.
|
||||
*/
|
||||
|
||||
|
||||
%{
|
||||
|
||||
#define YYDEBUG 0
|
||||
#include <string.h>
|
||||
#include "aalogparse.h"
|
||||
#include "parser.h"
|
||||
#include "grammar.h"
|
||||
#include "scanner.h"
|
||||
|
||||
aa_log_record *ret_record;
|
||||
|
||||
/* 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
|
||||
* emit messages when asked for. */
|
||||
void aalogparse_error(void *scanner, char const *s)
|
||||
{
|
||||
/* printf("Error: %s\n", s); */
|
||||
ret_record->event = AA_RECORD_INVALID;
|
||||
}
|
||||
|
||||
struct aa_type_table {
|
||||
unsigned int audit_type;
|
||||
aa_record_event_type event;
|
||||
};
|
||||
|
||||
static struct aa_type_table aa_type_table[] = {
|
||||
{AUDIT_APPARMOR_AUDIT, AA_RECORD_AUDIT},
|
||||
{AUDIT_APPARMOR_ALLOWED, AA_RECORD_ALLOWED},
|
||||
{AUDIT_APPARMOR_DENIED, AA_RECORD_DENIED},
|
||||
{AUDIT_APPARMOR_HINT, AA_RECORD_HINT},
|
||||
{AUDIT_APPARMOR_STATUS, AA_RECORD_STATUS},
|
||||
{AUDIT_APPARMOR_ERROR, AA_RECORD_ERROR},
|
||||
{0, AA_RECORD_INVALID},
|
||||
};
|
||||
|
||||
aa_record_event_type lookup_aa_event(unsigned int type)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; aa_type_table[i].audit_type != 0; i++)
|
||||
if (type == aa_type_table[i].audit_type)
|
||||
break;
|
||||
|
||||
return aa_type_table[i].event;
|
||||
}
|
||||
%}
|
||||
|
||||
%defines
|
||||
%pure_parser
|
||||
%lex-param{void *scanner}
|
||||
%parse-param{void *scanner}
|
||||
|
||||
%union
|
||||
{
|
||||
char *t_str;
|
||||
long t_long;
|
||||
}
|
||||
|
||||
%type <t_str> old_profile safe_string protocol
|
||||
%token <t_long> TOK_DIGITS TOK_TYPE_UNKNOWN
|
||||
%token <t_str> TOK_QUOTED_STRING TOK_PATH TOK_ID TOK_NULL_COMPLAIN TOK_MODE TOK_DMESG_STAMP
|
||||
%token <t_str> TOK_SINGLE_QUOTED_STRING TOK_AUDIT_DIGITS TOK_DATE_MONTH TOK_DATE_TIME
|
||||
%token <t_str> TOK_HEXSTRING TOK_TYPE_OTHER TOK_MSG_REST
|
||||
|
||||
%token TOK_EQUALS
|
||||
%token TOK_COLON
|
||||
%token TOK_OPEN_PAREN
|
||||
%token TOK_CLOSE_PAREN
|
||||
%token TOK_PERIOD
|
||||
|
||||
%token TOK_TYPE_REJECT
|
||||
%token TOK_TYPE_AUDIT
|
||||
%token TOK_TYPE_COMPLAIN
|
||||
%token TOK_TYPE_HINT
|
||||
%token TOK_TYPE_STATUS
|
||||
%token TOK_TYPE_ERROR
|
||||
%token TOK_OLD_TYPE_APPARMOR
|
||||
%token TOK_OLD_APPARMOR_REJECT
|
||||
%token TOK_OLD_APPARMOR_PERMIT
|
||||
%token TOK_OLD_APPARMOR_AUDIT
|
||||
%token TOK_OLD_APPARMOR_LOGPROF_HINT
|
||||
%token TOK_OLD_UNKNOWN_HAT
|
||||
%token TOK_OLD_ACTIVE
|
||||
%token TOK_OLD_UNKNOWN_PROFILE
|
||||
%token TOK_OLD_MISSING_PROFILE
|
||||
%token TOK_OLD_CHANGING_PROFILE
|
||||
%token TOK_OLD_ACCESS
|
||||
%token TOK_OLD_TO
|
||||
%token TOK_OLD_FROM
|
||||
%token TOK_OLD_PIPE
|
||||
%token TOK_OLD_EXTENDED
|
||||
%token TOK_OLD_ATTRIBUTE
|
||||
%token TOK_OLD_ON
|
||||
%token TOK_OLD_MKDIR
|
||||
%token TOK_OLD_RMDIR
|
||||
%token TOK_OLD_XATTR
|
||||
%token TOK_OLD_CHANGE
|
||||
%token TOK_OLD_CAPABILITY
|
||||
%token TOK_OLD_SYSCALL
|
||||
%token TOK_OLD_LINK
|
||||
%token TOK_OLD_FORK
|
||||
%token TOK_OLD_CHILD
|
||||
|
||||
%token TOK_KEY_TYPE
|
||||
%token TOK_KEY_MSG
|
||||
%token TOK_KEY_OPERATION
|
||||
%token TOK_KEY_NAME
|
||||
%token TOK_KEY_NAME2
|
||||
%token TOK_KEY_DENIED_MASK
|
||||
%token TOK_KEY_REQUESTED_MASK
|
||||
%token TOK_KEY_ATTRIBUTE
|
||||
%token TOK_KEY_TASK
|
||||
%token TOK_KEY_PARENT
|
||||
%token TOK_KEY_MAGIC_TOKEN
|
||||
%token TOK_KEY_INFO
|
||||
%token TOK_KEY_PID
|
||||
%token TOK_KEY_PROFILE
|
||||
%token TOK_AUDIT
|
||||
%token TOK_KEY_IMAGE
|
||||
%token TOK_KEY_FAMILY
|
||||
%token TOK_KEY_SOCK_TYPE
|
||||
%token TOK_KEY_PROTOCOL
|
||||
|
||||
%token TOK_SYSLOG_KERNEL
|
||||
|
||||
%%
|
||||
|
||||
log_message: audit_type
|
||||
| syslog_type
|
||||
;
|
||||
|
||||
audit_type: TOK_KEY_TYPE TOK_EQUALS type_syntax ;
|
||||
|
||||
type_syntax: old_syntax { ret_record->version = AA_RECORD_SYNTAX_V1; }
|
||||
| new_syntax { ret_record->version = AA_RECORD_SYNTAX_V2; }
|
||||
| other_audit
|
||||
;
|
||||
|
||||
old_syntax: TOK_OLD_TYPE_APPARMOR audit_msg old_msg
|
||||
| TOK_TYPE_UNKNOWN audit_msg old_msg
|
||||
;
|
||||
|
||||
new_syntax:
|
||||
TOK_TYPE_REJECT audit_msg key_list { ret_record->event = AA_RECORD_DENIED; }
|
||||
| TOK_TYPE_AUDIT audit_msg key_list { ret_record->event = AA_RECORD_AUDIT; }
|
||||
| TOK_TYPE_COMPLAIN audit_msg key_list { ret_record->event = AA_RECORD_ALLOWED; }
|
||||
| TOK_TYPE_HINT audit_msg key_list { ret_record->event = AA_RECORD_HINT; }
|
||||
| TOK_TYPE_STATUS audit_msg key_list { ret_record->event = AA_RECORD_STATUS; }
|
||||
| TOK_TYPE_ERROR audit_msg key_list { ret_record->event = AA_RECORD_ERROR; }
|
||||
| TOK_TYPE_UNKNOWN audit_msg key_list { ret_record->event = lookup_aa_event($1); }
|
||||
;
|
||||
|
||||
other_audit: TOK_TYPE_OTHER audit_msg TOK_MSG_REST
|
||||
{
|
||||
ret_record->operation = $1;
|
||||
ret_record->event = AA_RECORD_INVALID;
|
||||
ret_record->info = $3;
|
||||
}
|
||||
;
|
||||
|
||||
syslog_type:
|
||||
syslog_date TOK_ID TOK_SYSLOG_KERNEL audit_id old_msg
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V1; }
|
||||
| syslog_date TOK_ID TOK_SYSLOG_KERNEL audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; }
|
||||
| syslog_date TOK_ID TOK_SYSLOG_KERNEL TOK_DMESG_STAMP audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; }
|
||||
;
|
||||
|
||||
old_msg:
|
||||
old_permit_reject_type old_permit_reject_syntax
|
||||
| TOK_OLD_APPARMOR_LOGPROF_HINT old_logprof_syntax { ret_record->event = AA_RECORD_HINT; }
|
||||
;
|
||||
|
||||
old_permit_reject_type:
|
||||
TOK_OLD_APPARMOR_REJECT { ret_record->event = AA_RECORD_DENIED; }
|
||||
| TOK_OLD_APPARMOR_PERMIT { ret_record->event = AA_RECORD_ALLOWED; }
|
||||
| TOK_OLD_APPARMOR_AUDIT { ret_record->event = AA_RECORD_AUDIT; }
|
||||
;
|
||||
|
||||
old_permit_reject_syntax:
|
||||
TOK_MODE TOK_OLD_ACCESS old_permit_reject_path_pipe_extended
|
||||
TOK_OPEN_PAREN old_process_state TOK_CLOSE_PAREN
|
||||
{
|
||||
ret_record->requested_mask = $1;
|
||||
ret_record->operation = strdup("access");
|
||||
}
|
||||
| dir_action TOK_OLD_ON TOK_PATH
|
||||
TOK_OPEN_PAREN old_process_state TOK_CLOSE_PAREN
|
||||
{
|
||||
ret_record->name = $3;
|
||||
}
|
||||
| TOK_OLD_XATTR TOK_ID TOK_OLD_ON TOK_PATH
|
||||
TOK_OPEN_PAREN old_process_state TOK_CLOSE_PAREN
|
||||
{
|
||||
ret_record->operation = strdup("xattr");
|
||||
ret_record->attribute = $2;
|
||||
ret_record->name = $4;
|
||||
}
|
||||
| TOK_KEY_ATTRIBUTE TOK_OPEN_PAREN TOK_ID TOK_CLOSE_PAREN
|
||||
TOK_OLD_CHANGE TOK_OLD_TO TOK_PATH
|
||||
TOK_OPEN_PAREN old_process_state TOK_CLOSE_PAREN
|
||||
{
|
||||
ret_record->operation = strdup("setattr");
|
||||
ret_record->attribute = $3;
|
||||
ret_record->name = $7;
|
||||
}
|
||||
| TOK_OLD_ACCESS TOK_OLD_TO TOK_OLD_CAPABILITY TOK_SINGLE_QUOTED_STRING
|
||||
TOK_OPEN_PAREN old_process_state TOK_CLOSE_PAREN
|
||||
{
|
||||
ret_record->operation = strdup("capability");
|
||||
ret_record->name = $4;
|
||||
}
|
||||
| TOK_OLD_ACCESS TOK_OLD_TO TOK_OLD_SYSCALL TOK_SINGLE_QUOTED_STRING
|
||||
TOK_OPEN_PAREN old_process_state TOK_CLOSE_PAREN
|
||||
{
|
||||
ret_record->operation = strdup("syscall");
|
||||
ret_record->name = $4;
|
||||
}
|
||||
| TOK_OLD_LINK TOK_OLD_ACCESS TOK_OLD_FROM TOK_PATH TOK_OLD_TO TOK_PATH
|
||||
TOK_OPEN_PAREN old_process_state TOK_CLOSE_PAREN
|
||||
{
|
||||
ret_record->requested_mask = strdup("l");
|
||||
ret_record->name = $4;
|
||||
ret_record->name2 = $6;
|
||||
}
|
||||
;
|
||||
|
||||
dir_action:
|
||||
TOK_OLD_MKDIR { ret_record->operation = strdup("mkdir"); }
|
||||
| TOK_OLD_RMDIR { ret_record->operation = strdup("rmdir"); }
|
||||
;
|
||||
|
||||
old_process_state:
|
||||
TOK_ID TOK_OPEN_PAREN TOK_ID TOK_CLOSE_PAREN old_profile_names
|
||||
{
|
||||
ret_record->info = $1;
|
||||
ret_record->pid = atol($3);
|
||||
free($3);
|
||||
}
|
||||
;
|
||||
|
||||
old_profile_names:
|
||||
TOK_KEY_PROFILE old_profile TOK_OLD_ACTIVE old_profile
|
||||
{ ret_record->profile = $2;
|
||||
ret_record->active_hat = $4;
|
||||
}
|
||||
;
|
||||
|
||||
old_permit_reject_path_pipe_extended:
|
||||
TOK_OLD_TO TOK_PATH
|
||||
{
|
||||
ret_record->name = $2;
|
||||
}
|
||||
| TOK_OLD_TO TOK_OLD_PIPE /* Frankly, I don't think this is used */
|
||||
{
|
||||
ret_record->info = strdup("pipe");
|
||||
}
|
||||
| TOK_OLD_EXTENDED TOK_KEY_ATTRIBUTE /* Nor this */
|
||||
{
|
||||
ret_record->info = strdup("extended attribute");
|
||||
}
|
||||
;
|
||||
old_logprof_syntax:
|
||||
old_logprof_syntax2 key_pid
|
||||
TOK_KEY_PROFILE TOK_EQUALS old_profile TOK_OLD_ACTIVE TOK_EQUALS old_profile
|
||||
{
|
||||
ret_record->profile = strdup($5);
|
||||
free($5);
|
||||
ret_record->active_hat = strdup($8);
|
||||
free($8);
|
||||
}
|
||||
| old_logprof_fork_syntax
|
||||
| TOK_OLD_CHANGING_PROFILE key_pid
|
||||
{ ret_record->profile = strdup("null-complain-profile"); }
|
||||
;
|
||||
|
||||
old_logprof_syntax2:
|
||||
TOK_OLD_UNKNOWN_PROFILE TOK_KEY_IMAGE TOK_EQUALS TOK_ID
|
||||
{
|
||||
ret_record->operation = strdup("profile_set");
|
||||
ret_record->info = strdup("unknown profile");
|
||||
ret_record->name = strdup($4);
|
||||
free($4);
|
||||
}
|
||||
| TOK_OLD_MISSING_PROFILE TOK_KEY_IMAGE TOK_EQUALS TOK_ID
|
||||
{
|
||||
ret_record->operation = strdup("exec");
|
||||
ret_record->info = strdup("mandatory profile missing");
|
||||
ret_record->name = strdup($4);
|
||||
free($4);
|
||||
}
|
||||
| TOK_OLD_UNKNOWN_HAT TOK_ID
|
||||
{
|
||||
ret_record->operation = strdup("change_hat");
|
||||
ret_record->name = strdup($2);
|
||||
free($2);
|
||||
ret_record->info = strdup("unknown_hat");
|
||||
}
|
||||
;
|
||||
|
||||
/* TODO: Clean this up */
|
||||
old_logprof_fork_syntax:
|
||||
TOK_OLD_FORK key_pid
|
||||
TOK_OLD_CHILD TOK_EQUALS TOK_DIGITS old_logprof_fork_addition
|
||||
{
|
||||
ret_record->operation = strdup("clone");
|
||||
ret_record->task = $5;
|
||||
}
|
||||
;
|
||||
|
||||
old_logprof_fork_addition:
|
||||
/* Nothin */
|
||||
| TOK_KEY_PROFILE TOK_EQUALS old_profile TOK_OLD_ACTIVE TOK_EQUALS old_profile
|
||||
{
|
||||
ret_record->profile = $3;
|
||||
ret_record->active_hat = $6;
|
||||
}
|
||||
;
|
||||
|
||||
old_profile:
|
||||
TOK_PATH { $$ = $1; }
|
||||
| TOK_ID { $$ = $1; }
|
||||
| TOK_NULL_COMPLAIN { $$ = strdup("null-complain-profile"); }
|
||||
;
|
||||
|
||||
audit_msg: TOK_KEY_MSG TOK_EQUALS audit_id
|
||||
;
|
||||
|
||||
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
|
||||
{
|
||||
asprintf(&ret_record->audit_id, "%s.%s:%s", $3, $5, $7);
|
||||
ret_record->epoch = atol($3);
|
||||
ret_record->audit_sub_id = atoi($7);
|
||||
free($3);
|
||||
free($5);
|
||||
free($7);
|
||||
} ;
|
||||
|
||||
syslog_date: TOK_DATE_MONTH TOK_DIGITS TOK_DATE_TIME { /* do nothing? */ }
|
||||
;
|
||||
|
||||
key_list: key
|
||||
| key_list key
|
||||
;
|
||||
|
||||
key: TOK_KEY_OPERATION TOK_EQUALS TOK_QUOTED_STRING
|
||||
{ ret_record->operation = $3;}
|
||||
| TOK_KEY_NAME TOK_EQUALS safe_string
|
||||
{ ret_record->name = $3;}
|
||||
| TOK_KEY_NAME2 TOK_EQUALS safe_string
|
||||
{ ret_record->name2 = $3;}
|
||||
| TOK_KEY_DENIED_MASK TOK_EQUALS TOK_QUOTED_STRING
|
||||
{ ret_record->denied_mask = $3;}
|
||||
| TOK_KEY_REQUESTED_MASK TOK_EQUALS TOK_QUOTED_STRING
|
||||
{ ret_record->requested_mask = $3;}
|
||||
| TOK_KEY_ATTRIBUTE TOK_EQUALS TOK_QUOTED_STRING
|
||||
{ ret_record->attribute = $3;}
|
||||
| TOK_KEY_TASK TOK_EQUALS TOK_DIGITS
|
||||
{ ret_record->task = $3;}
|
||||
| TOK_KEY_PARENT TOK_EQUALS TOK_DIGITS
|
||||
{ ret_record->parent = $3;}
|
||||
| TOK_KEY_MAGIC_TOKEN TOK_EQUALS TOK_DIGITS
|
||||
{ ret_record->magic_token = $3;}
|
||||
| TOK_KEY_INFO TOK_EQUALS TOK_QUOTED_STRING
|
||||
{ ret_record->info = $3;}
|
||||
| key_pid
|
||||
| TOK_KEY_PROFILE TOK_EQUALS safe_string
|
||||
{ ret_record->profile = $3;}
|
||||
| TOK_KEY_FAMILY TOK_EQUALS TOK_QUOTED_STRING
|
||||
{ ret_record->net_family = $3;}
|
||||
| TOK_KEY_SOCK_TYPE TOK_EQUALS TOK_QUOTED_STRING
|
||||
{ ret_record->net_sock_type = $3;}
|
||||
| TOK_KEY_PROTOCOL TOK_EQUALS protocol
|
||||
{ ret_record->net_protocol = $3;}
|
||||
| TOK_KEY_TYPE TOK_EQUALS TOK_DIGITS
|
||||
{ ret_record->event = lookup_aa_event($3);}
|
||||
;
|
||||
|
||||
key_pid: TOK_KEY_PID TOK_EQUALS TOK_DIGITS { ret_record->pid = $3; }
|
||||
;
|
||||
|
||||
safe_string: TOK_QUOTED_STRING
|
||||
| TOK_HEXSTRING
|
||||
;
|
||||
|
||||
protocol: TOK_QUOTED_STRING
|
||||
| TOK_DIGITS
|
||||
{ /* FIXME: this should probably convert back to a string proto name */
|
||||
char *ret = NULL;
|
||||
if (asprintf(&ret, "%ld", $1) < 0)
|
||||
yyerror(NULL, "Unable to allocate protocol string");
|
||||
$$ = ret;
|
||||
}
|
||||
;
|
||||
%%
|
||||
|
||||
aa_log_record *
|
||||
_parse_yacc(char *str)
|
||||
{
|
||||
/* yydebug = 1; */
|
||||
YY_BUFFER_STATE lex_buf;
|
||||
yyscan_t scanner;
|
||||
int parser_return;
|
||||
|
||||
ret_record = NULL;
|
||||
ret_record = (aa_log_record *) malloc(sizeof(aa_log_record));
|
||||
|
||||
_init_log_record(ret_record);
|
||||
|
||||
if (ret_record == NULL)
|
||||
return NULL;
|
||||
|
||||
aalogparse_lex_init(&scanner);
|
||||
lex_buf = aalogparse__scan_string(str, scanner);
|
||||
parser_return = aalogparse_parse(scanner);
|
||||
aalogparse__delete_buffer(lex_buf, scanner);
|
||||
aalogparse_lex_destroy(scanner);
|
||||
return ret_record;
|
||||
}
|
@@ -1,139 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
* NOVELL (All rights reserved)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact Novell, Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author Matt Barringer <mbarringer@suse.de>
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
*
|
||||
* - Convert the text permission mask into a bitmask
|
||||
* - Clean up parser grammar
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "aalogparse.h"
|
||||
#include "parser.h"
|
||||
|
||||
/* This is mostly just a wrapper around the code in grammar.y */
|
||||
aa_log_record *parse_record(char *str)
|
||||
{
|
||||
if (str == NULL)
|
||||
return NULL;
|
||||
|
||||
return _parse_yacc(str);
|
||||
}
|
||||
|
||||
void free_record(aa_log_record *record)
|
||||
{
|
||||
if (record != NULL)
|
||||
{
|
||||
if (record->operation != NULL)
|
||||
free(record->operation);
|
||||
if (record->requested_mask != NULL)
|
||||
free(record->requested_mask);
|
||||
if (record->denied_mask != NULL)
|
||||
free(record->denied_mask);
|
||||
if (record->profile != NULL)
|
||||
free(record->profile);
|
||||
if (record->name != NULL)
|
||||
free(record->name);
|
||||
if (record->name2 != NULL)
|
||||
free(record->name2);
|
||||
if (record->attribute != NULL)
|
||||
free(record->attribute);
|
||||
if (record->info != NULL)
|
||||
free(record->info);
|
||||
if (record->active_hat != NULL)
|
||||
free(record->active_hat);
|
||||
if (record->audit_id != NULL)
|
||||
free(record->audit_id);
|
||||
if (record->net_family != NULL)
|
||||
free(record->net_family);
|
||||
if (record->net_protocol != NULL)
|
||||
free(record->net_protocol);
|
||||
if (record->net_sock_type != NULL)
|
||||
free(record->net_sock_type);
|
||||
|
||||
free(record);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set all of the fields to appropriate values */
|
||||
void _init_log_record(aa_log_record *record)
|
||||
{
|
||||
if (record == NULL)
|
||||
return;
|
||||
|
||||
record->version = AA_RECORD_SYNTAX_UNKNOWN;
|
||||
record->event = AA_RECORD_INVALID;
|
||||
record->pid = 0;
|
||||
record->bitmask = 0;
|
||||
record->task = 0;
|
||||
record->magic_token = 0;
|
||||
record->epoch = 0;
|
||||
record->audit_sub_id = 0;
|
||||
|
||||
record->audit_id = NULL;
|
||||
record->operation = NULL;
|
||||
record->denied_mask = NULL;
|
||||
record->requested_mask = NULL;
|
||||
record->profile = NULL;
|
||||
record->name = NULL;
|
||||
record->name2 = NULL;
|
||||
record->attribute = NULL;
|
||||
record->parent = 0;
|
||||
record->info = NULL;
|
||||
record->active_hat = NULL;
|
||||
record->net_family = NULL;
|
||||
record->net_protocol = NULL;
|
||||
record->net_sock_type = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* convert a hex-encoded string to its char* version */
|
||||
char *hex_to_string(char *hexstring)
|
||||
{
|
||||
char *ret = NULL;
|
||||
char buf[3], *endptr;
|
||||
size_t len;
|
||||
int i;
|
||||
|
||||
if (!hexstring)
|
||||
goto out;
|
||||
|
||||
len = strlen(hexstring) / 2;
|
||||
ret = malloc(len + 1);
|
||||
if (!ret)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
sprintf(buf, "%.2s", hexstring);
|
||||
hexstring += 2;
|
||||
ret[i] = (unsigned char) strtoul(buf, &endptr, 16);
|
||||
}
|
||||
ret[len] = '\0';
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
@@ -1,25 +0,0 @@
|
||||
IMMUNIX_1.0 {
|
||||
global:
|
||||
change_hat;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
||||
APPARMOR_1.0 {
|
||||
global:
|
||||
change_hat;
|
||||
parse_record;
|
||||
free_record;
|
||||
local:
|
||||
*;
|
||||
} IMMUNIX_1.0;
|
||||
|
||||
APPARMOR_1.1 {
|
||||
global:
|
||||
aa_change_hat;
|
||||
aa_change_profile;
|
||||
parse_record;
|
||||
free_record;
|
||||
local:
|
||||
*;
|
||||
} APPARMOR_1.0;
|
@@ -1,23 +0,0 @@
|
||||
/* $Id: libimmunix_warning.c 13 2006-04-12 21:43:34Z steve-beattie $
|
||||
|
||||
Copyright (c) 2006 Novell, Inc. (All rights reserved)
|
||||
The libimmunix library is licensed under the terms of the GNU
|
||||
Lesser General Public License, version 2.1. Please see the file
|
||||
COPYING.LGPL.
|
||||
|
||||
*/
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
void __libimmunix_warning(void) __attribute__ ((constructor));
|
||||
void __libimmunix_warning(void)
|
||||
{
|
||||
extern const char *__progname; /* global from linux crt0 */
|
||||
openlog (__progname, LOG_PID|LOG_PERROR, LOG_USER);
|
||||
syslog(LOG_NOTICE,
|
||||
"%s links against libimmunix.so, which is deprecated. "
|
||||
"Please link against libapparmor instead\n",
|
||||
__progname);
|
||||
closelog();
|
||||
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
* NOVELL (All rights reserved)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact Novell, Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __AA_LOG_PARSER_H__
|
||||
#define __AA_LOG_PARSER_H__
|
||||
|
||||
extern void _init_log_record(aa_log_record *record);
|
||||
extern aa_log_record *_parse_yacc(char *str);
|
||||
extern char *hex_to_string(char *str);
|
||||
|
||||
/* FIXME: this ought to be pulled from <linux/audit.h> but there's no
|
||||
* guarantee these will exist there. */
|
||||
#define AUDIT_APPARMOR_AUDIT 1501 /* AppArmor audited grants */
|
||||
#define AUDIT_APPARMOR_ALLOWED 1502 /* Allowed Access for learning */
|
||||
#define AUDIT_APPARMOR_DENIED 1503
|
||||
#define AUDIT_APPARMOR_HINT 1504 /* Process Tracking information */
|
||||
#define AUDIT_APPARMOR_STATUS 1505 /* Changes in config */
|
||||
#define AUDIT_APPARMOR_ERROR 1506 /* Internal AppArmor Errors */
|
||||
|
||||
#endif
|
||||
|
@@ -1,320 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
* NOVELL (All rights reserved)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact Novell, Inc.
|
||||
*/
|
||||
|
||||
%option noyywrap
|
||||
%option reentrant
|
||||
%option prefix="aalogparse_"
|
||||
%option bison-bridge
|
||||
%option header-file="scanner.h"
|
||||
%option outfile="scanner.c"
|
||||
%option stack
|
||||
%{
|
||||
|
||||
#include "grammar.h"
|
||||
#include "aalogparse.h"
|
||||
#include "parser.h"
|
||||
%}
|
||||
|
||||
ws [ \t\r\n]
|
||||
|
||||
equals "="
|
||||
digits [0-9]+
|
||||
hex [A-F0-9]
|
||||
colon ":"
|
||||
open_paren "("
|
||||
close_paren ")"
|
||||
ID [^ \t\n\(\)="'!]
|
||||
path "/"{ID}*
|
||||
hexstring ({hex}{hex})+
|
||||
period "\."
|
||||
mode_chars ([RrWwLalMmkXx])|([Pp][Xx])|([Uu][Xx])|([Ii][Xx])
|
||||
modes {mode_chars}+
|
||||
|
||||
/* New message types */
|
||||
|
||||
reject_type "APPARMOR_DENIED"
|
||||
audit_type "APPARMOR_AUDIT"
|
||||
complain_type "APPARMOR_ALLOWED"
|
||||
hint_type "APPARMOR_HINT"
|
||||
status_type "APPARMOR_STATUS"
|
||||
error_type "APPARMOR_ERROR"
|
||||
unknown_type UNKNOWN\[{digits}+\]
|
||||
other_audit_type [[:alnum:]\[\]_-]+
|
||||
|
||||
/* Old message tokens */
|
||||
|
||||
old_apparmor_type "APPARMOR"
|
||||
old_apparmor_reject "REJECTING"
|
||||
old_apparmor_permit "PERMITTING"
|
||||
old_apparmor_audit "AUDITING"
|
||||
old_apparmor_logprof "LOGPROF-HINT"
|
||||
old_unknown_hat "unknown_hat"
|
||||
old_unknown_profile "unknown_profile"
|
||||
old_missing_profile "missing_mandatory_profile"
|
||||
old_changing_profile "changing_profile"
|
||||
old_active "active"
|
||||
old_access "access"
|
||||
old_from "from"
|
||||
old_to "to"
|
||||
old_pipe "pipe"
|
||||
old_extended "extended"
|
||||
old_rmdir "rmdir"
|
||||
old_mkdir "mkdir"
|
||||
old_on "on"
|
||||
old_xattr "xattr"
|
||||
old_change "change"
|
||||
old_capability "capability"
|
||||
old_syscall "syscall"
|
||||
old_link "link"
|
||||
old_fork "fork"
|
||||
old_child "child"
|
||||
|
||||
null_complain "null-complain-profile"
|
||||
|
||||
/* Key tokens */
|
||||
|
||||
key_type "type"
|
||||
key_msg "msg"
|
||||
key_operation "operation"
|
||||
key_name "name"
|
||||
key_name2 "name2"
|
||||
key_denied_mask "denied_mask"
|
||||
key_requested_mask "requested_mask"
|
||||
key_attribute "attribute"
|
||||
key_task "task"
|
||||
key_parent "parent"
|
||||
key_magic_token "magic_token"
|
||||
key_info "info"
|
||||
key_pid "pid"
|
||||
key_profile "profile"
|
||||
key_image "image"
|
||||
key_family "family"
|
||||
key_sock_type "sock_type"
|
||||
key_protocol "protocol"
|
||||
audit "audit"
|
||||
|
||||
/* syslog tokens */
|
||||
syslog_kernel kernel{colon}
|
||||
syslog_month Jan(uary)?|Feb(ruary)?|Mar(ch)?|Apr(il)?|May|Jun(e)?|Jul(y)?|Aug(ust)?|Sep(tember)?|Oct(ober)?|Nov(ember)?|Dec(ember)?
|
||||
syslog_time {digits}{digits}{colon}{digits}{digits}{colon}{digits}{digits}
|
||||
syslog_hostname [[:alnum:]_-]+
|
||||
dmesg_timestamp \[[[:digit:] ]{5,}\.[[:digit:]]{6,}\]
|
||||
|
||||
%x quoted_string
|
||||
%x sub_id
|
||||
%x audit_id
|
||||
%x single_quoted_string
|
||||
%x hostname
|
||||
%x dmesg_timestamp
|
||||
%x safe_string
|
||||
%x audit_types
|
||||
%x other_audit
|
||||
%x unknown_message
|
||||
|
||||
%%
|
||||
%{
|
||||
char string_buf[512];
|
||||
char *string_buf_ptr = string_buf; /* assignment to quiet gcc warning */
|
||||
|
||||
/* yy_flex_debug = 1; */
|
||||
%}
|
||||
|
||||
{ws}+ { /* Skip whitespace */ }
|
||||
|
||||
<audit_id>{
|
||||
{digits} { yylval->t_str = strdup(yytext); return(TOK_AUDIT_DIGITS);}
|
||||
{colon} { return(TOK_COLON); }
|
||||
{period} { return(TOK_PERIOD); }
|
||||
{open_paren} { return(TOK_OPEN_PAREN); }
|
||||
{close_paren} { yy_pop_state(yyscanner); return(TOK_CLOSE_PAREN); }
|
||||
}
|
||||
|
||||
<sub_id>{
|
||||
{open_paren} { return(TOK_OPEN_PAREN); }
|
||||
{close_paren} { BEGIN(INITIAL); return(TOK_CLOSE_PAREN); }
|
||||
"'" { string_buf_ptr = string_buf; BEGIN(single_quoted_string); }
|
||||
{ws} { }
|
||||
\" { string_buf_ptr = string_buf; BEGIN(quoted_string); }
|
||||
{ID}+ {
|
||||
yylval->t_str = strdup(yytext);
|
||||
BEGIN(INITIAL);
|
||||
return(TOK_ID);
|
||||
}
|
||||
{equals} { return(TOK_EQUALS); }
|
||||
}
|
||||
|
||||
|
||||
"'" { string_buf_ptr = string_buf; BEGIN(single_quoted_string); }
|
||||
<single_quoted_string>"'" { /* End of the quoted string */
|
||||
BEGIN(INITIAL);
|
||||
*string_buf_ptr = '\0';
|
||||
yylval->t_str = strdup(string_buf);
|
||||
return(TOK_SINGLE_QUOTED_STRING);
|
||||
}
|
||||
|
||||
|
||||
<single_quoted_string>\\(.|\n) { *string_buf_ptr++ = yytext[1]; }
|
||||
|
||||
<single_quoted_string>[^\\\n\'\"]+ {
|
||||
char *yptr = yytext;
|
||||
while (*yptr)
|
||||
{
|
||||
*string_buf_ptr++ = *yptr++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
\" { string_buf_ptr = string_buf; BEGIN(quoted_string); }
|
||||
<quoted_string>\" { /* End of the quoted string */
|
||||
BEGIN(INITIAL);
|
||||
*string_buf_ptr = '\0';
|
||||
yylval->t_str = strdup(string_buf);
|
||||
return(TOK_QUOTED_STRING);
|
||||
}
|
||||
|
||||
|
||||
<quoted_string>\\(.|\n) { *string_buf_ptr++ = yytext[1]; }
|
||||
|
||||
<quoted_string>[^\\\n\"]+ {
|
||||
char *yptr = yytext;
|
||||
while (*yptr)
|
||||
{
|
||||
*string_buf_ptr++ = *yptr++;
|
||||
}
|
||||
}
|
||||
|
||||
<safe_string>{
|
||||
"'" { string_buf_ptr = string_buf; BEGIN(single_quoted_string); }
|
||||
\" { string_buf_ptr = string_buf; BEGIN(quoted_string); }
|
||||
{hexstring} { yylval->t_str = hex_to_string(yytext); BEGIN(INITIAL); return(TOK_HEXSTRING);}
|
||||
{equals} { return(TOK_EQUALS); }
|
||||
. { /* eek, error! try another state */ BEGIN(INITIAL); yyless(0); }
|
||||
}
|
||||
|
||||
<audit_types>{
|
||||
{equals} { return(TOK_EQUALS); }
|
||||
{digits} { yylval->t_long = atol(yytext); BEGIN(INITIAL); return(TOK_DIGITS); }
|
||||
{reject_type} { BEGIN(INITIAL); return(TOK_TYPE_REJECT); }
|
||||
{audit_type} { BEGIN(INITIAL); return(TOK_TYPE_AUDIT); }
|
||||
{complain_type} { BEGIN(INITIAL); return(TOK_TYPE_COMPLAIN); }
|
||||
{hint_type} { BEGIN(INITIAL); return(TOK_TYPE_HINT); }
|
||||
{status_type} { BEGIN(INITIAL); return(TOK_TYPE_STATUS); }
|
||||
{error_type} { BEGIN(INITIAL); return(TOK_TYPE_ERROR); }
|
||||
{unknown_type} { char *yptr = yytext;
|
||||
while (*yptr && *yptr != '[')
|
||||
yptr++;
|
||||
if (*yptr)
|
||||
yylval->t_long = atol(yptr + 1); /* skip '[' */
|
||||
BEGIN(INITIAL);
|
||||
return(TOK_TYPE_UNKNOWN);
|
||||
}
|
||||
{old_apparmor_type} { BEGIN(INITIAL); return(TOK_OLD_TYPE_APPARMOR); }
|
||||
{other_audit_type} { yylval->t_str = strdup(yytext);
|
||||
BEGIN(other_audit);
|
||||
return(TOK_TYPE_OTHER);
|
||||
}
|
||||
}
|
||||
|
||||
{equals} { return(TOK_EQUALS); }
|
||||
{digits} { yylval->t_long = atol(yytext); return(TOK_DIGITS); }
|
||||
{colon} { return(TOK_COLON); }
|
||||
{open_paren} {
|
||||
BEGIN(sub_id);
|
||||
return(TOK_OPEN_PAREN);
|
||||
}
|
||||
{close_paren} { return(TOK_CLOSE_PAREN); }
|
||||
{path} { yylval->t_str = strdup(yytext); return(TOK_PATH); }
|
||||
{period} { return(TOK_PERIOD); }
|
||||
|
||||
{old_apparmor_reject} { return(TOK_OLD_APPARMOR_REJECT); }
|
||||
{old_apparmor_permit} { return(TOK_OLD_APPARMOR_PERMIT); }
|
||||
{old_apparmor_audit} { return(TOK_OLD_APPARMOR_AUDIT); }
|
||||
{old_apparmor_logprof} { return(TOK_OLD_APPARMOR_LOGPROF_HINT); }
|
||||
{old_unknown_hat} { BEGIN(sub_id); return(TOK_OLD_UNKNOWN_HAT); }
|
||||
{old_unknown_profile} { return(TOK_OLD_UNKNOWN_PROFILE); }
|
||||
{old_missing_profile} { return(TOK_OLD_MISSING_PROFILE); }
|
||||
{old_changing_profile} { return(TOK_OLD_CHANGING_PROFILE); }
|
||||
{old_active} { BEGIN(sub_id); return(TOK_OLD_ACTIVE); }
|
||||
{old_access} { return(TOK_OLD_ACCESS); }
|
||||
{old_to} { return(TOK_OLD_TO); }
|
||||
{old_from} { return(TOK_OLD_FROM); }
|
||||
{old_pipe} { return(TOK_OLD_PIPE); }
|
||||
{old_extended} { return(TOK_OLD_EXTENDED); }
|
||||
{old_mkdir} { return(TOK_OLD_MKDIR); }
|
||||
{old_rmdir} { return(TOK_OLD_RMDIR); }
|
||||
{old_on} { return(TOK_OLD_ON); }
|
||||
{old_xattr} { BEGIN(sub_id); return(TOK_OLD_XATTR); }
|
||||
{old_change} { return(TOK_OLD_CHANGE); }
|
||||
{old_capability} { BEGIN(sub_id); return(TOK_OLD_CAPABILITY); }
|
||||
{old_syscall} { return(TOK_OLD_SYSCALL); }
|
||||
{old_link} { return(TOK_OLD_LINK); }
|
||||
{old_fork} { return(TOK_OLD_FORK); }
|
||||
{old_child} { return(TOK_OLD_CHILD); }
|
||||
{modes} { yylval->t_str = strdup(yytext); return(TOK_MODE); }
|
||||
|
||||
{key_type} { BEGIN(audit_types); return(TOK_KEY_TYPE); }
|
||||
{key_msg} { return(TOK_KEY_MSG); }
|
||||
{key_operation} { return(TOK_KEY_OPERATION); }
|
||||
{key_name} { BEGIN(safe_string); return(TOK_KEY_NAME); }
|
||||
{key_name2} { BEGIN(safe_string); return(TOK_KEY_NAME2); }
|
||||
{key_denied_mask} { return(TOK_KEY_DENIED_MASK); }
|
||||
{key_requested_mask} { return(TOK_KEY_REQUESTED_MASK); }
|
||||
{key_attribute} { BEGIN(sub_id); return(TOK_KEY_ATTRIBUTE); }
|
||||
{key_task} { return(TOK_KEY_TASK); }
|
||||
{key_parent} { return(TOK_KEY_PARENT); }
|
||||
{key_magic_token} { return(TOK_KEY_MAGIC_TOKEN); }
|
||||
{key_info} { return(TOK_KEY_INFO); }
|
||||
{key_pid} { return(TOK_KEY_PID); }
|
||||
{key_profile} { BEGIN(safe_string); return(TOK_KEY_PROFILE); }
|
||||
{key_family} { return(TOK_KEY_FAMILY); }
|
||||
{key_sock_type} { return(TOK_KEY_SOCK_TYPE); }
|
||||
{key_protocol} { return(TOK_KEY_PROTOCOL); }
|
||||
|
||||
{syslog_kernel} { BEGIN(dmesg_timestamp); return(TOK_SYSLOG_KERNEL); }
|
||||
{syslog_month} { yylval->t_str = strdup(yytext); return(TOK_DATE_MONTH); }
|
||||
{syslog_time} { yylval->t_str = strdup(yytext); BEGIN(hostname); return(TOK_DATE_TIME); }
|
||||
|
||||
{audit} { yy_push_state(audit_id, yyscanner); return(TOK_AUDIT); }
|
||||
{null_complain} { return(TOK_NULL_COMPLAIN); }
|
||||
{key_image} { BEGIN(sub_id); return(TOK_KEY_IMAGE); }
|
||||
|
||||
<hostname>{
|
||||
{ws}+ { /* eat whitespace */ }
|
||||
{syslog_hostname} { yylval->t_str = strdup(yytext); BEGIN(INITIAL); return(TOK_ID); }
|
||||
}
|
||||
|
||||
<dmesg_timestamp>{
|
||||
{ws}+ { /* eat whitespace */ }
|
||||
{dmesg_timestamp} { yylval->t_str = strdup(yytext); BEGIN(INITIAL); return(TOK_DMESG_STAMP); }
|
||||
. { /* no timestamp in this message */ BEGIN(INITIAL); yyless(0); }
|
||||
}
|
||||
|
||||
<other_audit>{
|
||||
{ws}+ { /* eat whitespace */ }
|
||||
{audit} { yy_push_state(audit_id, yyscanner); return(TOK_AUDIT); }
|
||||
{key_msg} { return(TOK_KEY_MSG); }
|
||||
{equals} { return(TOK_EQUALS); }
|
||||
{colon} { return(TOK_COLON); }
|
||||
. { BEGIN(unknown_message); yyless(0); /* dump the rest */ }
|
||||
}
|
||||
|
||||
<unknown_message>{
|
||||
.* { yylval->t_str = strdup(yytext); return(TOK_MSG_REST); }
|
||||
\n { /* not sure why needed here and not elsewhere */ }
|
||||
}
|
||||
|
||||
%%
|
@@ -1,35 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "aalogparse.h"
|
||||
#include "parser.h"
|
||||
|
||||
|
||||
#define MY_TEST(statement, error) \
|
||||
if (!(statement)) { \
|
||||
fprintf(stderr, "FAIL: %s\n", error); \
|
||||
rc = 1; \
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int rc = 0;
|
||||
char *retstr = NULL;
|
||||
|
||||
retstr = hex_to_string(NULL);
|
||||
MY_TEST(!retstr, "basic NULL test");
|
||||
|
||||
retstr = hex_to_string("2F746D702F646F6573206E6F74206578697374");
|
||||
MY_TEST(retstr, "basic allocation");
|
||||
MY_TEST(strcmp(retstr, "/tmp/does not exist") == 0, "basic dehex 1");
|
||||
|
||||
retstr = hex_to_string("61");
|
||||
MY_TEST(strcmp(retstr, "a") == 0, "basic dehex 2");
|
||||
|
||||
retstr = hex_to_string("");
|
||||
MY_TEST(strcmp(retstr, "") == 0, "empty string");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@@ -1,14 +0,0 @@
|
||||
%module LibAppArmor
|
||||
|
||||
%{
|
||||
#include "aalogparse.h"
|
||||
extern int aa_change_hat(const char *subprofile, unsigned long magic_token);
|
||||
extern int aa_change_profile(const char *profile, unsigned long magic_token);
|
||||
|
||||
%}
|
||||
|
||||
%include "typemaps.i"
|
||||
%include "aalogparse.h"
|
||||
extern int aa_change_hat(const char *subprofile, unsigned long magic_token);
|
||||
extern int aa_change_profile(const char *profile, unsigned long magic_token);
|
||||
|
@@ -1,9 +0,0 @@
|
||||
use ExtUtils::MakeMaker;
|
||||
|
||||
use vars qw($CCFLAGS $OBJECT $VERSION $OPTIMIZE);
|
||||
|
||||
WriteMakefile(
|
||||
'NAME' => 'LibAppArmor',
|
||||
'MAKEFILE' => 'Makefile.perl',
|
||||
'FIRST_MAKEFILE' => 'Makefile.perl',
|
||||
);
|
@@ -1,34 +0,0 @@
|
||||
if HAVE_PERL
|
||||
|
||||
PERL_MAKEFILE = Makefile.perl
|
||||
|
||||
WRAPPER_SOURCES = libapparmor_wrap.c LibAppArmor.pm
|
||||
|
||||
all-local: .build-stamp
|
||||
|
||||
.build-stamp: $(WRAPPER_SOURCES) $(PERL_MAKEFILE)
|
||||
make -f $(PERL_MAKEFILE)
|
||||
touch .build-stamp
|
||||
|
||||
check-local: .build-stamp
|
||||
make -f $(PERL_MAKEFILE) test
|
||||
|
||||
install-exec-local: .build-stamp
|
||||
make -f $(PERL_MAKEFILE) install_vendor
|
||||
|
||||
clean-local: $(PERL_MAKEFILE)
|
||||
make -f $(PERL_MAKEFILE) clean
|
||||
rm -f $(PERL_MAKEFILE).old
|
||||
rm -rf build
|
||||
|
||||
$(PERL_MAKEFILE): Makefile.PL
|
||||
$(PERL) Makefile.PL VERSION="0.1" OBJECT="../../src/.libs/libapparmor.so libapparmor_wrap.o" CCFLAGS="-I../../src -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -fno-strict-aliasing -pipe -Wdeclaration-after-statement" OPTIMIZE="$(CFLAGS) -shared -I$(includedir) -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -fno-strict-aliasing -pipe -Wdeclaration-after-statement"
|
||||
|
||||
|
||||
$(WRAPPER_SOURCES): ../SWIG/*.i
|
||||
$(SWIG) -perl -I../../src -I../SWIG -o libapparmor_wrap.c libapparmor.i
|
||||
|
||||
endif
|
||||
|
||||
EXTRA_DIST = Makefile.PL $(WRAPPER_SOURCES) examples/*.pl
|
||||
|
@@ -1,15 +0,0 @@
|
||||
require LibAppArmor;
|
||||
|
||||
$msg = "type=APPARMOR msg=audit(1168662182.495:58): PERMITTING r access to /home/matt/projects/change_hat_test/test (test_hat(27871) profile /home/matt/projects/change_hat_test/test_hat active null-complain-profile)";
|
||||
|
||||
my($test) = AppArmorLogRecordParser::parse_record($msg);
|
||||
|
||||
if (AppArmorLogRecordParser::aa_log_record::swig_event_get($test) == $AppArmorLogRecordParser::AA_RECORD_ALLOWED )
|
||||
{
|
||||
print "AA_RECORD_ALLOWED\n";
|
||||
}
|
||||
|
||||
print "Audit ID: " . AppArmorLogRecordParser::aa_log_record::swig_audit_id_get($test) . "\n";
|
||||
print "PID: " . AppArmorLogRecordParser::aa_log_record::swig_pid_get($test) . "\n";
|
||||
|
||||
AppArmorLogRecordParser::free_record($test);
|
@@ -1,17 +0,0 @@
|
||||
if HAVE_PYTHON
|
||||
BUILT_SOURCES = libapparmor_wrap.c
|
||||
|
||||
SWIG_SOURCES = ../SWIG/libapparmor.i
|
||||
|
||||
|
||||
pkgpython_PYTHON = LibAppArmor.py
|
||||
pkgpyexec_LTLIBRARIES = _libapparmor.la
|
||||
_libapparmor_la_SOURCES = libapparmor_wrap.c $(SWIG_SOURCES)
|
||||
_libapparmor_la_CPPFLAGS = $(SWIG_PYTHON_CFLAGS) -I$(top_srcdir)/src -I/usr/include/python
|
||||
_libapparmor_la_LDFLAGS = -module
|
||||
_libapparmor_la_LIBADD = ../../src/.libs/libapparmor.so
|
||||
|
||||
libapparmor_wrap.c: $(SWIG_SOURCES)
|
||||
$(SWIG) -python -I$(top_srcdir)/src -o $@ $<
|
||||
|
||||
endif
|
@@ -1,24 +0,0 @@
|
||||
if HAVE_RUBY
|
||||
|
||||
RUBY_MAKEFILE = Makefile.ruby
|
||||
|
||||
WRAPPER_FILES = LibAppArmor_wrap.* LibAppArmor.so extension.mak .build-stamp
|
||||
|
||||
BUILT_SOURCES = LibAppArmor_wrap.c
|
||||
|
||||
all-local: .build-stamp
|
||||
|
||||
.build-stamp: LibAppArmor_wrap.c
|
||||
CFLAGS="$(CFLAGS) -I../../src" $(RUBY) extconf.rb build
|
||||
touch .build-stamp
|
||||
|
||||
install-exec-local: .build-stamp
|
||||
make -f $(RUBY_MAKEFILE) install
|
||||
|
||||
LibAppArmor_wrap.c: ../SWIG/*.i
|
||||
$(SWIG) -ruby -I../SWIG -I../../src -o ./LibAppArmor_wrap.c libapparmor.i
|
||||
|
||||
endif
|
||||
|
||||
EXTRA_DIST = extconf.rb $(BUILT_SOURCES) examples/*.rb
|
||||
|
@@ -1,76 +0,0 @@
|
||||
require 'mkmf'
|
||||
require 'ftools'
|
||||
|
||||
$CFLAGS += " " + (ENV['CFLAGS'] || "") + (ENV['CXXFLAGS'] || "")
|
||||
$LDFLAGS = "../../src/.libs/libapparmor.so"
|
||||
|
||||
def usage
|
||||
puts <<EOF
|
||||
Usage: ruby extconf.rb command
|
||||
build Build the extension
|
||||
clean Clean the source directory
|
||||
install Install the extention
|
||||
test Test the extension
|
||||
wrap Generate SWIG wrappers
|
||||
EOF
|
||||
exit
|
||||
end
|
||||
|
||||
cmd = ARGV.shift or usage()
|
||||
cmd = cmd.downcase
|
||||
|
||||
usage() unless ['build', 'clean', 'install', 'test', 'wrap'].member? cmd
|
||||
usage() if ARGV.shift
|
||||
|
||||
class Commands
|
||||
def initialize(&block)
|
||||
@block = block
|
||||
end
|
||||
|
||||
def execute
|
||||
@block.call
|
||||
end
|
||||
end
|
||||
|
||||
Build = Commands.new {
|
||||
# I don't think we can tell mkmf to generate a makefile with a different name
|
||||
if File.exists?("Makefile")
|
||||
File.rename("Makefile", "Makefile.old")
|
||||
end
|
||||
create_makefile('LibAppArmor')
|
||||
File.rename("Makefile", "Makefile.ruby")
|
||||
if File.exists?("Makefile.old")
|
||||
File.rename("Makefile.old", "Makefile")
|
||||
end
|
||||
system("make -f Makefile.ruby")
|
||||
}
|
||||
Install = Commands.new {
|
||||
Build.execute
|
||||
if defined? Prefix
|
||||
# strip old prefix and add the new one
|
||||
oldPrefix = Config::CONFIG["prefix"]
|
||||
if defined? Debian
|
||||
archDir = Config::CONFIG["archdir"]
|
||||
libDir = Config::CONFIG["rubylibdir"]
|
||||
else
|
||||
archDir = Config::CONFIG["sitearchdir"]
|
||||
libDir = Config::CONFIG["sitelibdir"]
|
||||
end
|
||||
archDir = Prefix + archDir.gsub(/^#{oldPrefix}/,"")
|
||||
libDir = Prefix + libDir.gsub(/^#{oldPrefix}/,"")
|
||||
else
|
||||
archDir = Config::CONFIG["sitearchdir"]
|
||||
libDir = Config::CONFIG["sitelibdir"]
|
||||
end
|
||||
[archDir,libDir].each { |path| File.makedirs path }
|
||||
binary = 'LibAppArmor.so'
|
||||
File.install "./"+binary, archDir+"/"+binary, 0555, true
|
||||
File.install "./LibAppArmor.so", libDir+"/LibAppArmor.so", 0555, true
|
||||
}
|
||||
|
||||
availableCommands = {
|
||||
"build" => Build,
|
||||
"install" => Install
|
||||
}
|
||||
|
||||
availableCommands[cmd].execute
|
@@ -1,171 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "aalogparse.h"
|
||||
|
||||
int print_results(aa_log_record *record);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *testcase;
|
||||
char log_line[1024];
|
||||
aa_log_record *test = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: test_multi.multi <filename>\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
printf("START\n");
|
||||
printf("File: %s\n", argv[1]);
|
||||
|
||||
testcase = fopen(argv[1], "r");
|
||||
if (testcase == NULL)
|
||||
{
|
||||
perror("Could not open testcase: ");
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (fgets(log_line, 1023, testcase) == NULL)
|
||||
{
|
||||
fprintf(stderr, "Could not read testcase.\n");
|
||||
fclose(testcase);
|
||||
return(1);
|
||||
}
|
||||
|
||||
fclose(testcase);
|
||||
|
||||
test = parse_record(log_line);
|
||||
|
||||
if (test == NULL)
|
||||
{
|
||||
fprintf(stderr,"Parsing failed.\n");
|
||||
return(1);
|
||||
}
|
||||
ret = print_results(test);
|
||||
free_record(test);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int print_results(aa_log_record *record)
|
||||
{
|
||||
printf("Event type: ");
|
||||
switch(record->event)
|
||||
{
|
||||
case AA_RECORD_ERROR:
|
||||
{
|
||||
printf("AA_RECORD_ERROR\n");
|
||||
break;
|
||||
}
|
||||
case AA_RECORD_INVALID:
|
||||
{
|
||||
printf("AA_RECORD_INVALID\n");
|
||||
break;
|
||||
}
|
||||
case AA_RECORD_AUDIT:
|
||||
{
|
||||
printf("AA_RECORD_AUDIT\n");
|
||||
break;
|
||||
}
|
||||
case AA_RECORD_ALLOWED:
|
||||
{
|
||||
printf("AA_RECORD_ALLOWED\n");
|
||||
break;
|
||||
}
|
||||
case AA_RECORD_DENIED:
|
||||
{
|
||||
printf("AA_RECORD_DENIED\n");
|
||||
break;
|
||||
}
|
||||
case AA_RECORD_HINT:
|
||||
{
|
||||
printf("AA_RECORD_HINT\n");
|
||||
break;
|
||||
}
|
||||
case AA_RECORD_STATUS:
|
||||
{
|
||||
printf("AA_RECORD_STATUS\n");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
printf("UNKNOWN EVENT TYPE\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (record->audit_id != NULL)
|
||||
{
|
||||
printf("Audit ID: %s\n", record->audit_id);
|
||||
}
|
||||
if (record->operation != NULL)
|
||||
{
|
||||
printf("Operation: %s\n", record->operation);
|
||||
}
|
||||
if (record->requested_mask != NULL)
|
||||
{
|
||||
printf("Mask: %s\n", record->requested_mask);
|
||||
}
|
||||
if (record->denied_mask != NULL)
|
||||
{
|
||||
printf("Denied Mask: %s\n", record->denied_mask);
|
||||
}
|
||||
if (record->profile != NULL)
|
||||
{
|
||||
printf("Profile: %s\n", record->profile);
|
||||
}
|
||||
if (record->name != NULL)
|
||||
{
|
||||
printf("Name: %s\n", record->name);
|
||||
}
|
||||
if (record->name2 != NULL)
|
||||
{
|
||||
printf("Name2: %s\n", record->name2);
|
||||
}
|
||||
if (record->attribute != NULL)
|
||||
{
|
||||
printf("Attribute: %s\n", record->attribute);
|
||||
}
|
||||
if (record->task != 0)
|
||||
{
|
||||
printf("Task: %ld\n", record->task);
|
||||
}
|
||||
if (record->parent != 0)
|
||||
{
|
||||
printf("Parent: %ld\n", record->parent);
|
||||
}
|
||||
if (record->magic_token != 0)
|
||||
{
|
||||
printf("Token: %lu\n", record->magic_token);
|
||||
}
|
||||
if (record->info != NULL)
|
||||
{
|
||||
printf("Info: %s\n", record->info);
|
||||
}
|
||||
if (record->pid != 0)
|
||||
{
|
||||
printf("PID: %ld\n", record->pid);
|
||||
}
|
||||
if (record->active_hat != NULL)
|
||||
{
|
||||
printf("Active hat: %s\n", record->active_hat);
|
||||
}
|
||||
if (record->net_family != NULL)
|
||||
{
|
||||
printf("Network family: %s\n", record->net_family);
|
||||
}
|
||||
if (record->net_sock_type != NULL)
|
||||
{
|
||||
printf("Socket type: %s\n", record->net_sock_type);
|
||||
}
|
||||
if (record->net_protocol != NULL)
|
||||
{
|
||||
printf("Protocol: %s\n", record->net_protocol);
|
||||
}
|
||||
printf("Epoch: %lu\n", record->epoch);
|
||||
printf("Audit subid: %u\n", record->audit_sub_id);
|
||||
return(0);
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
START
|
||||
File: test_multi/testcase10.in
|
||||
Event type: AA_RECORD_HINT
|
||||
Audit ID: 1168661976.062:55
|
||||
Operation: clone
|
||||
Profile: /home/matt/projects/change_hat_test/test_hat
|
||||
Task: 38229
|
||||
PID: 27764
|
||||
Active hat: /home/matt/projects/change_hat_test/test_hat
|
||||
Epoch: 1168661976
|
||||
Audit subid: 55
|
@@ -1,9 +0,0 @@
|
||||
START
|
||||
File: test_multi/testcase11.in
|
||||
Event type: AA_RECORD_HINT
|
||||
Audit ID: 1168661976.062:55
|
||||
Operation: clone
|
||||
Task: 38229
|
||||
PID: 27764
|
||||
Epoch: 1168661976
|
||||
Audit subid: 55
|
@@ -1,13 +0,0 @@
|
||||
START
|
||||
File: test_multi/testcase18.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1157215966.604:46
|
||||
Operation: access
|
||||
Mask: r
|
||||
Profile: /usr/sbin/httpd2-prefork
|
||||
Name: /bin/df
|
||||
Info: sh
|
||||
PID: 7902
|
||||
Active hat: SYSINFO
|
||||
Epoch: 1157215966
|
||||
Audit subid: 46
|
@@ -1,8 +0,0 @@
|
||||
START
|
||||
File: test_multi/testcase19.in
|
||||
Event type: AA_RECORD_HINT
|
||||
Audit ID: 1164007073.953:518
|
||||
Profile: null-complain-profile
|
||||
PID: 29420
|
||||
Epoch: 1164007073
|
||||
Audit subid: 518
|
@@ -1,13 +0,0 @@
|
||||
START
|
||||
File: test_multi/testcase2.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1168662182.495:58
|
||||
Operation: access
|
||||
Mask: r
|
||||
Profile: /home/matt/projects/change_hat_test/test_hat
|
||||
Name: /home/matt/projects/change_hat_test/test
|
||||
Info: test_hat
|
||||
PID: 27871
|
||||
Active hat: null-complain-profile
|
||||
Epoch: 1168662182
|
||||
Audit subid: 58
|
@@ -1,13 +0,0 @@
|
||||
START
|
||||
File: test_multi/testcase20.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1167188680.127:54
|
||||
Operation: access
|
||||
Mask: r
|
||||
Profile: /bin/freak-aa-out
|
||||
Name: /bin/freak-aa-out
|
||||
Info: bash
|
||||
PID: 23415
|
||||
Active hat: /bin/freak-aa-out
|
||||
Epoch: 1167188680
|
||||
Audit subid: 54
|
@@ -1 +0,0 @@
|
||||
Sep 13 13:11:13 lizaveta kernel: AppArmor: REJECTING exec(2) of image '/usr/lib/mailman/mail/mailman'. Profile mandatory and not found (local(20700) profile /usr/lib/postfix/local active /usr/lib/postfix/local)
|
@@ -1,13 +0,0 @@
|
||||
START
|
||||
File: test_multi/testcase27.in
|
||||
Event type: AA_RECORD_AUDIT
|
||||
Audit ID: 1177962426.395:2107
|
||||
Operation: access
|
||||
Mask: mr
|
||||
Profile: /home/steve/svn/apparmor-forge/tests/regression/subdomain/changehat_wrapper
|
||||
Name: /lib/ld-2.4.so
|
||||
Info: open
|
||||
PID: 7139
|
||||
Active hat: open
|
||||
Epoch: 1177962426
|
||||
Audit subid: 2107
|
@@ -1,12 +0,0 @@
|
||||
START
|
||||
File: test_multi/testcase28.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1173790298.651:1662
|
||||
Operation: syscall
|
||||
Profile: /home/steve/svn/trunk-forge/tests/regression/subdomain/syscall_ptrace
|
||||
Name: ptrace
|
||||
Info: syscall_ptrace
|
||||
PID: 25210
|
||||
Active hat: /home/steve/svn/trunk-forge/tests/regression/subdomain/syscall_ptrace
|
||||
Epoch: 1173790298
|
||||
Audit subid: 1662
|
@@ -1,12 +0,0 @@
|
||||
START
|
||||
File: test_multi/testcase29.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1173790298.983:1669
|
||||
Operation: syscall
|
||||
Profile: /home/steve/svn/trunk-forge/tests/regression/subdomain/syscall_sysctl
|
||||
Name: sysctl (write)
|
||||
Info: syscall_sysctl
|
||||
PID: 25423
|
||||
Active hat: /home/steve/svn/trunk-forge/tests/regression/subdomain/syscall_sysctl
|
||||
Epoch: 1173790298
|
||||
Audit subid: 1669
|
@@ -1,12 +0,0 @@
|
||||
START
|
||||
File: test_multi/testcase3.in
|
||||
Event type: AA_RECORD_HINT
|
||||
Audit ID: 1168661976.062:55
|
||||
Operation: change_hat
|
||||
Profile: /home/matt/projects/change_hat_test/test_hat
|
||||
Name: TESTHAT
|
||||
Info: unknown_hat
|
||||
PID: 27764
|
||||
Active hat: /home/matt/projects/change_hat_test/test_hat
|
||||
Epoch: 1168661976
|
||||
Audit subid: 55
|
@@ -1,13 +0,0 @@
|
||||
START
|
||||
File: test_multi/testcase30.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1177962395.525:1837
|
||||
Mask: l
|
||||
Profile: /home/steve/svn/apparmor-forge/tests/regression/subdomain/link
|
||||
Name: /tmp/sdtest.3676-13458-it3683/target
|
||||
Name2: /tmp/sdtest.3676-13458-it3683/src
|
||||
Info: link
|
||||
PID: 3823
|
||||
Active hat: /home/steve/svn/apparmor-forge/tests/regression/subdomain/link
|
||||
Epoch: 1177962395
|
||||
Audit subid: 1837
|
@@ -1,13 +0,0 @@
|
||||
START
|
||||
File: test_multi/testcase4.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1167188680.127:54
|
||||
Operation: access
|
||||
Mask: r
|
||||
Profile: /bin/freak-aa-out
|
||||
Name: /bin/freak-aa-out
|
||||
Info: bash
|
||||
PID: 23415
|
||||
Active hat: /bin/freak-aa-out
|
||||
Epoch: 1167188680
|
||||
Audit subid: 54
|
@@ -1,12 +0,0 @@
|
||||
START
|
||||
File: test_multi/testcase5.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1167188680.127:54
|
||||
Operation: mkdir
|
||||
Profile: /bin/freak-aa-out
|
||||
Name: /path/to/something
|
||||
Info: bash
|
||||
PID: 23415
|
||||
Active hat: /bin/freak-aa-out
|
||||
Epoch: 1167188680
|
||||
Audit subid: 54
|
@@ -1,12 +0,0 @@
|
||||
START
|
||||
File: test_multi/testcase6.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1167188680.127:54
|
||||
Operation: rmdir
|
||||
Profile: /bin/freak-aa-out
|
||||
Name: /path/to/something
|
||||
Info: bash
|
||||
PID: 23415
|
||||
Active hat: /bin/freak-aa-out
|
||||
Epoch: 1167188680
|
||||
Audit subid: 54
|
@@ -1,13 +0,0 @@
|
||||
START
|
||||
File: test_multi/testcase7.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1167188680.127:54
|
||||
Operation: xattr
|
||||
Profile: /bin/freak-aa-out
|
||||
Name: /path/to/something
|
||||
Attribute: set
|
||||
Info: bash
|
||||
PID: 23415
|
||||
Active hat: /bin/freak-aa-out
|
||||
Epoch: 1167188680
|
||||
Audit subid: 54
|
@@ -1,13 +0,0 @@
|
||||
START
|
||||
File: test_multi/testcase8.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1167188680.127:54
|
||||
Operation: setattr
|
||||
Profile: /bin/freak-aa-out
|
||||
Name: /else
|
||||
Attribute: something
|
||||
Info: bash
|
||||
PID: 23415
|
||||
Active hat: /bin/freak-aa-out
|
||||
Epoch: 1167188680
|
||||
Audit subid: 54
|
@@ -1,12 +0,0 @@
|
||||
START
|
||||
File: test_multi/testcase9.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1167188680.127:54
|
||||
Operation: capability
|
||||
Profile: /bin/freak-aa-out
|
||||
Name: cap
|
||||
Info: bash
|
||||
PID: 23415
|
||||
Active hat: /bin/freak-aa-out
|
||||
Epoch: 1167188680
|
||||
Audit subid: 54
|
@@ -1,4 +1,3 @@
|
||||
# $Id$
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2004, 2005 NOVELL (All rights reserved)
|
||||
#
|
||||
@@ -42,16 +41,48 @@ APXS:=$(shell if [ -x "/usr/sbin/apxs2" ] ; then \
|
||||
fi )
|
||||
APXS_INSTALL_DIR=$(shell ${APXS} -q LIBEXECDIR)
|
||||
DESTDIR=
|
||||
LIBAPPARMOR_FLAGS=$(shell if [ -f /usr/lib/libapparmor.so -o -f /usr/lib64/libapparmor.so ] ; then \
|
||||
echo -lapparmor ; \
|
||||
else \
|
||||
echo -DUSE_COMPAT_IMMUNIX_H -limmunix ;\
|
||||
fi)
|
||||
ifdef USE_SYSTEM
|
||||
LIBAPPARMOR = $(shell if pkg-config --exists libapparmor ; then \
|
||||
pkg-config --silence-errors --libs libapparmor ; \
|
||||
elif ldconfig -p | grep -q libapparmor\.so$$ ; then \
|
||||
echo -lapparmor ; \
|
||||
fi )
|
||||
ifeq ($(strip $(LIBAPPARMOR)),)
|
||||
ERROR_MESSAGE = $(error ${nl}\
|
||||
************************************************************************${nl}\
|
||||
Unable to find libapparmor installed on this system; either${nl}\
|
||||
install libapparmor devel packages, set the LIBAPPARMOR variable${nl}\
|
||||
manually, or build against in-tree libapparmor.${nl}\
|
||||
************************************************************************${nl})
|
||||
endif # LIBAPPARMOR not set
|
||||
LDLIBS += $(LIBAPPARMOR)
|
||||
else
|
||||
LIBAPPARMOR_SRC := ../../libraries/libapparmor/
|
||||
LIBAPPARMOR_INCLUDE = $(LIBAPPARMOR_SRC)/include
|
||||
LIBAPPARMOR_PATH := $(LIBAPPARMOR_SRC)/src/.libs/
|
||||
ifeq ($(realpath $(LIBAPPARMOR_PATH)/libapparmor.a),)
|
||||
ERROR_MESSAGE = $(error ${nl}\
|
||||
************************************************************************${nl}\
|
||||
$(LIBAPPARMOR_PATH)/libapparmor.a is missing; either build against${nl}\
|
||||
the in-tree libapparmor by building it first and then trying again${nl}\
|
||||
(see the top-level README for help) or build against the system${nl}\
|
||||
libapparmor by adding USE_SYSTEM=1 to your make command.${nl}\
|
||||
************************************************************************${nl})
|
||||
endif
|
||||
# Need to pass -Wl twice here to get past both apxs2 and libtool, as
|
||||
# libtool will add the path to the RPATH of the library if passed -L/some/path
|
||||
LIBAPPARMOR_FLAGS = -I$(LIBAPPARMOR_INCLUDE) -Wl,-Wl,-L$(LIBAPPARMOR_PATH)
|
||||
LDLIBS = -lapparmor
|
||||
endif
|
||||
|
||||
all: $(TARGET) ${MANPAGES} ${HTMLMANPAGES}
|
||||
.PHONY: libapparmor_check
|
||||
.SILENT: libapparmor_check
|
||||
libapparmor_check: ; $(ERROR_MESSAGE)
|
||||
|
||||
all: libapparmor_check $(TARGET) ${MANPAGES} ${HTMLMANPAGES}
|
||||
|
||||
%.so: %.c
|
||||
${APXS} ${LIBAPPARMOR_FLAGS} -c $<
|
||||
${APXS} ${LIBAPPARMOR_FLAGS} -c $< ${LDLIBS}
|
||||
mv .libs/$@ .
|
||||
|
||||
.PHONY: install
|
||||
@@ -64,3 +95,6 @@ install: ${TARGET} ${MANPAGES}
|
||||
clean: _clean
|
||||
rm -rf .libs
|
||||
rm -f *.la *.lo *.so *.o *.slo Make.rules
|
||||
|
||||
.PHONY: check
|
||||
check: check_pod_files
|
||||
|
@@ -1,4 +1,3 @@
|
||||
# $Id$
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2004, 2005 NOVELL (All rights reserved)
|
||||
#
|
||||
|
@@ -1,6 +1,5 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# $Id: frob_sysconfig 5910 2005-12-09 03:41:29Z steve $
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2004, 2005 NOVELL (All rights reserved)
|
||||
#
|
||||
|
@@ -1,13 +1,13 @@
|
||||
/* $Id$
|
||||
*
|
||||
/*
|
||||
* Copyright (c) 2004, 2005, 2006 NOVELL (All rights reserved)
|
||||
* Copyright (c) 2014 Canonical, Ltd. (All rights reserved)
|
||||
*
|
||||
* The mod_apparmor module is licensed under the terms of the GNU
|
||||
* Lesser General Public License, version 2.1. Please see the file
|
||||
* COPYING.LGPL.
|
||||
*
|
||||
* mod_apparmor - (apache 2.0.x)
|
||||
* Author: Steve Beattie <sbeattie@suse.de>
|
||||
* Author: Steve Beattie <steve@nxnw.org>
|
||||
*
|
||||
* This currently only implements change_hat functionality, but could be
|
||||
* extended for other stuff we decide to do.
|
||||
@@ -18,187 +18,240 @@
|
||||
#include "http_config.h"
|
||||
#include "http_request.h"
|
||||
#include "http_log.h"
|
||||
#include "http_main.h"
|
||||
#include "http_protocol.h"
|
||||
#include "util_filter.h"
|
||||
#include "apr.h"
|
||||
#include "apr_strings.h"
|
||||
#include "apr_lib.h"
|
||||
|
||||
#ifndef USE_COMPAT_IMMUNIX_H
|
||||
#include <sys/apparmor.h>
|
||||
#else
|
||||
#include <sys/immunix.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
/* #define DEBUG */
|
||||
#ifndef __unused
|
||||
#define __unused __attribute__((unused))
|
||||
#endif
|
||||
|
||||
/* should the following be configurable? */
|
||||
#define DEFAULT_HAT "HANDLING_UNTRUSTED_INPUT"
|
||||
#define DEFAULT_URI_HAT "DEFAULT_URI"
|
||||
|
||||
/* Compatibility with apache 2.2 */
|
||||
#if AP_SERVER_MAJORVERSION_NUMBER == 2 && AP_SERVER_MINORVERSION_NUMBER < 3
|
||||
#define APLOG_TRACE1 APLOG_DEBUG
|
||||
server_rec *ap_server_conf = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef APLOG_USE_MODULE
|
||||
APLOG_USE_MODULE(apparmor);
|
||||
#endif
|
||||
module AP_MODULE_DECLARE_DATA apparmor_module;
|
||||
|
||||
static unsigned int magic_token = 0;
|
||||
static unsigned long magic_token = 0;
|
||||
static int inside_default_hat = 0;
|
||||
|
||||
typedef struct {
|
||||
const char * hat_name;
|
||||
char * path;
|
||||
} immunix_dir_cfg;
|
||||
const char *hat_name;
|
||||
char *path;
|
||||
} apparmor_dir_cfg;
|
||||
|
||||
typedef struct {
|
||||
const char * hat_name;
|
||||
int is_initialized;
|
||||
} immunix_srv_cfg;
|
||||
const char *hat_name;
|
||||
int is_initialized;
|
||||
} apparmor_srv_cfg;
|
||||
|
||||
/* immunix_init() gets invoked in the post_config stage of apache.
|
||||
/* aa_init() gets invoked in the post_config stage of apache.
|
||||
* Unfortunately, apache reads its config once when it starts up, then
|
||||
* it re-reads it when goes into its restart loop, where it starts it's
|
||||
* children. This means we cannot call change_hat here, as the modules
|
||||
* memory will be wiped out, and the magic_token will be lost, so apache
|
||||
* wouldn't be able to change_hat back out. */
|
||||
static int
|
||||
immunix_init (apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
|
||||
static int
|
||||
aa_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
|
||||
{
|
||||
apr_file_t * file;
|
||||
apr_size_t size = sizeof (magic_token);
|
||||
apr_file_t *file;
|
||||
apr_size_t size = sizeof(magic_token);
|
||||
int ret;
|
||||
|
||||
ret = apr_file_open (&file, "/dev/urandom", APR_READ, APR_OS_DEFAULT, p);
|
||||
if (!ret) {
|
||||
apr_file_read (file, (void *) &magic_token, &size);
|
||||
apr_file_close (file);
|
||||
apr_file_read(file, (void *) &magic_token, &size);
|
||||
apr_file_close(file);
|
||||
} else {
|
||||
ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "Failed to open /dev/urandom");
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf,
|
||||
"Failed to open /dev/urandom");
|
||||
}
|
||||
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "Opened /dev/urandom successfully");
|
||||
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
|
||||
"Opened /dev/urandom successfully");
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/* As each child starts up, we'll change_hat into a default hat, mostly
|
||||
* to protect ourselves from bugs in parsing network input, but before
|
||||
* we change_hat to the uri specific hat. */
|
||||
static void
|
||||
immunix_child_init (apr_pool_t *p, server_rec *s)
|
||||
static void
|
||||
aa_child_init(apr_pool_t *p, server_rec *s)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "init: calling change_hat");
|
||||
ret = change_hat (DEFAULT_HAT, magic_token);
|
||||
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
|
||||
"init: calling change_hat with '%s'", DEFAULT_HAT);
|
||||
ret = aa_change_hat(DEFAULT_HAT, magic_token);
|
||||
if (ret < 0) {
|
||||
change_hat (NULL, magic_token);
|
||||
ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "Failed to change_hat to '%s'",
|
||||
DEFAULT_HAT);
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, errno, ap_server_conf,
|
||||
"Failed to change_hat to '%s'", DEFAULT_HAT);
|
||||
} else {
|
||||
inside_default_hat = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
debug_dump_uri (apr_uri_t * uri)
|
||||
debug_dump_uri(request_rec *r)
|
||||
{
|
||||
if (uri)
|
||||
ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "Dumping uri info "
|
||||
"scheme='%s' host='%s' path='%s' query='%s' fragment='%s'",
|
||||
uri->scheme, uri->hostname, uri->path, uri->query,
|
||||
uri->fragment);
|
||||
apr_uri_t *uri = &r->parsed_uri;
|
||||
if (uri)
|
||||
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Dumping uri info "
|
||||
"scheme='%s' host='%s' path='%s' query='%s' fragment='%s'",
|
||||
uri->scheme, uri->hostname, uri->path, uri->query,
|
||||
uri->fragment);
|
||||
else
|
||||
ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "Asked to dump NULL uri");
|
||||
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Asked to dump NULL uri");
|
||||
|
||||
}
|
||||
#else
|
||||
static void
|
||||
debug_dump_uri (apr_uri_t * __unused uri) { }
|
||||
#endif
|
||||
|
||||
/*
|
||||
immunix_enter_hat will attempt to change_hat in the following order:
|
||||
(1) to a hatname in a location directive
|
||||
(2) to the uri
|
||||
(3) to a per-server default
|
||||
(4) to DEFAULT_URI
|
||||
(5) back to the parent profile
|
||||
*/
|
||||
static int
|
||||
immunix_enter_hat (request_rec *r)
|
||||
{
|
||||
int sd_ret = -1;
|
||||
immunix_dir_cfg * dcfg = (immunix_dir_cfg *)
|
||||
ap_get_module_config (r->per_dir_config, &apparmor_module);
|
||||
immunix_srv_cfg * scfg = (immunix_srv_cfg *)
|
||||
ap_get_module_config (r->server->module_config, &apparmor_module);
|
||||
|
||||
debug_dump_uri (&r->parsed_uri);
|
||||
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "in immunix_enter_hat (%s) n:0x%lx p:0x%lx main:0x%lx",
|
||||
dcfg->path, (unsigned long) r->next, (unsigned long) r->prev,
|
||||
(unsigned long) r->main);
|
||||
/*
|
||||
aa_enter_hat will attempt to change_hat in the following order:
|
||||
(1) to a hatname in a location directive
|
||||
(2) to the server name or a defined per-server default
|
||||
(3) to the server name + "-" + uri
|
||||
(4) to the uri
|
||||
(5) to DEFAULT_URI
|
||||
(6) back to the parent profile
|
||||
*/
|
||||
static int
|
||||
aa_enter_hat(request_rec *r)
|
||||
{
|
||||
int aa_ret = -1;
|
||||
apparmor_dir_cfg *dcfg = (apparmor_dir_cfg *)
|
||||
ap_get_module_config(r->per_dir_config, &apparmor_module);
|
||||
apparmor_srv_cfg *scfg = (apparmor_srv_cfg *)
|
||||
ap_get_module_config(r->server->module_config, &apparmor_module);
|
||||
const char *aa_hat_array[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
|
||||
int i = 0;
|
||||
char *aa_con, *aa_mode, *aa_hat;
|
||||
const char *vhost_uri;
|
||||
|
||||
debug_dump_uri(r);
|
||||
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "aa_enter_hat (%s) n:0x%lx p:0x%lx main:0x%lx",
|
||||
dcfg->path, (unsigned long) r->next, (unsigned long) r->prev,
|
||||
(unsigned long) r->main);
|
||||
|
||||
/* We only call change_hat for the main request, not subrequests */
|
||||
if (r->main)
|
||||
return OK;
|
||||
if (r->main)
|
||||
return OK;
|
||||
|
||||
if (inside_default_hat) {
|
||||
change_hat (NULL, magic_token);
|
||||
inside_default_hat = 0;
|
||||
aa_change_hat(NULL, magic_token);
|
||||
inside_default_hat = 0;
|
||||
}
|
||||
|
||||
if (dcfg != NULL && dcfg->hat_name != NULL) {
|
||||
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "calling change_hat [dcfg] %s", dcfg->hat_name);
|
||||
sd_ret = change_hat (dcfg->hat_name, magic_token);
|
||||
if (sd_ret < 0) {
|
||||
change_hat (NULL, magic_token);
|
||||
} else {
|
||||
return OK;
|
||||
}
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
|
||||
"[dcfg] adding hat '%s' to aa_change_hat vector", dcfg->hat_name);
|
||||
aa_hat_array[i++] = dcfg->hat_name;
|
||||
}
|
||||
|
||||
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "calling change_hat [uri] %s", r->uri);
|
||||
sd_ret = change_hat (r->uri, magic_token);
|
||||
if (sd_ret < 0) {
|
||||
change_hat (NULL, magic_token);
|
||||
if (scfg) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "Dumping scfg info: "
|
||||
"scfg='0x%lx' scfg->hat_name='%s'",
|
||||
(unsigned long) scfg, scfg->hat_name);
|
||||
} else {
|
||||
return OK;
|
||||
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "scfg is null");
|
||||
}
|
||||
if (scfg != NULL) {
|
||||
if (scfg->hat_name != NULL) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
|
||||
"[scfg] adding hat '%s' to aa_change_hat vector", scfg->hat_name);
|
||||
aa_hat_array[i++] = scfg->hat_name;
|
||||
} else {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
|
||||
"[scfg] adding server_name '%s' to aa_change_hat vector",
|
||||
r->server->server_hostname);
|
||||
aa_hat_array[i++] = r->server->server_hostname;
|
||||
}
|
||||
|
||||
vhost_uri = apr_pstrcat(r->pool, r->server->server_hostname, "-", r->uri, NULL);
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
|
||||
"[vhost+uri] adding vhost+uri '%s' to aa_change_hat vector", vhost_uri);
|
||||
aa_hat_array[i++] = vhost_uri;
|
||||
}
|
||||
|
||||
if (scfg != NULL && scfg->hat_name != NULL) {
|
||||
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "calling change_hat [scfg] %s", scfg->hat_name);
|
||||
sd_ret = change_hat (scfg->hat_name, magic_token);
|
||||
if (sd_ret < 0) {
|
||||
change_hat (NULL, magic_token);
|
||||
} else {
|
||||
return OK;
|
||||
}
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
|
||||
"[uri] adding uri '%s' to aa_change_hat vector", r->uri);
|
||||
aa_hat_array[i++] = r->uri;
|
||||
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
|
||||
"[default] adding '%s' to aa_change_hat vector", DEFAULT_URI_HAT);
|
||||
aa_hat_array[i++] = DEFAULT_URI_HAT;
|
||||
|
||||
aa_ret = aa_change_hatv(aa_hat_array, magic_token);
|
||||
if (aa_ret < 0) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_WARNING, errno, r, "aa_change_hatv call failed");
|
||||
}
|
||||
|
||||
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "calling change_hat DEFAULT_URI");
|
||||
sd_ret = change_hat (DEFAULT_URI_HAT, magic_token);
|
||||
if (sd_ret < 0) change_hat (NULL, magic_token);
|
||||
/* Check to see if a defined AAHatName or AADefaultHatName would
|
||||
* apply, but wasn't the hat we landed up in; report a warning if
|
||||
* that's the case. */
|
||||
aa_ret = aa_getcon(&aa_con, &aa_mode);
|
||||
if (aa_ret < 0) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_WARNING, errno, r, "aa_getcon call failed");
|
||||
} else {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
|
||||
"AA checks: aa_getcon result is '%s', mode '%s'", aa_con, aa_mode);
|
||||
/* TODO: use libapparmor get hat_name fn here once it is implemented */
|
||||
aa_hat = strstr(aa_con, "//");
|
||||
if (aa_hat != NULL && strcmp(aa_mode, "enforce") == 0) {
|
||||
aa_hat += 2; /* skip "//" */
|
||||
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
|
||||
"AA checks: apache is in hat '%s', mode '%s'", aa_hat, aa_mode);
|
||||
if (dcfg != NULL && dcfg->hat_name != NULL) {
|
||||
if (strcmp(aa_hat, dcfg->hat_name) != 0)
|
||||
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
|
||||
"AAHatName '%s' applies, but does not appear to be a hat in the apache apparmor policy",
|
||||
dcfg->hat_name);
|
||||
} else if (scfg != NULL && scfg->hat_name != NULL) {
|
||||
if (strcmp(aa_hat, scfg->hat_name) != 0 &&
|
||||
strcmp(aa_hat, r->uri) != 0)
|
||||
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
|
||||
"AADefaultHatName '%s' applies, but does not appear to be a hat in the apache apparmor policy",
|
||||
scfg->hat_name);
|
||||
}
|
||||
}
|
||||
free(aa_con);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int
|
||||
immunix_exit_hat (request_rec *r)
|
||||
static int
|
||||
aa_exit_hat(request_rec *r)
|
||||
{
|
||||
int sd_ret;
|
||||
immunix_dir_cfg * dcfg = (immunix_dir_cfg *)
|
||||
ap_get_module_config (r->per_dir_config, &apparmor_module);
|
||||
/* immunix_srv_cfg * scfg = (immunix_srv_cfg *)
|
||||
ap_get_module_config (r->server->module_config, &apparmor_module); */
|
||||
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "exiting change_hat - dir hat %s path %s", dcfg->hat_name, dcfg->path);
|
||||
change_hat (NULL, magic_token);
|
||||
int aa_ret;
|
||||
apparmor_dir_cfg *dcfg = (apparmor_dir_cfg *)
|
||||
ap_get_module_config(r->per_dir_config, &apparmor_module);
|
||||
/* apparmor_srv_cfg *scfg = (apparmor_srv_cfg *)
|
||||
ap_get_module_config(r->server->module_config, &apparmor_module); */
|
||||
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "exiting change_hat: dir hat %s dir path %s",
|
||||
dcfg->hat_name, dcfg->path);
|
||||
|
||||
sd_ret = change_hat (DEFAULT_HAT, magic_token);
|
||||
if (sd_ret < 0) {
|
||||
change_hat (NULL, magic_token);
|
||||
ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "Failed to change_hat to '%s'",
|
||||
DEFAULT_HAT);
|
||||
/* can convert the following back to aa_change_hat() when the
|
||||
* aa_change_hat() bug addressed in trunk commit 2329 lands in most
|
||||
* system libapparmors */
|
||||
aa_change_hatv(NULL, magic_token);
|
||||
|
||||
aa_ret = aa_change_hat(DEFAULT_HAT, magic_token);
|
||||
if (aa_ret < 0) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
|
||||
"Failed to change_hat to '%s'", DEFAULT_HAT);
|
||||
} else {
|
||||
inside_default_hat = 1;
|
||||
}
|
||||
@@ -207,15 +260,15 @@ immunix_exit_hat (request_rec *r)
|
||||
}
|
||||
|
||||
static const char *
|
||||
aa_cmd_ch_path (cmd_parms * cmd, void * mconfig, const char * parm1)
|
||||
aa_cmd_ch_path(cmd_parms *cmd, void *mconfig, const char *parm1)
|
||||
{
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "config change hat %s",
|
||||
parm1 ? parm1 : "DEFAULT");
|
||||
immunix_dir_cfg * dcfg = mconfig;
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "directory config change hat %s",
|
||||
parm1 ? parm1 : "DEFAULT");
|
||||
apparmor_dir_cfg *dcfg = mconfig;
|
||||
if (parm1 != NULL) {
|
||||
dcfg->hat_name = parm1;
|
||||
dcfg->hat_name = parm1;
|
||||
} else {
|
||||
dcfg->hat_name = "DEFAULT";
|
||||
dcfg->hat_name = "DEFAULT";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -223,26 +276,27 @@ aa_cmd_ch_path (cmd_parms * cmd, void * mconfig, const char * parm1)
|
||||
static int path_warn_once;
|
||||
|
||||
static const char *
|
||||
immunix_cmd_ch_path (cmd_parms * cmd, void * mconfig, const char * parm1)
|
||||
immunix_cmd_ch_path(cmd_parms *cmd, void *mconfig, const char *parm1)
|
||||
{
|
||||
if (path_warn_once == 0) {
|
||||
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL, "ImmHatName is "
|
||||
"deprecated, please use AAHatName instead");
|
||||
path_warn_once = 1;
|
||||
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "ImmHatName is "
|
||||
"deprecated, please use AAHatName instead");
|
||||
path_warn_once = 1;
|
||||
}
|
||||
return aa_cmd_ch_path(cmd, mconfig, parm1);
|
||||
}
|
||||
|
||||
static const char *
|
||||
aa_cmd_ch_srv (cmd_parms * cmd, void * mconfig, const char * parm1)
|
||||
aa_cmd_ch_srv(cmd_parms *cmd, void *mconfig, const char *parm1)
|
||||
{
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "config change hat %s",
|
||||
parm1 ? parm1 : "DEFAULT");
|
||||
immunix_srv_cfg * scfg = mconfig;
|
||||
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "server config change hat %s",
|
||||
parm1 ? parm1 : "DEFAULT");
|
||||
apparmor_srv_cfg *scfg = (apparmor_srv_cfg *)
|
||||
ap_get_module_config(cmd->server->module_config, &apparmor_module);
|
||||
if (parm1 != NULL) {
|
||||
scfg->hat_name = parm1;
|
||||
scfg->hat_name = parm1;
|
||||
} else {
|
||||
scfg->hat_name = "DEFAULT";
|
||||
scfg->hat_name = "DEFAULT";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -250,27 +304,29 @@ aa_cmd_ch_srv (cmd_parms * cmd, void * mconfig, const char * parm1)
|
||||
static int srv_warn_once;
|
||||
|
||||
static const char *
|
||||
immunix_cmd_ch_srv (cmd_parms * cmd, void * mconfig, const char * parm1)
|
||||
immunix_cmd_ch_srv(cmd_parms *cmd, void *mconfig, const char *parm1)
|
||||
{
|
||||
if (srv_warn_once == 0) {
|
||||
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL, "ImmDefaultHatName is "
|
||||
"deprecated, please use AADefaultHatName instead");
|
||||
srv_warn_once = 1;
|
||||
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "ImmDefaultHatName is "
|
||||
"deprecated, please use AADefaultHatName instead");
|
||||
srv_warn_once = 1;
|
||||
}
|
||||
return aa_cmd_ch_srv(cmd, mconfig, parm1);
|
||||
}
|
||||
|
||||
static void *
|
||||
immunix_create_dir_config (apr_pool_t * p, char * path)
|
||||
aa_create_dir_config(apr_pool_t *p, char *path)
|
||||
{
|
||||
immunix_dir_cfg * newcfg = (immunix_dir_cfg *) apr_pcalloc(p, sizeof(* newcfg));
|
||||
apparmor_dir_cfg *newcfg = (apparmor_dir_cfg *) apr_pcalloc(p, sizeof(*newcfg));
|
||||
|
||||
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "in immunix_create_dir (%s)", path ? path : ":no path:");
|
||||
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
|
||||
"aa_create_dir_cfg (%s)", path ? path : ":no path:");
|
||||
if (newcfg == NULL) {
|
||||
ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "immunix_create_dir: couldn't alloc dir config");
|
||||
return NULL;
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
|
||||
"aa_create_dir_config: couldn't alloc dir config");
|
||||
return NULL;
|
||||
}
|
||||
newcfg->path = apr_pstrdup (p, path ? path : ":no path:");
|
||||
newcfg->path = apr_pstrdup(p, path ? path : ":no path:");
|
||||
|
||||
return newcfg;
|
||||
}
|
||||
@@ -278,83 +334,93 @@ immunix_create_dir_config (apr_pool_t * p, char * path)
|
||||
/* XXX: Should figure out an appropriate action to take here, if any
|
||||
|
||||
static void *
|
||||
immunix_merge_dir_config (apr_pool_t * p, void * parent, void * child)
|
||||
aa_merge_dir_config(apr_pool_t *p, void *parent, void *child)
|
||||
{
|
||||
immunix_dir_cfg * newcfg = (immunix_dir_cfg *) apr_pcalloc(p, sizeof(* newcfg));
|
||||
apparmor_dir_cfg *newcfg = (apparmor_dir_cfg *) apr_pcalloc(p, sizeof(*newcfg));
|
||||
|
||||
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "in immunix_merge_dir ()");
|
||||
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf, "in immunix_merge_dir ()");
|
||||
if (newcfg == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return newcfg;
|
||||
}
|
||||
*/
|
||||
|
||||
static void *
|
||||
immunix_create_srv_config (apr_pool_t * p, server_rec * srv)
|
||||
aa_create_srv_config(apr_pool_t *p, server_rec *srv)
|
||||
{
|
||||
immunix_srv_cfg * newcfg = (immunix_srv_cfg *) apr_pcalloc(p, sizeof(* newcfg));
|
||||
apparmor_srv_cfg *newcfg = (apparmor_srv_cfg *) apr_pcalloc(p, sizeof(*newcfg));
|
||||
|
||||
ap_log_error (APLOG_MARK, APLOG_DEBUG, 0, NULL, "in immunix_create_srv");
|
||||
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, ap_server_conf,
|
||||
"in aa_create_srv_config");
|
||||
if (newcfg == NULL) {
|
||||
ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "immunix_create_srv: couldn't alloc srv config");
|
||||
return NULL;
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
|
||||
"aa_create_srv_config: couldn't alloc srv config");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return newcfg;
|
||||
}
|
||||
|
||||
|
||||
static const command_rec immunix_cmds[] = {
|
||||
static const command_rec mod_apparmor_cmds[] = {
|
||||
|
||||
AP_INIT_TAKE1 (
|
||||
AP_INIT_TAKE1(
|
||||
"ImmHatName",
|
||||
immunix_cmd_ch_path,
|
||||
NULL,
|
||||
ACCESS_CONF,
|
||||
""
|
||||
immunix_cmd_ch_path,
|
||||
NULL,
|
||||
ACCESS_CONF,
|
||||
""
|
||||
),
|
||||
AP_INIT_TAKE1 (
|
||||
AP_INIT_TAKE1(
|
||||
"ImmDefaultHatName",
|
||||
immunix_cmd_ch_srv,
|
||||
NULL,
|
||||
RSRC_CONF,
|
||||
""
|
||||
immunix_cmd_ch_srv,
|
||||
NULL,
|
||||
RSRC_CONF,
|
||||
""
|
||||
),
|
||||
AP_INIT_TAKE1 (
|
||||
AP_INIT_TAKE1(
|
||||
"AAHatName",
|
||||
aa_cmd_ch_path,
|
||||
NULL,
|
||||
ACCESS_CONF,
|
||||
""
|
||||
aa_cmd_ch_path,
|
||||
NULL,
|
||||
ACCESS_CONF,
|
||||
""
|
||||
),
|
||||
AP_INIT_TAKE1 (
|
||||
AP_INIT_TAKE1(
|
||||
"AADefaultHatName",
|
||||
aa_cmd_ch_srv,
|
||||
NULL,
|
||||
RSRC_CONF,
|
||||
""
|
||||
aa_cmd_ch_srv,
|
||||
NULL,
|
||||
RSRC_CONF,
|
||||
""
|
||||
),
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static void
|
||||
register_hooks (apr_pool_t *p)
|
||||
static void
|
||||
register_hooks(apr_pool_t *p)
|
||||
{
|
||||
ap_hook_post_config (immunix_init, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
ap_hook_child_init (immunix_child_init, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
ap_hook_access_checker(immunix_enter_hat, NULL, NULL, APR_HOOK_FIRST);
|
||||
/* ap_hook_post_read_request(immunix_enter_hat, NULL, NULL, APR_HOOK_FIRST); */
|
||||
ap_hook_log_transaction(immunix_exit_hat, NULL, NULL, APR_HOOK_LAST);
|
||||
ap_hook_post_config(aa_init, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
ap_hook_child_init(aa_child_init, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
|
||||
#if AP_SERVER_MAJORVERSION_NUMBER == 2 && AP_SERVER_MINORVERSION_NUMBER < 3
|
||||
/* Compatibility with apache 2.2 */
|
||||
ap_hook_access_checker(aa_enter_hat, NULL, NULL, APR_HOOK_FIRST);
|
||||
#else
|
||||
/* apache 2.4 mod_authz hook */
|
||||
ap_hook_check_access_ex(aa_enter_hat, NULL, NULL, APR_HOOK_FIRST, AP_AUTH_INTERNAL_PER_CONF);
|
||||
#endif
|
||||
|
||||
/* ap_hook_post_read_request(aa_enter_hat, NULL, NULL, APR_HOOK_FIRST); */
|
||||
ap_hook_log_transaction(aa_exit_hat, NULL, NULL, APR_HOOK_LAST);
|
||||
}
|
||||
|
||||
module AP_MODULE_DECLARE_DATA apparmor_module = {
|
||||
STANDARD20_MODULE_STUFF,
|
||||
immunix_create_dir_config, /* dir config creater */
|
||||
NULL, /* dir merger --- default is to override */
|
||||
/* immunix_merge_dir_config, */ /* dir merger --- default is to override */
|
||||
immunix_create_srv_config, /* server config */
|
||||
NULL, /* merge server config */
|
||||
immunix_cmds, /* command table */
|
||||
register_hooks /* register hooks */
|
||||
aa_create_dir_config, /* dir config creater */
|
||||
NULL, /* dir merger --- default is to override */
|
||||
/* immunix_merge_dir_config, */ /* dir merger --- default is to override */
|
||||
aa_create_srv_config, /* server config */
|
||||
NULL, /* merge server config */
|
||||
mod_apparmor_cmds, /* command table */
|
||||
register_hooks /* register hooks */
|
||||
};
|
||||
|
@@ -1,96 +1,145 @@
|
||||
# $Id$
|
||||
# This publication is intellectual property of Novell Inc. Its contents
|
||||
# can be duplicated, either in part or in whole, provided that a copyright
|
||||
# label is visibly located on each copy.
|
||||
# This publication is intellectual property of Novell Inc. and 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 SUSE LINUX GmbH, the authors, nor the translators shall be held
|
||||
# liable for possible errors or the consequences thereof.
|
||||
# Neither SUSE LINUX GmbH, 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. SUSE LINUX GmbH
|
||||
# essentially adheres to the manufacturer's spelling.
|
||||
# and Canonical Ltd. essentially adhere 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.
|
||||
#
|
||||
# Please direct suggestions and comments to apparmor-general@forge.novell.com.
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
mod_apparmor - fine-grained AppArmor confinement for apache
|
||||
mod_apparmor - fine-grained AppArmor confinement for Apache
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
An AppArmor profile applies to an executable program; if a portion of
|
||||
the program needs different access permissions than other portions,
|
||||
the program can "change hats" via change_hat(2) to a different role,
|
||||
also known as a subprofile. The mod_apparmor apache module uses the
|
||||
change_hat(2) mechanism to offer more fine-grained confinement of dynamic
|
||||
elements within apache such as individual php and perl scripts, while
|
||||
the program can "change hats" via aa_change_hat(2) to a different role,
|
||||
also known as a subprofile. The mod_apparmor Apache module uses the
|
||||
aa_change_hat(2) mechanism to offer more fine-grained confinement of dynamic
|
||||
elements within Apache such as individual php and perl scripts, while
|
||||
still allowing the performance benefits of using mod_php and mod_perl.
|
||||
|
||||
To use mod_apparmor with apache, ensure that mod_apparmor is configured to
|
||||
be loaded into apache, either via yast or manual editing of the httpd(8)
|
||||
configuration files, and restart apache. Make sure that apparmor is also
|
||||
functioning.
|
||||
To use mod_apparmor with Apache, ensure that mod_apparmor is configured to
|
||||
be loaded into Apache, either via a2enmod, yast or manual editing of the
|
||||
apache2(8)/httpd(8) configuration files, and restart Apache. Make sure that
|
||||
apparmor is also functioning.
|
||||
|
||||
Once mod_apparmor is loaded within apache, all requests to apache will
|
||||
cause mod_apparmor to attempt to change into a hat named by the URI
|
||||
(e.g. /app/some.cgi). If no such hat is found, it will fall back to
|
||||
attempting to use the hat DEFAULT_URI; if that also does not exist,
|
||||
it will fall back to using the global apache profile. Most static web
|
||||
pages can simply make use of the DEFAULT_URI hat.
|
||||
Once mod_apparmor is loaded within Apache, all requests to Apache will
|
||||
cause mod_apparmor to attempt to change into a hat that matches the
|
||||
ServerName for the server/vhost. If no such hat is found, it will
|
||||
first fall back by attempting to change into a hat composed of the
|
||||
ServerName-URI (e.g. "www.example.com-/app/some.cgi"). If that hat
|
||||
is not found, it will fall back to attempting to use the hat named
|
||||
by the URI (e.g. "/app/some.cgi"). If that hat is not found, it will
|
||||
fall back to attempting to use the hat DEFAULT_URI; if that also does
|
||||
not exist, it will fall back to using the global Apache profile. Most
|
||||
static web pages can simply make use of the DEFAULT_URI hat.
|
||||
|
||||
However, defining hats for every URI/URL would become tedious, so there
|
||||
are a couple of configuration options that mod_apparmor supports:
|
||||
Additionally, before any requests come in to Apache, mod_apparmor
|
||||
will attempt to change hat into the HANDLING_UNTRUSTED_INPUT hat.
|
||||
mod_apparmor will attempt to use this hat while Apache is doing the
|
||||
initial parsing of a given http request, before its given to a specific
|
||||
handler (like mod_php) for processing.
|
||||
|
||||
Because defining hats for every URI/URL often becomes tedious, mod_apparmor
|
||||
provides the AAHatName and AADefaultHatName Apache configuration options.
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<AAHatName>
|
||||
|
||||
AAHatName allows you to specify a hat to be used for a given apache
|
||||
directory or location directive (see the apache documenation for more
|
||||
AAHatName allows you to specify a hat to be used for a given Apache
|
||||
E<lt>DirectoryE<gt>, E<lt>DirectoryMatchE<gt>, E<lt>LocationE<gt> or
|
||||
E<lt>LocationMatchE<gt> directive (see the Apache documenation for more
|
||||
details). Note that mod_apparmor behavior can become confused if
|
||||
directory and location directives are intermingled; it's preferred to
|
||||
stick to one type of directive. If the hat specified by AAHatName does
|
||||
not exist in the apache profile, then it falls back to the behavior
|
||||
above.
|
||||
E<lt>Directory*E<gt> and E<lt>Location*E<gt> directives are intermingled
|
||||
and it is recommended to use one type of directive. If the hat specified by
|
||||
AAHatName does not exist in the Apache profile, then it falls back to the
|
||||
behavior described above.
|
||||
|
||||
=item B<AADefaultHatName>
|
||||
|
||||
AADefaultHatName allows you to specify a default hat to be used for
|
||||
vhosts and other apache server directives, so that you can have
|
||||
virtual hosts and other Apache server directives, so that you can have
|
||||
different defaults for different virtual hosts. This can be overridden
|
||||
by an AAHatName directive. If the AADefaultHatName hat does not exist,
|
||||
it falls back to the behavior described above.
|
||||
by the AAHatName directive and is checked for only if there isn't
|
||||
a matching AAHatName. The default value of AADefaultHatName is the
|
||||
ServerName for the server/vhost configuration. If the AADefaultHatName
|
||||
hat does not exist, then it falls back to the behavior described above.
|
||||
|
||||
=back
|
||||
|
||||
Additionally, before any requests come in to apache, mod_apparmor
|
||||
will attempt to change hat into the HANDLING_UNTRUSTED_INPUT hat.
|
||||
mod_apparmor will attempt to use this hat while apache is doing the
|
||||
initial parsing of a given http request, before its given to a specific
|
||||
handler (like mod_php) for processing.
|
||||
=head1 URI REQUEST SUMMARY
|
||||
|
||||
When profiling with mod_apparmor, it is helpful to keep the following order
|
||||
of operations in mind:
|
||||
|
||||
On each URI request, mod_apparmor will first aa_change_hat(2) into
|
||||
^HANDLING_UNTRUSTED_INPUT, if it exists.
|
||||
|
||||
Then, after performing the initial parsing of the request, mod_apparmor
|
||||
will:
|
||||
|
||||
=over 4
|
||||
|
||||
=item 1
|
||||
|
||||
try to aa_change_hat(2) into a matching AAHatName hat if it exists and
|
||||
applies, otherwise it will
|
||||
|
||||
=item 2
|
||||
|
||||
try to aa_change_hat(2) into an AADefaultHatName hat, either the
|
||||
ServerName (the default) or the configuration value specified by the
|
||||
AADefaultHatName directive, for the server/vhost, otherwise it will
|
||||
|
||||
=item 3
|
||||
|
||||
try to aa_change_hat(2) into the ServerName-URI, otherwise it will
|
||||
|
||||
=item 4
|
||||
|
||||
try to aa_change_hat(2) into the URI itself, otherwise it will
|
||||
|
||||
=item 5
|
||||
|
||||
try to aa_change_hat(2) into the DEFAULT_URI hat, if it exists, otherwise it
|
||||
will
|
||||
|
||||
=item 6
|
||||
|
||||
fall back to the global Apache policy
|
||||
|
||||
=back
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
mod_apparmor() currently only supports apache2, and has only been tested
|
||||
with the prefork MPM configuration -- threaded configurations of apache
|
||||
may not work correctly.
|
||||
with the prefork MPM configuration -- threaded configurations of Apache
|
||||
may not work correctly. For Apache 2.4 users, you should enable the mpm_prefork
|
||||
module.
|
||||
|
||||
There are likely other bugs lurking about; if you find any, please report
|
||||
them to bugzilla at L<http://bugzilla.novell.com>.
|
||||
them at L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), subdomain.conf(5), apparmor_parser(8), and
|
||||
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.
|
||||
apparmor(7), subdomain.conf(5), apparmor_parser(8), aa_change_hat(2) and
|
||||
L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -1,4 +1,3 @@
|
||||
# $Id$
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 1999, 2004, 2005 NOVELL (All rights reserved)
|
||||
#
|
||||
@@ -27,12 +26,50 @@ common/Make.rules: $(COMMONDIR)/Make.rules
|
||||
ln -sf $(COMMONDIR) .
|
||||
endif
|
||||
|
||||
EXTRA_CFLAGS=$(CFLAGS) -fPIC -shared -Wall
|
||||
LINK_FLAGS=-Xlinker -x
|
||||
LIBS=-lpam -lapparmor
|
||||
ifdef USE_SYSTEM
|
||||
LIBAPPARMOR = $(shell if pkg-config --exists libapparmor ; then \
|
||||
pkg-config --silence-errors --libs libapparmor ; \
|
||||
elif ldconfig -p | grep -q libapparmor\.so$$ ; then \
|
||||
echo -lapparmor ; \
|
||||
fi )
|
||||
ifeq ($(strip $(LIBAPPARMOR)),)
|
||||
ERROR_MESSAGE = $(error ${nl}\
|
||||
************************************************************************${nl}\
|
||||
Unable to find libapparmor installed on this system; either${nl}\
|
||||
install libapparmor devel packages, set the LIBAPPARMOR variable${nl}\
|
||||
manually, or build against in-tree libapparmor.${nl}\
|
||||
************************************************************************${nl})
|
||||
endif
|
||||
LIBAPPARMOR_INCLUDE =
|
||||
AA_LDLIBS = $(LIBAPPARMOR)
|
||||
AA_LINK_FLAGS =
|
||||
else
|
||||
LIBAPPARMOR_SRC := ../../libraries/libapparmor/
|
||||
LIBAPPARMOR_INCLUDE_PATH = $(LIBAPPARMOR_SRC)/include
|
||||
LIBAPPARMOR_PATH := $(LIBAPPARMOR_SRC)/src/.libs/
|
||||
ifeq ($(realpath $(LIBAPPARMOR_PATH)/libapparmor.a),)
|
||||
ERROR_MESSAGE = $(error ${nl}\
|
||||
************************************************************************${nl}\
|
||||
$(LIBAPPARMOR_PATH)/libapparmor.a is missing; either build against${nl}\
|
||||
the in-tree libapparmor by building it first and then trying again${nl}\
|
||||
(see the top-level README for help) or build against the system${nl}\
|
||||
libapparmor by adding USE_SYSTEM=1 to your make command.${nl}\
|
||||
************************************************************************${nl})
|
||||
endif
|
||||
LIBAPPARMOR_INCLUDE = -I$(LIBAPPARMOR_INCLUDE_PATH)
|
||||
AA_LINK_FLAGS = -L$(LIBAPPARMOR_PATH)
|
||||
AA_LDLIBS = -lapparmor
|
||||
endif
|
||||
EXTRA_CFLAGS=$(CFLAGS) -fPIC -shared -Wall $(LIBAPPARMOR_INCLUDE)
|
||||
LINK_FLAGS=-Xlinker -x $(AA_LINK_FLAGS)
|
||||
LIBS=-lpam $(AA_LDLIBS)
|
||||
OBJECTS=${NAME}.o get_options.o
|
||||
|
||||
all: $(NAME).so
|
||||
.PHONY: libapparmor_check
|
||||
.SILENT: libapparmor_check
|
||||
libapparmor_check: ; $(ERROR_MESSAGE)
|
||||
|
||||
all: libapparmor_check $(NAME).so
|
||||
|
||||
$(NAME).so: ${OBJECTS}
|
||||
$(CC) $(EXTRA_CFLAGS) $(LINK_FLAGS) -o $@ ${OBJECTS} $(LIBS)
|
||||
@@ -42,7 +79,7 @@ $(NAME).so: ${OBJECTS}
|
||||
|
||||
# need some better way of determining this
|
||||
DESTDIR=/
|
||||
SECDIR=${DESTDIR}/lib/security
|
||||
SECDIR ?= ${DESTDIR}/lib/security
|
||||
|
||||
.PHONY: install
|
||||
install: $(NAME).so
|
||||
|
@@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Written by Steve Beattie <sbeattie@suse.de> 2006/10/25
|
||||
*
|
||||
* Modeled after the option parsing code in pam_unix2 by:
|
||||
|
@@ -1,10 +1,14 @@
|
||||
/* pam_apparmor module */
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
* Copyright (c) 2006
|
||||
* NOVELL (All rights reserved)
|
||||
*
|
||||
* Copyright (c) 2010
|
||||
* Canonical, Ltd. (All rights reserved)
|
||||
*
|
||||
* Written by Jesse Michael <jmichael@suse.de> 2006/08/24
|
||||
* and Steve Beattie <sbeattie@suse.de> 2006/10/25
|
||||
* and Steve Beattie <sbeattie@ubuntu.com> 2006/10/25
|
||||
*
|
||||
* Based off of pam_motd by:
|
||||
* Ben Collins <bcollins@debian.org> 2005/10/04
|
||||
@@ -165,8 +169,8 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
|
||||
* stop attempting to use change_hat */
|
||||
goto nodefault;
|
||||
break;
|
||||
case EPERM: /* Disable when ECHILD patch gets accepted */
|
||||
case EACCES:
|
||||
case ENOENT:
|
||||
/* failed to change into attempted hat, so we'll
|
||||
* jump back out and try the next one */
|
||||
break;
|
||||
|
@@ -1,8 +1,6 @@
|
||||
/* pam_apparmor module */
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Written by Jesse Michael <jmichael@suse.de> 2006/08/24
|
||||
* and Steve Beattie <sbeattie@suse.de> 2006/10/25
|
||||
*
|
||||
|
@@ -1,4 +1,3 @@
|
||||
# $Id: Makefile 10 2006-04-12 20:31:08Z steve-beattie $
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 1999, 2004, 2005, 2006 NOVELL (All rights reserved)
|
||||
#
|
||||
@@ -38,4 +37,4 @@ clean:
|
||||
rm -f tomcat_apparmor.spec ${NAME}-*.tar.gz Make.rules
|
||||
|
||||
install: $(SPECFILE)
|
||||
ant -Dversion=$(VERSION) -Drelease=$(RELEASE) -Dcatalina_home=${CATALINA_HOME} -Dinstall_lib=${LIB} install_jar install_jni
|
||||
ant -Dversion=$(VERSION) -Drelease=$(MAN_RELEASE) -Dcatalina_home=${CATALINA_HOME} -Dinstall_lib=${LIB} install_jar install_jni
|
||||
|
@@ -13,7 +13,7 @@
|
||||
|
||||
#include "jni.h"
|
||||
#include <errno.h>
|
||||
#include "sys/apparmor.h"
|
||||
#include <sys/apparmor.h>
|
||||
#include "com_novell_apparmor_JNIChangeHat.h"
|
||||
|
||||
/* c intermediate lib call for Java -> JNI -> c library execution of the change_hat call */
|
||||
|
@@ -1,4 +1,3 @@
|
||||
# $Id:$
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2006 NOVELL (All rights reserved)
|
||||
#
|
||||
|
@@ -1,4 +1,3 @@
|
||||
# $Id: Makefile 10 2006-04-12 20:31:08Z steve-beattie $
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 1999, 2004, 2005, 2006 NOVELL (All rights reserved)
|
||||
#
|
||||
@@ -38,4 +37,4 @@ clean:
|
||||
rm -f tomcat_apparmor.spec ${NAME}-*.tar.gz Make.rules
|
||||
|
||||
install: $(SPECFILE)
|
||||
ant -Dversion=$(VERSION) -Drelease=$(RELEASE) -Dcatalina_home=${CATALINA_HOME} -Dinstall_lib=${LIB} install_jar install_jni
|
||||
ant -Dversion=$(VERSION) -Drelease=$(MAN_RELEASE) -Dcatalina_home=${CATALINA_HOME} -Dinstall_lib=${LIB} install_jar install_jni
|
||||
|
@@ -4,8 +4,8 @@
|
||||
<property name="jni_src" location="src/jni_src"/>
|
||||
<property name="build" location="build"/>
|
||||
<property name="install_root" location="/"/>
|
||||
<property name="catalina_home" location="/usr/share/tomcat5"/>
|
||||
<property name="lib" location="lib"/>
|
||||
<property name="catalina_home" location="/usr/share/tomcat6"/>
|
||||
<property name="lib" location="/usr/share/tomcat6/bin"/>
|
||||
<property name="install_lib" value="/lib"/>
|
||||
<property name="dist" location="dist"/>
|
||||
<property name="jarfile" location="${dist}/${ant.project.name}.jar"/>
|
||||
@@ -18,10 +18,11 @@
|
||||
<include name="**/*.jar"/>
|
||||
</fileset>
|
||||
|
||||
<fileset id="tomcat.jars" dir="${catalina_home}/server/lib">
|
||||
<fileset id="tomcat.jars" dir="${catalina_home}/lib">
|
||||
<include name="**/*.jar"/>
|
||||
</fileset>
|
||||
<fileset id="servlet.jars" dir="${catalina_home}/common/lib">
|
||||
|
||||
<fileset id="servlet.jars" dir="${catalina_home}/lib">
|
||||
<include name="**/*.jar"/>
|
||||
</fileset>
|
||||
|
||||
@@ -80,9 +81,9 @@
|
||||
</target>
|
||||
|
||||
<target name="install_jar" depends="jni_so" description="Install jar file">
|
||||
<mkdir dir="${install_root}/${catalina_home}/server/lib/"/>
|
||||
<copy file="${jarfile}" tofile="${install_root}/${catalina_home}/server/lib/${ant.project.name}.jar"/>
|
||||
<chmod perm="644" file="${install_root}/${catalina_home}/server/lib/${ant.project.name}.jar"/>
|
||||
<mkdir dir="${install_root}/${catalina_home}/lib/"/>
|
||||
<copy file="${jarfile}" tofile="${install_root}/${catalina_home}/lib/${ant.project.name}.jar"/>
|
||||
<chmod perm="644" file="${install_root}/${catalina_home}/lib/${ant.project.name}.jar"/>
|
||||
</target>
|
||||
|
||||
<target name="clean" description="Remove build and dist directories">
|
||||
|
@@ -13,7 +13,7 @@
|
||||
|
||||
#include "jni.h"
|
||||
#include <errno.h>
|
||||
#include "sys/apparmor.h"
|
||||
#include <sys/apparmor.h>
|
||||
#include "com_novell_apparmor_JNIChangeHat.h"
|
||||
|
||||
/* c intermediate lib call for Java -> JNI -> c library execution of the change_hat call */
|
||||
|
@@ -4,7 +4,7 @@ LIB = lib/
|
||||
LIBDIR = /usr/${LIB}
|
||||
INCLUDE = ${LIBDIR}/jvm/java/include
|
||||
CFLAGS = -g -O2 -Wall -Wstrict-prototypes -Wl,-soname,$@.${SO_VERS} -pipe -fpic -D_REENTRANT
|
||||
INCLUDES = -I$(INCLUDE) -I$(INCLUDE)/linux
|
||||
INCLUDES = -I$(INCLUDE) -I$(INCLUDE)/linux -I$(TOP)/../../../libraries/libapparmor/src/
|
||||
CLASSFILE = ${CLASSPATH}/com/novell/apparmor/${JAVA_CLASSNAME}.class
|
||||
DESTDIR = ${TOP}/dist
|
||||
SO_VERS = 1
|
||||
@@ -20,7 +20,7 @@ ${JAVA_CLASSNAME}.java com_novell_apparmor_${JAVA_CLASSNAME}.h: ${CLASSFILE}
|
||||
javah -jni -classpath ${CLASSPATH} com.novell.apparmor.${JAVA_CLASSNAME}
|
||||
|
||||
${TARGET}.so: ${JAVA_CLASSNAME}.c ${JAVA_CLASSNAME}.java com_novell_apparmor_${JAVA_CLASSNAME}.h
|
||||
gcc ${INCLUDES} ${CFLAGS} -shared -o ${TARGET}.so ${JAVA_CLASSNAME}.c -lapparmor
|
||||
gcc ${INCLUDES} ${CFLAGS} -shared -o ${TARGET}.so ${JAVA_CLASSNAME}.c -L$(TOP)/../../../libraries/libapparmor/src/.libs -lapparmor
|
||||
|
||||
install: ${TARGET}.so
|
||||
install -d $(DESTDIR)/${LIB} $(DESTDIR)${LIBDIR}
|
||||
|
@@ -1,4 +1,3 @@
|
||||
# $Id:$
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2006 NOVELL (All rights reserved)
|
||||
#
|
||||
|
@@ -1,12 +1,19 @@
|
||||
# $Id$
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (c) 1999-2008 NOVELL (All rights reserved)
|
||||
# Copyright 2009-2010 Canonical Ltd.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# The including makefile needs to define LANG, which lists the lang
|
||||
@@ -14,13 +21,14 @@
|
||||
# exist
|
||||
LOCALEDIR=/usr/share/locale
|
||||
|
||||
XGETTEXT_ARGS=--copyright-holder="NOVELL, Inc." --msgid-bugs-address=apparmor-general@forge.novell.com -d ${NAME}
|
||||
XGETTEXT_ARGS=--copyright-holder="NOVELL, Inc." --msgid-bugs-address=apparmor@lists.ubuntu.com -d ${NAME}
|
||||
|
||||
# When making the .pot file, it's expected that the parent Makefile will
|
||||
# pass in the list of sources in the SOURCES variable
|
||||
PARENT_SOURCES=$(foreach source, ${SOURCES}, ../${source})
|
||||
|
||||
LANGS=$(patsubst %.po, %, $(wildcard *.po))
|
||||
# Can override by passing LANGS=whatever here
|
||||
LANGS?=$(patsubst %.po, %, $(wildcard *.po))
|
||||
TARGET_MOS=$(foreach lang, $(filter-out $(DISABLED_LANGS),$(LANGS)), ${lang}.mo)
|
||||
|
||||
.PHONY: all
|
||||
|
@@ -1,7 +1,7 @@
|
||||
# $Id$
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) 2010 Canonical, Ltd.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -25,7 +25,21 @@
|
||||
# directories
|
||||
|
||||
DISTRIBUTION=AppArmor
|
||||
VERSION=2.1.2
|
||||
VERSION=$(shell cat common/Version)
|
||||
|
||||
# Convenience functions
|
||||
pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
|
||||
map = $(foreach a,$(2),$(call $(1),$(a)))
|
||||
|
||||
AWK:=$(shell which awk)
|
||||
ifndef AWK
|
||||
$(error awk utility required for build but not available)
|
||||
endif
|
||||
|
||||
define nl
|
||||
|
||||
|
||||
endef
|
||||
|
||||
# OVERRIDABLE variables
|
||||
# Set these variables before including Make.rules to change its behavior
|
||||
@@ -48,16 +62,21 @@ BUILDDIR=$(shell if [ -d "${TESTBUILDDIR}" ] ; then \
|
||||
echo "/tmp/${NAME}" ; \
|
||||
fi ;)
|
||||
endif
|
||||
RPMHOSTVENDOR=$(shell rpm --eval "%{_host_vendor}")
|
||||
ifndef DISTRO
|
||||
DISTRO=$(shell if [ -f /etc/slackware-version ] ; then \
|
||||
echo slackware ; \
|
||||
elif [ -f /etc/debian_version ] ; then \
|
||||
echo debian ;\
|
||||
elif [ ${RPMHOSTVENDOR} = "suse" ] ; then \
|
||||
echo suse ;\
|
||||
elif [ ${RPMHOSTVENDOR} = "redhat" ] ; then \
|
||||
echo rhel4 ;\
|
||||
elif which rpm > /dev/null ; then \
|
||||
if [ "$(rpm --eval '0%{?suse_version}')" != "0" ] ; then \
|
||||
echo suse ;\
|
||||
elif [ "$(rpm --eval '%{_host_vendor}')" = redhat ] ; then \
|
||||
echo rhel4 ;\
|
||||
elif [ "$(rpm --eval '0%{?fedora}')" != "0" ] ; then \
|
||||
echo rhel4 ;\
|
||||
else \
|
||||
echo unknown ;\
|
||||
fi ;\
|
||||
else \
|
||||
echo unknown ;\
|
||||
fi)
|
||||
@@ -70,20 +89,7 @@ RPMARG=--define "_topdir $(BUILDDIR:/=)" \
|
||||
$(shell [ -d ${BUILDDIR}/BUILDROOT ] && echo --define \"buildroot $(BUILDDIR:/=)/BUILDROOT\") \
|
||||
$(shell [ -n "${DISTRO}" ] && echo --define \"distro ${DISTRO}\")
|
||||
|
||||
#REPO_VERSION=$(shell if [ -x /usr/bin/svn ] ; then \
|
||||
# if ! /usr/bin/svn info -r HEAD . 2> /dev/null | grep "^Last Changed Rev:" | sed "s/^Last Changed Rev: //" ; then \
|
||||
# /usr/bin/svn info . 2> /dev/null | grep "^Last Changed Rev:" | sed "s/^Last Changed Rev: //" ; \
|
||||
# fi ; \
|
||||
# fi)
|
||||
REPO_VERSION=$(shell if [ -x /usr/bin/svn ] ; then \
|
||||
/usr/bin/svn info . 2> /dev/null | grep "^Last Changed Rev:" | sed "s/^Last Changed Rev: //" ; \
|
||||
fi)
|
||||
REPO_URL=$(shell if [ -x /usr/bin/svn ] ; then \
|
||||
/usr/bin/svn info . 2> /dev/null | grep "^URL:" | sed "s/^URL: //" ; \
|
||||
fi)
|
||||
COMMON_REPO_URL=$(shell if [ -x /usr/bin/svn ] ; then \
|
||||
/usr/bin/svn info $(COMMONDIR) 2> /dev/null | grep "^URL:" | sed "s/^URL: //" ; \
|
||||
fi)
|
||||
REPO_VERSION_CMD=([ -x /usr/bin/bzr ] && /usr/bin/bzr version-info . 2> /dev/null || awk '{ print "revno: "$2 }' common/.stamp_rev) | awk '/^revno:/ { print $2 }'
|
||||
|
||||
ifdef EXTERNAL_PACKAGE
|
||||
RPMARG+=--define "_sourcedir $(shell pwd)"
|
||||
@@ -92,30 +98,14 @@ endif
|
||||
ifndef SPECFILE
|
||||
SPECFILE = $(NAME).spec
|
||||
endif
|
||||
RELEASE = $(shell rpm -q --specfile --define "_sourcedir ." ${RPMARG} --qf "%{RELEASE}" ${SPECFILE})
|
||||
RELEASE_DIR = $(NAME)-$(VERSION)
|
||||
TARBALL = $(NAME)-$(VERSION)-${REPO_VERSION}.tar.gz
|
||||
TAR = /bin/tar czvp -h --exclude .svn --exclude CVS --exclude .cvsignore --exclude ${TARBALL} --exclude ${RELEASE_DIR}/${RELEASE_DIR} $(shell test -f ${NAME}.exclude && echo "-X ${NAME}.exclude")
|
||||
TAR = /bin/tar czvp -h --exclude .svn --exclude .bzr --exclude .bzrignore --exclude ${RELEASE_DIR}/${RELEASE_DIR} $(shell test -f ${NAME}.exclude && echo "-X ${NAME}.exclude")
|
||||
LDCONFIG = /sbin/ldconfig
|
||||
|
||||
CVSPKG_VERSION=$(shell rpm -q --specfile --define "_sourcedir ." ${RPMARG} ${SPECFILE} | head -1 | tr "." "_")
|
||||
|
||||
RPMSUBDIRS=SOURCES SPECS BUILD BUILDROOT SRPMS RPMS/i386 RPMS/i586 \
|
||||
RPMS/i686 RPMS/athlon RPMS/noarch RPMS/x86_64
|
||||
BUILDRPMSUBDIRS=$(foreach subdir, $(RPMSUBDIRS), $(BUILDDIR:/=)/$(subdir))
|
||||
|
||||
.PHONY: cvs_tag
|
||||
cvs_tag:
|
||||
cvs tag IMMUNIX-${CVSPKG_VERSION}
|
||||
|
||||
.PHONY: checkin
|
||||
checkin:
|
||||
if cvs -q up -d | grep -q "^\?" ; then echo "Hey! You have" \
|
||||
"files in the directory you have not added into cvs."; exit 1; \
|
||||
fi
|
||||
cvs ci
|
||||
make cvs_tag
|
||||
|
||||
ifdef EXTERNAL_PACKAGE
|
||||
.PHONY: rpm
|
||||
rpm: clean $(BUILDRPMSUBDIRS)
|
||||
@@ -123,21 +113,25 @@ rpm: clean $(BUILDRPMSUBDIRS)
|
||||
|
||||
else
|
||||
.PHONY: rpm
|
||||
rpm: clean $(TARBALL) $(BUILDRPMSUBDIRS)
|
||||
cp $(TARBALL) $(BUILDDIR)/SOURCES/
|
||||
rpm: clean $(BUILDRPMSUBDIRS)
|
||||
__REPO_VERSION=`$(value REPO_VERSION_CMD)` ; \
|
||||
__TARBALL=$(NAME)-$(VERSION)-$${__REPO_VERSION}.tar.gz ; \
|
||||
make $${__TARBALL} ; \
|
||||
cp $${__TARBALL} $(BUILDDIR)/SOURCES/
|
||||
cp ${SPECFILE} $(BUILDDIR)/SPECS/
|
||||
rpmbuild -ba ${RPMARG} ${SPECFILE}
|
||||
|
||||
.PHONY: ${SPECFILE}
|
||||
${SPECFILE}: ${SPECFILE}.in
|
||||
__REPO_VERSION=`$(value REPO_VERSION_CMD)` ; \
|
||||
sed -e "s/@@immunix_version@@/${VERSION}/g" \
|
||||
-e "s/@@repo_version@@/${REPO_VERSION}/g" $< > $@
|
||||
-e "s/@@repo_version@@/$${__REPO_VERSION}/g" $< > $@
|
||||
|
||||
${TARBALL}: clean ${SPECFILE}
|
||||
%.tar.gz: clean ${SPECFILE}
|
||||
-rm -rf $(RELEASE_DIR)
|
||||
mkdir $(RELEASE_DIR)
|
||||
$(TAR) . | tar xz -C $(RELEASE_DIR)
|
||||
$(TAR) -f $@ $(RELEASE_DIR)
|
||||
$(TAR) --exclude $@ . | tar xz -C $(RELEASE_DIR)
|
||||
$(TAR) --exclude $@ -f $@ $(RELEASE_DIR)
|
||||
rm -rf $(RELEASE_DIR)
|
||||
|
||||
ifndef OVERRIDE_TARBALL
|
||||
@@ -145,22 +139,30 @@ ifndef OVERRIDE_TARBALL
|
||||
tarball: clean $(TARBALL)
|
||||
endif
|
||||
|
||||
.PHONY: dist
|
||||
dist: clean $(SPECFILE)
|
||||
-rm -rf $(RELEASE_DIR)
|
||||
svn export -r $(REPO_VERSION) $(REPO_URL) $(RELEASE_DIR)
|
||||
svn export $(COMMON_REPO_URL) $(RELEASE_DIR)/common
|
||||
make -C $(RELEASE_DIR) $(SPECFILE) REPO_VERSION=${REPO_VERSION} COMMONDIR_EXISTS=false
|
||||
$(TAR) -f $(TARBALL) $(RELEASE_DIR)
|
||||
rm -rf $(RELEASE_DIR)
|
||||
|
||||
endif
|
||||
|
||||
ifndef PYTHON_VERSIONS
|
||||
PYTHON_VERSIONS = $(call map, pathsearch, python2 python3)
|
||||
endif
|
||||
|
||||
ifndef PYTHON
|
||||
PYTHON = $(firstword ${PYTHON_VERSIONS})
|
||||
endif
|
||||
|
||||
#Helper function to be used with $(call pyalldo, run_test_with_all.py)
|
||||
pyalldo=set -e; $(foreach py, $(PYTHON_VERSIONS), $(py) $(1);)
|
||||
|
||||
.PHONY: version
|
||||
.SILENT: version
|
||||
version:
|
||||
rpm -q --define "_sourcedir ." ${RPMARG} --specfile ${SPECFILE}
|
||||
|
||||
.PHONY: repo_version
|
||||
.SILENT: repo_version
|
||||
repo_version:
|
||||
$(value REPO_VERSION_CMD)
|
||||
|
||||
|
||||
.PHONY: build_dir
|
||||
build_dir: $(BUILDRPMSUBDIRS)
|
||||
|
||||
@@ -173,6 +175,40 @@ _clean:
|
||||
-rm -f ${NAME}-${VERSION}-*.tar.gz
|
||||
-rm -f ${MANPAGES} *.[0-9].gz ${HTMLMANPAGES} pod2htm*.tmp
|
||||
|
||||
# =====================
|
||||
# generate list of capabilities based on
|
||||
# /usr/include/linux/capabilities.h for use in multiple locations in
|
||||
# the source tree
|
||||
# =====================
|
||||
|
||||
# emits defined capabilities in a simple list, e.g. "CAP_NAME CAP_NAME2"
|
||||
CAPABILITIES=$(shell echo "\#include <linux/capability.h>" | cpp -dM | LC_ALL=C sed -n -e '/CAP_EMPTY_SET/d' -e 's/^\#define[ \t]\+CAP_\([A-Z0-9_]\+\)[ \t]\+\([0-9xa-f]\+\)\(.*\)$$/CAP_\1/p' | sort)
|
||||
|
||||
.PHONY: list_capabilities
|
||||
list_capabilities: /usr/include/linux/capability.h
|
||||
@echo "$(CAPABILITIES)"
|
||||
|
||||
# =====================
|
||||
# generate list of network protocols based on
|
||||
# sys/socket.h for use in multiple locations in
|
||||
# the source tree
|
||||
# =====================
|
||||
|
||||
# These are the families that it doesn't make sense for apparmor
|
||||
# to mediate. We use PF_ here since that is what is required in
|
||||
# bits/socket.h, but we will rewrite these as AF_.
|
||||
|
||||
FILTER_FAMILIES=PF_UNSPEC PF_UNIX
|
||||
|
||||
__FILTER=$(shell echo $(strip $(FILTER_FAMILIES)) | sed -e 's/ /\\\|/g')
|
||||
|
||||
# emits the AF names in a "AF_NAME NUMBER," pattern
|
||||
AF_NAMES=$(shell echo "\#include <sys/socket.h>" | cpp -dM | LC_ALL=C sed -n -e '/$(__FILTER)/d' -e 's/PF_LOCAL/PF_UNIX/' -e 's/^\#define[ \t]\+PF_\([A-Z0-9_]\+\)[ \t]\+\([0-9]\+\).*$$/AF_\1 \2,/p' | sort -n -k2)
|
||||
|
||||
.PHONY: list_af_names
|
||||
list_af_names:
|
||||
@echo "$(AF_NAMES)"
|
||||
|
||||
# =====================
|
||||
# manpages
|
||||
# =====================
|
||||
@@ -191,32 +227,12 @@ install_manpages: $(MANPAGES)
|
||||
$(foreach dir, ${MANDIRS}, \
|
||||
install -d ${DESTDIR}/${MANDIR}/man${dir} ; \
|
||||
install -m 644 $(filter %.${dir}, ${MANPAGES}) ${DESTDIR}/${MANDIR}/man${dir}; \
|
||||
$(foreach aa_page, $(filter %.${dir}, ${AA_MANPAGES}), \
|
||||
ln -sf $(aa_page) ${DESTDIR}/${MANDIR}/man${dir}/${aa_page:%=aa-%};))
|
||||
)
|
||||
|
||||
%.1: %.pod
|
||||
$(POD2MAN) $< --release=NOVELL/SUSE --center=AppArmor --section=1 > $@
|
||||
MAN_RELEASE="AppArmor ${VERSION}"
|
||||
|
||||
%.2: %.pod
|
||||
$(POD2MAN) $< --release=NOVELL/SUSE --center=AppArmor --section=2 > $@
|
||||
|
||||
%.3: %.pod
|
||||
$(POD2MAN) $< --release=NOVELL/SUSE --center=AppArmor --section=3 > $@
|
||||
|
||||
%.4: %.pod
|
||||
$(POD2MAN) $< --release=NOVELL/SUSE --center=AppArmor --section=4 > $@
|
||||
|
||||
%.5: %.pod
|
||||
$(POD2MAN) $< --release=NOVELL/SUSE --center=AppArmor --section=5 > $@
|
||||
|
||||
%.6: %.pod
|
||||
$(POD2MAN) $< --release=NOVELL/SUSE --center=AppArmor --section=6 > $@
|
||||
|
||||
%.7: %.pod
|
||||
$(POD2MAN) $< --release=NOVELL/SUSE --center=AppArmor --section=7 > $@
|
||||
|
||||
%.8: %.pod
|
||||
$(POD2MAN) $< --release=NOVELL/SUSE --center=AppArmor --section=8 > $@
|
||||
%.1 %.2 %.3 %.4 %.5 %.6 %.7 %.8: %.pod
|
||||
$(POD2MAN) $< --release=$(MAN_RELEASE) --center=AppArmor --stderr --section=$(subst .,,$(suffix $@)) > $@
|
||||
|
||||
%.1.html: %.pod
|
||||
$(POD2HTML) --header --css apparmor.css --infile=$< --outfile=$@
|
||||
@@ -242,43 +258,6 @@ install_manpages: $(MANPAGES)
|
||||
%.8.html: %.pod
|
||||
$(POD2HTML) --header --css apparmor.css --infile=$< --outfile=$@
|
||||
|
||||
# =====================
|
||||
# Slackware poo
|
||||
# =====================
|
||||
.PHONY: slack
|
||||
slack:
|
||||
rm -rf ${BUILDDIR}
|
||||
mkdir -p ${BUILDDIR}/install
|
||||
make install DESTDIR=${BUILDDIR} DISTRO=slackware
|
||||
# comment line is there so grep always has something to match
|
||||
( echo "# install script pulled from ${SPECFILE}" ; rpm -q --specfile --define "_sourcedir ." ${RPMARG} --qf "%{POSTIN}\n" ${SPECFILE}) | grep -v "^(none)$$" >> ${BUILDDIR}/install/doinst.sh
|
||||
( cd ${BUILDDIR} && makepkg -l y -c y -p ${PWD}/${NAME}-${VERSION}-${RELEASE}.tgz )
|
||||
|
||||
# =====================
|
||||
# Debian poo
|
||||
# =====================
|
||||
.PHONY: deb
|
||||
deb: ${TARBALL}
|
||||
rm -rf ${BUILDDIR}
|
||||
mkdir -p ${BUILDDIR}
|
||||
tar -xvzf ${TARBALL} -C ${BUILDDIR}
|
||||
( cd ${BUILDDIR}/${RELEASE_DIR} && sh -c "DEBFULLNAME='NOVELL, Inc' dh_make -e apparmor-general@forge.novell.com --library -f ~/svn/immunix/immunix/libimmunix/libimmunix-2.0.tar.gz << EOM \
|
||||
\
|
||||
EOM" )
|
||||
make ${NAME}-deb -C ${BUILDDIR}/${RELEASE_DIR}
|
||||
# ( cd ${BUILDDIR}/${RELEASE_DIR} && dpkg-buildpackage -b -sd -rfakeroot)
|
||||
|
||||
DEBIAN_DISTRO=stable
|
||||
|
||||
DEB_CHANGELOG_OUTPUT="${NAME} (${VERSION}-${RELEASE}) ${DEBIAN_DISTRO}; urgency=low\n\
|
||||
\n * Automatically generated by the AppArmor Build System.\n\
|
||||
\n -- AppArmor Development Team <apparmor-general@forge.novell.com> $(shell date -R)"
|
||||
|
||||
|
||||
.PHONY: debian/changelog
|
||||
debian/changelog:
|
||||
echo -e ${DEB_CHANGELOG_OUTPUT} > $@
|
||||
|
||||
A2PS_ARGS=-Ec -g --line-numbers=1
|
||||
ENSCRIPT_ARGS=-C -2jGr -f Courier6 -E
|
||||
%.c.ps: %.c
|
||||
@@ -287,3 +266,7 @@ ENSCRIPT_ARGS=-C -2jGr -f Courier6 -E
|
||||
|
||||
%.pm.ps: %.pm
|
||||
enscript ${ENSCRIPT_ARGS} -o $@ $<
|
||||
|
||||
.PHONY: check_pod_files
|
||||
check_pod_files:
|
||||
LANG=C podchecker -warning -warning *.pod
|
||||
|
1
common/Version
Normal file
1
common/Version
Normal file
@@ -0,0 +1 @@
|
||||
2.8.97
|
@@ -1,7 +1,4 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $Id: rc.aaeventd.suse 268 2006-12-12 10:54:44Z steve-beattie $
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
# NOVELL (All rights reserved)
|
||||
@@ -136,5 +133,5 @@ case "$1" in
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
esac
|
||||
exit $rc
|
@@ -1,7 +1,4 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 1999, 2000, 2001, 2002, 2003 2004, 2005, 2006, 2007
|
||||
# NOVELL (All rights reserved)
|
||||
@@ -30,7 +27,7 @@
|
||||
### BEGIN INIT INFO
|
||||
# Provides: aaeventd
|
||||
# Required-Start: apparmor
|
||||
# Required-Stop:
|
||||
# Required-Stop: $null
|
||||
# Default-Start: 2 3 5
|
||||
# Default-Stop:
|
||||
# Short-Description: AppArmor Notification and Reporting
|
||||
@@ -81,9 +78,9 @@ usage() {
|
||||
|
||||
start_aa_event() {
|
||||
if [ -x "$AA_EV_BIN" -a "${APPARMOR_ENABLE_AAEVENTD}" = "yes" ] ; then
|
||||
sd_action "Starting AppArmor Event daemon" startproc -f -p $AA_EV_PIDFILE $AA_EV_BIN -p $AA_EV_PIDFILE
|
||||
sd_action "Starting AppArmor Event daemon" startproc -p $AA_EV_PIDFILE $AA_EV_BIN -p $AA_EV_PIDFILE
|
||||
elif [ -x "$SD_EV_BIN" -a "${APPARMOR_ENABLE_AAEVENTD}" = "yes" ] ; then
|
||||
sd_action "Starting AppArmor Event daemon" startproc -f -p $SD_EV_PIDFILE $SD_EV_BIN -p $SD_EV_PIDFILE
|
||||
sd_action "Starting AppArmor Event daemon" startproc -p $SD_EV_PIDFILE $SD_EV_BIN -p $SD_EV_PIDFILE
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -131,6 +128,6 @@ case "$1" in
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
esac
|
||||
exit $rc
|
||||
|
File diff suppressed because it is too large
Load Diff
124
deprecated/utils/Immunix/Config.pm
Normal file
124
deprecated/utils/Immunix/Config.pm
Normal file
@@ -0,0 +1,124 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2006 Novell, Inc. All Rights Reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, contact Novell, Inc.
|
||||
#
|
||||
# To contact Novell about this file by physical or electronic mail,
|
||||
# you may find current contact information at www.novell.com.
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
package Immunix::Config;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Carp;
|
||||
use Cwd qw(cwd realpath);
|
||||
use File::Basename;
|
||||
use File::Temp qw/ tempfile tempdir /;
|
||||
use Data::Dumper;
|
||||
use Locale::gettext;
|
||||
use POSIX;
|
||||
|
||||
require Exporter;
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw(
|
||||
read_config
|
||||
write_config
|
||||
find_first_file
|
||||
find_first_dir
|
||||
);
|
||||
|
||||
our $confdir = "/etc/apparmor";
|
||||
|
||||
# config vars
|
||||
our $cfg;
|
||||
our $repo_cfg;
|
||||
|
||||
sub read_config {
|
||||
my $filename = shift;
|
||||
my $config;
|
||||
|
||||
if (open(CONF, "$confdir/$filename")) {
|
||||
my $which;
|
||||
while (<CONF>) {
|
||||
chomp;
|
||||
# ignore comments
|
||||
next if /^\s*#/;
|
||||
if (m/^\[(\S+)\]/) {
|
||||
$which = $1;
|
||||
} elsif (m/^\s*(\S+)\s*=\s*(.*)\s*$/) {
|
||||
my ($key, $value) = ($1, $2);
|
||||
$config->{$which}{$key} = $value;
|
||||
}
|
||||
}
|
||||
close(CONF);
|
||||
}
|
||||
|
||||
# LP: #692406
|
||||
# Explicitly disable the repository until there is an alternative, since
|
||||
# the OpenSUSE site went away
|
||||
if ($filename eq "repository.conf") {
|
||||
$config->{repository}{enabled} = "no";
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
sub write_config {
|
||||
my ($filename, $config) = @_;
|
||||
if (open(my $CONF, ">$confdir/$filename")) {
|
||||
for my $section (sort keys %$config) {
|
||||
print $CONF "[$section]\n";
|
||||
|
||||
for my $key (sort keys %{$config->{$section}}) {
|
||||
print $CONF " $key = $config->{$section}{$key}\n"
|
||||
if ($config->{$section}{$key});
|
||||
}
|
||||
}
|
||||
chmod(0600, $CONF);
|
||||
close($CONF);
|
||||
} else {
|
||||
die "Can't write config file $filename: $!";
|
||||
}
|
||||
}
|
||||
|
||||
sub find_first_file {
|
||||
my $list = shift;
|
||||
return if ( not defined $list );
|
||||
my $filename;
|
||||
for my $f (split(/\s+/, $list)) {
|
||||
if (-f $f) {
|
||||
$filename = $f;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
return $filename;
|
||||
}
|
||||
|
||||
sub find_first_dir {
|
||||
my $list = shift;
|
||||
return if ( not defined $list );
|
||||
my $dirname;
|
||||
for my $f (split(/\s+/, $list)) {
|
||||
if (-d $f) {
|
||||
$dirname = $f;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
return $dirname;
|
||||
}
|
||||
|
||||
1;
|
@@ -1,4 +1,3 @@
|
||||
# $Id$
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2005-2006 Novell/SUSE
|
||||
@@ -14,7 +13,7 @@ package Immunix::Reports;
|
||||
################################################################################
|
||||
# /usr/lib/perl5/site_perl/Reports.pm
|
||||
#
|
||||
# - Parses /var/log/messages for SubDomain messages
|
||||
# - Parses /var/log/messages for AppArmor messages
|
||||
# - Writes results to .html or comma-delimited (.csv) files (Optional)
|
||||
#
|
||||
# Requires:
|
||||
@@ -967,7 +966,7 @@ sub getEssStats {
|
||||
};
|
||||
|
||||
if ($@) {
|
||||
ycp::y2error(sprintf(gettext("DBI Execution failed: %s"), $DBI::errstr));
|
||||
ycp::y2error(sprintf(gettext("DBI Execution failed: %s."), $DBI::errstr));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -980,7 +979,7 @@ sub getEssStats {
|
||||
};
|
||||
|
||||
if ($@) {
|
||||
ycp::y2error(sprintf(gettext("DBI Execution failed: %s"), $DBI::errstr));
|
||||
ycp::y2error(sprintf(gettext("DBI Execution failed: %s."), $DBI::errstr));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -988,7 +987,7 @@ sub getEssStats {
|
||||
eval { $ret = $dbh->selectall_arrayref("$query"); };
|
||||
|
||||
if ($@) {
|
||||
ycp::y2error(sprintf(gettext("DBI Execution failed: %s"), $DBI::errstr));
|
||||
ycp::y2error(sprintf(gettext("DBI Execution failed: %s."), $DBI::errstr));
|
||||
return;
|
||||
}
|
||||
|
354
deprecated/utils/Immunix/Repository.pm
Normal file
354
deprecated/utils/Immunix/Repository.pm
Normal file
@@ -0,0 +1,354 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2008 Dominic Reynolds
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
package Immunix::Repository;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Carp;
|
||||
use Cwd qw(cwd realpath);
|
||||
use Data::Dumper;
|
||||
use File::Basename;
|
||||
use File::Temp qw/ tempfile tempdir /;
|
||||
use Immunix::Config;
|
||||
use Locale::gettext;
|
||||
use POSIX;
|
||||
use RPC::XML;
|
||||
use RPC::XML::Client;
|
||||
|
||||
|
||||
require Exporter;
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw(
|
||||
get_repo_client
|
||||
did_result_succeed
|
||||
get_result_error
|
||||
user_login
|
||||
user_register
|
||||
upload_profile
|
||||
fetch_profile_by_id
|
||||
fetch_profiles_by_user
|
||||
fetch_profiles_by_name
|
||||
fetch_profiles_by_name_and_user
|
||||
fetch_newer_profile
|
||||
get_repo_config
|
||||
set_repo_config
|
||||
);
|
||||
|
||||
our %clients;
|
||||
our %uid2login;
|
||||
our $DEBUGGING = 0;
|
||||
our $repo_cfg;
|
||||
our $aa_cfg;
|
||||
|
||||
sub get_repo_client ($) {
|
||||
my $repo_url = shift;
|
||||
unless ( $clients{$repo_url} ) {
|
||||
$clients{$repo_url} = new RPC::XML::Client $repo_url;
|
||||
}
|
||||
return $clients{$repo_url};
|
||||
}
|
||||
|
||||
sub did_result_succeed {
|
||||
my $result = shift;
|
||||
|
||||
my $ref = ref $result;
|
||||
return ($ref && $ref ne "RPC::XML::fault") ? 1 : 0;
|
||||
}
|
||||
|
||||
sub get_result_error {
|
||||
my $result = shift;
|
||||
|
||||
if (ref $result) {
|
||||
if (ref $result eq "RPC::XML::fault") {
|
||||
$result = $result->string;
|
||||
} else {
|
||||
$result = $$result;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
sub user_login ($$$) {
|
||||
my ($repo_url,$user,$pass) = @_;
|
||||
my ($status,$detail);
|
||||
my $repo_client = get_repo_client( $repo_url );
|
||||
if ( $repo_client ) {
|
||||
my $res = $repo_client->send_request('LoginConfirm', $user, $pass);
|
||||
if (did_result_succeed($res)) {
|
||||
$status = 1;
|
||||
$detail = "";
|
||||
} else {
|
||||
$status = 0;
|
||||
$detail = get_result_error($res);
|
||||
}
|
||||
}
|
||||
return $status,$detail;
|
||||
}
|
||||
|
||||
|
||||
sub user_register ($$$$) {
|
||||
my ($repo_url,$user,$pass,$email) = @_;
|
||||
my $repo_client = get_repo_client( $repo_url );
|
||||
my ($status,$detail);
|
||||
if ( $repo_client ) {
|
||||
my $res = $repo_client->send_request('Signup', $user, $pass, $email);
|
||||
if (did_result_succeed($res)) {
|
||||
$status = 1;
|
||||
$detail = "";
|
||||
} else {
|
||||
$status = 0;
|
||||
$detail = get_result_error($res);
|
||||
}
|
||||
}
|
||||
return $status,$detail;
|
||||
}
|
||||
|
||||
sub upload_profile ($$$$$$$) {
|
||||
my ($repo_url,$user,$pass,$distro,$pname,$profile,$changelog) = @_;
|
||||
my ($status,$detail);
|
||||
my $repo_client = get_repo_client( $repo_url );
|
||||
my $res = $repo_client->send_request( 'Create', $user, $pass, $distro,
|
||||
$pname, $profile, $changelog);
|
||||
if (did_result_succeed($res)) {
|
||||
$detail = $res->value;
|
||||
$status = 1;
|
||||
} else {
|
||||
$detail = get_result_error($res);
|
||||
$status = 0;
|
||||
}
|
||||
return $status,$detail;
|
||||
}
|
||||
|
||||
sub fetch_profile_by_id ($$) {
|
||||
my ($repo_url,$id) = @_;
|
||||
my $repo_client = get_repo_client( $repo_url );
|
||||
my $repo_profile;
|
||||
my ($status,$detail);
|
||||
my $res = $repo_client->send_request('Show', $id);
|
||||
if (did_result_succeed($res)) {
|
||||
$status = 1;
|
||||
$detail = $res->value();
|
||||
} else {
|
||||
$status = 0;
|
||||
$detail = get_result_error($res);
|
||||
}
|
||||
|
||||
return $status, $detail;
|
||||
}
|
||||
|
||||
|
||||
sub fetch_profiles ($$$$) {
|
||||
my ($repo_url,$distro,$username,$fqdn) = @_;
|
||||
my $p_hash = {};
|
||||
my ($status,$detail);
|
||||
my $repo_client = get_repo_client( $repo_url );
|
||||
my $res =
|
||||
$repo_client->send_request('FindProfiles', $distro, $fqdn, $username);
|
||||
if (did_result_succeed($res)) {
|
||||
$status = 1;
|
||||
for my $p ( @$res ) {
|
||||
my $p_repo = $p->{profile}->value();
|
||||
$p_repo =~ s/flags=\(complain\)// if ( $p_repo ); #strip complain flag
|
||||
$p->{profile} = $p_repo;
|
||||
$p->{user_id} = $p->{user_id}->value();
|
||||
$p->{id} = $p->{id}->value();
|
||||
$p->{name} = $p->{name}->value();
|
||||
$p->{created_at} = $p->{created_at}->value();
|
||||
$p->{downloaded_count} = $p->{downloaded_count}->value();
|
||||
}
|
||||
$detail = $res;
|
||||
} else {
|
||||
$status = 0;
|
||||
$detail = get_result_error($res);
|
||||
}
|
||||
return $status,$detail;
|
||||
}
|
||||
|
||||
sub fetch_profiles_by_user ($$$) {
|
||||
my ($repo_url,$distro,$username) = @_;
|
||||
my $p_hash = {};
|
||||
my ($status,$detail) = fetch_profiles( $repo_url, $distro, $username, "" );
|
||||
if ( $status ) {
|
||||
for my $p ( @$detail ) {
|
||||
my $p_repo = $p->{profile};
|
||||
if ($p_repo ne "") {
|
||||
$p->{username} = $username;
|
||||
$p_hash->{$p->{name}} = $p;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return ($status,$detail);
|
||||
}
|
||||
return($status,$p_hash);
|
||||
}
|
||||
|
||||
|
||||
sub fetch_profiles_by_name_and_user ($$$$) {
|
||||
my ($repo_url,$distro,$fqdbin, $username) = @_;
|
||||
my $p_hash = {};
|
||||
my ($status,$detail) = fetch_profiles( $repo_url, $distro, $username, $fqdbin );
|
||||
if ( $status ) {
|
||||
for my $p ( @$detail ) {
|
||||
my $p_repo = $p->{profile}?$p->{profile}:"";
|
||||
$p_hash->{$p->{name}} = $p if ($p_repo ne "");
|
||||
}
|
||||
} else {
|
||||
return ($status,$detail);
|
||||
}
|
||||
return($status,$p_hash);
|
||||
}
|
||||
|
||||
|
||||
sub fetch_profiles_by_name ($$$) {
|
||||
my ($repo_url,$distro,$fqdbin) = @_;
|
||||
my ($status,$detail,$data);
|
||||
$detail = {};
|
||||
($status,$data) = fetch_profiles( $repo_url, $distro, "", $fqdbin);
|
||||
if ($status) {
|
||||
my @uids;
|
||||
for my $p (@$data) {
|
||||
push @uids, $p->{user_id};
|
||||
}
|
||||
my ($status_unames,$unames) = fetch_usernames_from_uids($repo_url, @uids);
|
||||
if ( $status_unames ) {
|
||||
for my $p (@$data) {
|
||||
if ( $unames->{$p->{user_id}} ) {
|
||||
$p->{username} = $unames->{$p->{user_id}};
|
||||
} else {
|
||||
$p->{username} = "unkown-" . $p->{user_id};
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
print STDOUT "ERROR UID\n";
|
||||
}
|
||||
for my $p (@$data) {
|
||||
$p->{profile_type} = "REPOSITORY";
|
||||
$detail->{$p->{username}} = $p;
|
||||
}
|
||||
} else {
|
||||
$detail = $data;
|
||||
}
|
||||
return $status,$detail;
|
||||
}
|
||||
|
||||
|
||||
sub fetch_newer_profile ($$$$$) {
|
||||
my ($repo_url,$distro,$user,$id,$profile) = @_;
|
||||
my $repo_client = get_repo_client( $repo_url );
|
||||
my $p;
|
||||
my ($status,$detail);
|
||||
|
||||
if ($repo_client) {
|
||||
my $res =
|
||||
$repo_client->send_request('FindProfiles', $distro, $profile, $user);
|
||||
if (did_result_succeed($res)) {
|
||||
my @profiles;
|
||||
my @profile_list = @{$res->value};
|
||||
$status = 1;
|
||||
|
||||
if (@profile_list) {
|
||||
if ($profile_list[0]->{id} > $id) {
|
||||
$p = $profile_list[0];
|
||||
}
|
||||
}
|
||||
$detail = $p;
|
||||
} else {
|
||||
$status = 0;
|
||||
$detail = get_result_error($res);
|
||||
}
|
||||
}
|
||||
return $status,$detail;
|
||||
}
|
||||
|
||||
sub fetch_usernames_from_uids ($) {
|
||||
my ($repo_url,@searchuids) = @_;
|
||||
my ($status,$result) = (1,{});
|
||||
my @uids;
|
||||
|
||||
for my $uid ( @searchuids ) {
|
||||
if ( $uid2login{$uid} ) {
|
||||
$result->{$uid} = $uid2login{$uid};
|
||||
} else {
|
||||
push @uids, $uid;
|
||||
}
|
||||
}
|
||||
if (@uids) {
|
||||
my $repo_client = get_repo_client( $repo_url );
|
||||
#RPC::XML will serialize the array into XML with the is_utf8 flag set
|
||||
#which causes, HTTP:Message to fail. Looping on the array elements
|
||||
#stops this from happening, and since these are all numbers it
|
||||
#will not cause problems.
|
||||
for my $foo (@uids) {
|
||||
Encode::_utf8_off($foo);
|
||||
}
|
||||
my $res = $repo_client->send_request('LoginNamesFromUserIds', [@uids]);
|
||||
if (did_result_succeed($res)) {
|
||||
my @usernames = @{ $res->value };
|
||||
for my $uid (@uids) {
|
||||
my $username = shift @usernames;
|
||||
$uid2login{$uid} = $username;
|
||||
$result->{$uid} = $uid2login{$uid};
|
||||
}
|
||||
} else {
|
||||
$status = 0;
|
||||
$result = get_result_error($res);
|
||||
}
|
||||
}
|
||||
return $status,$result;
|
||||
}
|
||||
|
||||
sub get_repo_config {
|
||||
unless ( $repo_cfg ) {
|
||||
$repo_cfg = Immunix::Config::read_config("repository.conf");
|
||||
}
|
||||
unless ( $aa_cfg ) {
|
||||
$aa_cfg = Immunix::Config::read_config("logprof.conf");
|
||||
}
|
||||
return {
|
||||
"url" => $aa_cfg->{repository}{url},
|
||||
"distro" => $aa_cfg->{repository}{distro},
|
||||
"enabled" => $repo_cfg->{repository}{enabled},
|
||||
"upload" => $repo_cfg->{repository}{upload},
|
||||
"user" => $repo_cfg->{repository}{user},
|
||||
"password" => $repo_cfg->{repository}{pass},
|
||||
"email" => $repo_cfg->{repository}{email}
|
||||
};
|
||||
}
|
||||
|
||||
sub set_repo_config ($) {
|
||||
my $cfg = shift;
|
||||
my ($url,$distro,$enabled,$upload,$user,$pass);
|
||||
unless ( $repo_cfg ) {
|
||||
$repo_cfg = Immunix::Config::read_config("repository.conf");
|
||||
}
|
||||
unless ( $aa_cfg ) {
|
||||
$aa_cfg = Immunix::Config::read_config("logprof.conf");
|
||||
}
|
||||
$repo_cfg->{repository}{enabled} = $cfg->{enabled} if ( $cfg->{enabled} );
|
||||
$repo_cfg->{repository}{upload} = $cfg->{upload} if ( $cfg->{upload} );
|
||||
$repo_cfg->{repository}{user} = $cfg->{user} if ( $cfg->{user} );
|
||||
$repo_cfg->{repository}{pass} = $cfg->{password}if ( $cfg->{password} );
|
||||
$repo_cfg->{repository}{email} = $cfg->{email} if ( $cfg->{email} );
|
||||
$aa_cfg->{repository}{distro} = $cfg->{distro} if ( $cfg->{distro} );
|
||||
$aa_cfg->{repository}{url} = $cfg->{url} if ( $cfg->{url} );
|
||||
write_config("repository.conf", $repo_cfg);
|
||||
write_config("logprof.conf", $aa_cfg);
|
||||
}
|
||||
|
||||
|
||||
1;
|
@@ -1,4 +1,3 @@
|
||||
# $Id$
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2005-2006 Novell/SUSE
|
69
deprecated/utils/Makefile
Normal file
69
deprecated/utils/Makefile
Normal file
@@ -0,0 +1,69 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 1999, 2004-2009 NOVELL (All rights reserved)
|
||||
# Copyright (c) 2010-2011, 2014 Canonical Ltd.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, contact Novell, Inc.
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
# NOTE: this Makefile has been adjusted from the original to assist in
|
||||
# the installation of the Immunix perl modules, if they're still needed
|
||||
# by users. Because the utilities conflict with their replacments, make
|
||||
# install *will* *not* install them.
|
||||
|
||||
NAME = apparmor-utils
|
||||
all:
|
||||
COMMONDIR=../../common/
|
||||
|
||||
include common/Make.rules
|
||||
|
||||
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
|
||||
ifeq ($(COMMONDIR_EXISTS), true)
|
||||
common/Make.rules: $(COMMONDIR)/Make.rules
|
||||
ln -sf $(COMMONDIR) .
|
||||
endif
|
||||
|
||||
MODDIR = Immunix
|
||||
PERLTOOLS = aa-genprof aa-logprof aa-autodep aa-audit aa-complain aa-enforce \
|
||||
aa-unconfined aa-disable
|
||||
MODULES = ${MODDIR}/AppArmor.pm ${MODDIR}/Repository.pm \
|
||||
${MODDIR}/Config.pm ${MODDIR}/Severity.pm
|
||||
|
||||
all:
|
||||
|
||||
# need some better way of determining this
|
||||
DESTDIR=/
|
||||
BINDIR=${DESTDIR}/usr/sbin
|
||||
CONFDIR=${DESTDIR}/etc/apparmor
|
||||
VENDOR_PERL=$(shell perl -e 'use Config; print $$Config{"vendorlib"};')
|
||||
PERLDIR=${DESTDIR}${VENDOR_PERL}/${MODDIR}
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
install -d ${PERLDIR}
|
||||
install -m 644 ${MODULES} ${PERLDIR}
|
||||
|
||||
.PHONY: clean
|
||||
ifndef VERBOSE
|
||||
.SILENT: clean
|
||||
endif
|
||||
clean: _clean
|
||||
rm -f core core.* *.o *.s *.a *~
|
||||
rm -f Make.rules
|
||||
rm -rf staging/ build/
|
||||
|
||||
.PHONY: check
|
||||
.SILENT: check
|
||||
check:
|
||||
for i in ${MODULES} ${PERLTOOLS} ; do \
|
||||
perl -c $$i || exit 1; \
|
||||
done
|
@@ -1,9 +1,7 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
|
||||
# Copyright (c) 2011 Canonical, Ltd.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -25,7 +23,7 @@ use strict;
|
||||
use FindBin;
|
||||
use Getopt::Long;
|
||||
|
||||
use Immunix::SubDomain;
|
||||
use Immunix::AppArmor;
|
||||
|
||||
use Data::Dumper;
|
||||
|
||||
@@ -53,7 +51,7 @@ GetOptions(
|
||||
$profiledir = get_full_path($profiledir);
|
||||
|
||||
unless (-d $profiledir) {
|
||||
UI_Important("Can't find subdomain profiles in $profiledir.");
|
||||
UI_Important("Can't find AppArmor profiles in $profiledir.");
|
||||
exit 1;
|
||||
}
|
||||
|
||||
@@ -107,14 +105,19 @@ for my $profiling (@profiling) {
|
||||
print "\n";
|
||||
setprofileflags($filename, "audit");
|
||||
|
||||
system("cat $filename | $parser -I$profiledir -r >/dev/null 2>&1")
|
||||
if check_for_subdomain();
|
||||
my $cmd_info = qx(cat $filename | $parser -I$profiledir -r 2>&1 1>/dev/null);
|
||||
if ($? != 0) {
|
||||
UI_Info($cmd_info);
|
||||
exit $?;
|
||||
}
|
||||
|
||||
# if check_for_subdomain();
|
||||
} else {
|
||||
if ($profiling =~ /^[^\/]+$/) {
|
||||
UI_Info(sprintf(gettext('Can\'t find %s in the system path list. If the name of the application is correct, please run \'which %s\' as a user with the correct PATH environment set up in order to find the fully-qualified path.'), $profiling, $profiling));
|
||||
exit 1;
|
||||
} else {
|
||||
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.') . $profiling));
|
||||
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.'), $profiling));
|
||||
exit 1;
|
||||
}
|
||||
}
|
@@ -1,9 +1,7 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
|
||||
# Copyright (c) 2011 Canonical, Ltd.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -25,7 +23,7 @@ use strict;
|
||||
use FindBin;
|
||||
use Getopt::Long;
|
||||
|
||||
use Immunix::SubDomain;
|
||||
use Immunix::AppArmor;
|
||||
|
||||
use Data::Dumper;
|
||||
|
||||
@@ -60,7 +58,7 @@ my $sd_mountpoint = check_for_subdomain();
|
||||
$profiledir = get_full_path($profiledir);
|
||||
|
||||
unless (-d $profiledir) {
|
||||
UI_Important(sprintf(gettext('Can\'t find subdomain profiles in %s.'), $profiledir));
|
||||
UI_Important(sprintf(gettext('Can\'t find AppArmor profiles in %s.'), $profiledir));
|
||||
exit 1;
|
||||
}
|
||||
|
||||
@@ -109,7 +107,7 @@ for my $profiling (@profiling) {
|
||||
UI_Info(sprintf(gettext('Can\'t find %s in the system path list. If the name of the application is correct, please run \'which %s\' as a user with the correct PATH environment set up in order to find the fully-qualified path.'), $profiling, $profiling));
|
||||
exit 1;
|
||||
} else {
|
||||
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.') . $profiling));
|
||||
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.'), $profiling));
|
||||
exit 1;
|
||||
}
|
||||
}
|
@@ -1,7 +1,4 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
|
||||
#
|
||||
@@ -25,7 +22,7 @@ use strict;
|
||||
use FindBin;
|
||||
use Getopt::Long;
|
||||
|
||||
use Immunix::SubDomain;
|
||||
use Immunix::AppArmor;
|
||||
|
||||
use Data::Dumper;
|
||||
|
||||
@@ -53,7 +50,7 @@ GetOptions(
|
||||
$profiledir = get_full_path($profiledir);
|
||||
|
||||
unless (-d $profiledir) {
|
||||
UI_Important("Can't find subdomain profiles in $profiledir.");
|
||||
UI_Important("Can't find AppArmor profiles in $profiledir.");
|
||||
exit 1;
|
||||
}
|
||||
|
||||
@@ -107,8 +104,13 @@ for my $profiling (@profiling) {
|
||||
print "\n";
|
||||
setprofileflags($filename, "complain");
|
||||
|
||||
system("cat $filename | $parser -I$profiledir -r >/dev/null 2>&1")
|
||||
if check_for_subdomain();
|
||||
my $cmd_info = qx(cat $filename | $parser -I$profiledir -r 2>&1 1>/dev/null);
|
||||
if ($? != 0) {
|
||||
UI_Info($cmd_info);
|
||||
exit $?;
|
||||
}
|
||||
|
||||
# if check_for_subdomain();
|
||||
} else {
|
||||
if ($profiling =~ /^[^\/]+$/) {
|
||||
UI_Info(sprintf(gettext('Can\'t find %s in the system path list. If the name of the application is correct, please run \'which %s\' as a user with the correct PATH environment set up in order to find the fully-qualified path.'), $profiling, $profiling));
|
152
deprecated/utils/aa-disable
Executable file
152
deprecated/utils/aa-disable
Executable file
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/perl
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2005-2010 Novell, Inc. All Rights Reserved.
|
||||
# Copyright (c) 2011 Canonical, Inc. All Rights Reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, contact Canonical, Inc.
|
||||
#
|
||||
# To contact Canonical about this file by physical or electronic mail,
|
||||
# you may find current contact information at www.canonical.com.
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
use strict;
|
||||
use FindBin;
|
||||
use Getopt::Long;
|
||||
|
||||
use Immunix::AppArmor;
|
||||
|
||||
use Data::Dumper;
|
||||
|
||||
use Locale::gettext;
|
||||
use POSIX;
|
||||
use File::Basename;
|
||||
|
||||
# initialize the local poo
|
||||
setlocale(LC_MESSAGES, "");
|
||||
textdomain("apparmor-utils");
|
||||
|
||||
$UI_Mode = "text";
|
||||
|
||||
# options variables
|
||||
my $help = '';
|
||||
|
||||
GetOptions(
|
||||
'dir|d=s' => \$profiledir,
|
||||
'help|h' => \$help,
|
||||
);
|
||||
|
||||
# tell 'em how to use it...
|
||||
&usage && exit if $help;
|
||||
|
||||
# let's convert it to full path...
|
||||
$profiledir = get_full_path($profiledir);
|
||||
|
||||
unless (-d $profiledir) {
|
||||
UI_Important("Can't find AppArmor profiles in $profiledir.");
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $disabledir = "$profiledir/disable";
|
||||
unless (-d $disabledir) {
|
||||
UI_Important("Can't find AppArmor disable directory '$disabledir'.");
|
||||
exit 1;
|
||||
}
|
||||
|
||||
# what are we profiling?
|
||||
my @profiling = @ARGV;
|
||||
|
||||
unless (@profiling) {
|
||||
@profiling = (UI_GetString(gettext("Please enter the program whose profile should be disabled: "), ""));
|
||||
}
|
||||
|
||||
for my $profiling (@profiling) {
|
||||
|
||||
next unless $profiling;
|
||||
|
||||
my $fqdbin;
|
||||
if (-e $profiling) {
|
||||
$fqdbin = get_full_path($profiling);
|
||||
chomp($fqdbin);
|
||||
} else {
|
||||
if ($profiling !~ /\//) {
|
||||
opendir(DIR,$profiledir);
|
||||
my @tmp_fqdbin = grep ( /$profiling/, readdir(DIR));
|
||||
closedir(DIR);
|
||||
if (scalar @tmp_fqdbin eq 1) {
|
||||
$fqdbin = "$profiledir/$tmp_fqdbin[0]";
|
||||
} else {
|
||||
my $which = which($profiling);
|
||||
if ($which) {
|
||||
$fqdbin = get_full_path($which);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (-e $fqdbin) {
|
||||
|
||||
my $filename;
|
||||
if ($fqdbin =~ /^$profiledir\//) {
|
||||
$filename = $fqdbin;
|
||||
} else {
|
||||
$filename = getprofilefilename($fqdbin);
|
||||
}
|
||||
|
||||
# argh, skip directories
|
||||
next unless -f $filename;
|
||||
|
||||
# skip package manager backup files
|
||||
next if isSkippableFile($filename);
|
||||
|
||||
my ($bname, $dname, $suffix) = File::Basename::fileparse($filename);
|
||||
if ($bname eq "") {
|
||||
UI_Info(sprintf(gettext('Could not find basename for %s.'), $filename));
|
||||
exit 1;
|
||||
}
|
||||
|
||||
printf(gettext('Disabling %s.'), $fqdbin);
|
||||
print "\n";
|
||||
|
||||
my $link = "$disabledir/$bname";
|
||||
if (! -e $link) {
|
||||
if (symlink($filename, $link) != 1) {
|
||||
UI_Info(sprintf(gettext('Could not create %s symlink.'), $link));
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
|
||||
my $cmd_info = qx(cat $filename | $parser -I$profiledir -R 2>&1 1>/dev/null);
|
||||
if ($? != 0) {
|
||||
UI_Info($cmd_info);
|
||||
exit $?;
|
||||
}
|
||||
|
||||
# if check_for_subdomain();
|
||||
} else {
|
||||
if ($profiling =~ /^[^\/]+$/) {
|
||||
UI_Info(sprintf(gettext('Can\'t find %s in the system path list. If the name of the application is correct, please run \'which %s\' as a user with the correct PATH environment set up in order to find the fully-qualified path.'), $profiling, $profiling));
|
||||
exit 1;
|
||||
} else {
|
||||
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.'), $profiling));
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit 0;
|
||||
|
||||
sub usage {
|
||||
UI_Info(sprintf(gettext("usage: \%s [ -d /path/to/profiles ] [ program to have profile disabled ]"), $0));
|
||||
exit 0;
|
||||
}
|
||||
|
@@ -1,9 +1,7 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
|
||||
# Copyright (c) 2011 Canonical, Ltd.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -25,7 +23,7 @@ use strict;
|
||||
use FindBin;
|
||||
use Getopt::Long;
|
||||
|
||||
use Immunix::SubDomain;
|
||||
use Immunix::AppArmor;
|
||||
|
||||
use Data::Dumper;
|
||||
|
||||
@@ -53,7 +51,7 @@ GetOptions(
|
||||
$profiledir = get_full_path($profiledir);
|
||||
|
||||
unless (-d $profiledir) {
|
||||
UI_Important("Can't find subdomain profiles in $profiledir.");
|
||||
UI_Important("Can't find AppArmor profiles in $profiledir.");
|
||||
exit 1;
|
||||
}
|
||||
|
||||
@@ -106,14 +104,30 @@ for my $profiling (@profiling) {
|
||||
print "\n";
|
||||
setprofileflags($filename, "");
|
||||
|
||||
system("cat $filename | $parser -I$profiledir -r >/dev/null 2>&1")
|
||||
if check_for_subdomain();
|
||||
# remove symlink in $profiledir/force-complain as well
|
||||
my $complainlink = $filename;
|
||||
$complainlink =~ s/^$profiledir/$profiledir\/force-complain/;
|
||||
-e $complainlink and unlink($complainlink);
|
||||
|
||||
# remove symlink in $profiledir/disable as well
|
||||
my $disablelink = $filename;
|
||||
$disablelink =~ s/^$profiledir/$profiledir\/disable/;
|
||||
-e $disablelink and unlink($disablelink);
|
||||
|
||||
my $cmd_info = qx(cat $filename | $parser -I$profiledir -r 2>&1 1>/dev/null);
|
||||
if ($? != 0) {
|
||||
UI_Info($cmd_info);
|
||||
exit $?;
|
||||
}
|
||||
|
||||
|
||||
# if check_for_subdomain();
|
||||
} else {
|
||||
if ($profiling =~ /^[^\/]+$/) {
|
||||
UI_Info(sprintf(gettext('Can\'t find %s in the system path list. If the name of the application is correct, please run \'which %s\' as a user with the correct PATH environment set up in order to find the fully-qualified path.'), $profiling, $profiling));
|
||||
exit 1;
|
||||
} else {
|
||||
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.') . $profiling));
|
||||
UI_Info(sprintf(gettext('%s does not exist, please double-check the path.'), $profiling));
|
||||
exit 1;
|
||||
}
|
||||
}
|
@@ -1,7 +1,5 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
# $Id$
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
|
||||
#
|
@@ -1,7 +1,4 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
|
||||
#
|
||||
@@ -24,13 +21,33 @@
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
|
||||
use Immunix::SubDomain;
|
||||
use Immunix::AppArmor;
|
||||
|
||||
use Data::Dumper;
|
||||
|
||||
use Locale::gettext;
|
||||
use POSIX;
|
||||
|
||||
sub sysctl_read($) {
|
||||
my $path = shift;
|
||||
my $value = undef;
|
||||
if (open(SYSCTL, "<$path")) {
|
||||
$value = int(<SYSCTL>);
|
||||
}
|
||||
close(SYSCTL);
|
||||
return $value;
|
||||
}
|
||||
|
||||
sub sysctl_write($$) {
|
||||
my $path = shift;
|
||||
my $value = shift;
|
||||
return if (!defined($value));
|
||||
if (open(SYSCTL, ">$path")) {
|
||||
print SYSCTL $value;
|
||||
close(SYSCTl);
|
||||
}
|
||||
}
|
||||
|
||||
# force $PATH to be sane
|
||||
$ENV{PATH} = "/bin:/sbin:/usr/bin:/usr/sbin";
|
||||
|
||||
@@ -52,14 +69,14 @@ GetOptions(
|
||||
|
||||
my $sd_mountpoint = check_for_subdomain();
|
||||
unless ($sd_mountpoint) {
|
||||
fatal_error(gettext("SubDomain does not appear to be started. Please enable SubDomain and try again."));
|
||||
fatal_error(gettext("AppArmor does not appear to be started. Please enable AppArmor and try again."));
|
||||
}
|
||||
|
||||
# let's convert it to full path...
|
||||
$profiledir = get_full_path($profiledir);
|
||||
|
||||
unless (-d $profiledir) {
|
||||
fatal_error "Can't find subdomain profiles in $profiledir.";
|
||||
fatal_error "Can't find AppArmor profiles in $profiledir.";
|
||||
}
|
||||
|
||||
# what are we profiling?
|
||||
@@ -112,6 +129,17 @@ if ($helpers{$fqdbin} eq "enforce") {
|
||||
reload($fqdbin);
|
||||
}
|
||||
|
||||
# When reading from syslog, it is possible to hit the default kernel
|
||||
# printk ratelimit. This will result in audit entries getting skipped,
|
||||
# making profile generation inaccurate. When using genprof, disable
|
||||
# the printk ratelimit, and restore it on exit.
|
||||
my $ratelimit_sysctl = "/proc/sys/kernel/printk_ratelimit";
|
||||
my $ratelimit_saved = sysctl_read($ratelimit_sysctl);
|
||||
END { sysctl_write($ratelimit_sysctl, $ratelimit_saved); }
|
||||
sysctl_write($ratelimit_sysctl, 0);
|
||||
|
||||
UI_Info(gettext("\nBefore you begin, you may wish to check if a\nprofile already exists for the application you\nwish to confine. See the following wiki page for\nmore information:\nhttp://wiki.apparmor.net/index.php/Profiles"));
|
||||
|
||||
UI_Important(gettext("Please start the application to be profiled in \nanother window and exercise its functionality now.\n\nOnce completed, select the \"Scan\" button below in \norder to scan the system logs for AppArmor events. \n\nFor each AppArmor event, you will be given the \nopportunity to choose whether the access should be \nallowed or denied."));
|
||||
|
||||
my $syslog = 1;
|
||||
@@ -166,7 +194,8 @@ for my $p (sort keys %helpers) {
|
||||
}
|
||||
}
|
||||
|
||||
UI_Info(gettext("Reloaded SubDomain profiles in enforce mode."));
|
||||
UI_Info(gettext("Reloaded AppArmor profiles in enforce mode."));
|
||||
UI_Info(gettext("\nPlease consider contributing your new profile! See\nthe following wiki page for more information:\nhttp://wiki.apparmor.net/index.php/Profiles\n"));
|
||||
UI_Info(sprintf(gettext('Finished generating profile for %s.'), $fqdbin));
|
||||
exit 0;
|
||||
|
@@ -1,7 +1,4 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
|
||||
#
|
||||
@@ -27,7 +24,7 @@ use Getopt::Long;
|
||||
use Locale::gettext;
|
||||
use POSIX;
|
||||
|
||||
use Immunix::SubDomain;
|
||||
use Immunix::AppArmor;
|
||||
|
||||
# force $PATH to be sane
|
||||
$ENV{PATH} = "/bin:/sbin:/usr/bin:/usr/sbin";
|
||||
@@ -56,7 +53,7 @@ GetOptions(
|
||||
$profiledir = get_full_path($profiledir);
|
||||
|
||||
unless (-d $profiledir) {
|
||||
fatal_error "Can't find subdomain profiles in $profiledir.";
|
||||
fatal_error "Can't find AppArmor profiles in $profiledir.";
|
||||
}
|
||||
|
||||
# load all the include files
|
821
deprecated/utils/aa-repo.pl
Normal file
821
deprecated/utils/aa-repo.pl
Normal file
@@ -0,0 +1,821 @@
|
||||
#!/usr/bin/perl
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2008 Dominic Reynolds. All Rights Reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
#
|
||||
my $usage =
|
||||
"aa-repo.pl --command args\n";
|
||||
|
||||
my $usage_search =
|
||||
" --search [author=XXX] [prog=XXX] [id=XXX]
|
||||
Search the repository for profiles matching the search criteria
|
||||
and return the results.
|
||||
NOTE: One --search switch per option
|
||||
|
||||
--verbose|v
|
||||
Verbosity level. Supply either one or two switches. Two switches
|
||||
adds full profile text in returned search results.\n";
|
||||
|
||||
my $usage_push =
|
||||
|
||||
" --push [--profile=XXX|all] [--changelog=XXX]
|
||||
Push local profiles to repository, uses configured user and upon
|
||||
overwrite of an existing profile in the repository then prompt
|
||||
user with a diff for confirmation XXX the name of the application
|
||||
whose profile should be uploaded or \"all\" to upload all
|
||||
profiles. Multiple --profile switches may be passed to supply
|
||||
multiple profile names
|
||||
|
||||
e.g. --push --profile /usr/sbin/mdnsd --profile /usr/sbin/ftp
|
||||
e.g. --push --profile all\n";
|
||||
|
||||
my $usage_pull =
|
||||
" --pull [--author=XXX] [--profile=XXX] or [--id=XXX] [--mode=complain]
|
||||
pull remote profiles and install on local system
|
||||
If operation will change local profiles then prompt user with
|
||||
diff for confirmation
|
||||
NOTE: One --pull switch per option and there are three acceptable
|
||||
combinations
|
||||
|
||||
--pull --author=XXX
|
||||
* pull all profiles in the repo for the author
|
||||
|
||||
--pull --author=XXX --profile=XXXX
|
||||
* pull the profile for prog owned by author
|
||||
|
||||
--pull --id=XXXX
|
||||
* pull the profile with id
|
||||
|
||||
--pull --mode=complain
|
||||
* set the profile(s) to complain mode when installed
|
||||
|
||||
Profiles are checked for conflicts with currently installed
|
||||
profiles and presented as a list to the user to confirm and view.\n";
|
||||
|
||||
|
||||
my $usage_sync =
|
||||
" --sync [--up] [--down] [--noconfirm]
|
||||
Synchronize local profile set with the repository - showing
|
||||
changes and allowing prompting the user with the diffs and
|
||||
suggest the newest version to be activated. If the --all option
|
||||
is passed then treat profiles not marked as remote as new
|
||||
profiles that will be uploaded to the repository.\n";
|
||||
|
||||
my $usage_stat =
|
||||
" --status
|
||||
Show the current status of the local profile set. This operation
|
||||
is similar to sync but does not prompt the user to up|down load
|
||||
changes\n";
|
||||
|
||||
my $usage_getconfig =
|
||||
" --getconfig|c
|
||||
Print the current configuration for the repsository\n";
|
||||
|
||||
|
||||
my $usage_setconfig =
|
||||
" --setconfig [url=xxx] [username=xxxx] [password=xxxx] [enabled=(yes|no)]
|
||||
[upload=(yes|no)]
|
||||
Set the configuration options for the repository.
|
||||
NOTE: One --setconfig switch per option\n";
|
||||
|
||||
my $usage_bottom =
|
||||
" --quiet|q Don't prompt user - assume that all changes should be made.
|
||||
|
||||
ISSUES:
|
||||
o Should changes made to the system be recorded somehow? An audit event?
|
||||
o Should the tool allow a repo/distro to be passed for each operation?
|
||||
|
||||
";
|
||||
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
|
||||
use Immunix::AppArmor;
|
||||
use Immunix::Repository;
|
||||
use Data::Dumper;
|
||||
|
||||
use Locale::gettext;
|
||||
use POSIX;
|
||||
|
||||
# force $PATH to be sane
|
||||
$ENV{PATH} = "/bin:/sbin:/usr/bin:/usr/sbin";
|
||||
|
||||
# initialize the local poo
|
||||
setlocale(LC_MESSAGES, "");
|
||||
textdomain("apparmor-utils");
|
||||
|
||||
# options variables
|
||||
my $help = '';
|
||||
my $verbose = '';
|
||||
|
||||
my ( $id, $author, $mode, %search, $sync, $getconfig, $push,
|
||||
$pull, %setconfig, @profiles, $all, $changelog, $stat );
|
||||
|
||||
GetOptions(
|
||||
'search=s%' => \%search,
|
||||
'sync=s' => \$sync,
|
||||
'status' => \$stat,
|
||||
'getconfig|c' => \$getconfig,
|
||||
'setconfig=s%' => \%setconfig,
|
||||
'push' => \$push,
|
||||
'id=s' => \$id,
|
||||
'author=s' => \$author,
|
||||
'profile=s' => \@profiles,
|
||||
'changelog=s' => \$changelog,
|
||||
'pull' => \$pull,
|
||||
'all|a' => \$all,
|
||||
'help|h' => \$help,
|
||||
'verbose|v+' => \$verbose
|
||||
);
|
||||
|
||||
#
|
||||
# Root privs required to run the repo tool
|
||||
#
|
||||
if ( geteuid() != 0 ) {
|
||||
print STDERR gettext(
|
||||
"You must be logged in with root user privileges to use this program.\n"
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
# --help
|
||||
# tell 'em how to use it...
|
||||
&usage && exit if $help;
|
||||
|
||||
my $config = get_repo_config();
|
||||
|
||||
#
|
||||
# --getconfig operation
|
||||
#
|
||||
&config && exit if $getconfig;
|
||||
|
||||
my $sd_mountpoint = check_for_subdomain();
|
||||
unless ($sd_mountpoint) {
|
||||
fatal_error(gettext(
|
||||
"AppArmor does not appear to be started. Please enable AppArmor and try again."
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#
|
||||
# --setconfig operation
|
||||
#
|
||||
if ( keys %setconfig ) {
|
||||
$config->{url} = $setconfig{url} if ( $setconfig{url} );
|
||||
$config->{distro} = $setconfig{distro} if ( $setconfig{distro} );
|
||||
$config->{enabled} = $setconfig{enabled} if ( $setconfig{enabled} );
|
||||
$config->{email} = $setconfig{email} if ( $setconfig{email} );
|
||||
$config->{user} = $setconfig{username} if ( $setconfig{username} );
|
||||
$config->{password} = $setconfig{password} if ( $setconfig{password} );
|
||||
$config->{upload} = $setconfig{upload} if ( $setconfig{upload} );
|
||||
set_repo_config( $config );
|
||||
}
|
||||
|
||||
#
|
||||
# --push operation
|
||||
#
|
||||
if ( $push ) {
|
||||
my ($conflicts, $repo_profiles, $local_profiles, @overrides);
|
||||
if ( ! @profiles ) {
|
||||
print STDERR gettext(
|
||||
"Must supply at least one profile using \"--profile XXX\" to --push\n"
|
||||
);
|
||||
exit 1;
|
||||
} else {
|
||||
print STDERR Data::Dumper->Dump([@profiles], [qw(*profiles)]);
|
||||
}
|
||||
my $changelog = $changelog?$changelog:"none";
|
||||
push_profiles( \@profiles, $changelog, 1 );
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# --pull operation
|
||||
#
|
||||
if ( $pull ) {
|
||||
my $type = "";
|
||||
if ( $id ) {
|
||||
if ( $author || @profiles ) {
|
||||
print STDERR gettext(
|
||||
"Option --id=XX is only allowed by itself and not in combination to
|
||||
other options for the --pull command.\n"
|
||||
);
|
||||
exit 1;
|
||||
}
|
||||
$type = "id";
|
||||
}
|
||||
if ( @profiles && ! $author ) {
|
||||
print STDERR gettext(
|
||||
"Option --profile=XX requires that the --author=XX option be supplied
|
||||
to distinguish a specific profile.\n"
|
||||
);
|
||||
exit 1;
|
||||
} else {
|
||||
$type = "profile";
|
||||
}
|
||||
|
||||
my $mode = $mode eq "complain"?1:0;
|
||||
pull_profiles( \@profiles, $type, $mode, 1 );
|
||||
}
|
||||
|
||||
#
|
||||
# --search operation
|
||||
#
|
||||
if ( keys %search ) {
|
||||
if ( $search{id} ) {
|
||||
my($status,$result) = fetch_profile_by_id( $config->{url},
|
||||
$search{id} );
|
||||
if ($status) {
|
||||
my $title = sprintf(gettext( "Profile ID %s\n"), $search{id});
|
||||
console_print_search_results( $title,
|
||||
"profile",
|
||||
{ $result->{name} => $result }
|
||||
);
|
||||
|
||||
} else {
|
||||
print STDERR "ERROR $result\n";
|
||||
}
|
||||
} elsif ( $search{author} && $search{prog} ) {
|
||||
my($status,$result) =
|
||||
fetch_profiles_by_name_and_user( $config->{url},
|
||||
$config->{distro},
|
||||
$search{prog},
|
||||
$search{author}
|
||||
);
|
||||
if ( $status ) {
|
||||
my $title =
|
||||
sprintf(gettext("Profiles matching user: %s and program: %s\n"),
|
||||
$search{author},
|
||||
$search{prog}
|
||||
);
|
||||
console_print_search_results( $title, "profile", $result );
|
||||
} else {
|
||||
print STDERR "ERROR $result\n";
|
||||
}
|
||||
} elsif ( $search{author} ) {
|
||||
my($status,$result) = fetch_profiles_by_user( $config->{url},
|
||||
$config->{distro},
|
||||
$search{author}
|
||||
);
|
||||
if ( $status ) {
|
||||
my $title = sprintf(gettext( "Profiles for %s\n"), $search{author});
|
||||
console_print_search_results( $title, "profile", $result );
|
||||
} else {
|
||||
print STDERR "ERROR $result\n";
|
||||
}
|
||||
} elsif ( $search{prog} ) {
|
||||
my($status,$result) = fetch_profiles_by_name( $config->{url},
|
||||
$config->{distro},
|
||||
$search{prog},
|
||||
);
|
||||
if ( $status ) {
|
||||
my $title = sprintf(gettext("Profiles matching program: %s\n"),
|
||||
$search{prog});
|
||||
console_print_search_results( $title, "user", $result );
|
||||
} else {
|
||||
print STDERR "ERROR $result\n";
|
||||
}
|
||||
} else {
|
||||
print STDERR
|
||||
"Unsupported search criteria. Please specify at least one of
|
||||
author=XXX prog=XXX id=XXX\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ( $stat ) {
|
||||
my ( $local_profiles, $remote_profiles );
|
||||
my $msg =
|
||||
" The following profiles are stored in the repository but
|
||||
are not synchronized with the copy in the repository\n";
|
||||
|
||||
my ($status, $result) = fetch_profiles_by_user( $config->{url},
|
||||
$config->{distro},
|
||||
$config->{user}
|
||||
);
|
||||
if ( $status ) {
|
||||
$remote_profiles = $result;
|
||||
} else {
|
||||
print STDERR sprintf(gettext("ERROR connecting to repository: %s\n"),
|
||||
$result);
|
||||
exit;
|
||||
}
|
||||
|
||||
readprofiles();
|
||||
$local_profiles = serialize_local_profiles( \%sd );
|
||||
my ($local_only,$unsynched,$synched,$conflicts) = ({}, {}, {});
|
||||
$unsynched = find_profile_conflicts($remote_profiles, $local_profiles);
|
||||
for my $p ( keys %$local_profiles ) {
|
||||
if ( ! $remote_profiles->{$p} ) {
|
||||
$local_only->{$p} = $local_profiles->{$p};
|
||||
}
|
||||
}
|
||||
|
||||
for my $p ( keys %$remote_profiles ) {
|
||||
$synched->{$p} =
|
||||
$remote_profiles->{$p}->{profile} if ( ! %$unsynched->{$p} );
|
||||
}
|
||||
UI_status($synched, $unsynched, $local_only);
|
||||
}
|
||||
|
||||
######################
|
||||
# Helper functions
|
||||
######################
|
||||
|
||||
#
|
||||
# Compare the local profile set with the remote profile set.
|
||||
# Return a list of the conflicting profiles as a list
|
||||
# { PROFILE_NAME => [LOCAL_PROFILE, REMOTE_PROFILE] ]
|
||||
#
|
||||
#
|
||||
# remote_profiles = repository profiles as returned by one of the
|
||||
# Immunix::Repository::fetch... functions
|
||||
# local_profiles = hash ref containing
|
||||
# { name => serialized local profile }
|
||||
#
|
||||
#
|
||||
|
||||
sub find_profile_conflicts ($$) {
|
||||
my ($remote_profiles,$local_profiles) = @_;
|
||||
my $conflicts = {};
|
||||
for my $p ( keys(%$local_profiles) ) {
|
||||
if ( $local_profiles->{$p} and $remote_profiles->{$p} ) {
|
||||
my $p_local = $local_profiles->{$p};
|
||||
my $p_remote = $remote_profiles->{$p}->{profile};
|
||||
chomp($p_local);
|
||||
chomp($p_remote);
|
||||
if ( $p_remote ne $p_local ) {
|
||||
$conflicts->{$p} = [ $p_local, $p_remote ];
|
||||
}
|
||||
}
|
||||
}
|
||||
return( $conflicts );
|
||||
}
|
||||
|
||||
sub serialize_local_profiles ($) {
|
||||
my $profiles = shift;
|
||||
my $local_profiles = {};
|
||||
for my $p ( keys %$profiles ) {
|
||||
my $serialize_opts = {};
|
||||
$serialize_opts->{NO_FLAGS} = 1;
|
||||
my $p_local = serialize_profile( $profiles->{$p},
|
||||
$p,
|
||||
$serialize_opts );
|
||||
$local_profiles->{$p} = $p_local;
|
||||
}
|
||||
return $local_profiles;
|
||||
}
|
||||
|
||||
|
||||
sub console_print_search_results ($$$) {
|
||||
my ($title, $type,$result) = @_;
|
||||
open(PAGER, "| less") or die "Can't open pager";
|
||||
print PAGER $title;
|
||||
print PAGER "Found " . values(%$result) . " profiles \n";
|
||||
for my $p ( values(%$result) ) {
|
||||
if ( $verbose ) {
|
||||
if ( $type eq "user" ) {
|
||||
print PAGER " Author [ " . $p->{username} . " ]\n";
|
||||
} elsif ( $type eq "profile" ) {
|
||||
print PAGER " Name [ " . $p->{name} . " ]\n";
|
||||
}
|
||||
print PAGER " Created [ " . $p->{created_at} . " ]\n";
|
||||
print PAGER " Downloads [ " . $p->{downloaded_count} . " ]\n";
|
||||
print PAGER " ID [ " . $p->{id} . " ]\n";
|
||||
if ( $verbose > 1 ) {
|
||||
print PAGER " Profile [ \n" . $p->{profile} . " ]\n\n";
|
||||
} else {
|
||||
print PAGER "\n";
|
||||
}
|
||||
} else {
|
||||
my $data = $type eq "user"?$p->{username}:$p->{name};
|
||||
print PAGER " " . $data . "\n";
|
||||
}
|
||||
}
|
||||
close PAGER;
|
||||
}
|
||||
|
||||
sub UI_resolve_profile_conflicts {
|
||||
|
||||
my ($explanation, $conflict_hash) = @_;
|
||||
my $url = $config->{url};
|
||||
my @conflicts = map { [ $_,
|
||||
$conflict_hash->{$_}->[0],
|
||||
$conflict_hash->{$_}->[1]
|
||||
] }
|
||||
keys %$conflict_hash;
|
||||
my @commits = [];
|
||||
my $title = "Profile conflicts";
|
||||
my %resolution = ();
|
||||
my $q = {};
|
||||
$q->{title} = $title;
|
||||
$q->{headers} = [ "Repository", $url, ];
|
||||
|
||||
$q->{explanation} = $explanation;
|
||||
|
||||
$q->{functions} = [ "CMD_OVERWRITE",
|
||||
"CMD_KEEP",
|
||||
"CMD_VIEW_CHANGES",
|
||||
"CMD_ABORT",
|
||||
"CMD_CONTINUE", ];
|
||||
|
||||
$q->{default} = "CMD_OVERWRITE";
|
||||
$q->{options} = [ map { $_->[0] } @conflicts ];
|
||||
$q->{selected} = 0;
|
||||
|
||||
my ($ans, $arg);
|
||||
do {
|
||||
($ans, $arg) = UI_PromptUser($q);
|
||||
|
||||
if ($ans eq "CMD_VIEW_CHANGES") {
|
||||
display_changes($conflicts[$arg]->[2], $conflicts[$arg]->[1]);
|
||||
}
|
||||
if ( $ans eq "CMD_OVERWRITE") {
|
||||
$q->{options} =
|
||||
[ map { $_ =~ /$conflicts[$arg]->[0]( K| O)?$/?
|
||||
$conflicts[$arg]->[0] . " O":
|
||||
$_ }
|
||||
@{$q->{options}}
|
||||
];
|
||||
$resolution{$conflicts[$arg]->[0]} = "O";
|
||||
}
|
||||
if ( $ans eq "CMD_KEEP") {
|
||||
$q->{options} =
|
||||
[ map { $_ =~ /$conflicts[$arg]->[0]( K| O)?$/?
|
||||
$conflicts[$arg]->[0] . " K":
|
||||
$_ }
|
||||
@{$q->{options}}
|
||||
];
|
||||
$resolution{$conflicts[$arg]->[0]} = "K";
|
||||
}
|
||||
$q->{selected} = ($arg+1) % @conflicts;
|
||||
} until $ans =~ /^CMD_CONTINUE/;
|
||||
if ($ans eq "CMD_CONTINUE") {
|
||||
my @results = ();
|
||||
for my $p ( keys %resolution ) {
|
||||
if ( $resolution{$p} eq "O" ) {
|
||||
push @results, $p;
|
||||
}
|
||||
}
|
||||
return @results;
|
||||
}
|
||||
}
|
||||
|
||||
sub UI_display_profiles {
|
||||
my ($explanation, $profile_hash) = @_;
|
||||
my $url = $config->{url};
|
||||
my @profiles = map { [ $_, $profile_hash->{$_} ] } keys %$profile_hash;
|
||||
my $title = gettext("Profiles");
|
||||
my $q = {};
|
||||
$q->{title} = $title;
|
||||
$q->{headers} = [ "Repository", $url, ];
|
||||
|
||||
$q->{explanation} = $explanation;
|
||||
|
||||
$q->{functions} = [ "CMD_VIEW",
|
||||
"CMD_CONTINUE", ];
|
||||
|
||||
$q->{default} = "CMD_CONTINUE";
|
||||
$q->{options} = [ map { $_->[0] } @profiles ];
|
||||
$q->{selected} = 0;
|
||||
|
||||
my ($ans, $arg);
|
||||
do {
|
||||
($ans, $arg) = UI_PromptUser($q);
|
||||
|
||||
if ($ans eq "CMD_VIEW") {
|
||||
my $pager = get_pager();
|
||||
open ( PAGER, "| $pager" ) or die "Can't open $pager";
|
||||
print PAGER gettext("Profile: ") . $profiles[$arg]->[0] . "\n";
|
||||
print PAGER $profiles[$arg]->[1];
|
||||
close PAGER;
|
||||
}
|
||||
$q->{selected} = ($arg+1) % @profiles;
|
||||
} until $ans =~ /^CMD_CONTINUE/;
|
||||
return;
|
||||
}
|
||||
|
||||
sub UI_display_profile_conflicts {
|
||||
my ($explanation, $conflict_hash) = @_;
|
||||
my $url = $config->{url};
|
||||
my @conflicts = map { [ $_,
|
||||
$conflict_hash->{$_}->[0],
|
||||
$conflict_hash->{$_}->[1]
|
||||
] }
|
||||
keys %$conflict_hash;
|
||||
my @commits = [];
|
||||
my $title = gettext("Profile conflicts");
|
||||
my $q = {};
|
||||
$q->{title} = $title;
|
||||
$q->{headers} = [ "Repository", $url, ];
|
||||
|
||||
$q->{explanation} = $explanation;
|
||||
|
||||
$q->{functions} = [ "CMD_VIEW_CHANGES",
|
||||
"CMD_CONTINUE", ];
|
||||
|
||||
$q->{default} = "CMD_CONTINUE";
|
||||
$q->{options} = [ map { $_->[0] } @conflicts ];
|
||||
$q->{selected} = 0;
|
||||
|
||||
my ($ans, $arg);
|
||||
do {
|
||||
($ans, $arg) = UI_PromptUser($q);
|
||||
|
||||
if ($ans eq "CMD_VIEW_CHANGES") {
|
||||
display_changes($conflicts[$arg]->[2], $conflicts[$arg]->[1]);
|
||||
}
|
||||
$q->{selected} = ($arg+1) % @conflicts;
|
||||
} until $ans =~ /^CMD_CONTINUE/;
|
||||
return;
|
||||
}
|
||||
|
||||
sub usage {
|
||||
if ( $help eq "push" ) {
|
||||
print STDERR $usage . $usage_push ."\n";
|
||||
} elsif ( $help eq "pull" ) {
|
||||
print STDERR $usage . $usage_pull ."\n";
|
||||
} elsif ( $help eq "sync" ) {
|
||||
print STDERR $usage . $usage_sync ."\n";
|
||||
} elsif ( $help eq "getconfig" ) {
|
||||
print STDERR $usage . $usage_getconfig ."\n";
|
||||
} elsif ( $help eq "setconfig" ) {
|
||||
print STDERR $usage . $usage_setconfig ."\n";
|
||||
} elsif ( $help eq "status" ) {
|
||||
print STDERR $usage . $usage_stat ."\n";
|
||||
} elsif ( $help eq "search" ) {
|
||||
print STDERR $usage . $usage_search ."\n";
|
||||
} else {
|
||||
open(PAGER, "| less") or die "Can't open pager";
|
||||
print PAGER $usage .
|
||||
$usage_search .
|
||||
$usage_push .
|
||||
$usage_pull .
|
||||
$usage_sync .
|
||||
$usage_stat .
|
||||
$usage_setconfig .
|
||||
$usage_getconfig .
|
||||
$usage_bottom . "\n";
|
||||
close PAGER;
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# --getconfig helper function
|
||||
#
|
||||
sub config {
|
||||
my $configstr = gettext("Current config\n");
|
||||
my $config = get_repo_config();
|
||||
$configstr .= "\turl:\t\t$config->{url}\n";
|
||||
$configstr .= "\tdistro:\t\t$config->{distro}\n";
|
||||
$configstr .= "\tenabled:\t$config->{enabled}\n";
|
||||
$configstr .= "\temail:\t\t$config->{email}\n";
|
||||
$configstr .= "\tusername:\t$config->{user}\n";
|
||||
$configstr .= "\tpassword:\t$config->{password}\n";
|
||||
$configstr .= "\tupload:\t\t$config->{upload}\n";
|
||||
print STDERR $configstr . "\n";
|
||||
}
|
||||
|
||||
#
|
||||
# helper function to push profiles to the repository
|
||||
# used by --push and --sync options
|
||||
#
|
||||
sub push_profiles($$$) {
|
||||
my ( $p_ref, $changelog, $confirm ) = @_;
|
||||
my ( $conflicts, $remote_profiles, $local_profiles, @overrides );
|
||||
my @profiles = @$p_ref;
|
||||
|
||||
my $conflict_msg =
|
||||
" The following profile(s) selected for upload conflicts with a profile already
|
||||
stored in the repository for your account. Please choose whether to keep the
|
||||
current version or overwrite it.\n";
|
||||
$all = 0;
|
||||
|
||||
readprofiles();
|
||||
my ($status, $result) = fetch_profiles_by_user( $config->{url},
|
||||
$config->{distro},
|
||||
$config->{user}
|
||||
);
|
||||
if ( $status ) {
|
||||
$remote_profiles = $result;
|
||||
} else {
|
||||
print STDERR sprintf(gettext("ERROR connecting to repository: %s\n"),
|
||||
$result);
|
||||
exit;
|
||||
}
|
||||
|
||||
$all = 1 if ( grep(/^all$/, @profiles) );
|
||||
|
||||
if ( $all ) {
|
||||
$local_profiles = serialize_local_profiles( \%sd );
|
||||
} else {
|
||||
my $local_sd = {};
|
||||
for my $p ( @profiles ) {
|
||||
if ( !$sd{$p} ) {
|
||||
print STDERR
|
||||
sprintf(gettext("Profile for [%s] does not exist\n"), $p);
|
||||
exit;
|
||||
}
|
||||
$local_sd->{$p} = $sd{$p};
|
||||
}
|
||||
$local_profiles = serialize_local_profiles( $local_sd );
|
||||
}
|
||||
|
||||
$conflicts = find_profile_conflicts($remote_profiles, $local_profiles);
|
||||
|
||||
if ( keys %$conflicts ) {
|
||||
@overrides = UI_resolve_profile_conflicts( $conflict_msg, $conflicts );
|
||||
}
|
||||
|
||||
if ( $local_profiles ) {
|
||||
my @uploads;
|
||||
for my $p ( keys %$local_profiles ) {
|
||||
unless ( $conflicts->{$p} and !grep(/^$p$/, @overrides) ) {
|
||||
print STDERR gettext("Uploading ") . $p . "... ";
|
||||
my ($status,$result) = upload_profile( $config->{url},
|
||||
$config->{user},
|
||||
$config->{password},
|
||||
$config->{distro},
|
||||
$p,
|
||||
$local_profiles->{$p},
|
||||
$changelog
|
||||
);
|
||||
print STDERR gettext("done") . "\n";
|
||||
}
|
||||
if ( $status ) {
|
||||
push @uploads, $p;
|
||||
} else {
|
||||
print STDERR gettext("Error uploading") . "$p: $result\n";
|
||||
}
|
||||
}
|
||||
if ( @uploads ) {
|
||||
#
|
||||
# Currently the upload API with the repository returns the
|
||||
# the current users profile set before the update so we have
|
||||
# to refetch to obtain the metadata to update the local profiles
|
||||
#
|
||||
my $repo_p = [];
|
||||
print STDERR gettext("Updating local profile metedata....\n");
|
||||
my ($status,$result) = fetch_profiles_by_user( $config->{url},
|
||||
$config->{distro},
|
||||
$config->{user} );
|
||||
if ( $status ) {
|
||||
for my $p ( @uploads ) {
|
||||
push( @$repo_p, [$p, $result->{$p}] ) if ( $result->{$p} );
|
||||
}
|
||||
activate_repo_profiles( $config->{url}, $repo_p, 0 );
|
||||
print STDERR gettext(" done\n");
|
||||
} else {
|
||||
print STDERR gettext(
|
||||
"Failed to retrieve updated profiles from the repository. Error: "
|
||||
) . $result . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Helper function for pulling profiles from the repository
|
||||
# used by --pull and --sync options
|
||||
#
|
||||
sub pull_profiles($$$$) {
|
||||
my ( $p_ref, $mode, $confirm, $opts ) = @_;
|
||||
my @profiles = @$p_ref;
|
||||
my ( $conflicts, $commit_list, $remote_profiles,
|
||||
$local_profiles, @overrides );
|
||||
|
||||
my $conflict_msg =
|
||||
" The following profiles selected for download conflict with profiles
|
||||
already deployed on the system. Please choose whether to keep the local
|
||||
version or overwrite with the version from the repository\n";
|
||||
|
||||
readprofiles();
|
||||
|
||||
if ( $opts->{id} ) {
|
||||
my ($status,$newp) = fetch_profile_by_id( $config->{url}, $opts->{id} );
|
||||
if ( ! $status ) {
|
||||
print STDERR gettext(
|
||||
sprintf("Error occured during operation\n\t[%s]\n",
|
||||
$newp
|
||||
)
|
||||
);
|
||||
exit 1;
|
||||
} else {
|
||||
$remote_profiles = { $newp->{name} => $newp->{profile} };
|
||||
}
|
||||
} elsif ( @profiles && $opts->{author} ) {
|
||||
$remote_profiles = {};
|
||||
for my $p ( @profiles ) {
|
||||
my ($status,$profiles) =
|
||||
fetch_profiles_by_name_and_user( $config->{url},
|
||||
$config->{distro},
|
||||
$p,
|
||||
$opts->{author} );
|
||||
if ( ! $status ) {
|
||||
print STDERR gettext(sprintf(
|
||||
"Error occured during operation\n\t[%s]\n",
|
||||
$profiles
|
||||
)
|
||||
);
|
||||
exit 1;
|
||||
} else {
|
||||
$remote_profiles->{$p} = $profiles->{$p};
|
||||
}
|
||||
}
|
||||
} elsif ( $opts->{author} ) {
|
||||
my ($status,$profiles) = fetch_profiles_by_user( $config->{url},
|
||||
$config->{distro},
|
||||
$opts->{author} );
|
||||
if ( ! $status ) {
|
||||
print STDERR gettext(sprintf(
|
||||
"Error occured during operation\n\t[%s]\n",
|
||||
$profiles
|
||||
)
|
||||
);
|
||||
exit 1;
|
||||
} else {
|
||||
$remote_profiles = $profiles;
|
||||
}
|
||||
}
|
||||
$local_profiles = serialize_local_profiles( \%sd );
|
||||
$conflicts = find_profile_conflicts( $remote_profiles, $local_profiles );
|
||||
if ( keys %$conflicts ) {
|
||||
@overrides = UI_resolve_profile_conflicts( $conflict_msg, $conflicts );
|
||||
}
|
||||
for my $p ( keys %$remote_profiles ) {
|
||||
unless ( $conflicts->{$p} and !grep(/^$p$/, @overrides) ) {
|
||||
$remote_profiles->{$p}->{username} = $opts->{author};
|
||||
push @$commit_list, [$p, $remote_profiles->{$p}];
|
||||
}
|
||||
}
|
||||
|
||||
if ( $commit_list and @$commit_list ) {
|
||||
activate_repo_profiles( $config->{url}, $commit_list, $mode );
|
||||
system("rcapparmor reload");
|
||||
} else {
|
||||
UI_Info(gettext("No changes to make"));
|
||||
}
|
||||
}
|
||||
|
||||
sub UI_status {
|
||||
|
||||
my ($synched, $unsynched, $local) = @_;
|
||||
my $url = $config->{url};
|
||||
my $synched_text = gettext("Synchronized repository profiles:\t\t") .
|
||||
keys %$synched;
|
||||
my $unsynched_text = gettext("Unsynchronized repository profiles:\t") .
|
||||
keys %$unsynched;
|
||||
my $local_text = gettext("Local only profiles :\t\t\t") . keys %$local;
|
||||
my $options = [ $synched_text, $unsynched_text, $local_text ];
|
||||
my $title = gettext("Profile Status");
|
||||
my $explanation = gettext(
|
||||
" This is the current status of active profiles on the system.
|
||||
To view the profiles or unsyncronized changes select VIEW\n"
|
||||
);
|
||||
my $q = {};
|
||||
$q->{title} = $title;
|
||||
$q->{headers} = [ "Repository", $url, ];
|
||||
$q->{explanation} = $explanation;
|
||||
$q->{functions} = [ "CMD_VIEW", "CMD_FINISHED", ];
|
||||
$q->{default} = "CMD_FINISHED";
|
||||
$q->{options} = $options;
|
||||
$q->{selected} = 0;
|
||||
|
||||
my ($ans, $arg);
|
||||
do {
|
||||
($ans, $arg) = UI_PromptUser($q);
|
||||
|
||||
if ($ans eq "CMD_VIEW") {
|
||||
if ( $arg == 0 ) {
|
||||
UI_display_profiles(
|
||||
gettext("Profiles stored in the repository"),
|
||||
$synched
|
||||
);
|
||||
} elsif ( $arg == 1 ) {
|
||||
UI_display_profile_conflicts(
|
||||
gettext("Unsyncronised profile changes"),
|
||||
$unsynched
|
||||
);
|
||||
} elsif ( $arg == 2 ) {
|
||||
UI_display_profiles(
|
||||
gettext("Profiles stored in the repository"),
|
||||
$local
|
||||
);
|
||||
}
|
||||
}
|
||||
} until $ans =~ /^CMD_FINSHED/;
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,4 @@
|
||||
#!/usr/bin/perl -w
|
||||
# $Id$
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2005-2006 Novell/SUSE
|
||||
@@ -184,11 +183,11 @@ if ($count_complain) {
|
||||
if ($verbose) {
|
||||
print keys(%profiles) . " profiles are loaded.\n";
|
||||
print $#enforced_profiles + 1 . " profiles are in enforce mode.\n";
|
||||
for (@enforced_profiles) {
|
||||
for (sort(@enforced_profiles)) {
|
||||
print " " . $_ . "\n";
|
||||
}
|
||||
print $#complain_profiles + 1 . " profiles are in complain mode.\n";
|
||||
for (@complain_profiles) {
|
||||
for (sort(@complain_profiles)) {
|
||||
print " " . $_ . "\n";
|
||||
}
|
||||
}
|
||||
@@ -203,15 +202,15 @@ if ($verbose) {
|
||||
}
|
||||
print keys(%processes) . " processes have profiles defined.\n";
|
||||
print keys(%enforced_processes) . " processes are in enforce mode :\n";
|
||||
for (keys(%enforced_processes)) {
|
||||
for (sort { $enforced_processes{$a}{'profile'} cmp $enforced_processes{$b}{'profile'} } keys(%enforced_processes)) {
|
||||
print " " . $enforced_processes{$_}{'profile'} . " ($_) \n";
|
||||
}
|
||||
print keys(%complain_processes) . " processes are in complain mode.\n";
|
||||
for (keys(%complain_processes)) {
|
||||
for (sort { $complain_processes{$a}{'profile'} cmp $complain_processes{$b}{'profile'} } keys(%complain_processes)) {
|
||||
print " " . $complain_processes{$_}{'profile'} . " ($_) \n";
|
||||
}
|
||||
print keys(%unconfined_processes) . " processes are unconfined but have a profile defined.\n";
|
||||
for (keys(%unconfined_processes)) {
|
||||
for (sort { $unconfined_processes{$a}{'profile'} cmp $unconfined_processes{$b}{'profile'} } keys(%unconfined_processes)) {
|
||||
print " " . $unconfined_processes{$_}{'profile'} . " ($_) \n";
|
||||
}
|
||||
}
|
@@ -1,7 +1,4 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
|
||||
#
|
||||
@@ -25,9 +22,10 @@
|
||||
# audit local system for processes listening on network connections
|
||||
# that are not currently running with a profile.
|
||||
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
|
||||
use Immunix::SubDomain;
|
||||
use Immunix::AppArmor;
|
||||
use Locale::gettext;
|
||||
use POSIX;
|
||||
|
||||
@@ -53,7 +51,7 @@ sub usage {
|
||||
|
||||
my $subdomainfs = check_for_subdomain();
|
||||
|
||||
die gettext("SubDomain does not appear to be started. Please enable SubDomain and try again.") . "\n"
|
||||
die gettext("AppArmor does not appear to be started. Please enable AppArmor and try again.") . "\n"
|
||||
unless $subdomainfs;
|
||||
|
||||
my @pids;
|
||||
@@ -62,7 +60,7 @@ if ($paranoid) {
|
||||
@pids = grep { /^\d+$/ } readdir(PROC);
|
||||
closedir(PROC);
|
||||
} else {
|
||||
if (open(NETSTAT, "/bin/netstat -nlp |")) {
|
||||
if (open(NETSTAT, "LANG=C /bin/netstat -nlp |")) {
|
||||
while (<NETSTAT>) {
|
||||
chomp;
|
||||
push @pids, $5
|
||||
@@ -82,29 +80,34 @@ for my $pid (sort { $a <=> $b } @pids) {
|
||||
}
|
||||
close(CURRENT);
|
||||
}
|
||||
my $cmdline = `cat /proc/$pid/cmdline`;
|
||||
my $pname = (split(/\0/, $cmdline))[0];
|
||||
if ($pname =~ /\// && !($pname eq $prog)) {
|
||||
$pname = "($pname) ";
|
||||
} else {
|
||||
$pname = "";
|
||||
}
|
||||
if (not $attr) {
|
||||
if ($prog =~ m/^(\/usr\/bin\/python|\/usr\/bin\/perl|\/bin\/bash)$/) {
|
||||
|
||||
#my $scriptname = (split(/\0/, `cat /proc/$pid/cmdline`))[1];
|
||||
my $cmdline = `cat /proc/$pid/cmdline`;
|
||||
$cmdline =~ s/\0/ /g;
|
||||
$cmdline =~ s/\s+$//;
|
||||
chomp $cmdline;
|
||||
print "$pid $prog ($cmdline) " . gettext("not confined\n");
|
||||
} else {
|
||||
print "$pid $prog " . gettext("not confined\n");
|
||||
print "$pid $prog $pname" . gettext("not confined\n");
|
||||
}
|
||||
} else {
|
||||
if ($prog =~ m/^(\/usr\/bin\/python|\/usr\/bin\/perl|\/bin\/bash)$/) {
|
||||
|
||||
#my $scriptname = (split(/\0/, `cat /proc/$pid/cmdline`))[1];
|
||||
my $cmdline = `cat /proc/$pid/cmdline`;
|
||||
$cmdline =~ s/\0/ /g;
|
||||
$cmdline =~ s/\s+$//;
|
||||
chomp $cmdline;
|
||||
print "$pid $prog ($cmdline) " . gettext("confined by") . " '$attr'\n";
|
||||
} else {
|
||||
print "$pid $prog " . gettext("confined by") . " '$attr'\n";
|
||||
print "$pid $prog $pname" . gettext("confined by") . " '$attr'\n";
|
||||
}
|
||||
}
|
||||
}
|
BIN
documentation/AppArmor Developer 1 - Kernel Notes.odt
Normal file
BIN
documentation/AppArmor Developer 1 - Kernel Notes.odt
Normal file
Binary file not shown.
Binary file not shown.
BIN
documentation/AppArmor Developer 3 - HFA.odt
Normal file
BIN
documentation/AppArmor Developer 3 - HFA.odt
Normal file
Binary file not shown.
BIN
documentation/AppArmor Developer 4 - Policy compilation.odt
Normal file
BIN
documentation/AppArmor Developer 4 - Policy compilation.odt
Normal file
Binary file not shown.
Binary file not shown.
BIN
documentation/AppArmor Policy.odt
Normal file
BIN
documentation/AppArmor Policy.odt
Normal file
Binary file not shown.
BIN
documentation/AppArmor Techdoc - HFA variables.odt
Normal file
BIN
documentation/AppArmor Techdoc - HFA variables.odt
Normal file
Binary file not shown.
@@ -1,72 +0,0 @@
|
||||
From: Tony Jones <tonyj@suse.de>
|
||||
Subject: Export audit subsystem for use by modules
|
||||
|
||||
Update kenel audit range comments to show AppArmor's registered range of
|
||||
1500-1599. This range used to be reserved for LSPP but LSPP uses the
|
||||
SE Linux range and the range was given to AppArmor.
|
||||
Adds necessary export symbols for audit subsystem routines.
|
||||
Changes audit_log_vformat to be externally visible (analagous to vprintf)
|
||||
Patch is not in mainline -- pending AppArmor code submission to lkml
|
||||
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
|
||||
---
|
||||
include/linux/audit.h | 12 +++++++++++-
|
||||
kernel/audit.c | 6 ++++--
|
||||
2 files changed, 15 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/include/linux/audit.h
|
||||
+++ b/include/linux/audit.h
|
||||
@@ -33,7 +33,7 @@
|
||||
* 1200 - 1299 messages internal to the audit daemon
|
||||
* 1300 - 1399 audit event messages
|
||||
* 1400 - 1499 SE Linux use
|
||||
- * 1500 - 1599 kernel LSPP events
|
||||
+ * 1500 - 1599 AppArmor use
|
||||
* 1600 - 1699 kernel crypto events
|
||||
* 1700 - 1799 kernel anomaly records
|
||||
* 1800 - 1999 future kernel use (maybe integrity labels and related events)
|
||||
@@ -116,6 +116,13 @@
|
||||
#define AUDIT_MAC_IPSEC_DELSPD 1414 /* Not used */
|
||||
#define AUDIT_MAC_IPSEC_EVENT 1415 /* Audit an IPSec event */
|
||||
|
||||
+#define AUDIT_APPARMOR_AUDIT 1501 /* AppArmor audited grants */
|
||||
+#define AUDIT_APPARMOR_ALLOWED 1502 /* Allowed Access for learning */
|
||||
+#define AUDIT_APPARMOR_DENIED 1503
|
||||
+#define AUDIT_APPARMOR_HINT 1504 /* Process Tracking information */
|
||||
+#define AUDIT_APPARMOR_STATUS 1505 /* Changes in config */
|
||||
+#define AUDIT_APPARMOR_ERROR 1506 /* Internal AppArmor Errors */
|
||||
+
|
||||
#define AUDIT_FIRST_KERN_ANOM_MSG 1700
|
||||
#define AUDIT_LAST_KERN_ANOM_MSG 1799
|
||||
#define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */
|
||||
@@ -513,6 +520,9 @@ extern void audit_log(struct audit_
|
||||
__attribute__((format(printf,4,5)));
|
||||
|
||||
extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type);
|
||||
+extern void audit_log_vformat(struct audit_buffer *ab,
|
||||
+ const char *fmt, va_list args)
|
||||
+ __attribute__((format(printf,2,0)));
|
||||
extern void audit_log_format(struct audit_buffer *ab,
|
||||
const char *fmt, ...)
|
||||
__attribute__((format(printf,2,3)));
|
||||
--- a/kernel/audit.c
|
||||
+++ b/kernel/audit.c
|
||||
@@ -1215,8 +1215,7 @@ static inline int audit_expand(struct au
|
||||
* will be called a second time. Currently, we assume that a printk
|
||||
* can't format message larger than 1024 bytes, so we don't either.
|
||||
*/
|
||||
-static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
|
||||
- va_list args)
|
||||
+void audit_log_vformat(struct audit_buffer *ab, const char *fmt, va_list args)
|
||||
{
|
||||
int len, avail;
|
||||
struct sk_buff *skb;
|
||||
@@ -1471,3 +1470,6 @@ EXPORT_SYMBOL(audit_log_start);
|
||||
EXPORT_SYMBOL(audit_log_end);
|
||||
EXPORT_SYMBOL(audit_log_format);
|
||||
EXPORT_SYMBOL(audit_log);
|
||||
+EXPORT_SYMBOL_GPL(audit_log_vformat);
|
||||
+EXPORT_SYMBOL_GPL(audit_log_untrustedstring);
|
||||
+EXPORT_SYMBOL_GPL(audit_log_d_path);
|
@@ -1,61 +0,0 @@
|
||||
---
|
||||
security/apparmor/Kconfig | 17 +++++++++++++++++
|
||||
security/apparmor/lsm.c | 16 ++++++++++++++++
|
||||
2 files changed, 33 insertions(+)
|
||||
|
||||
--- a/security/apparmor/Kconfig
|
||||
+++ b/security/apparmor/Kconfig
|
||||
@@ -7,4 +7,21 @@ config SECURITY_APPARMOR
|
||||
Required userspace tools (if they are not included in your
|
||||
distribution) and further information may be found at
|
||||
<http://forge.novell.com/modules/xfmod/project/?apparmor>
|
||||
+
|
||||
If you are unsure how to answer this question, answer N.
|
||||
+
|
||||
+config SECURITY_APPARMOR_BOOTPARAM_VALUE
|
||||
+ int "AppArmor boot parameter default value"
|
||||
+ depends on SECURITY_APPARMOR
|
||||
+ range 0 1
|
||||
+ default 1
|
||||
+ help
|
||||
+ This option sets the default value for the kernel parameter
|
||||
+ 'apparmor', which allows AppArmor to be enabled or disabled
|
||||
+ at boot. If this option is set to 0 (zero), the AppArmor
|
||||
+ kernel parameter will default to 0, disabling AppArmor at
|
||||
+ bootup. If this option is set to 1 (one), the AppArmor
|
||||
+ kernel parameter will default to 1, enabling AppArmor at
|
||||
+ bootup.
|
||||
+
|
||||
+ If you are unsure how to answer this question, answer 1.
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -23,6 +23,17 @@
|
||||
#include "apparmor.h"
|
||||
#include "inline.h"
|
||||
|
||||
+/* Boot time disable flag */
|
||||
+int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
|
||||
+
|
||||
+static int __init apparmor_enabled_setup(char *str)
|
||||
+{
|
||||
+ apparmor_enabled = simple_strtol(str, NULL, 0);
|
||||
+ return 1;
|
||||
+}
|
||||
+__setup("apparmor=", apparmor_enabled_setup);
|
||||
+
|
||||
+
|
||||
static int param_set_aabool(const char *val, struct kernel_param *kp);
|
||||
static int param_get_aabool(char *buffer, struct kernel_param *kp);
|
||||
#define param_check_aabool(name, p) __param_check(name, p, int)
|
||||
@@ -883,6 +894,11 @@ static int __init apparmor_init(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
+ if (!apparmor_enabled) {
|
||||
+ info_message("AppArmor disabled by boottime parameter\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
if ((error = create_apparmorfs())) {
|
||||
AA_ERROR("Unable to activate AppArmor filesystem\n");
|
||||
goto createfs_out;
|
@@ -1,66 +0,0 @@
|
||||
---
|
||||
security/apparmor/Kconfig | 2 +-
|
||||
security/apparmor/lsm.c | 42 ------------------------------------------
|
||||
2 files changed, 1 insertion(+), 43 deletions(-)
|
||||
|
||||
--- a/security/apparmor/Kconfig
|
||||
+++ b/security/apparmor/Kconfig
|
||||
@@ -1,5 +1,5 @@
|
||||
config SECURITY_APPARMOR
|
||||
- tristate "AppArmor support"
|
||||
+ bool "AppArmor support"
|
||||
depends on SECURITY
|
||||
select AUDIT
|
||||
help
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -932,49 +932,7 @@ createfs_out:
|
||||
|
||||
}
|
||||
|
||||
-static void __exit apparmor_exit(void)
|
||||
-{
|
||||
- /* Remove and release all the profiles on the profile list. */
|
||||
- mutex_lock(&aa_interface_lock);
|
||||
- write_lock(&profile_list_lock);
|
||||
- while (!list_empty(&profile_list)) {
|
||||
- struct aa_profile *profile =
|
||||
- list_entry(profile_list.next, struct aa_profile, list);
|
||||
-
|
||||
- /* Remove the profile from each task context it is on. */
|
||||
- lock_profile(profile);
|
||||
- profile->isstale = 1;
|
||||
- aa_unconfine_tasks(profile);
|
||||
- unlock_profile(profile);
|
||||
-
|
||||
- /* Release the profile itself. */
|
||||
- list_del_init(&profile->list);
|
||||
- aa_put_profile(profile);
|
||||
- }
|
||||
- write_unlock(&profile_list_lock);
|
||||
-
|
||||
- /* FIXME: cleanup profiles references on files */
|
||||
-
|
||||
- free_null_complain_profile();
|
||||
-
|
||||
- /*
|
||||
- * Delay for an rcu cycle to make sure that all active task
|
||||
- * context readers have finished, and all profiles have been
|
||||
- * freed by their rcu callbacks.
|
||||
- */
|
||||
- synchronize_rcu();
|
||||
-
|
||||
- destroy_apparmorfs();
|
||||
- mutex_unlock(&aa_interface_lock);
|
||||
-
|
||||
- if (unregister_security(&apparmor_ops))
|
||||
- info_message("Unable to properly unregister AppArmor");
|
||||
-
|
||||
- info_message("AppArmor protection removed");
|
||||
-}
|
||||
-
|
||||
module_init(apparmor_init);
|
||||
-module_exit(apparmor_exit);
|
||||
|
||||
MODULE_DESCRIPTION("AppArmor process confinement");
|
||||
MODULE_AUTHOR("Novell/Immunix, http://bugs.opensuse.org");
|
@@ -1,14 +0,0 @@
|
||||
---
|
||||
security/apparmor/lsm.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -205,6 +205,7 @@ static int apparmor_sysctl(struct ctl_ta
|
||||
}
|
||||
|
||||
out:
|
||||
+ aa_put_profile(profile);
|
||||
return error;
|
||||
}
|
||||
|
@@ -1,42 +0,0 @@
|
||||
From: John Johansen <jjohansen@suse.de>
|
||||
Subject: Add AppArmor LSM to security/Makefile
|
||||
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
|
||||
---
|
||||
security/Kconfig | 1 +
|
||||
security/Makefile | 1 +
|
||||
security/apparmor/Kconfig | 3 ++-
|
||||
3 files changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/security/Kconfig
|
||||
+++ b/security/Kconfig
|
||||
@@ -104,6 +104,7 @@ config SECURITY_ROOTPLUG
|
||||
If you are unsure how to answer this question, answer N.
|
||||
|
||||
source security/selinux/Kconfig
|
||||
+source security/apparmor/Kconfig
|
||||
|
||||
endmenu
|
||||
|
||||
--- a/security/Makefile
|
||||
+++ b/security/Makefile
|
||||
@@ -14,5 +14,6 @@ endif
|
||||
obj-$(CONFIG_SECURITY) += security.o dummy.o inode.o
|
||||
# Must precede capability.o in order to stack properly.
|
||||
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
|
||||
+obj-$(CONFIG_SECURITY_APPARMOR) += commoncap.o apparmor/
|
||||
obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
|
||||
obj-$(CONFIG_SECURITY_ROOTPLUG) += commoncap.o root_plug.o
|
||||
--- a/security/apparmor/Kconfig
|
||||
+++ b/security/apparmor/Kconfig
|
||||
@@ -1,6 +1,7 @@
|
||||
config SECURITY_APPARMOR
|
||||
tristate "AppArmor support"
|
||||
- depends on SECURITY!=n
|
||||
+ depends on SECURITY
|
||||
+ select AUDIT
|
||||
help
|
||||
This enables the AppArmor security module.
|
||||
Required userspace tools (if they are not included in your
|
@@ -1,856 +0,0 @@
|
||||
From: John Johansen <jjohansen@suse.de>
|
||||
Subject: AppArmor: Module and LSM hooks
|
||||
|
||||
Module parameters, LSM hooks, initialization and teardown.
|
||||
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
|
||||
---
|
||||
security/apparmor/lsm.c | 841 ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 841 insertions(+)
|
||||
|
||||
--- /dev/null
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -0,0 +1,841 @@
|
||||
+/*
|
||||
+ * Copyright (C) 1998-2007 Novell/SUSE
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation, version 2 of the
|
||||
+ * License.
|
||||
+ *
|
||||
+ * AppArmor LSM interface
|
||||
+ */
|
||||
+
|
||||
+#include <linux/security.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/mm.h>
|
||||
+#include <linux/mman.h>
|
||||
+#include <linux/mount.h>
|
||||
+#include <linux/namei.h>
|
||||
+#include <linux/ctype.h>
|
||||
+#include <linux/sysctl.h>
|
||||
+#include <linux/audit.h>
|
||||
+
|
||||
+#include "apparmor.h"
|
||||
+#include "inline.h"
|
||||
+
|
||||
+static int param_set_aabool(const char *val, struct kernel_param *kp);
|
||||
+static int param_get_aabool(char *buffer, struct kernel_param *kp);
|
||||
+#define param_check_aabool(name, p) __param_check(name, p, int)
|
||||
+
|
||||
+static int param_set_aauint(const char *val, struct kernel_param *kp);
|
||||
+static int param_get_aauint(char *buffer, struct kernel_param *kp);
|
||||
+#define param_check_aauint(name, p) __param_check(name, p, int)
|
||||
+
|
||||
+/* Flag values, also controllable via /sys/module/apparmor/parameters
|
||||
+ * We define special types as we want to do additional mediation.
|
||||
+ *
|
||||
+ * Complain mode -- in complain mode access failures result in auditing only
|
||||
+ * and task is allowed access. audit events are processed by userspace to
|
||||
+ * generate policy. Default is 'enforce' (0).
|
||||
+ * Value is also togglable per profile and referenced when global value is
|
||||
+ * enforce.
|
||||
+ */
|
||||
+int apparmor_complain = 0;
|
||||
+module_param_named(complain, apparmor_complain, aabool, S_IRUSR | S_IWUSR);
|
||||
+MODULE_PARM_DESC(apparmor_complain, "Toggle AppArmor complain mode");
|
||||
+
|
||||
+/* Debug mode */
|
||||
+int apparmor_debug = 0;
|
||||
+module_param_named(debug, apparmor_debug, aabool, S_IRUSR | S_IWUSR);
|
||||
+MODULE_PARM_DESC(apparmor_debug, "Toggle AppArmor debug mode");
|
||||
+
|
||||
+/* Audit mode */
|
||||
+int apparmor_audit = 0;
|
||||
+module_param_named(audit, apparmor_audit, aabool, S_IRUSR | S_IWUSR);
|
||||
+MODULE_PARM_DESC(apparmor_audit, "Toggle AppArmor audit mode");
|
||||
+
|
||||
+/* Syscall logging mode */
|
||||
+int apparmor_logsyscall = 0;
|
||||
+module_param_named(logsyscall, apparmor_logsyscall, aabool, S_IRUSR | S_IWUSR);
|
||||
+MODULE_PARM_DESC(apparmor_logsyscall, "Toggle AppArmor logsyscall mode");
|
||||
+
|
||||
+/* Maximum pathname length before accesses will start getting rejected */
|
||||
+unsigned int apparmor_path_max = 2 * PATH_MAX;
|
||||
+module_param_named(path_max, apparmor_path_max, aauint, S_IRUSR | S_IWUSR);
|
||||
+MODULE_PARM_DESC(apparmor_path_max, "Maximum pathname length allowed");
|
||||
+
|
||||
+static int param_set_aabool(const char *val, struct kernel_param *kp)
|
||||
+{
|
||||
+ if (aa_task_context(current))
|
||||
+ return -EPERM;
|
||||
+ return param_set_bool(val, kp);
|
||||
+}
|
||||
+
|
||||
+static int param_get_aabool(char *buffer, struct kernel_param *kp)
|
||||
+{
|
||||
+ if (aa_task_context(current))
|
||||
+ return -EPERM;
|
||||
+ return param_get_bool(buffer, kp);
|
||||
+}
|
||||
+
|
||||
+static int param_set_aauint(const char *val, struct kernel_param *kp)
|
||||
+{
|
||||
+ if (aa_task_context(current))
|
||||
+ return -EPERM;
|
||||
+ return param_set_uint(val, kp);
|
||||
+}
|
||||
+
|
||||
+static int param_get_aauint(char *buffer, struct kernel_param *kp)
|
||||
+{
|
||||
+ if (aa_task_context(current))
|
||||
+ return -EPERM;
|
||||
+ return param_get_uint(buffer, kp);
|
||||
+}
|
||||
+
|
||||
+static int aa_reject_syscall(struct task_struct *task, gfp_t flags,
|
||||
+ const char *name)
|
||||
+{
|
||||
+ struct aa_profile *profile = aa_get_profile(task);
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (profile) {
|
||||
+ error = aa_audit_syscallreject(profile, flags, name);
|
||||
+ aa_put_profile(profile);
|
||||
+ }
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_ptrace(struct task_struct *parent,
|
||||
+ struct task_struct *child)
|
||||
+{
|
||||
+ struct aa_task_context *cxt;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ /*
|
||||
+ * parent can ptrace child when
|
||||
+ * - parent is unconfined
|
||||
+ * - parent & child are in the same namespace &&
|
||||
+ * - parent is in complain mode
|
||||
+ * - parent and child are confined by the same profile
|
||||
+ * - parent profile has CAP_SYS_PTRACE
|
||||
+ */
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ cxt = aa_task_context(parent);
|
||||
+ if (cxt) {
|
||||
+ if (parent->nsproxy != child->nsproxy) {
|
||||
+ struct aa_audit sa;
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.operation = "ptrace";
|
||||
+ sa.gfp_mask = GFP_ATOMIC;
|
||||
+ sa.parent = parent->pid;
|
||||
+ sa.task = child->pid;
|
||||
+ sa.info = "different namespaces";
|
||||
+ aa_audit_reject(cxt->profile, &sa);
|
||||
+ error = -EPERM;
|
||||
+ } else {
|
||||
+ struct aa_task_context *child_cxt =
|
||||
+ aa_task_context(child);
|
||||
+
|
||||
+ error = aa_may_ptrace(cxt, child_cxt ?
|
||||
+ child_cxt->profile : NULL);
|
||||
+ if (PROFILE_COMPLAIN(cxt->profile)) {
|
||||
+ struct aa_audit sa;
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.operation = "ptrace";
|
||||
+ sa.gfp_mask = GFP_ATOMIC;
|
||||
+ sa.parent = parent->pid;
|
||||
+ sa.task = child->pid;
|
||||
+ aa_audit_hint(cxt->profile, &sa);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_capable(struct task_struct *task, int cap)
|
||||
+{
|
||||
+ int error;
|
||||
+
|
||||
+ /* cap_capable returns 0 on success, else -EPERM */
|
||||
+ error = cap_capable(task, cap);
|
||||
+
|
||||
+ if (!error) {
|
||||
+ struct aa_task_context *cxt;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ cxt = aa_task_context(task);
|
||||
+ if (cxt)
|
||||
+ error = aa_capability(cxt, cap);
|
||||
+ rcu_read_unlock();
|
||||
+ }
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_sysctl(struct ctl_table *table, int op)
|
||||
+{
|
||||
+ struct aa_profile *profile = aa_get_profile(current);
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (profile) {
|
||||
+ char *buffer, *name;
|
||||
+ int mask;
|
||||
+
|
||||
+ mask = 0;
|
||||
+ if (op & 4)
|
||||
+ mask |= MAY_READ;
|
||||
+ if (op & 2)
|
||||
+ mask |= MAY_WRITE;
|
||||
+
|
||||
+ error = -ENOMEM;
|
||||
+ buffer = (char*)__get_free_page(GFP_KERNEL);
|
||||
+ if (!buffer)
|
||||
+ goto out;
|
||||
+ name = sysctl_pathname(table, buffer, PAGE_SIZE);
|
||||
+ if (name && name - buffer >= 5) {
|
||||
+ name -= 5;
|
||||
+ memcpy(name, "/proc", 5);
|
||||
+ error = aa_perm_path(profile, "sysctl", name, mask);
|
||||
+ }
|
||||
+ free_page((unsigned long)buffer);
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_bprm_set_security(struct linux_binprm *bprm)
|
||||
+{
|
||||
+ /* handle capability bits with setuid, etc */
|
||||
+ cap_bprm_set_security(bprm);
|
||||
+ /* already set based on script name */
|
||||
+ if (bprm->sh_bang)
|
||||
+ return 0;
|
||||
+ return aa_register(bprm);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_bprm_secureexec(struct linux_binprm *bprm)
|
||||
+{
|
||||
+ int ret = cap_bprm_secureexec(bprm);
|
||||
+
|
||||
+ if (!ret && (unsigned long)bprm->security & AA_SECURE_EXEC_NEEDED) {
|
||||
+ AA_DEBUG("%s: secureexec required for %s\n",
|
||||
+ __FUNCTION__, bprm->filename);
|
||||
+ ret = 1;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_sb_mount(char *dev_name, struct nameidata *nd, char *type,
|
||||
+ unsigned long flags, void *data)
|
||||
+{
|
||||
+ return aa_reject_syscall(current, GFP_KERNEL, "mount");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_umount(struct vfsmount *mnt, int flags)
|
||||
+{
|
||||
+ return aa_reject_syscall(current, GFP_KERNEL, "umount");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_mkdir(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, int mask)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (!mnt || !mediated_filesystem(dir))
|
||||
+ goto out;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+
|
||||
+ if (profile)
|
||||
+ error = aa_perm_dir(profile, "inode_mkdir", dentry, mnt,
|
||||
+ MAY_WRITE);
|
||||
+
|
||||
+ aa_put_profile(profile);
|
||||
+
|
||||
+out:
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_rmdir(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (!mnt || !mediated_filesystem(dir))
|
||||
+ goto out;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+
|
||||
+ if (profile)
|
||||
+ error = aa_perm_dir(profile, "inode_rmdir", dentry, mnt,
|
||||
+ MAY_WRITE);
|
||||
+
|
||||
+ aa_put_profile(profile);
|
||||
+
|
||||
+out:
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int aa_permission(const char *operation, struct inode *inode,
|
||||
+ struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ int mask, int check)
|
||||
+{
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (mnt && mediated_filesystem(inode)) {
|
||||
+ struct aa_profile *profile;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+ if (profile)
|
||||
+ error = aa_perm(profile, operation, dentry, mnt, mask,
|
||||
+ check);
|
||||
+ aa_put_profile(profile);
|
||||
+ }
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static inline int aa_mask_permissions(int mask)
|
||||
+{
|
||||
+ if (mask & MAY_APPEND)
|
||||
+ mask &= (MAY_READ | MAY_APPEND | MAY_EXEC);
|
||||
+ else
|
||||
+ mask &= (MAY_READ | MAY_WRITE | MAY_EXEC);
|
||||
+ return mask;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_create(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, int mask)
|
||||
+{
|
||||
+ /* FIXME: may move to MAY_APPEND later */
|
||||
+ return aa_permission("inode_create", dir, dentry, mnt, MAY_WRITE, 0);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_link(struct dentry *old_dentry,
|
||||
+ struct vfsmount *old_mnt, struct inode *dir,
|
||||
+ struct dentry *new_dentry,
|
||||
+ struct vfsmount *new_mnt)
|
||||
+{
|
||||
+ int error = 0;
|
||||
+ struct aa_profile *profile;
|
||||
+
|
||||
+ if (!old_mnt || !new_mnt || !mediated_filesystem(dir))
|
||||
+ goto out;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+
|
||||
+ if (profile)
|
||||
+ error = aa_link(profile, new_dentry, new_mnt,
|
||||
+ old_dentry, old_mnt);
|
||||
+
|
||||
+ aa_put_profile(profile);
|
||||
+
|
||||
+out:
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_unlink(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt)
|
||||
+{
|
||||
+ int check = 0;
|
||||
+
|
||||
+ if (S_ISDIR(dentry->d_inode->i_mode))
|
||||
+ check |= AA_CHECK_DIR;
|
||||
+ return aa_permission("inode_unlink", dir, dentry, mnt, MAY_WRITE,
|
||||
+ check);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_symlink(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, const char *old_name)
|
||||
+{
|
||||
+ return aa_permission("inode_symlink", dir, dentry, mnt, MAY_WRITE, 0);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_mknod(struct inode *dir, struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, int mode, dev_t dev)
|
||||
+{
|
||||
+ return aa_permission("inode_mknod", dir, dentry, mnt, MAY_WRITE, 0);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_rename(struct inode *old_dir,
|
||||
+ struct dentry *old_dentry,
|
||||
+ struct vfsmount *old_mnt,
|
||||
+ struct inode *new_dir,
|
||||
+ struct dentry *new_dentry,
|
||||
+ struct vfsmount *new_mnt)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if ((!old_mnt && !new_mnt) || !mediated_filesystem(old_dir))
|
||||
+ goto out;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+
|
||||
+ if (profile) {
|
||||
+ struct inode *inode = old_dentry->d_inode;
|
||||
+ int check = 0;
|
||||
+
|
||||
+ if (inode && S_ISDIR(inode->i_mode))
|
||||
+ check |= AA_CHECK_DIR;
|
||||
+ if (old_mnt)
|
||||
+ error = aa_perm(profile, "inode_rename", old_dentry,
|
||||
+ old_mnt, MAY_READ | MAY_WRITE, check);
|
||||
+
|
||||
+ if (!error && new_mnt) {
|
||||
+ error = aa_perm(profile, "inode_rename", new_dentry,
|
||||
+ new_mnt, MAY_WRITE, check);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ aa_put_profile(profile);
|
||||
+
|
||||
+out:
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_permission(struct inode *inode, int mask,
|
||||
+ struct nameidata *nd)
|
||||
+{
|
||||
+ int check = 0;
|
||||
+
|
||||
+ if (!nd || nd->flags & (LOOKUP_PARENT | LOOKUP_CONTINUE))
|
||||
+ return 0;
|
||||
+ mask = aa_mask_permissions(mask);
|
||||
+ if (S_ISDIR(inode->i_mode)) {
|
||||
+ check |= AA_CHECK_DIR;
|
||||
+ /* allow traverse accesses to directories */
|
||||
+ mask &= ~MAY_EXEC;
|
||||
+ }
|
||||
+ return aa_permission("inode_permission", inode, nd->dentry, nd->mnt,
|
||||
+ mask, check);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct iattr *iattr)
|
||||
+{
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (!mnt)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (mediated_filesystem(dentry->d_inode)) {
|
||||
+ struct aa_profile *profile;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+ /*
|
||||
+ * Mediate any attempt to change attributes of a file
|
||||
+ * (chmod, chown, chgrp, etc)
|
||||
+ */
|
||||
+ if (profile)
|
||||
+ error = aa_attr(profile, dentry, mnt, iattr);
|
||||
+
|
||||
+ aa_put_profile(profile);
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int aa_xattr_permission(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ const char *operation, int mask,
|
||||
+ struct file *file)
|
||||
+{
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (mnt && mediated_filesystem(dentry->d_inode)) {
|
||||
+ struct aa_profile *profile = aa_get_profile(current);
|
||||
+ int check = file ? AA_CHECK_FD : 0;
|
||||
+
|
||||
+ if (profile)
|
||||
+ error = aa_perm_xattr(profile, operation, dentry, mnt,
|
||||
+ mask, check);
|
||||
+ aa_put_profile(profile);
|
||||
+ }
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ char *name, void *value, size_t size,
|
||||
+ int flags, struct file *file)
|
||||
+{
|
||||
+ return aa_xattr_permission(dentry, mnt, "xattr set", MAY_WRITE, file);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ char *name, struct file *file)
|
||||
+{
|
||||
+ return aa_xattr_permission(dentry, mnt, "xattr get", MAY_READ, file);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
|
||||
+ struct file *file)
|
||||
+{
|
||||
+ return aa_xattr_permission(dentry, mnt, "xattr list", MAY_READ, file);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_inode_removexattr(struct dentry *dentry,
|
||||
+ struct vfsmount *mnt, char *name,
|
||||
+ struct file *file)
|
||||
+{
|
||||
+ return aa_xattr_permission(dentry, mnt, "xattr remove", MAY_WRITE,
|
||||
+ file);
|
||||
+}
|
||||
+
|
||||
+static int aa_file_permission(const char *op, struct file *file, int mask)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+ struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (!file_profile)
|
||||
+ goto out;
|
||||
+
|
||||
+ /*
|
||||
+ * If this file was opened under a different profile, we
|
||||
+ * revalidate the access against the current profile.
|
||||
+ */
|
||||
+ profile = aa_get_profile(current);
|
||||
+ if (profile && (file_profile != profile || mask & AA_MAY_LOCK)) {
|
||||
+ struct dentry *dentry = file->f_dentry;
|
||||
+ struct vfsmount *mnt = file->f_vfsmnt;
|
||||
+ struct inode *inode = dentry->d_inode;
|
||||
+ int check = AA_CHECK_FD;
|
||||
+
|
||||
+ /*
|
||||
+ * FIXME: We should remember which profiles we revalidated
|
||||
+ * against.
|
||||
+ */
|
||||
+ if (S_ISDIR(inode->i_mode))
|
||||
+ check |= AA_CHECK_DIR;
|
||||
+ error = aa_permission(op, inode, dentry, mnt, mask, check);
|
||||
+ }
|
||||
+ aa_put_profile(profile);
|
||||
+
|
||||
+out:
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_file_permission(struct file *file, int mask)
|
||||
+{
|
||||
+ return aa_file_permission("file_permission", file,
|
||||
+ aa_mask_permissions(mask));
|
||||
+}
|
||||
+
|
||||
+static inline int apparmor_file_lock (struct file *file, unsigned int cmd)
|
||||
+{
|
||||
+ int mask = AA_MAY_LOCK;
|
||||
+ if (cmd == F_WRLCK)
|
||||
+ mask |= MAY_WRITE;
|
||||
+ return aa_file_permission("file_lock", file, mask);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_file_alloc_security(struct file *file)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+ if (profile)
|
||||
+ file->f_security = profile;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void apparmor_file_free_security(struct file *file)
|
||||
+{
|
||||
+ struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
|
||||
+
|
||||
+ aa_put_profile(file_profile);
|
||||
+}
|
||||
+
|
||||
+static inline int aa_mmap(struct file *file, const char *operation,
|
||||
+ unsigned long prot, unsigned long flags)
|
||||
+{
|
||||
+ struct dentry *dentry;
|
||||
+ int mask = 0;
|
||||
+
|
||||
+ if (!file || !file->f_security)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (prot & PROT_READ)
|
||||
+ mask |= MAY_READ;
|
||||
+ /* Private mappings don't require write perms since they don't
|
||||
+ * write back to the files */
|
||||
+ if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE))
|
||||
+ mask |= MAY_WRITE;
|
||||
+ if (prot & PROT_EXEC)
|
||||
+ mask |= AA_EXEC_MMAP;
|
||||
+
|
||||
+ dentry = file->f_dentry;
|
||||
+ return aa_permission(operation, dentry->d_inode, dentry,
|
||||
+ file->f_vfsmnt, mask, AA_CHECK_FD);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
|
||||
+ unsigned long prot, unsigned long flags,
|
||||
+ unsigned long addr, unsigned long addr_only)
|
||||
+{
|
||||
+ return aa_mmap(file, "file_mmap", prot, flags);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_file_mprotect(struct vm_area_struct *vma,
|
||||
+ unsigned long reqprot, unsigned long prot)
|
||||
+{
|
||||
+ return aa_mmap(vma->vm_file, "file_mprotect", prot,
|
||||
+ !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_task_alloc_security(struct task_struct *task)
|
||||
+{
|
||||
+ return aa_clone(task);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Called from IRQ context from RCU callback.
|
||||
+ */
|
||||
+static void apparmor_task_free_security(struct task_struct *task)
|
||||
+{
|
||||
+ aa_release(task);
|
||||
+}
|
||||
+
|
||||
+static int apparmor_getprocattr(struct task_struct *task, char *name,
|
||||
+ char **value)
|
||||
+{
|
||||
+ unsigned len;
|
||||
+ int error;
|
||||
+ struct aa_profile *profile;
|
||||
+
|
||||
+ /* AppArmor only supports the "current" process attribute */
|
||||
+ if (strcmp(name, "current") != 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* must be task querying itself or admin */
|
||||
+ if (current != task && !capable(CAP_SYS_ADMIN))
|
||||
+ return -EPERM;
|
||||
+
|
||||
+ profile = aa_get_profile(task);
|
||||
+ error = aa_getprocattr(profile, value, &len);
|
||||
+ aa_put_profile(profile);
|
||||
+ if (!error)
|
||||
+ error = len;
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_setprocattr(struct task_struct *task, char *name,
|
||||
+ void *value, size_t size)
|
||||
+{
|
||||
+ char *command, *args;
|
||||
+ int error;
|
||||
+
|
||||
+ if (strcmp(name, "current") != 0 || size == 0 || size >= PAGE_SIZE)
|
||||
+ return -EINVAL;
|
||||
+ args = value;
|
||||
+ args[size] = '\0';
|
||||
+ args = strstrip(args);
|
||||
+ command = strsep(&args, " ");
|
||||
+ if (!args)
|
||||
+ return -EINVAL;
|
||||
+ while (isspace(*args))
|
||||
+ args++;
|
||||
+ if (!*args)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (strcmp(command, "changehat") == 0) {
|
||||
+ if (current != task)
|
||||
+ return -EACCES;
|
||||
+ error = aa_setprocattr_changehat(args);
|
||||
+ } else if (strcmp(command, "changeprofile") == 0) {
|
||||
+ if (current != task)
|
||||
+ return -EACCES;
|
||||
+ error = aa_setprocattr_changeprofile(args);
|
||||
+ } else if (strcmp(command, "setprofile") == 0) {
|
||||
+ struct aa_profile *profile;
|
||||
+
|
||||
+ /* Only an unconfined process with admin capabilities
|
||||
+ * may change the profile of another task.
|
||||
+ */
|
||||
+
|
||||
+ if (!capable(CAP_SYS_ADMIN))
|
||||
+ return -EACCES;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+ if (profile) {
|
||||
+ struct aa_audit sa;
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.operation = "profile_set";
|
||||
+ sa.gfp_mask = GFP_KERNEL;
|
||||
+ sa.task = task->pid;
|
||||
+ sa.info = "from confined process";
|
||||
+ aa_audit_reject(profile, &sa);
|
||||
+ aa_put_profile(profile);
|
||||
+ return -EACCES;
|
||||
+ }
|
||||
+ error = aa_setprocattr_setprofile(task, args);
|
||||
+ } else {
|
||||
+ struct aa_audit sa;
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.operation = "setprocattr";
|
||||
+ sa.gfp_mask = GFP_KERNEL;
|
||||
+ sa.info = "invalid command";
|
||||
+ sa.name = command;
|
||||
+ sa.task = task->pid;
|
||||
+ aa_audit_reject(NULL, &sa);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (!error)
|
||||
+ error = size;
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+struct security_operations apparmor_ops = {
|
||||
+ .ptrace = apparmor_ptrace,
|
||||
+ .capget = cap_capget,
|
||||
+ .capset_check = cap_capset_check,
|
||||
+ .capset_set = cap_capset_set,
|
||||
+ .sysctl = apparmor_sysctl,
|
||||
+ .capable = apparmor_capable,
|
||||
+ .syslog = cap_syslog,
|
||||
+
|
||||
+ .netlink_send = cap_netlink_send,
|
||||
+ .netlink_recv = cap_netlink_recv,
|
||||
+
|
||||
+ .bprm_apply_creds = cap_bprm_apply_creds,
|
||||
+ .bprm_set_security = apparmor_bprm_set_security,
|
||||
+ .bprm_secureexec = apparmor_bprm_secureexec,
|
||||
+
|
||||
+ .sb_mount = apparmor_sb_mount,
|
||||
+ .sb_umount = apparmor_umount,
|
||||
+
|
||||
+ .inode_mkdir = apparmor_inode_mkdir,
|
||||
+ .inode_rmdir = apparmor_inode_rmdir,
|
||||
+ .inode_create = apparmor_inode_create,
|
||||
+ .inode_link = apparmor_inode_link,
|
||||
+ .inode_unlink = apparmor_inode_unlink,
|
||||
+ .inode_symlink = apparmor_inode_symlink,
|
||||
+ .inode_mknod = apparmor_inode_mknod,
|
||||
+ .inode_rename = apparmor_inode_rename,
|
||||
+ .inode_permission = apparmor_inode_permission,
|
||||
+ .inode_setattr = apparmor_inode_setattr,
|
||||
+ .inode_setxattr = apparmor_inode_setxattr,
|
||||
+ .inode_getxattr = apparmor_inode_getxattr,
|
||||
+ .inode_listxattr = apparmor_inode_listxattr,
|
||||
+ .inode_removexattr = apparmor_inode_removexattr,
|
||||
+ .file_permission = apparmor_file_permission,
|
||||
+ .file_alloc_security = apparmor_file_alloc_security,
|
||||
+ .file_free_security = apparmor_file_free_security,
|
||||
+ .file_mmap = apparmor_file_mmap,
|
||||
+ .file_mprotect = apparmor_file_mprotect,
|
||||
+ .file_lock = apparmor_file_lock,
|
||||
+
|
||||
+ .task_alloc_security = apparmor_task_alloc_security,
|
||||
+ .task_free_security = apparmor_task_free_security,
|
||||
+ .task_post_setuid = cap_task_post_setuid,
|
||||
+ .task_reparent_to_init = cap_task_reparent_to_init,
|
||||
+
|
||||
+ .getprocattr = apparmor_getprocattr,
|
||||
+ .setprocattr = apparmor_setprocattr,
|
||||
+};
|
||||
+
|
||||
+static void info_message(const char *str)
|
||||
+{
|
||||
+ struct aa_audit sa;
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.gfp_mask = GFP_KERNEL;
|
||||
+ sa.info = str;
|
||||
+ printk(KERN_INFO "AppArmor: %s", str);
|
||||
+ aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
|
||||
+}
|
||||
+
|
||||
+static int __init apparmor_init(void)
|
||||
+{
|
||||
+ int error;
|
||||
+
|
||||
+ if ((error = create_apparmorfs())) {
|
||||
+ AA_ERROR("Unable to activate AppArmor filesystem\n");
|
||||
+ goto createfs_out;
|
||||
+ }
|
||||
+
|
||||
+ if ((error = alloc_null_complain_profile())){
|
||||
+ AA_ERROR("Unable to allocate null complain profile\n");
|
||||
+ goto alloc_out;
|
||||
+ }
|
||||
+
|
||||
+ if ((error = register_security(&apparmor_ops))) {
|
||||
+ AA_ERROR("Unable to register AppArmor\n");
|
||||
+ goto register_security_out;
|
||||
+ }
|
||||
+
|
||||
+ if (apparmor_complain)
|
||||
+ info_message("AppArmor initialized: complainmode enabled");
|
||||
+ else
|
||||
+ info_message("AppArmor initialized");
|
||||
+
|
||||
+ return error;
|
||||
+
|
||||
+register_security_out:
|
||||
+ free_null_complain_profile();
|
||||
+
|
||||
+alloc_out:
|
||||
+ destroy_apparmorfs();
|
||||
+
|
||||
+createfs_out:
|
||||
+ return error;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static void __exit apparmor_exit(void)
|
||||
+{
|
||||
+ /* Remove and release all the profiles on the profile list. */
|
||||
+ mutex_lock(&aa_interface_lock);
|
||||
+ write_lock(&profile_list_lock);
|
||||
+ while (!list_empty(&profile_list)) {
|
||||
+ struct aa_profile *profile =
|
||||
+ list_entry(profile_list.next, struct aa_profile, list);
|
||||
+
|
||||
+ /* Remove the profile from each task context it is on. */
|
||||
+ lock_profile(profile);
|
||||
+ profile->isstale = 1;
|
||||
+ aa_unconfine_tasks(profile);
|
||||
+ unlock_profile(profile);
|
||||
+
|
||||
+ /* Release the profile itself. */
|
||||
+ list_del_init(&profile->list);
|
||||
+ aa_put_profile(profile);
|
||||
+ }
|
||||
+ write_unlock(&profile_list_lock);
|
||||
+
|
||||
+ /* FIXME: cleanup profiles references on files */
|
||||
+
|
||||
+ free_null_complain_profile();
|
||||
+
|
||||
+ /*
|
||||
+ * Delay for an rcu cycle to make sure that all active task
|
||||
+ * context readers have finished, and all profiles have been
|
||||
+ * freed by their rcu callbacks.
|
||||
+ */
|
||||
+ synchronize_rcu();
|
||||
+
|
||||
+ destroy_apparmorfs();
|
||||
+ mutex_unlock(&aa_interface_lock);
|
||||
+
|
||||
+ if (unregister_security(&apparmor_ops))
|
||||
+ info_message("Unable to properly unregister AppArmor");
|
||||
+
|
||||
+ info_message("AppArmor protection removed");
|
||||
+}
|
||||
+
|
||||
+module_init(apparmor_init);
|
||||
+module_exit(apparmor_exit);
|
||||
+
|
||||
+MODULE_DESCRIPTION("AppArmor process confinement");
|
||||
+MODULE_AUTHOR("Novell/Immunix, http://bugs.opensuse.org");
|
||||
+MODULE_LICENSE("GPL");
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,978 +0,0 @@
|
||||
From: John Johansen <jjohansen@suse.de>
|
||||
Subject: AppArmor: Profile loading and manipulation, pathname matching
|
||||
|
||||
Pathname matching, transition table loading, profile loading and
|
||||
manipulation.
|
||||
|
||||
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||||
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||||
|
||||
---
|
||||
security/apparmor/match.c | 248 +++++++++++++
|
||||
security/apparmor/match.h | 83 ++++
|
||||
security/apparmor/module_interface.c | 623 +++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 954 insertions(+)
|
||||
|
||||
--- /dev/null
|
||||
+++ b/security/apparmor/match.c
|
||||
@@ -0,0 +1,248 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2007 Novell/SUSE
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation, version 2 of the
|
||||
+ * License.
|
||||
+ *
|
||||
+ * Regular expression transition table matching
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include "apparmor.h"
|
||||
+#include "match.h"
|
||||
+
|
||||
+static struct table_header *unpack_table(void *blob, size_t bsize)
|
||||
+{
|
||||
+ struct table_header *table = NULL;
|
||||
+ struct table_header th;
|
||||
+ size_t tsize;
|
||||
+
|
||||
+ if (bsize < sizeof(struct table_header))
|
||||
+ goto out;
|
||||
+
|
||||
+ th.td_id = be16_to_cpu(*(u16 *) (blob));
|
||||
+ th.td_flags = be16_to_cpu(*(u16 *) (blob + 2));
|
||||
+ th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8));
|
||||
+ blob += sizeof(struct table_header);
|
||||
+
|
||||
+ if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
|
||||
+ th.td_flags == YYTD_DATA8))
|
||||
+ goto out;
|
||||
+
|
||||
+ tsize = table_size(th.td_lolen, th.td_flags);
|
||||
+ if (bsize < tsize)
|
||||
+ goto out;
|
||||
+
|
||||
+ table = kmalloc(tsize, GFP_KERNEL);
|
||||
+ if (table) {
|
||||
+ *table = th;
|
||||
+ if (th.td_flags == YYTD_DATA8)
|
||||
+ UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
|
||||
+ u8, byte_to_byte);
|
||||
+ else if (th.td_flags == YYTD_DATA16)
|
||||
+ UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
|
||||
+ u16, be16_to_cpu);
|
||||
+ else
|
||||
+ UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
|
||||
+ u32, be32_to_cpu);
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ return table;
|
||||
+}
|
||||
+
|
||||
+int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size)
|
||||
+{
|
||||
+ int hsize, i;
|
||||
+ int error = -ENOMEM;
|
||||
+
|
||||
+ /* get dfa table set header */
|
||||
+ if (size < sizeof(struct table_set_header))
|
||||
+ goto fail;
|
||||
+
|
||||
+ if (ntohl(*(u32 *)blob) != YYTH_MAGIC)
|
||||
+ goto fail;
|
||||
+
|
||||
+ hsize = ntohl(*(u32 *)(blob + 4));
|
||||
+ if (size < hsize)
|
||||
+ goto fail;
|
||||
+
|
||||
+ blob += hsize;
|
||||
+ size -= hsize;
|
||||
+
|
||||
+ error = -EPROTO;
|
||||
+ while (size > 0) {
|
||||
+ struct table_header *table;
|
||||
+ table = unpack_table(blob, size);
|
||||
+ if (!table)
|
||||
+ goto fail;
|
||||
+
|
||||
+ switch(table->td_id) {
|
||||
+ case YYTD_ID_ACCEPT:
|
||||
+ case YYTD_ID_BASE:
|
||||
+ dfa->tables[table->td_id - 1] = table;
|
||||
+ if (table->td_flags != YYTD_DATA32)
|
||||
+ goto fail;
|
||||
+ break;
|
||||
+ case YYTD_ID_DEF:
|
||||
+ case YYTD_ID_NXT:
|
||||
+ case YYTD_ID_CHK:
|
||||
+ dfa->tables[table->td_id - 1] = table;
|
||||
+ if (table->td_flags != YYTD_DATA16)
|
||||
+ goto fail;
|
||||
+ break;
|
||||
+ case YYTD_ID_EC:
|
||||
+ dfa->tables[table->td_id - 1] = table;
|
||||
+ if (table->td_flags != YYTD_DATA8)
|
||||
+ goto fail;
|
||||
+ break;
|
||||
+ default:
|
||||
+ kfree(table);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ blob += table_size(table->td_lolen, table->td_flags);
|
||||
+ size -= table_size(table->td_lolen, table->td_flags);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+fail:
|
||||
+ for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
|
||||
+ if (dfa->tables[i]) {
|
||||
+ kfree(dfa->tables[i]);
|
||||
+ dfa->tables[i] = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * verify_dfa - verify that all the transitions and states in the dfa tables
|
||||
+ * are in bounds.
|
||||
+ * @dfa: dfa to test
|
||||
+ *
|
||||
+ * assumes dfa has gone through the verification done by unpacking
|
||||
+ */
|
||||
+int verify_dfa(struct aa_dfa *dfa)
|
||||
+{
|
||||
+ size_t i, state_count, trans_count;
|
||||
+ int error = -EPROTO;
|
||||
+
|
||||
+ /* check that required tables exist */
|
||||
+ if (!(dfa->tables[YYTD_ID_ACCEPT -1 ] &&
|
||||
+ dfa->tables[YYTD_ID_DEF - 1] &&
|
||||
+ dfa->tables[YYTD_ID_BASE - 1] &&
|
||||
+ dfa->tables[YYTD_ID_NXT - 1] &&
|
||||
+ dfa->tables[YYTD_ID_CHK - 1]))
|
||||
+ goto out;
|
||||
+
|
||||
+ /* accept.size == default.size == base.size */
|
||||
+ state_count = dfa->tables[YYTD_ID_BASE - 1]->td_lolen;
|
||||
+ if (!(state_count == dfa->tables[YYTD_ID_DEF - 1]->td_lolen &&
|
||||
+ state_count == dfa->tables[YYTD_ID_ACCEPT - 1]->td_lolen))
|
||||
+ goto out;
|
||||
+
|
||||
+ /* next.size == chk.size */
|
||||
+ trans_count = dfa->tables[YYTD_ID_NXT - 1]->td_lolen;
|
||||
+ if (trans_count != dfa->tables[YYTD_ID_CHK - 1]->td_lolen)
|
||||
+ goto out;
|
||||
+
|
||||
+ /* if equivalence classes then its table size must be 256 */
|
||||
+ if (dfa->tables[YYTD_ID_EC - 1] &&
|
||||
+ dfa->tables[YYTD_ID_EC - 1]->td_lolen != 256)
|
||||
+ goto out;
|
||||
+
|
||||
+ for (i = 0; i < state_count; i++) {
|
||||
+ if (DEFAULT_TABLE(dfa)[i] >= state_count)
|
||||
+ goto out;
|
||||
+ if (BASE_TABLE(dfa)[i] >= trans_count + 256)
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < trans_count ; i++) {
|
||||
+ if (NEXT_TABLE(dfa)[i] >= state_count)
|
||||
+ goto out;
|
||||
+ if (CHECK_TABLE(dfa)[i] >= state_count)
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* verify accept permissions */
|
||||
+ for (i = 0; i < state_count; i++) {
|
||||
+ int mode = ACCEPT_TABLE(dfa)[i];
|
||||
+
|
||||
+ if (mode & ~AA_VALID_PERM_MASK)
|
||||
+ goto out;
|
||||
+
|
||||
+ /* if MAY_EXEC, exactly one exec modifier must be set */
|
||||
+ if (mode & MAY_EXEC) {
|
||||
+ mode &= AA_EXEC_MODIFIERS;
|
||||
+ if (mode & (mode - 1))
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ error = 0;
|
||||
+out:
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+struct aa_dfa *aa_match_alloc(void)
|
||||
+{
|
||||
+ return kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
|
||||
+}
|
||||
+
|
||||
+void aa_match_free(struct aa_dfa *dfa)
|
||||
+{
|
||||
+ if (dfa) {
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(dfa->tables); i++)
|
||||
+ kfree(dfa->tables[i]);
|
||||
+ }
|
||||
+ kfree(dfa);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * aa_dfa_match - match @path against @dfa starting in @state
|
||||
+ * @dfa: the dfa to match @path against
|
||||
+ * @state: the state to start matching in
|
||||
+ * @path: the path to match against the dfa
|
||||
+ *
|
||||
+ * aa_dfa_match will match the full path length and return the state it
|
||||
+ * finished matching in. The final state is used to look up the accepting
|
||||
+ * label.
|
||||
+ */
|
||||
+unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str)
|
||||
+{
|
||||
+ u16 *def = DEFAULT_TABLE(dfa);
|
||||
+ u32 *base = BASE_TABLE(dfa);
|
||||
+ u16 *next = NEXT_TABLE(dfa);
|
||||
+ u16 *check = CHECK_TABLE(dfa);
|
||||
+ unsigned int state = 1, pos;
|
||||
+
|
||||
+ /* current state is <state>, matching character *str */
|
||||
+ if (dfa->tables[YYTD_ID_EC - 1]) {
|
||||
+ u8 *equiv = EQUIV_TABLE(dfa);
|
||||
+ while (*str) {
|
||||
+ pos = base[state] + equiv[(u8)*str++];
|
||||
+ if (check[pos] == state)
|
||||
+ state = next[pos];
|
||||
+ else
|
||||
+ state = def[state];
|
||||
+ }
|
||||
+ } else {
|
||||
+ while (*str) {
|
||||
+ pos = base[state] + (u8)*str++;
|
||||
+ if (check[pos] == state)
|
||||
+ state = next[pos];
|
||||
+ else
|
||||
+ state = def[state];
|
||||
+ }
|
||||
+ }
|
||||
+ return ACCEPT_TABLE(dfa)[state];
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/security/apparmor/match.h
|
||||
@@ -0,0 +1,83 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2007 Novell/SUSE
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation, version 2 of the
|
||||
+ * License.
|
||||
+ *
|
||||
+ * AppArmor submodule (match) prototypes
|
||||
+ */
|
||||
+
|
||||
+#ifndef __MATCH_H
|
||||
+#define __MATCH_H
|
||||
+
|
||||
+/**
|
||||
+ * The format used for transition tables is based on the GNU flex table
|
||||
+ * file format (--tables-file option; see Table File Format in the flex
|
||||
+ * info pages and the flex sources for documentation). The magic number
|
||||
+ * used in the header is 0x1B5E783D insted of 0xF13C57B1 though, because
|
||||
+ * the YY_ID_CHK (check) and YY_ID_DEF (default) tables are used
|
||||
+ * slightly differently (see the apparmor-parser package).
|
||||
+ */
|
||||
+
|
||||
+#define YYTH_MAGIC 0x1B5E783D
|
||||
+
|
||||
+struct table_set_header {
|
||||
+ u32 th_magic; /* YYTH_MAGIC */
|
||||
+ u32 th_hsize;
|
||||
+ u32 th_ssize;
|
||||
+ u16 th_flags;
|
||||
+ char th_version[];
|
||||
+};
|
||||
+
|
||||
+#define YYTD_ID_ACCEPT 1
|
||||
+#define YYTD_ID_BASE 2
|
||||
+#define YYTD_ID_CHK 3
|
||||
+#define YYTD_ID_DEF 4
|
||||
+#define YYTD_ID_EC 5
|
||||
+#define YYTD_ID_META 6
|
||||
+#define YYTD_ID_NXT 8
|
||||
+
|
||||
+
|
||||
+#define YYTD_DATA8 1
|
||||
+#define YYTD_DATA16 2
|
||||
+#define YYTD_DATA32 4
|
||||
+
|
||||
+struct table_header {
|
||||
+ u16 td_id;
|
||||
+ u16 td_flags;
|
||||
+ u32 td_hilen;
|
||||
+ u32 td_lolen;
|
||||
+ char td_data[];
|
||||
+};
|
||||
+
|
||||
+#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF - 1]->td_data))
|
||||
+#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE - 1]->td_data))
|
||||
+#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT - 1]->td_data))
|
||||
+#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK - 1]->td_data))
|
||||
+#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC - 1]->td_data))
|
||||
+#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT - 1]->td_data))
|
||||
+
|
||||
+struct aa_dfa {
|
||||
+ struct table_header *tables[YYTD_ID_NXT];
|
||||
+};
|
||||
+
|
||||
+#define byte_to_byte(X) (X)
|
||||
+
|
||||
+#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
|
||||
+ do { \
|
||||
+ typeof(LEN) __i; \
|
||||
+ TYPE *__t = (TYPE *) TABLE; \
|
||||
+ TYPE *__b = (TYPE *) BLOB; \
|
||||
+ for (__i = 0; __i < LEN; __i++) { \
|
||||
+ __t[__i] = NTOHX(__b[__i]); \
|
||||
+ } \
|
||||
+ } while (0)
|
||||
+
|
||||
+static inline size_t table_size(size_t len, size_t el_size)
|
||||
+{
|
||||
+ return ALIGN(sizeof(struct table_header) + len * el_size, 8);
|
||||
+}
|
||||
+
|
||||
+#endif /* __MATCH_H */
|
||||
--- /dev/null
|
||||
+++ b/security/apparmor/module_interface.c
|
||||
@@ -0,0 +1,623 @@
|
||||
+/*
|
||||
+ * Copyright (C) 1998-2007 Novell/SUSE
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation, version 2 of the
|
||||
+ * License.
|
||||
+ *
|
||||
+ * AppArmor userspace policy interface
|
||||
+ */
|
||||
+
|
||||
+#include <asm/unaligned.h>
|
||||
+
|
||||
+#include "apparmor.h"
|
||||
+#include "inline.h"
|
||||
+
|
||||
+/*
|
||||
+ * This mutex is used to synchronize profile adds, replacements, and
|
||||
+ * removals: we only allow one of these operations at a time.
|
||||
+ * We do not use the profile list lock here in order to avoid blocking
|
||||
+ * exec during those operations. (Exec involves a profile list lookup
|
||||
+ * for named-profile transitions.)
|
||||
+ */
|
||||
+DEFINE_MUTEX(aa_interface_lock);
|
||||
+
|
||||
+/*
|
||||
+ * The AppArmor interface treats data as a type byte followed by the
|
||||
+ * actual data. The interface has the notion of a a named entry
|
||||
+ * which has a name (AA_NAME typecode followed by name string) followed by
|
||||
+ * the entries typecode and data. Named types allow for optional
|
||||
+ * elements and extensions to be added and tested for without breaking
|
||||
+ * backwards compatability.
|
||||
+ */
|
||||
+
|
||||
+enum aa_code {
|
||||
+ AA_U8,
|
||||
+ AA_U16,
|
||||
+ AA_U32,
|
||||
+ AA_U64,
|
||||
+ AA_NAME, /* same as string except it is items name */
|
||||
+ AA_STRING,
|
||||
+ AA_BLOB,
|
||||
+ AA_STRUCT,
|
||||
+ AA_STRUCTEND,
|
||||
+ AA_LIST,
|
||||
+ AA_LISTEND,
|
||||
+ AA_ARRAY,
|
||||
+ AA_ARRAYEND,
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * aa_ext is the read of the buffer containing the serialized profile. The
|
||||
+ * data is copied into a kernel buffer in apparmorfs and then handed off to
|
||||
+ * the unpack routines.
|
||||
+ */
|
||||
+struct aa_ext {
|
||||
+ void *start;
|
||||
+ void *end;
|
||||
+ void *pos; /* pointer to current position in the buffer */
|
||||
+ u32 version;
|
||||
+};
|
||||
+
|
||||
+static inline int aa_inbounds(struct aa_ext *e, size_t size)
|
||||
+{
|
||||
+ return (size <= e->end - e->pos);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * aa_u16_chunck - test and do bounds checking for a u16 size based chunk
|
||||
+ * @e: serialized data read head
|
||||
+ * @chunk: start address for chunk of data
|
||||
+ *
|
||||
+ * return the size of chunk found with the read head at the end of
|
||||
+ * the chunk.
|
||||
+ */
|
||||
+static size_t aa_is_u16_chunk(struct aa_ext *e, char **chunk)
|
||||
+{
|
||||
+ void *pos = e->pos;
|
||||
+ size_t size = 0;
|
||||
+
|
||||
+ if (!aa_inbounds(e, sizeof(u16)))
|
||||
+ goto fail;
|
||||
+ size = le16_to_cpu(get_unaligned((u16 *)e->pos));
|
||||
+ e->pos += sizeof(u16);
|
||||
+ if (!aa_inbounds(e, size))
|
||||
+ goto fail;
|
||||
+ *chunk = e->pos;
|
||||
+ e->pos += size;
|
||||
+ return size;
|
||||
+
|
||||
+fail:
|
||||
+ e->pos = pos;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int aa_is_X(struct aa_ext *e, enum aa_code code)
|
||||
+{
|
||||
+ if (!aa_inbounds(e, 1))
|
||||
+ return 0;
|
||||
+ if (*(u8 *) e->pos != code)
|
||||
+ return 0;
|
||||
+ e->pos++;
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * aa_is_nameX - check is the next element is of type X with a name of @name
|
||||
+ * @e: serialized data extent information
|
||||
+ * @code: type code
|
||||
+ * @name: name to match to the serialized element.
|
||||
+ *
|
||||
+ * check that the next serialized data element is of type X and has a tag
|
||||
+ * name @name. If @name is specified then there must be a matching
|
||||
+ * name element in the stream. If @name is NULL any name element will be
|
||||
+ * skipped and only the typecode will be tested.
|
||||
+ * returns 1 on success (both type code and name tests match) and the read
|
||||
+ * head is advanced past the headers
|
||||
+ * returns %0 if either match failes, the read head does not move
|
||||
+ */
|
||||
+static int aa_is_nameX(struct aa_ext *e, enum aa_code code, const char *name)
|
||||
+{
|
||||
+ void *pos = e->pos;
|
||||
+ /*
|
||||
+ * Check for presence of a tagname, and if present name size
|
||||
+ * AA_NAME tag value is a u16.
|
||||
+ */
|
||||
+ if (aa_is_X(e, AA_NAME)) {
|
||||
+ char *tag;
|
||||
+ size_t size = aa_is_u16_chunk(e, &tag);
|
||||
+ /* if a name is specified it must match. otherwise skip tag */
|
||||
+ if (name && (!size || strcmp(name, tag)))
|
||||
+ goto fail;
|
||||
+ } else if (name) {
|
||||
+ /* if a name is specified and there is no name tag fail */
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ /* now check if type code matches */
|
||||
+ if (aa_is_X(e, code))
|
||||
+ return 1;
|
||||
+
|
||||
+fail:
|
||||
+ e->pos = pos;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int aa_is_u16(struct aa_ext *e, u16 *data, const char *name)
|
||||
+{
|
||||
+ void *pos = e->pos;
|
||||
+ if (aa_is_nameX(e, AA_U16, name)) {
|
||||
+ if (!aa_inbounds(e, sizeof(u16)))
|
||||
+ goto fail;
|
||||
+ if (data)
|
||||
+ *data = le16_to_cpu(get_unaligned((u16 *)e->pos));
|
||||
+ e->pos += sizeof(u16);
|
||||
+ return 1;
|
||||
+ }
|
||||
+fail:
|
||||
+ e->pos = pos;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int aa_is_u32(struct aa_ext *e, u32 *data, const char *name)
|
||||
+{
|
||||
+ void *pos = e->pos;
|
||||
+ if (aa_is_nameX(e, AA_U32, name)) {
|
||||
+ if (!aa_inbounds(e, sizeof(u32)))
|
||||
+ goto fail;
|
||||
+ if (data)
|
||||
+ *data = le32_to_cpu(get_unaligned((u32 *)e->pos));
|
||||
+ e->pos += sizeof(u32);
|
||||
+ return 1;
|
||||
+ }
|
||||
+fail:
|
||||
+ e->pos = pos;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static size_t aa_is_array(struct aa_ext *e, const char *name)
|
||||
+{
|
||||
+ void *pos = e->pos;
|
||||
+ if (aa_is_nameX(e, AA_ARRAY, name)) {
|
||||
+ int size;
|
||||
+ if (!aa_inbounds(e, sizeof(u16)))
|
||||
+ goto fail;
|
||||
+ size = (int) le16_to_cpu(get_unaligned((u16 *)e->pos));
|
||||
+ e->pos += sizeof(u16);
|
||||
+ return size;
|
||||
+ }
|
||||
+fail:
|
||||
+ e->pos = pos;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static size_t aa_is_blob(struct aa_ext *e, char **blob, const char *name)
|
||||
+{
|
||||
+ void *pos = e->pos;
|
||||
+ if (aa_is_nameX(e, AA_BLOB, name)) {
|
||||
+ u32 size;
|
||||
+ if (!aa_inbounds(e, sizeof(u32)))
|
||||
+ goto fail;
|
||||
+ size = le32_to_cpu(get_unaligned((u32 *)e->pos));
|
||||
+ e->pos += sizeof(u32);
|
||||
+ if (aa_inbounds(e, (size_t) size)) {
|
||||
+ * blob = e->pos;
|
||||
+ e->pos += size;
|
||||
+ return size;
|
||||
+ }
|
||||
+ }
|
||||
+fail:
|
||||
+ e->pos = pos;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int aa_is_dynstring(struct aa_ext *e, char **string, const char *name)
|
||||
+{
|
||||
+ char *src_str;
|
||||
+ size_t size = 0;
|
||||
+ void *pos = e->pos;
|
||||
+ *string = NULL;
|
||||
+ if (aa_is_nameX(e, AA_STRING, name) &&
|
||||
+ (size = aa_is_u16_chunk(e, &src_str))) {
|
||||
+ char *str;
|
||||
+ if (!(str = kmalloc(size, GFP_KERNEL)))
|
||||
+ goto fail;
|
||||
+ memcpy(str, src_str, size);
|
||||
+ *string = str;
|
||||
+ }
|
||||
+
|
||||
+ return size;
|
||||
+
|
||||
+fail:
|
||||
+ e->pos = pos;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * aa_unpack_dfa - unpack a file rule dfa
|
||||
+ * @e: serialized data extent information
|
||||
+ *
|
||||
+ * returns dfa or ERR_PTR
|
||||
+ */
|
||||
+struct aa_dfa *aa_unpack_dfa(struct aa_ext *e)
|
||||
+{
|
||||
+ char *blob = NULL;
|
||||
+ size_t size, error = 0;
|
||||
+ struct aa_dfa *dfa = NULL;
|
||||
+
|
||||
+ size = aa_is_blob(e, &blob, "aadfa");
|
||||
+ if (size) {
|
||||
+ dfa = aa_match_alloc();
|
||||
+ if (dfa) {
|
||||
+ /*
|
||||
+ * The dfa is aligned with in the blob to 8 bytes
|
||||
+ * from the beginning of the stream.
|
||||
+ */
|
||||
+ size_t sz = blob - (char *) e->start;
|
||||
+ size_t pad = ALIGN(sz, 8) - sz;
|
||||
+ error = unpack_dfa(dfa, blob + pad, size - pad);
|
||||
+ if (!error)
|
||||
+ error = verify_dfa(dfa);
|
||||
+ } else {
|
||||
+ error = -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ if (error) {
|
||||
+ aa_match_free(dfa);
|
||||
+ dfa = ERR_PTR(error);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return dfa;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * aa_unpack_profile - unpack a serialized profile
|
||||
+ * @e: serialized data extent information
|
||||
+ * @operation: operation profile is being unpacked for
|
||||
+ */
|
||||
+static struct aa_profile *aa_unpack_profile(struct aa_ext *e,
|
||||
+ const char *operation)
|
||||
+{
|
||||
+ struct aa_profile *profile = NULL;
|
||||
+ struct aa_audit sa;
|
||||
+
|
||||
+ int error = -EPROTO;
|
||||
+
|
||||
+ profile = alloc_aa_profile();
|
||||
+ if (!profile)
|
||||
+ return ERR_PTR(-ENOMEM);
|
||||
+
|
||||
+ /* check that we have the right struct being passed */
|
||||
+ if (!aa_is_nameX(e, AA_STRUCT, "profile"))
|
||||
+ goto fail;
|
||||
+ if (!aa_is_dynstring(e, &profile->name, NULL))
|
||||
+ goto fail;
|
||||
+
|
||||
+ /* per profile debug flags (complain, audit) */
|
||||
+ if (!aa_is_nameX(e, AA_STRUCT, "flags"))
|
||||
+ goto fail;
|
||||
+ if (!aa_is_u32(e, NULL, NULL))
|
||||
+ goto fail;
|
||||
+ if (!aa_is_u32(e, &(profile->flags.complain), NULL))
|
||||
+ goto fail;
|
||||
+ if (!aa_is_u32(e, &(profile->flags.audit), NULL))
|
||||
+ goto fail;
|
||||
+ if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
|
||||
+ goto fail;
|
||||
+
|
||||
+ if (!aa_is_u32(e, &(profile->capabilities), NULL))
|
||||
+ goto fail;
|
||||
+
|
||||
+ /* get file rules */
|
||||
+ profile->file_rules = aa_unpack_dfa(e);
|
||||
+ if (IS_ERR(profile->file_rules)) {
|
||||
+ error = PTR_ERR(profile->file_rules);
|
||||
+ profile->file_rules = NULL;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
|
||||
+ goto fail;
|
||||
+
|
||||
+ return profile;
|
||||
+
|
||||
+fail:
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.operation = operation;
|
||||
+ sa.gfp_mask = GFP_KERNEL;
|
||||
+ sa.name = profile && profile->name ? profile->name : "unknown";
|
||||
+ sa.info = "failed to unpack profile";
|
||||
+ aa_audit_status(NULL, &sa);
|
||||
+
|
||||
+ if (profile)
|
||||
+ free_aa_profile(profile);
|
||||
+
|
||||
+ return ERR_PTR(error);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * aa_verify_head - unpack serialized stream header
|
||||
+ * @e: serialized data read head
|
||||
+ * @operation: operation header is being verified for
|
||||
+ *
|
||||
+ * returns error or 0 if header is good
|
||||
+ */
|
||||
+static int aa_verify_header(struct aa_ext *e, const char *operation)
|
||||
+{
|
||||
+ /* get the interface version */
|
||||
+ if (!aa_is_u32(e, &e->version, "version")) {
|
||||
+ struct aa_audit sa;
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.operation = operation;
|
||||
+ sa.gfp_mask = GFP_KERNEL;
|
||||
+ sa.info = "invalid profile format";
|
||||
+ aa_audit_status(NULL, &sa);
|
||||
+ return -EPROTONOSUPPORT;
|
||||
+ }
|
||||
+
|
||||
+ /* check that the interface version is currently supported */
|
||||
+ if (e->version != 3) {
|
||||
+ struct aa_audit sa;
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.operation = operation;
|
||||
+ sa.gfp_mask = GFP_KERNEL;
|
||||
+ sa.info = "unsupported interface version";
|
||||
+ aa_audit_status(NULL, &sa);
|
||||
+ return -EPROTONOSUPPORT;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * aa_add_profile - Unpack and add a new profile to the profile list
|
||||
+ * @data: serialized data stream
|
||||
+ * @size: size of the serialized data stream
|
||||
+ */
|
||||
+ssize_t aa_add_profile(void *data, size_t size)
|
||||
+{
|
||||
+ struct aa_profile *profile = NULL;
|
||||
+ struct aa_ext e = {
|
||||
+ .start = data,
|
||||
+ .end = data + size,
|
||||
+ .pos = data
|
||||
+ };
|
||||
+ ssize_t error = aa_verify_header(&e, "profile_load");
|
||||
+ if (error)
|
||||
+ return error;
|
||||
+
|
||||
+ profile = aa_unpack_profile(&e, "profile_load");
|
||||
+ if (IS_ERR(profile))
|
||||
+ return PTR_ERR(profile);
|
||||
+
|
||||
+ mutex_lock(&aa_interface_lock);
|
||||
+ write_lock(&profile_list_lock);
|
||||
+ if (__aa_find_profile(profile->name, &profile_list)) {
|
||||
+ /* A profile with this name exists already. */
|
||||
+ write_unlock(&profile_list_lock);
|
||||
+ mutex_unlock(&aa_interface_lock);
|
||||
+ aa_put_profile(profile);
|
||||
+ return -EEXIST;
|
||||
+ }
|
||||
+ list_add(&profile->list, &profile_list);
|
||||
+ write_unlock(&profile_list_lock);
|
||||
+ mutex_unlock(&aa_interface_lock);
|
||||
+
|
||||
+ return size;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * task_replace - replace a task's profile
|
||||
+ * @task: task to replace profile on
|
||||
+ * @new_cxt: new aa_task_context to do replacement with
|
||||
+ * @new_profile: new profile
|
||||
+ */
|
||||
+static inline void task_replace(struct task_struct *task,
|
||||
+ struct aa_task_context *new_cxt,
|
||||
+ struct aa_profile *new_profile)
|
||||
+{
|
||||
+ struct aa_task_context *cxt = aa_task_context(task);
|
||||
+
|
||||
+ AA_DEBUG("%s: replacing profile for task %d "
|
||||
+ "profile=%s (%p)\n",
|
||||
+ __FUNCTION__,
|
||||
+ cxt->task->pid,
|
||||
+ cxt->profile->name, cxt->profile);
|
||||
+
|
||||
+ aa_change_task_context(task, new_cxt, new_profile, cxt->cookie,
|
||||
+ cxt->previous_profile);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * aa_replace_profile - replace a profile on the profile list
|
||||
+ * @udata: serialized data stream
|
||||
+ * @size: size of the serialized data stream
|
||||
+ *
|
||||
+ * unpack and replace a profile on the profile list and uses of that profile
|
||||
+ * by any aa_task_context. If the profile does not exist on the profile list
|
||||
+ * it is added. Return %0 or error.
|
||||
+ */
|
||||
+ssize_t aa_replace_profile(void *udata, size_t size)
|
||||
+{
|
||||
+ struct aa_profile *old_profile, *new_profile;
|
||||
+ struct aa_task_context *new_cxt;
|
||||
+ struct aa_ext e = {
|
||||
+ .start = udata,
|
||||
+ .end = udata + size,
|
||||
+ .pos = udata
|
||||
+ };
|
||||
+ ssize_t error = aa_verify_header(&e, "profile_replace");
|
||||
+ if (error)
|
||||
+ return error;
|
||||
+
|
||||
+ new_profile = aa_unpack_profile(&e, "profile_replace");
|
||||
+ if (IS_ERR(new_profile))
|
||||
+ return PTR_ERR(new_profile);
|
||||
+
|
||||
+ mutex_lock(&aa_interface_lock);
|
||||
+ write_lock(&profile_list_lock);
|
||||
+ old_profile = __aa_find_profile(new_profile->name, &profile_list);
|
||||
+ if (old_profile) {
|
||||
+ lock_profile(old_profile);
|
||||
+ old_profile->isstale = 1;
|
||||
+ unlock_profile(old_profile);
|
||||
+ list_del_init(&old_profile->list);
|
||||
+ }
|
||||
+ list_add(&new_profile->list, &profile_list);
|
||||
+ write_unlock(&profile_list_lock);
|
||||
+
|
||||
+ if (!old_profile)
|
||||
+ goto out;
|
||||
+
|
||||
+ /*
|
||||
+ * Replacement needs to allocate a new aa_task_context for each
|
||||
+ * task confined by old_profile. To do this the profile locks
|
||||
+ * are only held when the actual switch is done per task. While
|
||||
+ * looping to allocate a new aa_task_context the old_task list
|
||||
+ * may get shorter if tasks exit/change their profile but will
|
||||
+ * not get longer as new task will not use old_profile detecting
|
||||
+ * that is stale.
|
||||
+ */
|
||||
+ do {
|
||||
+ new_cxt = aa_alloc_task_context(GFP_KERNEL | __GFP_NOFAIL);
|
||||
+
|
||||
+ lock_both_profiles(old_profile, new_profile);
|
||||
+ if (!list_empty(&old_profile->task_contexts)) {
|
||||
+ struct task_struct *task =
|
||||
+ list_entry(old_profile->task_contexts.next,
|
||||
+ struct aa_task_context, list)->task;
|
||||
+ task_lock(task);
|
||||
+ task_replace(task, new_cxt, new_profile);
|
||||
+ task_unlock(task);
|
||||
+ new_cxt = NULL;
|
||||
+ }
|
||||
+ unlock_both_profiles(old_profile, new_profile);
|
||||
+ } while (!new_cxt);
|
||||
+ aa_free_task_context(new_cxt);
|
||||
+ aa_put_profile(old_profile);
|
||||
+
|
||||
+out:
|
||||
+ mutex_unlock(&aa_interface_lock);
|
||||
+ return size;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * aa_remove_profile - remove a profile from the system
|
||||
+ * @name: name of the profile to remove
|
||||
+ * @size: size of the name
|
||||
+ *
|
||||
+ * remove a profile from the profile list and all aa_task_context references
|
||||
+ * to said profile.
|
||||
+ */
|
||||
+ssize_t aa_remove_profile(const char *name, size_t size)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+
|
||||
+ mutex_lock(&aa_interface_lock);
|
||||
+ write_lock(&profile_list_lock);
|
||||
+ profile = __aa_find_profile(name, &profile_list);
|
||||
+ if (!profile) {
|
||||
+ write_unlock(&profile_list_lock);
|
||||
+ mutex_unlock(&aa_interface_lock);
|
||||
+ return -ENOENT;
|
||||
+ }
|
||||
+
|
||||
+ /* Remove the profile from each task context it is on. */
|
||||
+ lock_profile(profile);
|
||||
+ profile->isstale = 1;
|
||||
+ aa_unconfine_tasks(profile);
|
||||
+ unlock_profile(profile);
|
||||
+
|
||||
+ /* Release the profile itself. */
|
||||
+ list_del_init(&profile->list);
|
||||
+ aa_put_profile(profile);
|
||||
+ write_unlock(&profile_list_lock);
|
||||
+ mutex_unlock(&aa_interface_lock);
|
||||
+
|
||||
+ return size;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * free_aa_profile_kref - free aa_profile by kref (called by aa_put_profile)
|
||||
+ * @kr: kref callback for freeing of a profile
|
||||
+ */
|
||||
+void free_aa_profile_kref(struct kref *kref)
|
||||
+{
|
||||
+ struct aa_profile *p=container_of(kref, struct aa_profile, count);
|
||||
+
|
||||
+ free_aa_profile(p);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * alloc_aa_profile - allocate, initialize and return a new profile
|
||||
+ * Returns NULL on failure.
|
||||
+ */
|
||||
+struct aa_profile *alloc_aa_profile(void)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+
|
||||
+ profile = kzalloc(sizeof(*profile), GFP_KERNEL);
|
||||
+ AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
|
||||
+ if (profile) {
|
||||
+ INIT_LIST_HEAD(&profile->list);
|
||||
+ kref_init(&profile->count);
|
||||
+ INIT_LIST_HEAD(&profile->task_contexts);
|
||||
+ spin_lock_init(&profile->lock);
|
||||
+ }
|
||||
+ return profile;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * free_aa_profile - free a profile
|
||||
+ * @profile: the profile to free
|
||||
+ *
|
||||
+ * Free a profile, its hats and null_profile. All references to the profile,
|
||||
+ * its hats and null_profile must have been put.
|
||||
+ *
|
||||
+ * If the profile was referenced from a task context, free_aa_profile() will
|
||||
+ * be called from an rcu callback routine, so we must not sleep here.
|
||||
+ */
|
||||
+void free_aa_profile(struct aa_profile *profile)
|
||||
+{
|
||||
+ AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
|
||||
+
|
||||
+ if (!profile)
|
||||
+ return;
|
||||
+
|
||||
+ /* profile is still on global profile list -- invalid */
|
||||
+ if (!list_empty(&profile->list)) {
|
||||
+ AA_ERROR("%s: internal error, "
|
||||
+ "profile '%s' still on global list\n",
|
||||
+ __FUNCTION__,
|
||||
+ profile->name);
|
||||
+ BUG();
|
||||
+ }
|
||||
+
|
||||
+ aa_match_free(profile->file_rules);
|
||||
+
|
||||
+ if (profile->name) {
|
||||
+ AA_DEBUG("%s: %s\n", __FUNCTION__, profile->name);
|
||||
+ kfree(profile->name);
|
||||
+ }
|
||||
+
|
||||
+ kfree(profile);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * aa_unconfine_tasks - remove tasks on a profile's task context list
|
||||
+ * @profile: profile to remove tasks from
|
||||
+ *
|
||||
+ * Assumes that @profile lock is held.
|
||||
+ */
|
||||
+void aa_unconfine_tasks(struct aa_profile *profile)
|
||||
+{
|
||||
+ while (!list_empty(&profile->task_contexts)) {
|
||||
+ struct task_struct *task =
|
||||
+ list_entry(profile->task_contexts.next,
|
||||
+ struct aa_task_context, list)->task;
|
||||
+ task_lock(task);
|
||||
+ aa_change_task_context(task, NULL, NULL, 0, NULL);
|
||||
+ task_unlock(task);
|
||||
+ }
|
||||
+}
|
@@ -1,399 +0,0 @@
|
||||
---
|
||||
security/apparmor/Makefile | 7 +
|
||||
security/apparmor/apparmor.h | 7 +
|
||||
security/apparmor/lsm.c | 147 ++++++++++++++++++++++++++++++++++-
|
||||
security/apparmor/main.c | 96 ++++++++++++++++++++++
|
||||
security/apparmor/module_interface.c | 20 ++++
|
||||
5 files changed, 273 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/security/apparmor/Makefile
|
||||
+++ b/security/apparmor/Makefile
|
||||
@@ -8,6 +8,11 @@ apparmor-y := main.o list.o procattr.o l
|
||||
quiet_cmd_make-caps = GEN $@
|
||||
cmd_make-caps = sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z > $@
|
||||
|
||||
-$(obj)/main.o : $(obj)/capability_names.h
|
||||
+quiet_cmd_make-af = GEN $@
|
||||
+cmd_make-af = sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z > $@
|
||||
+
|
||||
+$(obj)/main.o : $(obj)/capability_names.h $(obj)/af_names.h
|
||||
$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
|
||||
$(call cmd,make-caps)
|
||||
+$(obj)/af_names.h : $(srctree)/include/linux/socket.h
|
||||
+ $(call cmd,make-af)
|
||||
--- a/security/apparmor/apparmor.h
|
||||
+++ b/security/apparmor/apparmor.h
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/binfmts.h>
|
||||
#include <linux/rcupdate.h>
|
||||
+#include <linux/socket.h>
|
||||
+#include <net/sock.h>
|
||||
|
||||
/*
|
||||
* We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags
|
||||
@@ -114,6 +116,7 @@ struct aa_profile {
|
||||
struct list_head task_contexts;
|
||||
spinlock_t lock;
|
||||
unsigned long int_flags;
|
||||
+ u16 network_families[AF_MAX];
|
||||
};
|
||||
|
||||
extern struct list_head profile_list;
|
||||
@@ -159,6 +162,7 @@ struct aa_audit {
|
||||
int requested_mask, denied_mask;
|
||||
struct iattr *iattr;
|
||||
pid_t task, parent;
|
||||
+ int family, type, protocol;
|
||||
int error_code;
|
||||
};
|
||||
|
||||
@@ -223,6 +227,9 @@ extern void aa_change_task_context(struc
|
||||
struct aa_profile *previous_profile);
|
||||
extern int aa_may_ptrace(struct aa_task_context *cxt,
|
||||
struct aa_profile *tracee);
|
||||
+extern int aa_net_perm(struct aa_profile *profile, char *operation,
|
||||
+ int family, int type, int protocol);
|
||||
+extern int aa_revalidate_sk(struct sock *sk, char *operation);
|
||||
|
||||
/* list.c */
|
||||
extern void aa_profilelist_release(void);
|
||||
--- a/security/apparmor/lsm.c
|
||||
+++ b/security/apparmor/lsm.c
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/audit.h>
|
||||
+#include <net/sock.h>
|
||||
|
||||
#include "apparmor.h"
|
||||
#include "inline.h"
|
||||
@@ -605,6 +606,133 @@ static void apparmor_task_free_security(
|
||||
aa_release(task);
|
||||
}
|
||||
|
||||
+static int apparmor_socket_create(int family, int type, int protocol, int kern)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ if (kern)
|
||||
+ return 0;
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+ if (profile)
|
||||
+ error = aa_net_perm(profile, "socket_create", family,
|
||||
+ type, protocol);
|
||||
+ aa_put_profile(profile);
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_post_create(struct socket * sock, int family,
|
||||
+ int type, int protocol, int kern)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ if (kern)
|
||||
+ return 0;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_post_create");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_bind(struct socket * sock,
|
||||
+ struct sockaddr * address, int addrlen)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_bind");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_connect(struct socket * sock,
|
||||
+ struct sockaddr * address, int addrlen)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_connect");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_listen(struct socket * sock, int backlog)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_listen");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_accept(struct socket * sock, struct socket * newsock)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_accept");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_sendmsg(struct socket * sock,
|
||||
+ struct msghdr * msg, int size)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_sendmsg");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_recvmsg(struct socket * sock,
|
||||
+ struct msghdr * msg, int size, int flags)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_recvmsg");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_getsockname(struct socket * sock)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_getsockname");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_getpeername(struct socket * sock)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_getpeername");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_getsockopt(struct socket * sock, int level,
|
||||
+ int optname)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_getsockopt");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_setsockopt(struct socket * sock, int level,
|
||||
+ int optname)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_setsockopt");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_shutdown(struct socket * sock, int how)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_shutdown");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_getpeersec_stream(struct socket *sock,
|
||||
+ char __user *optval, int __user *optlen, unsigned len)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_getpeersec_stream");
|
||||
+}
|
||||
+
|
||||
+static int apparmor_socket_getpeersec_dgram(struct socket *sock,
|
||||
+ struct sk_buff *skb, u32 *secid)
|
||||
+{
|
||||
+ struct sock *sk = sock->sk;
|
||||
+
|
||||
+ return aa_revalidate_sk(sk, "socket_getpeersec_dgram");
|
||||
+}
|
||||
+
|
||||
static int apparmor_getprocattr(struct task_struct *task, char *name,
|
||||
char **value)
|
||||
{
|
||||
@@ -705,9 +833,6 @@ struct security_operations apparmor_ops
|
||||
.capable = apparmor_capable,
|
||||
.syslog = cap_syslog,
|
||||
|
||||
- .netlink_send = cap_netlink_send,
|
||||
- .netlink_recv = cap_netlink_recv,
|
||||
-
|
||||
.bprm_apply_creds = cap_bprm_apply_creds,
|
||||
.bprm_set_security = apparmor_bprm_set_security,
|
||||
.bprm_secureexec = apparmor_bprm_secureexec,
|
||||
@@ -743,6 +868,22 @@ struct security_operations apparmor_ops
|
||||
|
||||
.getprocattr = apparmor_getprocattr,
|
||||
.setprocattr = apparmor_setprocattr,
|
||||
+
|
||||
+ .socket_create = apparmor_socket_create,
|
||||
+ .socket_post_create = apparmor_socket_post_create,
|
||||
+ .socket_bind = apparmor_socket_bind,
|
||||
+ .socket_connect = apparmor_socket_connect,
|
||||
+ .socket_listen = apparmor_socket_listen,
|
||||
+ .socket_accept = apparmor_socket_accept,
|
||||
+ .socket_sendmsg = apparmor_socket_sendmsg,
|
||||
+ .socket_recvmsg = apparmor_socket_recvmsg,
|
||||
+ .socket_getsockname = apparmor_socket_getsockname,
|
||||
+ .socket_getpeername = apparmor_socket_getpeername,
|
||||
+ .socket_getsockopt = apparmor_socket_getsockopt,
|
||||
+ .socket_setsockopt = apparmor_socket_setsockopt,
|
||||
+ .socket_shutdown = apparmor_socket_shutdown,
|
||||
+ .socket_getpeersec_stream = apparmor_socket_getpeersec_stream,
|
||||
+ .socket_getpeersec_dgram = apparmor_socket_getpeersec_dgram,
|
||||
};
|
||||
|
||||
static void info_message(const char *str)
|
||||
--- a/security/apparmor/main.c
|
||||
+++ b/security/apparmor/main.c
|
||||
@@ -14,6 +14,9 @@
|
||||
#include <linux/audit.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/ptrace.h>
|
||||
+#include <linux/socket.h>
|
||||
+#include <linux/net.h>
|
||||
+#include <net/sock.h>
|
||||
|
||||
#include "apparmor.h"
|
||||
|
||||
@@ -283,6 +286,24 @@ static void aa_audit_file_mask(struct au
|
||||
audit_log_format(ab, " %s=\"%s\"", name, mask_str);
|
||||
}
|
||||
|
||||
+static const char *address_families[] = {
|
||||
+#include "af_names.h"
|
||||
+};
|
||||
+
|
||||
+static const char *sock_types[] = {
|
||||
+ "unknown(0)",
|
||||
+ "stream",
|
||||
+ "dgram",
|
||||
+ "raw",
|
||||
+ "rdm",
|
||||
+ "seqpacket",
|
||||
+ "dccp",
|
||||
+ "unknown(7)",
|
||||
+ "unknown(8)",
|
||||
+ "unknown(9)",
|
||||
+ "packet",
|
||||
+};
|
||||
+
|
||||
/**
|
||||
* aa_audit - Log an audit event to the audit subsystem
|
||||
* @profile: profile to check against
|
||||
@@ -348,6 +369,24 @@ static int aa_audit_base(struct aa_profi
|
||||
audit_log_untrustedstring(ab, sa->name2);
|
||||
}
|
||||
|
||||
+ if (sa->family || sa->type) {
|
||||
+ if (address_families[sa->family])
|
||||
+ audit_log_format(ab, " family=\"%s\"",
|
||||
+ address_families[sa->family]);
|
||||
+ else
|
||||
+ audit_log_format(ab, " family=\"unknown(%d)\"",
|
||||
+ sa->family);
|
||||
+
|
||||
+ if (sock_types[sa->type])
|
||||
+ audit_log_format(ab, " sock_type=\"%s\"",
|
||||
+ sock_types[sa->type]);
|
||||
+ else
|
||||
+ audit_log_format(ab, " sock_type=\"unknown(%d)\"",
|
||||
+ sa->type);
|
||||
+
|
||||
+ audit_log_format(ab, " protocol=%d", sa->protocol);
|
||||
+ }
|
||||
+
|
||||
audit_log_format(ab, " pid=%d", current->pid);
|
||||
|
||||
if (profile) {
|
||||
@@ -660,6 +699,63 @@ int aa_link(struct aa_profile *profile,
|
||||
return error;
|
||||
}
|
||||
|
||||
+int aa_net_perm(struct aa_profile *profile, char *operation,
|
||||
+ int family, int type, int protocol)
|
||||
+{
|
||||
+ struct aa_audit sa;
|
||||
+ int error = 0;
|
||||
+ u16 family_mask;
|
||||
+
|
||||
+ if ((family < 0) || (family >= AF_MAX))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if ((type < 0) || (type >= SOCK_MAX))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* unix domain and netlink sockets are handled by ipc */
|
||||
+ if (family == AF_UNIX || family == AF_NETLINK)
|
||||
+ return 0;
|
||||
+
|
||||
+ family_mask = profile->network_families[family];
|
||||
+
|
||||
+ error = (family_mask & (1 << type)) ? 0 : -EACCES;
|
||||
+
|
||||
+ memset(&sa, 0, sizeof(sa));
|
||||
+ sa.operation = operation;
|
||||
+ sa.gfp_mask = GFP_KERNEL;
|
||||
+ sa.family = family;
|
||||
+ sa.type = type;
|
||||
+ sa.protocol = protocol;
|
||||
+ sa.error_code = error;
|
||||
+
|
||||
+ error = aa_audit(profile, &sa);
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
+int aa_revalidate_sk(struct sock *sk, char *operation)
|
||||
+{
|
||||
+ struct aa_profile *profile;
|
||||
+ int error = 0;
|
||||
+
|
||||
+ /* this is some debugging code to flush out the network hooks that
|
||||
+ that are called in interrupt context */
|
||||
+ if (in_interrupt()) {
|
||||
+ printk("AppArmor Debug: Hook being called from interrupt context\n");
|
||||
+ dump_stack();
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ profile = aa_get_profile(current);
|
||||
+ if (profile)
|
||||
+ error = aa_net_perm(profile, operation,
|
||||
+ sk->sk_family, sk->sk_type,
|
||||
+ sk->sk_protocol);
|
||||
+ aa_put_profile(profile);
|
||||
+
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
/*******************************
|
||||
* Global task related functions
|
||||
*******************************/
|
||||
--- a/security/apparmor/module_interface.c
|
||||
+++ b/security/apparmor/module_interface.c
|
||||
@@ -282,6 +282,8 @@ static struct aa_profile *aa_unpack_prof
|
||||
{
|
||||
struct aa_profile *profile = NULL;
|
||||
struct aa_audit sa;
|
||||
+ size_t size = 0;
|
||||
+ int i;
|
||||
|
||||
int error = -EPROTO;
|
||||
|
||||
@@ -310,6 +312,24 @@ static struct aa_profile *aa_unpack_prof
|
||||
if (!aa_is_u32(e, &(profile->capabilities), NULL))
|
||||
goto fail;
|
||||
|
||||
+ size = aa_is_array(e, "net_allowed_af");
|
||||
+ if (size) {
|
||||
+ if (size > AF_MAX)
|
||||
+ goto fail;
|
||||
+
|
||||
+ for (i = 0; i < size; i++) {
|
||||
+ if (!aa_is_u16(e, &profile->network_families[i], NULL))
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
|
||||
+ goto fail;
|
||||
+ /* allow unix domain and netlink sockets they are handled
|
||||
+ * by IPC
|
||||
+ */
|
||||
+ }
|
||||
+ profile->network_families[AF_UNIX] = 0xffff;
|
||||
+ profile->network_families[AF_NETLINK] = 0xffff;
|
||||
+
|
||||
/* get file rules */
|
||||
profile->file_rules = aa_unpack_dfa(e);
|
||||
if (IS_ERR(profile->file_rules)) {
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user