]> git.proxmox.com Git - mirror_lxc.git/blame - config/apparmor/lxc-generate-aa-rules.py
seccomp: use SOCK_SEQPACKET for the notify proxy
[mirror_lxc.git] / config / apparmor / lxc-generate-aa-rules.py
CommitLineData
e2f91e34 1#!/usr/bin/env python3
198b363f
SH
2
3import sys
4
5blocks = []
c70de0ea 6denies = []
198b363f
SH
7
8#
9# blocks is an array of paths under which we want to block by
10# default.
11#
12# blocks[0] = ['path' = '/sys', 'children' = [A,B] ]
13# blocks[1] = ['path' = '/proc/sys', 'children' = [ E ] ]
14# A = [ 'path' = 'fs', children = [C] ]
15# C = [ 'path' = 'cgroup', children = [F] ]
16# B = [ 'path' = 'class', children = [D] ]
17# D = [ 'path' = 'net', children = [F] ]
18# E = [ 'path' = 'shm*' ]
19# F = [ 'path' = '**' ]
20
21
22def add_block(path):
23 for b in blocks:
24 if b['path'] == path:
25 # duplicate
26 return
27 blocks.append({'path': path.strip(), 'children': []})
28
94a77f3f
SH
29# @prev is an array of dicts which containing 'path' and
30# 'children'. @path is a string. We are looking for an entry
31# in @prev which contains @path, and will return its
32# children array.
198b363f
SH
33def child_get(prev, path):
34 for p in prev:
35 if p['path'] == path:
94a77f3f 36 return p['children']
198b363f
SH
37 return None
38
39
40def add_allow(path):
41 # find which block we belong to
42 found = None
43 for b in blocks:
44 l = len(b['path'])
45 if len(path) <= l:
46 continue
94a77f3f 47 # TODO - should we find the longest match?
198b363f
SH
48 if path[0:l] == b['path']:
49 found = b
50 break
51 if found is None:
52 print("allow with no previous block at %s" % path)
53 sys.exit(1)
54 p = path[l:].strip()
55 while p[:1] == "/":
56 p = p[1:]
57 prev = b['children']
58 for s in p.split('/'):
59 n = {'path': s.strip(), 'children': []}
60 tmp = child_get(prev, n['path'])
61 if tmp is not None:
62 prev = tmp
63 else:
64 prev.append(n)
65 prev = n['children']
66
198b363f
SH
67
68def collect_chars(children, ref, index):
69 r = ""
70 for c in children:
71 if index >= len(c['path']):
72 continue
73 if ref[0:index] != c['path'][0:index]:
74 continue
75 if c['path'][index] not in r:
76 r = r + c['path'][index]
77 return r
78
79
80def append_deny(s):
81 s = "%s wklx," % s
82 if s not in denies:
83 denies.append(s)
84
85
86def gen_denies(pathsofar, children):
87 for c in children:
88 for char in range(len(c['path'])):
89 if char == len(c['path'])-1 and c['path'][char] == '*':
90 continue
91 if char == len(c['path'])-2:
92 if c['path'][char:char+2] == '**':
93 continue
94 x = collect_chars(children, c['path'], char)
95 newdeny = "deny %s/%s[^%s]*{,/**}" % (pathsofar,
96 c['path'][0:char], x)
97 append_deny(newdeny)
98 if c['path'] != '**' and c['path'][len(c['path'])-1] != '*':
99 newdeny = "deny %s/%s?*{,/**}" % (pathsofar, c['path'])
100 append_deny(newdeny)
101 elif c['path'] != '**':
102 newdeny = "deny %s/%s/**" % (pathsofar, c['path'])
103 append_deny(newdeny)
104 if len(c['children']) != 0:
105 newpath = "%s/%s" % (pathsofar, c['path'])
106 gen_denies(newpath, c['children'])
107
198b363f 108
c70de0ea
HB
109def main():
110 config = "config"
111 if len(sys.argv) > 1:
112 config = sys.argv[1]
113
114 lines = None
115 try:
116 with open(config) as f:
117 lines = f.readlines()
118 except FileNotFoundError as err:
119 print("Config file not found")
120 print(err)
121 sys.exit(1)
122
123 for line in lines:
124 line.strip()
125 if line.startswith('#'):
126 continue
127 try:
128 (cmd, path) = line.split(' ')
129 except: # blank line
130 continue
131 if cmd == "block":
132 add_block(path)
133 elif cmd == "allow":
134 add_allow(path)
135 else:
136 print("Unknown command: %s" % cmd)
137 sys.exit(1)
138 for block in blocks:
139 gen_denies(block['path'], block['children'])
140
141 denies.sort()
142
143 genby = " # generated by: lxc-generate-aa-rules.py"
144 for a in sys.argv[1:]:
145 genby += " %s" % a
146 print(genby)
147 for d in denies:
148 print(" %s" % d)
149
198b363f 150
c70de0ea
HB
151if __name__ == "__main__":
152 main()