blob: 5b2f14f8e53c46803666fa7ab94bdd7b5fa6a5a5 [file] [log] [blame]
Paul Lawrence7ea40902017-02-14 13:32:23 -08001#!/usr/bin/env python
2# Unit tests for genseccomp.py
3
4import cStringIO
5import textwrap
6import unittest
7
8import genseccomp
9
10class TestGenseccomp(unittest.TestCase):
11 def setUp(self):
12 genseccomp.set_dir()
13
14 def get_config(self, arch):
15 for i in genseccomp.POLICY_CONFIGS:
16 if i[0] == arch:
17 return i
18 self.fail("No such architecture")
19
20 def get_headers(self, arch):
21 return self.get_config(arch)[1]
22
23 def test_get_names(self):
24 syscalls = cStringIO.StringIO(textwrap.dedent("""\
25int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) arm,mips,x86
26int fchown:fchown(int, uid_t, gid_t) arm64,mips,mips64,x86_64
27 """))
28
29 whitelist = cStringIO.StringIO(textwrap.dedent("""\
30ssize_t read(int, void*, size_t) all
31 """))
32
33 syscall_files = [syscalls, whitelist]
34 names = genseccomp.get_names(syscall_files, "arm")
35 for f in syscall_files:
36 f.seek(0)
37 names64 = genseccomp.get_names(syscall_files, "arm64")
38
39 self.assertIn("fchown", names64)
40 self.assertNotIn("fchown", names)
41 self.assertIn("_llseek", names)
42 self.assertNotIn("_llseek", names64)
43 self.assertIn("read", names)
44 self.assertIn("read", names64)
45
46 def test_convert_names_to_NRs(self):
47 self.assertEquals(genseccomp.convert_names_to_NRs(["open"],
48 self.get_headers("arm")),
49 [("open", 5)])
50
51 self.assertEquals(genseccomp.convert_names_to_NRs(["__ARM_NR_set_tls"],
52 self.get_headers("arm")),
53 [('__ARM_NR_set_tls', 983045)])
54
55 self.assertEquals(genseccomp.convert_names_to_NRs(["openat"],
56 self.get_headers("arm64")),
57 [("openat", 56)])
58
59
60 def test_convert_NRs_to_ranges(self):
61 ranges = genseccomp.convert_NRs_to_ranges([("b", 2), ("a", 1)])
62 self.assertEquals(len(ranges), 1)
63 self.assertEquals(ranges[0].begin, 1)
64 self.assertEquals(ranges[0].end, 3)
65 self.assertItemsEqual(ranges[0].names, ["a", "b"])
66
67 ranges = genseccomp.convert_NRs_to_ranges([("b", 3), ("a", 1)])
68 self.assertEquals(len(ranges), 2)
69 self.assertEquals(ranges[0].begin, 1)
70 self.assertEquals(ranges[0].end, 2)
71 self.assertItemsEqual(ranges[0].names, ["a"])
72 self.assertEquals(ranges[1].begin, 3)
73 self.assertEquals(ranges[1].end, 4)
74 self.assertItemsEqual(ranges[1].names, ["b"])
75
76 def test_convert_to_intermediate_bpf(self):
77 ranges = genseccomp.convert_NRs_to_ranges([("b", 2), ("a", 1)])
78 bpf = genseccomp.convert_to_intermediate_bpf(ranges)
79 self.assertEquals(bpf, ['BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 3, {fail}, {allow}), //a|b'])
80
81 ranges = genseccomp.convert_NRs_to_ranges([("b", 3), ("a", 1)])
82 bpf = genseccomp.convert_to_intermediate_bpf(ranges)
83 self.assertEquals(bpf, ['BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 3, 1, 0),',
84 'BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 2, {fail}, {allow}), //a',
85 'BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4, {fail}, {allow}), //b'])
86
87 def test_convert_ranges_to_bpf(self):
88 ranges = genseccomp.convert_NRs_to_ranges([("b", 2), ("a", 1)])
89 bpf = genseccomp.convert_ranges_to_bpf(ranges)
90 self.assertEquals(bpf, ['BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 1, 0, 1),',
91 'BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 3, 1, 0), //a|b',
92 'BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),'])
93
94 ranges = genseccomp.convert_NRs_to_ranges([("b", 3), ("a", 1)])
95 bpf = genseccomp.convert_ranges_to_bpf(ranges)
96 self.assertEquals(bpf, ['BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 1, 0, 3),',
97 'BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 3, 1, 0),',
98 'BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 2, 2, 1), //a',
99 'BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4, 1, 0), //b',
100 'BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),'])
101
102 def test_convert_bpf_to_output(self):
103 output = genseccomp.convert_bpf_to_output(["line1", "line2"], "arm")
104 expected_output = textwrap.dedent("""\
105 // Autogenerated file - edit at your peril!!
106
107 #include <linux/filter.h>
108 #include <errno.h>
109
Paul Lawrencedfe84342017-02-16 09:24:39 -0800110 #include "seccomp_bpfs.h"
111 const sock_filter arm_filter[] = {
Paul Lawrence7ea40902017-02-14 13:32:23 -0800112 line1
113 line2
114 };
115
116 const size_t arm_filter_size = sizeof(arm_filter) / sizeof(struct sock_filter);
117 """)
118 self.assertEquals(output, expected_output)
119
120 def test_construct_bpf(self):
121 syscalls = cStringIO.StringIO(textwrap.dedent("""\
122 int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) arm,mips,x86
123 int fchown:fchown(int, uid_t, gid_t) arm64,mips,mips64,x86_64
124 """))
125
126 whitelist = cStringIO.StringIO(textwrap.dedent("""\
127 ssize_t read(int, void*, size_t) all
128 """))
129
130 syscall_files = [syscalls, whitelist]
131 output = genseccomp.construct_bpf(syscall_files, "arm", self.get_headers("arm"))
132
133 expected_output = textwrap.dedent("""\
134 // Autogenerated file - edit at your peril!!
135
136 #include <linux/filter.h>
137 #include <errno.h>
138
Paul Lawrencedfe84342017-02-16 09:24:39 -0800139 #include "seccomp_bpfs.h"
140 const sock_filter arm_filter[] = {
Paul Lawrence7ea40902017-02-14 13:32:23 -0800141 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 3, 0, 3),
142 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 140, 1, 0),
143 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4, 2, 1), //read
144 BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 141, 1, 0), //_llseek
145 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
146 };
147
148 const size_t arm_filter_size = sizeof(arm_filter) / sizeof(struct sock_filter);
149 """)
150 self.assertEquals(output, expected_output)
151
152
153if __name__ == '__main__':
154 unittest.main()