/src/selinux/libsepol/fuzz/binpolicy-fuzzer.c
Line | Count | Source |
1 | | #include <sepol/debug.h> |
2 | | #include <sepol/kernel_to_cil.h> |
3 | | #include <sepol/kernel_to_conf.h> |
4 | | #include <sepol/module_to_cil.h> |
5 | | #include <sepol/policydb/expand.h> |
6 | | #include <sepol/policydb/hierarchy.h> |
7 | | #include <sepol/policydb/link.h> |
8 | | #include <sepol/policydb/policydb.h> |
9 | | |
10 | | extern int policydb_validate(sepol_handle_t *handle, const policydb_t *p); |
11 | | |
12 | | extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); |
13 | | |
14 | | // set to 1 to enable more verbose libsepol logging |
15 | | #ifndef VERBOSE |
16 | 24.7k | #define VERBOSE 0 |
17 | | #endif |
18 | | |
19 | | static int write_binary_policy(policydb_t *p, FILE *outfp) |
20 | 1.05k | { |
21 | 1.05k | struct policy_file pf; |
22 | | |
23 | 1.05k | policy_file_init(&pf); |
24 | 1.05k | pf.type = PF_USE_STDIO; |
25 | 1.05k | pf.fp = outfp; |
26 | 1.05k | return policydb_write(p, &pf); |
27 | 1.05k | } |
28 | | |
29 | | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
30 | 12.2k | { |
31 | 12.2k | policydb_t policydb = {}, out = {}; |
32 | 12.2k | sidtab_t sidtab = {}; |
33 | 12.2k | struct policy_file pf; |
34 | 12.2k | FILE *devnull = NULL; |
35 | | |
36 | 12.2k | sepol_debug(VERBOSE); |
37 | | |
38 | 12.2k | policy_file_init(&pf); |
39 | 12.2k | pf.type = PF_USE_MEMORY; |
40 | 12.2k | pf.data = (char *)data; |
41 | 12.2k | pf.len = size; |
42 | | |
43 | 12.2k | if (policydb_init(&policydb)) |
44 | 0 | goto exit; |
45 | | |
46 | 12.2k | if (policydb_read(&policydb, &pf, VERBOSE)) |
47 | 11.1k | goto exit; |
48 | | |
49 | 1.05k | if (policydb_load_isids(&policydb, &sidtab)) |
50 | 4 | goto exit; |
51 | | |
52 | 1.05k | if (policydb.policy_type == POLICY_KERN) { |
53 | 881 | (void)policydb_optimize(&policydb); |
54 | | |
55 | 881 | if (policydb_validate(NULL, &policydb) == -1) |
56 | 0 | abort(); |
57 | 881 | } |
58 | | |
59 | 1.05k | if (policydb.global->branch_list) |
60 | 1.03k | (void)check_assertions(NULL, &policydb, |
61 | 1.03k | policydb.global->branch_list->avrules); |
62 | | |
63 | 1.05k | (void)hierarchy_check_constraints(NULL, &policydb); |
64 | | |
65 | 1.05k | devnull = fopen("/dev/null", "we"); |
66 | 1.05k | if (!devnull) |
67 | 0 | goto exit; |
68 | | |
69 | 1.05k | if (write_binary_policy(&policydb, devnull)) |
70 | 0 | abort(); |
71 | | |
72 | 1.05k | if (policydb.policy_type == POLICY_KERN) { |
73 | 881 | if (sepol_kernel_policydb_to_conf(devnull, &policydb)) |
74 | 0 | abort(); |
75 | | |
76 | 881 | if (sepol_kernel_policydb_to_cil(devnull, &policydb)) |
77 | 0 | abort(); |
78 | 881 | } else { |
79 | 170 | if (sepol_module_policydb_to_cil(devnull, &policydb, 0)) |
80 | 0 | abort(); |
81 | | |
82 | 170 | if (policydb.policy_type == POLICY_BASE) { |
83 | 163 | if (link_modules(NULL, &policydb, NULL, 0, VERBOSE)) |
84 | 42 | goto exit; |
85 | | |
86 | 121 | if (policydb_init(&out)) |
87 | 0 | goto exit; |
88 | | |
89 | 121 | if (expand_module(NULL, &policydb, &out, VERBOSE, |
90 | 121 | /*check_assertions=*/0)) |
91 | 121 | goto exit; |
92 | | |
93 | 0 | if (policydb_validate(NULL, &out)) |
94 | 0 | goto exit; |
95 | | |
96 | 0 | (void)check_assertions( |
97 | 0 | NULL, &out, out.global->branch_list->avrules); |
98 | 0 | (void)hierarchy_check_constraints(NULL, &out); |
99 | |
|
100 | 0 | if (write_binary_policy(&out, devnull)) |
101 | 0 | abort(); |
102 | | |
103 | 0 | if (sepol_kernel_policydb_to_conf(devnull, &out)) |
104 | 0 | abort(); |
105 | | |
106 | 0 | if (sepol_kernel_policydb_to_cil(devnull, &out)) |
107 | 0 | abort(); |
108 | 0 | } |
109 | 170 | } |
110 | | |
111 | 12.2k | exit: |
112 | 12.2k | if (devnull != NULL) |
113 | 1.05k | fclose(devnull); |
114 | | |
115 | 12.2k | policydb_destroy(&out); |
116 | 12.2k | policydb_destroy(&policydb); |
117 | 12.2k | sepol_sidtab_destroy(&sidtab); |
118 | | |
119 | | /* Non-zero return values are reserved for future use. */ |
120 | 12.2k | return 0; |
121 | 1.05k | } |
122 | | |
123 | | #ifdef DEFINEMAIN |
124 | | #include <sys/stat.h> |
125 | | #include <sys/mman.h> |
126 | | |
127 | | int main(int argc, char **argv) |
128 | | { |
129 | | if (argc < 2) { |
130 | | fprintf(stderr, "usage: %s fuzzer-input-file\n", argv[0]); |
131 | | exit(1); |
132 | | } |
133 | | |
134 | | FILE *fp = fopen(argv[1], "rb"); |
135 | | if (!fp) { |
136 | | perror(argv[1]); |
137 | | exit(1); |
138 | | } |
139 | | |
140 | | struct stat sb; |
141 | | int rc; |
142 | | |
143 | | rc = fstat(fileno(fp), &sb); |
144 | | if (rc < 0) { |
145 | | perror("fstat"); |
146 | | exit(1); |
147 | | } |
148 | | |
149 | | void *address = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, |
150 | | MAP_PRIVATE, fileno(fp), 0); |
151 | | if (address == MAP_FAILED) { |
152 | | perror("mmap"); |
153 | | exit(1); |
154 | | } |
155 | | |
156 | | return LLVMFuzzerTestOneInput(address, sb.st_size); |
157 | | } |
158 | | #endif |