New upstream version 2.7~rc2
Laurent Bigonville
6 years ago
0 | 2.6 2016-10-14 | |
1 | * Remove Android.mk files and only keep them in Android tree, from Bowgo Tsai. | |
2 | * Add types associated to a role in the current scope when parsing, from Nicolas Iooss. | |
3 | * Extend checkpolicy pathname matching, from Stephen Smalley. | |
4 | * Fix typos in test/dispol, from Petr Lautrbach. | |
5 | * Set flex as default lexer, from Julien Pivotto. | |
6 | * Fix checkmodule output message, from Petr Lautrbach. | |
7 | * Build policy on systems not supporting DCCP protocol, from Richard Haines. | |
8 | * Fail if module name different than output base filename, from James Carter | |
9 | * Add support for portcon dccp protocol, from Richard Haines | |
10 | ||
11 | 2.5 2016-02-23 | |
12 | * Add neverallow support for ioctl extended permissions, from Jeff Vander Stoep. | |
13 | * fix double free on name-based type transitions, from Stephen Smalley. | |
14 | * switch operations to extended perms, from Jeff Vander Stoep. | |
15 | * policy_define.c: fix compiler warnings, from Nick Kralevich. | |
16 | * Remove uses of -Wno-return-type, from Dan Albert. | |
17 | * Fix -Wreturn-type issues, from Dan Albert. | |
18 | * dispol: display operations as ranges, from Jeff Vander Stoep. | |
19 | * dispol: Extend to display operations, from Stephen Smalley. | |
20 | * Add support for ioctl command whitelisting, from Jeff Vander Stoep. | |
21 | * Add option to write CIL policy, from James Carter | |
22 | * Add device tree ocontext nodes to Xen policy, from Daniel De Graaf. | |
23 | * Widen Xen IOMEM context entries, from Daniel De Graaf. | |
24 | * Expand allowed character set in paths, from Daniel De Graaf. | |
25 | * Fix precedence between number and filesystem tokens, from Stephen Smalley. | |
26 | * dispol/dismod fgets function warnings fix, from Emre Can Kucukoglu. | |
27 | ||
28 | 2.4 2015-02-02 | |
29 | * Fix bugs found by hardened gcc flags, from Nicolas Iooss. | |
30 | * Add missing semicolon in cond_else parser rule, from Steven Capelli. | |
31 | * Clear errno before call to strtol(3) from Dan Albert. | |
32 | * Global C++11 compatibility from Dan Albert. | |
33 | * Allow libsepol C++ static library on device from Daniel Cashman. | |
34 | ||
35 | 2.3 2014-05-06 | |
36 | * Add Android support for building dispol. | |
37 | * Report source file and line information for neverallow failures. | |
38 | * Prevent incompatible option combinations for checkmodule. | |
39 | * Drop -lselinux from LDLIBS for test programs; not used. | |
40 | * Add debug feature to display constraints/validatetrans from Richard Haines. | |
41 | ||
42 | 2.2 2013-10-30 | |
43 | * Fix hyphen usage in man pages from Laurent Bigonville. | |
44 | * handle-unknown / -U required argument fix from Laurent Bigonville. | |
45 | * Support overriding Makefile PATH and LIBDIR from Laurent Bigonville. | |
46 | * Support space and : in filenames from Dan Walsh. | |
47 | ||
48 | 2.1.12 2013-02-01 | |
49 | * Fix errors found by coverity | |
50 | * implement default type policy syntax | |
51 | * Free allocated memory when clean up / exit. | |
52 | ||
53 | 2.1.11 2012-09-13 | |
54 | * fd leak reading policy | |
55 | * check return code on ebitmap_set_bit | |
56 | ||
57 | 2.1.10 2012-06-28 | |
58 | * sepolgen: We need to support files that have a + in them | |
59 | * Android/MacOS X build support | |
60 | ||
61 | 2.1.9 2012-03-28 | |
62 | * implement new default labeling behaviors for usr, role, range | |
63 | * Fix dead links to www.nsa.gov/selinux | |
64 | ||
65 | 2.1.8 2011-12-21 | |
66 | * add new helper to translate class sets into bitmaps | |
67 | ||
68 | 2.1.7 2011-12-05 | |
69 | * dis* fixed signed vs unsigned errors | |
70 | * dismod: fix unused parameter errors | |
71 | * test: Makefile: include -W and -Werror | |
72 | * allow ~ in filename transition rules | |
73 | ||
74 | 2.1.6 2011-11-03 | |
75 | * Revert "checkpolicy: Redo filename/filesystem syntax to support filename trans rules" | |
76 | * drop libsepol dynamic link in checkpolicy | |
77 | ||
78 | 2.1.5 2011-09-15 | |
79 | * Separate tunable from boolean during compile. | |
80 | ||
81 | 2.1.4 2011-08-26 | |
82 | * checkpolicy: fix spacing in output message | |
83 | ||
84 | 2.1.3 2011-08-17 | |
85 | * add missing ; to attribute_role_def | |
86 | *Redo filename/filesystem syntax to support filename trans | |
87 | ||
88 | 2.1.2 2011-08-02 | |
89 | * .gitignore changes | |
90 | * dispol output of role trans | |
91 | * man page update: build a module with an older policy version | |
92 | ||
93 | 2.1.1 2011-08-01 | |
94 | * Minor updates to filename trans rule output in dis{mod,pol} | |
95 | ||
96 | 2.1.0 2011-07-27 | |
97 | * Release, minor version bump | |
98 | ||
99 | 2.0.27 2011-07-25 | |
100 | * Add role attribute support by Harry Ciao | |
101 | ||
102 | 2.0.26 2011-05-16 | |
103 | * Wrap file names in filename transitions with quotes by Steve Lawrence. | |
104 | * Allow filesystem names to start with a digit by James Carter. | |
105 | ||
106 | 2.0.25 2011-05-02 | |
107 | * Add support for using the last path compnent in type transitions by Eric | |
108 | Paris. | |
109 | * Allow single digit module versions by Daniel Walsh. | |
110 | * Use better filename identifier for filenames by Daniel Walsh. | |
111 | * Use #defines for dismod selections by Eric Paris. | |
112 | ||
113 | 2.0.24 2011-04-11 | |
114 | * Add new class field in role_transition by Harry Ciao. | |
115 | ||
116 | 2.0.23 2010-12-16 | |
117 | * Remove unused variables to fix compliation under GCC 4.6 by Justin Mattock | |
118 | ||
119 | 2.0.22 2010-06-14 | |
120 | * Update checkmodule man page and usage by Daniel Walsh and Steve Lawrence | |
121 | ||
122 | 2.0.21 2009-11-27 | |
123 | * Add long options to checkpolicy and checkmodule by Guido | |
124 | Trentalancia <guido@trentalancia.com> | |
125 | ||
126 | 2.0.20 2009-10-14 | |
127 | * Add support for building Xen policies from Paul Nuzzi. | |
128 | ||
129 | 2.0.19 2009-02-18 | |
130 | * Fix alias field in module format, caused by boundary format change | |
131 | from Caleb Case. | |
132 | ||
133 | 2.0.18 2008-10-14 | |
134 | * Properly escape regex symbols in the lexer from Stephen Smalley. | |
135 | ||
136 | 2.0.17 2008-10-09 | |
137 | * Add bounds support from KaiGai Kohei. | |
138 | ||
139 | 2.0.16 2008-05-27 | |
140 | * Update checkpolicy for user and role mapping support from Joshua Brindle. | |
141 | ||
142 | 2.0.15 2008-05-05 | |
143 | * Fix for policy module versions that look like IPv4 addresses from Jim Carter. | |
144 | Resolves bug 444451. | |
145 | ||
146 | 2.0.14 2008-03-24 | |
147 | * Add permissive domain support from Eric Paris. | |
148 | ||
149 | 2.0.13 2008-03-05 | |
150 | * Split out non-grammar parts of policy_parse.yacc into | |
151 | policy_define.c and policy_define.h from Todd C. Miller. | |
152 | ||
153 | 2.0.12 2008-03-04 | |
154 | * Initialize struct policy_file before using it, from Todd C. Miller. | |
155 | ||
156 | 2.0.11 2008-03-03 | |
157 | * Remove unused define, move variable out of .y file, simplify COND_ERR, from Todd C. Miller. | |
158 | ||
159 | 2.0.10 2008-02-28 | |
160 | * Use yyerror2() where appropriate from Todd C. Miller. | |
161 | ||
162 | 2.0.9 2008-02-04 | |
163 | * Update dispol for libsepol avtab changes from Stephen Smalley. | |
164 | ||
165 | 2.0.8 2008-01-24 | |
166 | * Deprecate role dominance in parser. | |
167 | ||
168 | 2.0.7 2008-01-02 | |
169 | * Added support for policy capabilities from Todd Miller. | |
170 | ||
171 | 2.0.6 2007-11-15 | |
172 | * Initialize the source file name from the command line argument so that checkpolicy/checkmodule report something more useful than "unknown source". | |
173 | ||
174 | 2.0.5 2007-11-01 | |
175 | * Merged remove use of REJECT and trailing context in lex rules; make ipv4 address parsing like ipv6 from James Carter. | |
176 | ||
177 | 2.0.4 2007-09-18 | |
178 | * Merged handle unknown policydb flag support from Eric Paris. | |
179 | Adds new command line options -U {allow, reject, deny} for selecting | |
180 | the flag when a base module or kernel policy is built. | |
181 | ||
182 | 2.0.3 2007-05-31 | |
183 | * Merged fix for segfault on duplicate require of sensitivity from Caleb Case. | |
184 | * Merged fix for dead URLs in checkpolicy man pages from Dan Walsh. | |
185 | ||
186 | 2.0.2 2007-04-12 | |
187 | * Merged checkmodule man page fix from Dan Walsh. | |
188 | ||
189 | 2.0.1 2007-02-20 | |
190 | * Merged patch to allow dots in class identifiers from Caleb Case. | |
191 | ||
192 | 2.0.0 2007-02-01 | |
193 | * Merged patch to use new libsepol error codes by Karl MacMillan. | |
194 | ||
195 | 1.34.0 2007-01-18 | |
196 | * Updated version for stable branch. | |
197 | ||
198 | 1.33.1 2006-11-13 | |
199 | * Collapse user identifiers and identifiers together. | |
200 | ||
201 | 1.32 2006-10-17 | |
202 | * Updated version for release. | |
203 | ||
204 | 1.30.12 2006-09-28 | |
205 | * Merged user and range_transition support for modules from | |
206 | Darrel Goeddel | |
207 | ||
208 | 1.30.11 2006-09-05 | |
209 | * merged range_transition enhancements and user module format | |
210 | changes from Darrel Goeddel | |
211 | ||
212 | 1.30.10 2006-08-03 | |
213 | * Merged symtab datum patch from Karl MacMillan. | |
214 | ||
215 | 1.30.9 2006-06-29 | |
216 | * Lindent. | |
217 | ||
218 | 1.30.8 2006-06-29 | |
219 | * Merged patch to remove TE rule conflict checking from the parser | |
220 | from Joshua Brindle. This can only be done properly by the | |
221 | expander. | |
222 | ||
223 | 1.30.7 2006-06-27 | |
224 | * Merged patch to make checkpolicy/checkmodule handling of | |
225 | duplicate/conflicting TE rules the same as the expander | |
226 | from Joshua Brindle. | |
227 | ||
228 | 1.30.6 2006-06-26 | |
229 | * Merged optionals in base take 2 patch set from Joshua Brindle. | |
230 | ||
231 | 1.30.5 2006-05-05 | |
232 | * Merged compiler cleanup patch from Karl MacMillan. | |
233 | * Merged fix warnings patch from Karl MacMillan. | |
234 | ||
235 | 1.30.4 2006-04-05 | |
236 | * Changed require_class to reject permissions that have not been | |
237 | declared if building a base module. | |
238 | ||
239 | 1.30.3 2006-03-28 | |
240 | * Fixed checkmodule to call link_modules prior to expand_module | |
241 | to handle optionals. | |
242 | ||
243 | 1.30.2 2006-03-28 | |
244 | * Fixed require_class to avoid shadowing permissions already defined | |
245 | in an inherited common definition. | |
246 | ||
247 | 1.30.1 2006-03-22 | |
248 | * Moved processing of role and user require statements to 2nd pass. | |
249 | ||
250 | 1.30 2006-03-14 | |
251 | * Updated version for release. | |
252 | ||
253 | 1.29.5 2006-03-09 | |
254 | * Fixed bug in role dominance (define_role_dom). | |
255 | ||
256 | 1.29.4 2006-02-14 | |
257 | * Added a check for failure to declare each sensitivity in | |
258 | a level definition. | |
259 | ||
260 | 1.29.3 2006-02-13 | |
261 | * Changed to clone level data for aliased sensitivities to | |
262 | avoid double free upon sens_destroy. Bug reported by Kevin | |
263 | Carr of Tresys Technology. | |
264 | ||
265 | 1.29.2 2006-02-13 | |
266 | * Merged optionals in base patch from Joshua Brindle. | |
267 | ||
268 | 1.29.1 2006-02-01 | |
269 | * Merged sepol_av_to_string patch from Joshua Brindle. | |
270 | ||
271 | 1.28 2005-12-07 | |
272 | * Updated version for release. | |
273 | ||
274 | 1.27.20 2005-12-02 | |
275 | * Merged checkmodule man page from Dan Walsh, and edited it. | |
276 | ||
277 | 1.27.19 2005-12-01 | |
278 | * Added error checking of all ebitmap_set_bit calls for out of | |
279 | memory conditions. | |
280 | ||
281 | 1.27.18 2005-12-01 | |
282 | * Merged removal of compatibility handling of netlink classes | |
283 | (requirement that policies with newer versions include the | |
284 | netlink class definitions, remapping of fine-grained netlink | |
285 | classes in newer source policies to single netlink class when | |
286 | generating older policies) from George Coker. | |
287 | ||
288 | 1.27.17 2005-10-25 | |
289 | * Merged dismod fix from Joshua Brindle. | |
290 | ||
291 | 1.27.16 2005-10-20 | |
292 | * Removed obsolete cond_check_type_rules() function and call and | |
293 | cond_optimize_lists() call from checkpolicy.c; these are handled | |
294 | during parsing and expansion now. | |
295 | ||
296 | 1.27.15 2005-10-19 | |
297 | * Updated calls to expand_module for interface change. | |
298 | ||
299 | 1.27.14 2005-10-19 | |
300 | * Changed checkmodule to verify that expand_module succeeds | |
301 | when building base modules. | |
302 | ||
303 | 1.27.13 2005-10-19 | |
304 | * Merged module compiler fixes from Joshua Brindle. | |
305 | ||
306 | 1.27.12 2005-10-19 | |
307 | * Removed direct calls to hierarchy_check_constraints() and | |
308 | check_assertions() from checkpolicy since they are now called | |
309 | internally by expand_module(). | |
310 | ||
311 | 1.27.11 2005-10-18 | |
312 | * Updated for changes to sepol policydb_index_others interface. | |
313 | ||
314 | 1.27.10 2005-10-17 | |
315 | * Updated for changes to sepol expand_module and link_modules interfaces. | |
316 | ||
317 | 1.27.9 2005-10-13 | |
318 | * Merged support for require blocks inside conditionals from | |
319 | Joshua Brindle (Tresys). | |
320 | ||
321 | 1.27.8 2005-10-06 | |
322 | * Updated for changes to libsepol. | |
323 | ||
324 | 1.27.7 2005-10-05 | |
325 | * Merged several bug fixes from Joshua Brindle (Tresys). | |
326 | ||
327 | 1.27.6 2005-10-03 | |
328 | * Merged MLS in modules patch from Joshua Brindle (Tresys). | |
329 | ||
330 | 1.27.5 2005-09-28 | |
331 | * Merged error handling improvement in checkmodule from Karl MacMillan (Tresys). | |
332 | ||
333 | 1.27.4 2005-09-26 | |
334 | * Merged bugfix for dup role transition error messages from | |
335 | Karl MacMillan (Tresys). | |
336 | ||
337 | 1.27.3 2005-09-23 | |
338 | * Merged policyver/modulever patches from Joshua Brindle (Tresys). | |
339 | ||
340 | 1.27.2 2005-09-20 | |
341 | * Fixed parse_categories handling of undefined category. | |
342 | ||
343 | 1.27.1 2005-09-16 | |
344 | * Merged bug fix for role dominance handling from Darrel Goeddel (TCS). | |
345 | ||
346 | 1.26 2005-09-06 | |
347 | * Updated version for release. | |
348 | ||
349 | 1.25.12 2005-08-22 | |
350 | * Fixed handling of validatetrans constraint expressions. | |
351 | Bug reported by Dan Walsh for checkpolicy -M. | |
352 | ||
353 | 1.25.11 2005-08-18 | |
354 | * Merged use-after-free fix from Serge Hallyn (IBM). | |
355 | Bug found by Coverity. | |
356 | ||
357 | 1.25.10 2005-08-15 | |
358 | * Fixed further memory leaks found by valgrind. | |
359 | ||
360 | 1.25.9 2005-08-15 | |
361 | * Changed checkpolicy to destroy the policydbs prior to exit | |
362 | to allow leak detection. | |
363 | * Fixed several memory leaks found by valgrind. | |
364 | ||
365 | 1.25.8 2005-08-11 | |
366 | * Updated checkpolicy and dispol for the new avtab format. | |
367 | Converted users of ebitmaps to new inline operators. | |
368 | Note: The binary policy format version has been incremented to | |
369 | version 20 as a result of these changes. To build a policy | |
370 | for a kernel that does not yet include these changes, use | |
371 | the -c 19 option to checkpolicy. | |
372 | ||
373 | 1.25.7 2005-08-11 | |
374 | * Merged patch to prohibit use of "self" as a type name from Jason Tang (Tresys). | |
375 | ||
376 | 1.25.6 2005-08-10 | |
377 | * Merged patch to fix dismod compilation from Joshua Brindle (Tresys). | |
378 | ||
379 | 1.25.5 2005-08-09 | |
380 | * Fixed call to hierarchy checking code to pass the right policydb. | |
381 | ||
382 | 1.25.4 2005-08-02 | |
383 | * Merged patch to update dismod for the relocation of the | |
384 | module read/write code from libsemanage to libsepol, and | |
385 | to enable build of test subdirectory from Jason Tang (Tresys). | |
386 | ||
387 | 1.25.3 2005-07-18 | |
388 | * Merged hierarchy check fix from Joshua Brindle (Tresys). | |
389 | ||
390 | 1.25.2 2005-07-06 | |
391 | * Merged loadable module support from Tresys Technology. | |
392 | ||
393 | 1.25.1 2005-06-24 | |
394 | * Merged patch to prohibit the use of * and ~ in type sets | |
395 | (other than in neverallow statements) and in role sets | |
396 | from Joshua Brindle (Tresys). | |
397 | ||
398 | 1.24 2005-06-20 | |
399 | * Updated version for release. | |
400 | ||
401 | 1.23.4 2005-05-19 | |
402 | * Merged cleanup patch from Dan Walsh. | |
403 | ||
404 | 1.23.3 2005-05-13 | |
405 | * Added sepol_ prefix to Flask types to avoid namespace | |
406 | collision with libselinux. | |
407 | ||
408 | 1.23.2 2005-04-29 | |
409 | * Merged identifier fix from Joshua Brindle (Tresys). | |
410 | ||
411 | 1.23.1 2005-04-13 | |
412 | * Merged hierarchical type/role patch from Tresys Technology. | |
413 | * Merged MLS fixes from Darrel Goeddel of TCS. | |
414 | ||
415 | 1.22 2005-03-09 | |
416 | * Updated version for release. | |
417 | ||
418 | 1.21.4 2005-02-17 | |
419 | * Moved genpolusers utility to libsepol. | |
420 | * Merged range_transition support from Darrel Goeddel (TCS). | |
421 | ||
422 | 1.21.3 2005-02-16 | |
423 | * Merged define_user() cleanup patch from Darrel Goeddel (TCS). | |
424 | ||
425 | 1.21.2 2005-02-09 | |
426 | * Changed relabel Makefile target to use restorecon. | |
427 | ||
428 | 1.21.1 2005-01-26 | |
429 | * Merged enhanced MLS support from Darrel Goeddel (TCS). | |
430 | ||
431 | 1.20 2005-01-04 | |
432 | * Merged typeattribute statement patch from Darrel Goeddel of TCS. | |
433 | * Changed genpolusers to handle multiple user config files. | |
434 | * Merged nodecon ordering patch from Chad Hanson of TCS. | |
435 | ||
436 | 1.18 2004-10-07 | |
437 | * MLS build fix. | |
438 | * Fixed Makefile dependencies (Chris PeBenito). | |
439 | * Merged fix for role dominance ordering issue from Chad Hanson of TCS. | |
440 | * Preserve portcon ordering and apply more checking. | |
441 | ||
442 | 1.16 2004-08-13 | |
443 | * Allow empty conditional clauses. | |
444 | * Moved genpolbools utility to libsepol. | |
445 | * Updated for libsepol set functions. | |
446 | * Changed to link with libsepol.a. | |
447 | * Moved core functionality into libsepol. | |
448 | * Merged bug fix for conditional self handling from Karl MacMillan, Dave Caplan, and Joshua Brindle of Tresys. | |
449 | * Added genpolusers program. | |
450 | * Fixed bug in checkpolicy conditional code. | |
451 | ||
452 | 1.14 2004-06-28 | |
453 | * Merged fix for MLS logic from Daniel Thayer of TCS. | |
454 | * Require semicolon terminator for typealias statement. | |
455 | ||
456 | 1.12 2004-06-16 | |
457 | * Merged fine-grained netlink class support. | |
458 | ||
459 | 1.10 2004-04-07 | |
460 | * Merged ipv6 support from James Morris of RedHat. | |
461 | * Fixed compute_av bug discovered by Chad Hanson of TCS. | |
462 | ||
463 | 1.8 2004-03-09 | |
464 | * Merged policydb MLS patch from Chad Hanson of TCS. | |
465 | * Fixed mmap of policy file. | |
466 | ||
467 | 1.6 2004-02-18 | |
468 | * Merged conditional policy extensions from Tresys Technology. | |
469 | * Added typealias declaration support per Russell Coker's request. | |
470 | * Added support for excluding types from type sets based on | |
471 | a patch by David Caplan, but reimplemented as a change to the | |
472 | policy grammar. | |
473 | * Merged patch from Colin Walters to report source file name and line | |
474 | number for errors when available. | |
475 | * Un-deprecated role transitions. | |
476 | ||
477 | 1.4 2003-12-01 | |
478 | * Regenerated headers. | |
479 | * Merged patches from Bastian Blank and Joerg Hoh. | |
480 | ||
481 | 1.2 2003-09-30 | |
482 | * Merged MLS build patch from Karl MacMillan of Tresys. | |
483 | * Merged checkpolicy man page from Magosanyi Arpad. | |
484 | ||
485 | 1.1 2003-08-13 | |
486 | * Fixed endian bug in policydb_write for behavior value. | |
487 | * License -> GPL. | |
488 | * Merged coding style cleanups from James Morris. | |
489 | ||
490 | 1.0 2003-07-11 | |
491 | * Initial public release. | |
492 |
5 | 5 | MANDIR ?= $(PREFIX)/share/man |
6 | 6 | LIBDIR ?= $(PREFIX)/lib |
7 | 7 | INCLUDEDIR ?= $(PREFIX)/include |
8 | LIBSEPOLA ?= $(LIBDIR)/libsepol.a | |
8 | 9 | TARGETS = checkpolicy checkmodule |
9 | 10 | |
10 | 11 | LEX = flex |
12 | 13 | |
13 | 14 | CFLAGS ?= -g -Wall -Werror -Wshadow -O2 -pipe -fno-strict-aliasing |
14 | 15 | |
15 | override CFLAGS += -I. -I${INCLUDEDIR} | |
16 | override CFLAGS += -I. | |
16 | 17 | |
17 | 18 | CHECKOBJS = y.tab.o lex.yy.o queue.o module_compiler.o parse_util.o \ |
18 | 19 | policy_define.o |
19 | 20 | CHECKPOLOBJS = $(CHECKOBJS) checkpolicy.o |
20 | 21 | CHECKMODOBJS = $(CHECKOBJS) checkmodule.o |
21 | 22 | |
22 | LDLIBS=$(LIBDIR)/libsepol.a -lfl | |
23 | ||
24 | 23 | GENERATED=lex.yy.c y.tab.c y.tab.h |
25 | 24 | |
26 | 25 | all: $(TARGETS) |
27 | 26 | $(MAKE) -C test |
28 | 27 | |
29 | checkpolicy: $(CHECKPOLOBJS) | |
28 | checkpolicy: $(CHECKPOLOBJS) $(LIBSEPOLA) | |
30 | 29 | |
31 | checkmodule: $(CHECKMODOBJS) | |
30 | checkmodule: $(CHECKMODOBJS) $(LIBSEPOLA) | |
32 | 31 | |
33 | 32 | %.o: %.c |
34 | 33 | $(CC) $(CFLAGS) -o $@ -c $< |
123 | 123 | return policydb_write(p, &pf); |
124 | 124 | } |
125 | 125 | |
126 | static void usage(char *progname) | |
126 | static __attribute__((__noreturn__)) void usage(const char *progname) | |
127 | 127 | { |
128 | 128 | printf("usage: %s [-h] [-V] [-b] [-C] [-U handle_unknown] [-m] [-M] [-o FILE] [INPUT]\n", progname); |
129 | 129 | printf("Build base and policy modules.\n"); |
2 | 2 | checkpolicy \- SELinux policy compiler |
3 | 3 | .SH SYNOPSIS |
4 | 4 | .B checkpolicy |
5 | .I "[\-b] [\-C] [\-d] [\-M] [\-c policyvers] [\-o output_file] [input_file]" | |
5 | .I "[\-b[F]] [\-C] [\-d] [\-M] [\-c policyvers] [\-o output_file] [input_file]" | |
6 | 6 | .br |
7 | 7 | .SH "DESCRIPTION" |
8 | 8 | This manual page describes the |
25 | 25 | .TP |
26 | 26 | .B \-d,\-\-debug |
27 | 27 | Enter debug mode after loading the policy. |
28 | .TP | |
29 | .B \-F,\-\-conf | |
30 | Write policy.conf file rather than binary policy file. Can only be used with binary policy file. | |
28 | 31 | .TP |
29 | 32 | .B \-M,\-\-mls |
30 | 33 | Enable the MLS policy when checking and compiling the policy. |
21 | 21 | * |
22 | 22 | * Policy Module support. |
23 | 23 | * |
24 | * Copyright (C) 2017 Mellanox Technologies Inc. | |
24 | 25 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. |
25 | 26 | * Copyright (C) 2003 - 2005 Tresys Technology, LLC |
26 | 27 | * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> |
56 | 57 | * booleans or conditional rules are thrown away a warning is printed. |
57 | 58 | */ |
58 | 59 | |
60 | #include <ctype.h> | |
59 | 61 | #include <getopt.h> |
60 | 62 | #include <unistd.h> |
61 | 63 | #include <stdlib.h> |
72 | 74 | #include <errno.h> |
73 | 75 | #include <sys/mman.h> |
74 | 76 | |
75 | #ifdef __APPLE__ | |
76 | #include <ctype.h> | |
77 | #endif | |
78 | ||
79 | 77 | #include <sepol/module_to_cil.h> |
78 | #include <sepol/kernel_to_cil.h> | |
79 | #include <sepol/kernel_to_conf.h> | |
80 | 80 | #include <sepol/policydb/policydb.h> |
81 | 81 | #include <sepol/policydb/services.h> |
82 | 82 | #include <sepol/policydb/conditional.h> |
104 | 104 | |
105 | 105 | unsigned int policyvers = POLICYDB_VERSION_MAX; |
106 | 106 | |
107 | void usage(char *progname) | |
107 | static __attribute__((__noreturn__)) void usage(const char *progname) | |
108 | 108 | { |
109 | 109 | printf |
110 | ("usage: %s [-b] [-C] [-d] [-U handle_unknown (allow,deny,reject)] [-M]" | |
110 | ("usage: %s [-b[F]] [-C] [-d] [-U handle_unknown (allow,deny,reject)] [-M]" | |
111 | 111 | "[-c policyvers (%d-%d)] [-o output_file] [-t target_platform (selinux,xen)]" |
112 | 112 | "[input_file]\n", |
113 | 113 | progname, POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); |
390 | 390 | size_t scontext_len, pathlen; |
391 | 391 | unsigned int i; |
392 | 392 | unsigned int protocol, port; |
393 | unsigned int binary = 0, debug = 0, cil = 0; | |
393 | unsigned int binary = 0, debug = 0, cil = 0, conf = 0; | |
394 | 394 | struct val_to_name v; |
395 | 395 | int ret, ch, fd, target = SEPOL_TARGET_SELINUX; |
396 | 396 | unsigned int nel, uret; |
413 | 413 | {"handle-unknown", required_argument, NULL, 'U'}, |
414 | 414 | {"mls", no_argument, NULL, 'M'}, |
415 | 415 | {"cil", no_argument, NULL, 'C'}, |
416 | {"conf",no_argument, NULL, 'F'}, | |
416 | 417 | {"help", no_argument, NULL, 'h'}, |
417 | 418 | {NULL, 0, NULL, 0} |
418 | 419 | }; |
419 | 420 | |
420 | while ((ch = getopt_long(argc, argv, "o:t:dbU:MCVc:h", long_options, NULL)) != -1) { | |
421 | while ((ch = getopt_long(argc, argv, "o:t:dbU:MCFVc:h", long_options, NULL)) != -1) { | |
421 | 422 | switch (ch) { |
422 | 423 | case 'o': |
423 | 424 | outfile = optarg; |
462 | 463 | break; |
463 | 464 | case 'C': |
464 | 465 | cil = 1; |
466 | break; | |
467 | case 'F': | |
468 | conf = 1; | |
465 | 469 | break; |
466 | 470 | case 'c':{ |
467 | 471 | long int n; |
512 | 516 | sepol_set_policydb(&policydb); |
513 | 517 | sepol_set_sidtab(&sidtab); |
514 | 518 | |
519 | if (cil && conf) { | |
520 | fprintf(stderr, "Can't convert to CIL and policy.conf at the same time\n"); | |
521 | exit(1); | |
522 | } | |
523 | ||
515 | 524 | if (binary) { |
516 | if (cil) { | |
517 | fprintf(stderr, "%s: Converting kernel policy to CIL is not supported\n", | |
518 | argv[0]); | |
519 | exit(1); | |
520 | } | |
521 | 525 | fd = open(file, O_RDONLY); |
522 | 526 | if (fd < 0) { |
523 | 527 | fprintf(stderr, "Can't open '%s': %s\n", |
570 | 574 | } |
571 | 575 | } |
572 | 576 | } else { |
577 | if (conf) { | |
578 | fprintf(stderr, "Can only generate policy.conf from binary policy\n"); | |
579 | exit(1); | |
580 | } | |
573 | 581 | if (policydb_init(&parse_policy)) |
574 | 582 | exit(1); |
575 | 583 | /* We build this as a base policy first since that is all the parser understands */ |
623 | 631 | policydb.policyvers = policyvers; |
624 | 632 | |
625 | 633 | if (!cil) { |
626 | printf | |
627 | ("%s: writing binary representation (version %d) to %s\n", | |
628 | argv[0], policyvers, outfile); | |
629 | policydb.policy_type = POLICY_KERN; | |
630 | ||
631 | policy_file_init(&pf); | |
632 | pf.type = PF_USE_STDIO; | |
633 | pf.fp = outfp; | |
634 | ret = policydb_write(&policydb, &pf); | |
634 | if (!conf) { | |
635 | printf("%s: writing binary representation (version %d) to %s\n", argv[0], policyvers, outfile); | |
636 | ||
637 | policydb.policy_type = POLICY_KERN; | |
638 | ||
639 | policy_file_init(&pf); | |
640 | pf.type = PF_USE_STDIO; | |
641 | pf.fp = outfp; | |
642 | ret = policydb_write(&policydb, &pf); | |
643 | } else { | |
644 | printf("%s: writing policy.conf to %s\n", | |
645 | argv[0], outfile); | |
646 | ret = sepol_kernel_policydb_to_conf(outfp, policydbp); | |
647 | } | |
635 | 648 | if (ret) { |
636 | 649 | fprintf(stderr, "%s: error writing %s\n", |
637 | 650 | argv[0], outfile); |
639 | 652 | } |
640 | 653 | } else { |
641 | 654 | printf("%s: writing CIL to %s\n",argv[0], outfile); |
642 | ret = sepol_module_policydb_to_cil(outfp, policydbp, 1); | |
655 | if (binary) { | |
656 | ret = sepol_kernel_policydb_to_cil(outfp, policydbp); | |
657 | } else { | |
658 | ret = sepol_module_policydb_to_cil(outfp, policydbp, 1); | |
659 | } | |
643 | 660 | if (ret) { |
644 | 661 | fprintf(stderr, "%s: error writing %s\n", argv[0], outfile); |
645 | 662 | exit(1); |
656 | 673 | |
657 | 674 | if (!debug) { |
658 | 675 | policydb_destroy(&policydb); |
676 | sepol_sidtab_destroy(&sidtab); | |
659 | 677 | exit(0); |
660 | 678 | } |
661 | 679 | |
681 | 699 | printf("h) change a boolean value\n"); |
682 | 700 | printf("i) display constraint expressions\n"); |
683 | 701 | printf("j) display validatetrans expressions\n"); |
702 | printf("k) Call ibpkey_sid\n"); | |
703 | printf("l) Call ibendport_sid\n"); | |
684 | 704 | #ifdef EQUIVTYPES |
685 | 705 | printf("z) Show equivalent types\n"); |
686 | 706 | #endif |
1202 | 1222 | "\nNo validatetrans expressions found.\n"); |
1203 | 1223 | } |
1204 | 1224 | break; |
1225 | case 'k': | |
1226 | { | |
1227 | char *p; | |
1228 | struct in6_addr addr6; | |
1229 | uint64_t subnet_prefix; | |
1230 | unsigned int pkey; | |
1231 | ||
1232 | printf("subnet prefix? "); | |
1233 | FGETS(ans, sizeof(ans), stdin); | |
1234 | ans[strlen(ans) - 1] = 0; | |
1235 | p = (char *)&addr6; | |
1236 | ||
1237 | if (inet_pton(AF_INET6, ans, p) < 1) { | |
1238 | printf("error parsing subnet prefix\n"); | |
1239 | break; | |
1240 | } | |
1241 | ||
1242 | memcpy(&subnet_prefix, p, sizeof(subnet_prefix)); | |
1243 | printf("pkey? "); | |
1244 | FGETS(ans, sizeof(ans), stdin); | |
1245 | pkey = atoi(ans); | |
1246 | sepol_ibpkey_sid(subnet_prefix, pkey, &ssid); | |
1247 | printf("sid %d\n", ssid); | |
1248 | } | |
1249 | break; | |
1250 | case 'l': | |
1251 | printf("device name (eg. mlx4_0)? "); | |
1252 | FGETS(ans, sizeof(ans), stdin); | |
1253 | ans[strlen(ans) - 1] = 0; | |
1254 | ||
1255 | name = malloc((strlen(ans) + 1) * sizeof(char)); | |
1256 | if (!name) { | |
1257 | fprintf(stderr, "couldn't malloc string.\n"); | |
1258 | break; | |
1259 | } | |
1260 | strcpy(name, ans); | |
1261 | ||
1262 | printf("port? "); | |
1263 | FGETS(ans, sizeof(ans), stdin); | |
1264 | port = atoi(ans); | |
1265 | sepol_ibendport_sid(name, port, &ssid); | |
1266 | printf("sid %d\n", ssid); | |
1267 | free(name); | |
1268 | break; | |
1205 | 1269 | #ifdef EQUIVTYPES |
1206 | 1270 | case 'z': |
1207 | 1271 | identify_equiv_types(); |
49 | 49 | static scope_stack_t *stack_top = NULL; |
50 | 50 | static avrule_block_t *last_block; |
51 | 51 | static uint32_t next_decl_id = 1; |
52 | ||
53 | static const char * const flavor_str[SYM_NUM] = { | |
54 | [SYM_COMMONS] = "common", | |
55 | [SYM_CLASSES] = "class", | |
56 | [SYM_ROLES] = "role", | |
57 | [SYM_TYPES] = "type", | |
58 | [SYM_USERS] = "user", | |
59 | [SYM_BOOLS] = "bool", | |
60 | [SYM_LEVELS] = "level", | |
61 | [SYM_CATS] = "cat" | |
62 | }; | |
63 | ||
64 | static void print_error_msg(int ret, uint32_t symbol_type) | |
65 | { | |
66 | switch (ret) { | |
67 | case -3: | |
68 | yyerror("Out of memory!"); | |
69 | break; | |
70 | case -2: | |
71 | yyerror2("Duplicate declaration of %s", flavor_str[symbol_type]); | |
72 | break; | |
73 | case -1: | |
74 | yyerror2("Could not declare %s here", flavor_str[symbol_type]); | |
75 | break; | |
76 | default: | |
77 | yyerror("Unknown error"); | |
78 | } | |
79 | } | |
52 | 80 | |
53 | 81 | int define_policy(int pass, int module_header_given) |
54 | 82 | { |
101 | 129 | return 0; |
102 | 130 | } |
103 | 131 | |
104 | /* Given the current parse stack, returns 1 if a declaration would be | |
105 | * allowed here or 0 if not. For example, declarations are not | |
106 | * allowed in conditionals, so if there are any conditionals in the | |
132 | /* Given the current parse stack, returns 1 if a declaration or require would | |
133 | * be allowed here or 0 if not. For example, declarations and requirements are | |
134 | * not allowed in conditionals, so if there are any conditionals in the | |
107 | 135 | * current scope stack then this would return a 0. |
108 | 136 | */ |
109 | static int is_declaration_allowed(void) | |
137 | static int is_creation_allowed(void) | |
110 | 138 | { |
111 | 139 | if (stack_top->type != 1 || stack_top->in_else) { |
112 | 140 | return 0; |
113 | 141 | } |
114 | 142 | return 1; |
143 | } | |
144 | ||
145 | /* Attempt to declare or require a symbol within the current scope. | |
146 | * Returns: | |
147 | * 0: Success - Symbol had not been previously created. | |
148 | * 1: Success - Symbol had already been created and caller must free datum. | |
149 | * -1: Failure - Symbol cannot be created here | |
150 | * -2: Failure - Duplicate declaration or type/attribute mismatch | |
151 | * -3: Failure - Out of memory or some other error | |
152 | */ | |
153 | static int create_symbol(uint32_t symbol_type, hashtab_key_t key, hashtab_datum_t datum, | |
154 | uint32_t * dest_value, uint32_t scope) | |
155 | { | |
156 | avrule_decl_t *decl = stack_top->decl; | |
157 | int ret; | |
158 | ||
159 | if (!is_creation_allowed()) { | |
160 | return -1; | |
161 | } | |
162 | ||
163 | ret = symtab_insert(policydbp, symbol_type, key, datum, scope, | |
164 | decl->decl_id, dest_value); | |
165 | ||
166 | if (ret == 1 && dest_value) { | |
167 | symtab_datum_t *s = | |
168 | hashtab_search(policydbp->symtab[symbol_type].table, | |
169 | key); | |
170 | assert(s != NULL); | |
171 | ||
172 | if (symbol_type == SYM_LEVELS) { | |
173 | *dest_value = ((level_datum_t *)s)->level->sens; | |
174 | } else { | |
175 | *dest_value = s->value; | |
176 | } | |
177 | } else if (ret == -2) { | |
178 | return -2; | |
179 | } else if (ret < 0) { | |
180 | return -3; | |
181 | } | |
182 | ||
183 | return ret; | |
115 | 184 | } |
116 | 185 | |
117 | 186 | /* Attempt to declare a symbol within the current declaration. If |
128 | 197 | uint32_t * dest_value, uint32_t * datum_value) |
129 | 198 | { |
130 | 199 | avrule_decl_t *decl = stack_top->decl; |
131 | int retval; | |
132 | ||
133 | /* first check that symbols may be declared here */ | |
134 | if (!is_declaration_allowed()) { | |
135 | return -1; | |
136 | } | |
137 | retval = symtab_insert(policydbp, symbol_type, key, datum, | |
138 | SCOPE_DECL, decl->decl_id, dest_value); | |
139 | if (retval == 1 && dest_value) { | |
140 | symtab_datum_t *s = | |
141 | (symtab_datum_t *) hashtab_search(policydbp-> | |
142 | symtab[symbol_type].table, | |
143 | key); | |
144 | assert(s != NULL); | |
145 | ||
146 | if (symbol_type == SYM_LEVELS) { | |
147 | *dest_value = ((level_datum_t *)s)->level->sens; | |
148 | } else { | |
149 | *dest_value = s->value; | |
150 | } | |
151 | } else if (retval == -2) { | |
152 | return -2; | |
153 | } else if (retval < 0) { | |
200 | int ret = create_symbol(symbol_type, key, datum, dest_value, SCOPE_DECL); | |
201 | ||
202 | if (ret < 0) { | |
203 | return ret; | |
204 | } | |
205 | ||
206 | if (ebitmap_set_bit(decl->declared.scope + symbol_type, | |
207 | *datum_value - 1, 1)) { | |
154 | 208 | return -3; |
155 | } else { /* fall through possible if retval is 0 */ | |
156 | } | |
157 | if (datum_value != NULL) { | |
158 | if (ebitmap_set_bit(decl->declared.scope + symbol_type, | |
159 | *datum_value - 1, 1)) { | |
160 | return -3; | |
161 | } | |
162 | } | |
163 | return retval; | |
209 | } | |
210 | ||
211 | return ret; | |
164 | 212 | } |
165 | 213 | |
166 | 214 | static int role_implicit_bounds(hashtab_t roles_tab, |
200 | 248 | return 0; |
201 | 249 | } |
202 | 250 | |
203 | role_datum_t *declare_role(unsigned char isattr) | |
204 | { | |
205 | char *id = queue_remove(id_queue), *dest_id = NULL; | |
206 | role_datum_t *role = NULL, *dest_role = NULL; | |
207 | int retval; | |
251 | static int create_role(uint32_t scope, unsigned char isattr, role_datum_t **role, char **key) | |
252 | { | |
253 | char *id = queue_remove(id_queue); | |
254 | role_datum_t *datum = NULL; | |
255 | int ret; | |
208 | 256 | uint32_t value; |
257 | ||
258 | *role = NULL; | |
259 | *key = NULL; | |
260 | isattr = isattr ? ROLE_ATTRIB : ROLE_ROLE; | |
209 | 261 | |
210 | 262 | if (id == NULL) { |
211 | 263 | yyerror("no role name"); |
264 | return -1; | |
265 | } | |
266 | ||
267 | datum = malloc(sizeof(*datum)); | |
268 | if (datum == NULL) { | |
269 | yyerror("Out of memory!"); | |
270 | free(id); | |
271 | return -1; | |
272 | } | |
273 | ||
274 | role_datum_init(datum); | |
275 | datum->flavor = isattr; | |
276 | ||
277 | if (scope == SCOPE_DECL) { | |
278 | ret = declare_symbol(SYM_ROLES, id, datum, &value, &value); | |
279 | } else { | |
280 | ret = require_symbol(SYM_ROLES, id, datum, &value, &value); | |
281 | } | |
282 | ||
283 | datum->s.value = value; | |
284 | ||
285 | if (ret == 0) { | |
286 | *role = datum; | |
287 | *key = strdup(id); | |
288 | if (*key == NULL) { | |
289 | yyerror("Out of memory!"); | |
290 | return -1; | |
291 | } | |
292 | } else if (ret == 1) { | |
293 | *role = hashtab_search(policydbp->symtab[SYM_ROLES].table, id); | |
294 | if (*role && (isattr != (*role)->flavor)) { | |
295 | yyerror2("Identifier %s used as both an attribute and a role", | |
296 | id); | |
297 | free(id); | |
298 | role_datum_destroy(datum); | |
299 | free(datum); | |
300 | return -1; | |
301 | } | |
302 | *role = datum; | |
303 | *key = id; | |
304 | } else { | |
305 | print_error_msg(ret, SYM_ROLES); | |
306 | free(id); | |
307 | role_datum_destroy(datum); | |
308 | free(datum); | |
309 | } | |
310 | ||
311 | return ret; | |
312 | } | |
313 | ||
314 | role_datum_t *declare_role(unsigned char isattr) | |
315 | { | |
316 | char *key = NULL; | |
317 | role_datum_t *role = NULL; | |
318 | role_datum_t *dest_role = NULL; | |
319 | hashtab_t roles_tab; | |
320 | int ret, ret2; | |
321 | ||
322 | ret = create_role(SCOPE_DECL, isattr, &role, &key); | |
323 | if (ret < 0) { | |
212 | 324 | return NULL; |
213 | 325 | } |
214 | if ((role = (role_datum_t *) malloc(sizeof(*role))) == NULL) { | |
215 | yyerror("Out of memory!"); | |
216 | free(id); | |
217 | return NULL; | |
218 | } | |
219 | role_datum_init(role); | |
220 | role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE; | |
221 | retval = | |
222 | declare_symbol(SYM_ROLES, id, (hashtab_datum_t *) role, &value, | |
223 | &value); | |
224 | if (retval == 0) { | |
225 | role->s.value = value; | |
226 | if ((dest_id = strdup(id)) == NULL) { | |
227 | yyerror("Out of memory!"); | |
228 | return NULL; | |
229 | } | |
230 | } else { | |
231 | /* this role was already declared in this module, or error */ | |
232 | dest_id = id; | |
233 | role_datum_destroy(role); | |
234 | free(role); | |
235 | } | |
236 | if (retval == 0 || retval == 1) { | |
237 | /* create a new role_datum_t for this decl, if necessary */ | |
238 | hashtab_t roles_tab; | |
239 | assert(stack_top->type == 1); | |
240 | if (stack_top->parent == NULL) { | |
241 | /* in parent, so use global symbol table */ | |
242 | roles_tab = policydbp->p_roles.table; | |
243 | } else { | |
244 | roles_tab = stack_top->decl->p_roles.table; | |
245 | } | |
246 | dest_role = (role_datum_t *) hashtab_search(roles_tab, dest_id); | |
247 | if (dest_role == NULL) { | |
248 | if ((dest_role = | |
249 | (role_datum_t *) malloc(sizeof(*dest_role))) == | |
250 | NULL) { | |
326 | ||
327 | /* create a new role_datum_t for this decl, if necessary */ | |
328 | assert(stack_top->type == 1); | |
329 | ||
330 | if (stack_top->parent == NULL) { | |
331 | /* in parent, so use global symbol table */ | |
332 | roles_tab = policydbp->p_roles.table; | |
333 | } else { | |
334 | roles_tab = stack_top->decl->p_roles.table; | |
335 | } | |
336 | ||
337 | dest_role = hashtab_search(roles_tab, key); | |
338 | if (dest_role == NULL) { | |
339 | if (ret == 0) { | |
340 | dest_role = malloc(sizeof(*dest_role)); | |
341 | if (dest_role == NULL) { | |
251 | 342 | yyerror("Out of memory!"); |
252 | free(dest_id); | |
343 | free(key); | |
253 | 344 | return NULL; |
254 | 345 | } |
255 | 346 | role_datum_init(dest_role); |
256 | dest_role->s.value = value; | |
257 | dest_role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE; | |
258 | if (role_implicit_bounds(roles_tab, dest_id, dest_role)) { | |
259 | free(dest_id); | |
260 | role_datum_destroy(dest_role); | |
261 | free(dest_role); | |
262 | return NULL; | |
263 | } | |
264 | if (hashtab_insert(roles_tab, dest_id, dest_role)) { | |
265 | yyerror("Out of memory!"); | |
266 | free(dest_id); | |
267 | role_datum_destroy(dest_role); | |
268 | free(dest_role); | |
269 | return NULL; | |
270 | } | |
347 | dest_role->s.value = role->s.value; | |
348 | dest_role->flavor = role->flavor; | |
271 | 349 | } else { |
272 | free(dest_id); | |
273 | } | |
274 | } else { | |
275 | free(dest_id); | |
276 | } | |
277 | switch (retval) { | |
278 | case -3:{ | |
350 | dest_role = role; | |
351 | } | |
352 | ret2 = role_implicit_bounds(roles_tab, key, dest_role); | |
353 | if (ret2 != 0) { | |
354 | free(key); | |
355 | role_datum_destroy(dest_role); | |
356 | free(dest_role); | |
357 | return NULL; | |
358 | } | |
359 | ret2 = hashtab_insert(roles_tab, key, dest_role); | |
360 | if (ret2 != 0) { | |
279 | 361 | yyerror("Out of memory!"); |
362 | free(key); | |
363 | role_datum_destroy(dest_role); | |
364 | free(dest_role); | |
280 | 365 | return NULL; |
281 | 366 | } |
282 | case -2:{ | |
283 | yyerror("duplicate declaration of role"); | |
367 | } else { | |
368 | free(key); | |
369 | if (ret == 1) { | |
370 | role_datum_destroy(role); | |
371 | free(role); | |
372 | } | |
373 | } | |
374 | ||
375 | if (ret == 0) { | |
376 | ret2 = ebitmap_set_bit(&dest_role->dominates, dest_role->s.value - 1, 1); | |
377 | if (ret2 != 0) { | |
378 | yyerror("out of memory"); | |
284 | 379 | return NULL; |
285 | 380 | } |
286 | case -1:{ | |
287 | yyerror("could not declare role here"); | |
288 | return NULL; | |
289 | } | |
290 | case 0:{ | |
291 | if (ebitmap_set_bit | |
292 | (&dest_role->dominates, role->s.value - 1, 1)) { | |
293 | yyerror("out of memory"); | |
294 | return NULL; | |
295 | } | |
296 | return dest_role; | |
297 | } | |
298 | case 1:{ | |
299 | return dest_role; /* role already declared for this block */ | |
300 | } | |
301 | default:{ | |
302 | abort(); /* should never get here */ | |
303 | } | |
304 | } | |
305 | } | |
306 | ||
307 | type_datum_t *declare_type(unsigned char primary, unsigned char isattr) | |
381 | } | |
382 | ||
383 | return dest_role; | |
384 | } | |
385 | ||
386 | static int create_type(uint32_t scope, unsigned char isattr, type_datum_t **type) | |
308 | 387 | { |
309 | 388 | char *id; |
310 | type_datum_t *typdatum; | |
311 | int retval; | |
389 | type_datum_t *datum; | |
390 | int ret; | |
312 | 391 | uint32_t value = 0; |
392 | ||
393 | *type = NULL; | |
394 | isattr = isattr ? TYPE_ATTRIB : TYPE_TYPE; | |
313 | 395 | |
314 | 396 | id = (char *)queue_remove(id_queue); |
315 | 397 | if (!id) { |
316 | 398 | yyerror("no type/attribute name?"); |
317 | return NULL; | |
399 | return -1; | |
318 | 400 | } |
319 | 401 | if (strcmp(id, "self") == 0) { |
320 | yyerror | |
321 | ("'self' is a reserved type name and may not be declared."); | |
322 | free(id); | |
323 | return NULL; | |
324 | } | |
325 | ||
326 | typdatum = (type_datum_t *) malloc(sizeof(type_datum_t)); | |
327 | if (!typdatum) { | |
402 | yyerror("\"self\" is a reserved type name."); | |
403 | free(id); | |
404 | return -1; | |
405 | } | |
406 | ||
407 | datum = malloc(sizeof(*datum)); | |
408 | if (!datum) { | |
328 | 409 | yyerror("Out of memory!"); |
329 | 410 | free(id); |
330 | return NULL; | |
331 | } | |
332 | type_datum_init(typdatum); | |
333 | typdatum->primary = primary; | |
334 | typdatum->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE; | |
335 | ||
336 | retval = declare_symbol(SYM_TYPES, id, typdatum, &value, &value); | |
337 | if (retval == 0 || retval == 1) { | |
338 | if (typdatum->primary) { | |
339 | typdatum->s.value = value; | |
340 | } | |
341 | } else { | |
342 | /* error occurred (can't have duplicate type declarations) */ | |
343 | free(id); | |
344 | type_datum_destroy(typdatum); | |
345 | free(typdatum); | |
346 | } | |
347 | switch (retval) { | |
348 | case -3:{ | |
349 | yyerror("Out of memory!"); | |
350 | return NULL; | |
351 | } | |
352 | case -2:{ | |
353 | yyerror2("duplicate declaration of type/attribute"); | |
354 | return NULL; | |
355 | } | |
356 | case -1:{ | |
357 | yyerror("could not declare type/attribute here"); | |
358 | return NULL; | |
359 | } | |
360 | case 0: | |
361 | case 1:{ | |
362 | return typdatum; | |
363 | } | |
364 | default:{ | |
365 | abort(); /* should never get here */ | |
366 | } | |
367 | } | |
411 | return -1; | |
412 | } | |
413 | type_datum_init(datum); | |
414 | datum->primary = 1; | |
415 | datum->flavor = isattr; | |
416 | ||
417 | if (scope == SCOPE_DECL) { | |
418 | ret = declare_symbol(SYM_TYPES, id, datum, &value, &value); | |
419 | } else { | |
420 | ret = require_symbol(SYM_TYPES, id, datum, &value, &value); | |
421 | } | |
422 | ||
423 | if (ret == 0) { | |
424 | datum->s.value = value; | |
425 | *type = datum; | |
426 | } else if (ret == 1) { | |
427 | type_datum_destroy(datum); | |
428 | free(datum); | |
429 | *type = hashtab_search(policydbp->symtab[SYM_TYPES].table, id); | |
430 | if (*type && (isattr != (*type)->flavor)) { | |
431 | yyerror2("Identifier %s used as both an attribute and a type", | |
432 | id); | |
433 | free(id); | |
434 | return -1; | |
435 | } | |
436 | free(id); | |
437 | } else { | |
438 | print_error_msg(ret, SYM_TYPES); | |
439 | free(id); | |
440 | type_datum_destroy(datum); | |
441 | free(datum); | |
442 | } | |
443 | ||
444 | return ret; | |
445 | } | |
446 | ||
447 | type_datum_t *declare_type(unsigned char primary, unsigned char isattr) | |
448 | { | |
449 | type_datum_t *type = NULL; | |
450 | int ret = create_type(SCOPE_DECL, isattr, &type); | |
451 | ||
452 | if (ret == 0) { | |
453 | type->primary = primary; | |
454 | } | |
455 | ||
456 | return type; | |
368 | 457 | } |
369 | 458 | |
370 | 459 | static int user_implicit_bounds(hashtab_t users_tab, |
404 | 493 | return 0; |
405 | 494 | } |
406 | 495 | |
407 | user_datum_t *declare_user(void) | |
408 | { | |
409 | char *id = queue_remove(id_queue), *dest_id = NULL; | |
410 | user_datum_t *user = NULL, *dest_user = NULL; | |
411 | int retval; | |
412 | uint32_t value = 0; | |
496 | static int create_user(uint32_t scope, user_datum_t **user, char **key) | |
497 | { | |
498 | char *id = queue_remove(id_queue); | |
499 | user_datum_t *datum = NULL; | |
500 | int ret; | |
501 | uint32_t value; | |
502 | ||
503 | *user = NULL; | |
504 | *key = NULL; | |
413 | 505 | |
414 | 506 | if (id == NULL) { |
415 | 507 | yyerror("no user name"); |
508 | return -1; | |
509 | } | |
510 | ||
511 | datum = malloc(sizeof(*datum)); | |
512 | if (datum == NULL) { | |
513 | yyerror("Out of memory!"); | |
514 | free(id); | |
515 | return -1; | |
516 | } | |
517 | ||
518 | user_datum_init(datum); | |
519 | ||
520 | if (scope == SCOPE_DECL) { | |
521 | ret = declare_symbol(SYM_USERS, id, datum, &value, &value); | |
522 | } else { | |
523 | ret = require_symbol(SYM_USERS, id, datum, &value, &value); | |
524 | } | |
525 | ||
526 | datum->s.value = value; | |
527 | ||
528 | if (ret == 0) { | |
529 | *user = datum; | |
530 | *key = strdup(id); | |
531 | if (*key == NULL) { | |
532 | yyerror("Out of memory!"); | |
533 | return -1; | |
534 | } | |
535 | } else if (ret == 1) { | |
536 | *user = datum; | |
537 | *key = id; | |
538 | } else { | |
539 | print_error_msg(ret, SYM_USERS); | |
540 | free(id); | |
541 | user_datum_destroy(datum); | |
542 | free(datum); | |
543 | } | |
544 | ||
545 | return ret; | |
546 | } | |
547 | ||
548 | user_datum_t *declare_user(void) | |
549 | { | |
550 | char *key = NULL; | |
551 | user_datum_t *user = NULL; | |
552 | user_datum_t *dest_user = NULL; | |
553 | hashtab_t users_tab; | |
554 | int ret, ret2; | |
555 | ||
556 | ret = create_user(SCOPE_DECL, &user, &key); | |
557 | if (ret < 0) { | |
416 | 558 | return NULL; |
417 | 559 | } |
418 | if ((user = (user_datum_t *) malloc(sizeof(*user))) == NULL) { | |
419 | yyerror("Out of memory!"); | |
420 | free(id); | |
421 | return NULL; | |
422 | } | |
423 | user_datum_init(user); | |
424 | ||
425 | retval = | |
426 | declare_symbol(SYM_USERS, id, (hashtab_datum_t *) user, &value, | |
427 | &value); | |
428 | ||
429 | if (retval == 0) { | |
430 | user->s.value = value; | |
431 | if ((dest_id = strdup(id)) == NULL) { | |
432 | yyerror("Out of memory!"); | |
433 | return NULL; | |
434 | } | |
435 | } else { | |
436 | /* this user was already declared in this module, or error */ | |
437 | dest_id = id; | |
438 | user_datum_destroy(user); | |
439 | free(user); | |
440 | } | |
441 | if (retval == 0 || retval == 1) { | |
442 | /* create a new user_datum_t for this decl, if necessary */ | |
443 | hashtab_t users_tab; | |
444 | assert(stack_top->type == 1); | |
445 | if (stack_top->parent == NULL) { | |
446 | /* in parent, so use global symbol table */ | |
447 | users_tab = policydbp->p_users.table; | |
448 | } else { | |
449 | users_tab = stack_top->decl->p_users.table; | |
450 | } | |
451 | dest_user = (user_datum_t *) hashtab_search(users_tab, dest_id); | |
452 | if (dest_user == NULL) { | |
453 | if ((dest_user = | |
454 | (user_datum_t *) malloc(sizeof(*dest_user))) == | |
455 | NULL) { | |
560 | ||
561 | /* create a new user_datum_t for this decl, if necessary */ | |
562 | assert(stack_top->type == 1); | |
563 | ||
564 | if (stack_top->parent == NULL) { | |
565 | /* in parent, so use global symbol table */ | |
566 | users_tab = policydbp->p_users.table; | |
567 | } else { | |
568 | users_tab = stack_top->decl->p_users.table; | |
569 | } | |
570 | ||
571 | dest_user = hashtab_search(users_tab, key); | |
572 | if (dest_user == NULL) { | |
573 | if (ret == 0) { | |
574 | dest_user = malloc(sizeof(*dest_user)); | |
575 | if (dest_user == NULL) { | |
456 | 576 | yyerror("Out of memory!"); |
457 | free(dest_id); | |
577 | free(key); | |
458 | 578 | return NULL; |
459 | 579 | } |
460 | 580 | user_datum_init(dest_user); |
461 | dest_user->s.value = value; | |
462 | if (user_implicit_bounds(users_tab, dest_id, dest_user)) { | |
463 | free(dest_id); | |
464 | user_datum_destroy(dest_user); | |
465 | free(dest_user); | |
466 | return NULL; | |
467 | } | |
468 | if (hashtab_insert(users_tab, dest_id, dest_user)) { | |
469 | yyerror("Out of memory!"); | |
470 | free(dest_id); | |
471 | user_datum_destroy(dest_user); | |
472 | free(dest_user); | |
473 | return NULL; | |
474 | } | |
581 | dest_user->s.value = user->s.value; | |
475 | 582 | } else { |
476 | free(dest_id); | |
477 | } | |
478 | } else { | |
479 | free(dest_id); | |
480 | } | |
481 | switch (retval) { | |
482 | case -3:{ | |
583 | dest_user = user; | |
584 | } | |
585 | ret2 = user_implicit_bounds(users_tab, key, dest_user); | |
586 | if (ret2 != 0) { | |
587 | free(key); | |
588 | user_datum_destroy(dest_user); | |
589 | free(dest_user); | |
590 | return NULL; | |
591 | } | |
592 | ret2 = hashtab_insert(users_tab, key, dest_user); | |
593 | if (ret2 != 0) { | |
483 | 594 | yyerror("Out of memory!"); |
595 | free(key); | |
596 | user_datum_destroy(dest_user); | |
597 | free(dest_user); | |
484 | 598 | return NULL; |
485 | 599 | } |
486 | case -2:{ | |
487 | yyerror("duplicate declaration of user"); | |
488 | return NULL; | |
489 | } | |
490 | case -1:{ | |
491 | yyerror("could not declare user here"); | |
492 | return NULL; | |
493 | } | |
494 | case 0:{ | |
495 | return dest_user; | |
496 | } | |
497 | case 1:{ | |
498 | return dest_user; /* user already declared for this block */ | |
499 | } | |
500 | default:{ | |
501 | abort(); /* should never get here */ | |
502 | } | |
503 | } | |
600 | } else { | |
601 | free(key); | |
602 | if (ret == 1) { | |
603 | user_datum_destroy(user); | |
604 | free(user); | |
605 | } | |
606 | } | |
607 | ||
608 | return dest_user; | |
504 | 609 | } |
505 | 610 | |
506 | 611 | /* Return a type_datum_t for the local avrule_decl with the given ID. |
596 | 701 | } |
597 | 702 | |
598 | 703 | return dest_roledatum; |
599 | } | |
600 | ||
601 | /* Given the current parse stack, returns 1 if a requirement would be | |
602 | * allowed here or 0 if not. For example, the ELSE branch may never | |
603 | * have its own requirements. | |
604 | */ | |
605 | static int is_require_allowed(void) | |
606 | { | |
607 | if (stack_top->type == 1 && !stack_top->in_else) { | |
608 | return 1; | |
609 | } | |
610 | return 0; | |
611 | 704 | } |
612 | 705 | |
613 | 706 | /* Attempt to require a symbol within the current scope. If currently |
623 | 716 | uint32_t * dest_value, uint32_t * datum_value) |
624 | 717 | { |
625 | 718 | avrule_decl_t *decl = stack_top->decl; |
626 | int retval; | |
627 | ||
628 | /* first check that symbols may be required here */ | |
629 | if (!is_require_allowed()) { | |
630 | return -1; | |
631 | } | |
632 | retval = symtab_insert(policydbp, symbol_type, key, datum, | |
633 | SCOPE_REQ, decl->decl_id, dest_value); | |
634 | if (retval == 1) { | |
635 | symtab_datum_t *s = | |
636 | (symtab_datum_t *) hashtab_search(policydbp-> | |
637 | symtab[symbol_type].table, | |
638 | key); | |
639 | assert(s != NULL); | |
640 | ||
641 | if (symbol_type == SYM_LEVELS) { | |
642 | *dest_value = ((level_datum_t *)s)->level->sens; | |
643 | } else { | |
644 | *dest_value = s->value; | |
645 | } | |
646 | } else if (retval == -2) { | |
647 | /* ignore require statements if that symbol was | |
648 | * previously declared and is in current scope */ | |
649 | int prev_declaration_ok = 0; | |
650 | if (is_id_in_scope(symbol_type, key)) { | |
651 | if (symbol_type == SYM_TYPES) { | |
652 | /* check that previous symbol has same | |
653 | * type/attribute-ness */ | |
654 | unsigned char new_isattr = | |
655 | ((type_datum_t *) datum)->flavor; | |
656 | type_datum_t *old_datum = | |
657 | (type_datum_t *) hashtab_search(policydbp-> | |
658 | symtab | |
659 | [SYM_TYPES]. | |
660 | table, key); | |
661 | assert(old_datum != NULL); | |
662 | unsigned char old_isattr = old_datum->flavor; | |
663 | prev_declaration_ok = | |
664 | (old_isattr == new_isattr ? 1 : 0); | |
665 | } else { | |
666 | prev_declaration_ok = 1; | |
667 | } | |
668 | } | |
669 | if (prev_declaration_ok) { | |
670 | /* ignore this require statement because it | |
671 | * was already declared within my scope */ | |
672 | stack_top->require_given = 1; | |
673 | return 1; | |
674 | } else { | |
675 | /* previous declaration was not in scope or | |
676 | * had a mismatched type/attribute, so | |
677 | * generate an error */ | |
678 | return -2; | |
679 | } | |
680 | } else if (retval < 0) { | |
719 | int ret = create_symbol(symbol_type, key, datum, dest_value, SCOPE_REQ); | |
720 | ||
721 | if (ret < 0) { | |
722 | return ret; | |
723 | } | |
724 | ||
725 | if (ebitmap_set_bit(decl->required.scope + symbol_type, | |
726 | *datum_value - 1, 1)) { | |
681 | 727 | return -3; |
682 | } else { /* fall through possible if retval is 0 or 1 */ | |
683 | } | |
684 | if (datum_value != NULL) { | |
685 | if (ebitmap_set_bit(decl->required.scope + symbol_type, | |
686 | *datum_value - 1, 1)) { | |
687 | return -3; | |
688 | } | |
689 | } | |
728 | } | |
729 | ||
690 | 730 | stack_top->require_given = 1; |
691 | return retval; | |
731 | return ret; | |
692 | 732 | } |
693 | 733 | |
694 | 734 | int add_perm_to_class(uint32_t perm_value, uint32_t class_value) |
761 | 801 | if ((datum = calloc(1, sizeof(*datum))) == NULL || |
762 | 802 | symtab_init(&datum->permissions, PERM_SYMTAB_SIZE)) { |
763 | 803 | yyerror("Out of memory!"); |
764 | goto cleanup; | |
804 | return -1; | |
765 | 805 | } |
766 | 806 | ret = |
767 | 807 | require_symbol(SYM_CLASSES, class_id, datum, &datum->s.value, |
768 | 808 | &datum->s.value); |
769 | switch (ret) { | |
770 | case -3:{ | |
809 | if (ret < 0) { | |
810 | print_error_msg(ret, SYM_CLASSES); | |
811 | free(class_id); | |
812 | class_datum_destroy(datum); | |
813 | return -1; | |
814 | } | |
815 | ||
816 | if (ret == 0) { | |
817 | /* a new class was added; reindex everything */ | |
818 | if (policydb_index_classes(policydbp)) { | |
771 | 819 | yyerror("Out of memory!"); |
772 | free(class_id); | |
773 | class_datum_destroy(datum); | |
774 | goto cleanup; | |
775 | } | |
776 | case -2:{ | |
777 | yyerror("duplicate declaration of class"); | |
778 | free(class_id); | |
779 | class_datum_destroy(datum); | |
780 | goto cleanup; | |
781 | } | |
782 | case -1:{ | |
783 | yyerror("could not require class here"); | |
784 | free(class_id); | |
785 | class_datum_destroy(datum); | |
786 | goto cleanup; | |
787 | } | |
788 | case 0:{ | |
789 | /* a new class was added; reindex everything */ | |
790 | if (policydb_index_classes(policydbp)) { | |
791 | yyerror("Out of memory!"); | |
792 | goto cleanup; | |
793 | } | |
794 | break; | |
795 | } | |
796 | case 1:{ | |
797 | class_datum_destroy(datum); | |
798 | datum = | |
799 | hashtab_search(policydbp->p_classes.table, | |
800 | class_id); | |
801 | assert(datum); /* the class datum should have existed */ | |
802 | free(class_id); | |
803 | break; | |
804 | } | |
805 | default:{ | |
806 | abort(); /* should never get here */ | |
807 | } | |
820 | return -1; | |
821 | } | |
822 | } else { | |
823 | class_datum_destroy(datum); | |
824 | datum = hashtab_search(policydbp->p_classes.table, class_id); | |
825 | assert(datum); /* the class datum should have existed */ | |
826 | free(class_id); | |
808 | 827 | } |
809 | 828 | |
810 | 829 | /* now add each of the permissions to this class's requirements */ |
827 | 846 | ("Base policy - require of permission %s without prior declaration.", |
828 | 847 | perm_id); |
829 | 848 | free(perm_id); |
830 | goto cleanup; | |
849 | return -1; | |
831 | 850 | } |
832 | 851 | allocated = 1; |
833 | 852 | if ((perm = malloc(sizeof(*perm))) == NULL) { |
834 | 853 | yyerror("Out of memory!"); |
835 | 854 | free(perm_id); |
836 | goto cleanup; | |
855 | return -1; | |
837 | 856 | } |
838 | 857 | memset(perm, 0, sizeof(*perm)); |
839 | 858 | ret = |
843 | 862 | yyerror("Out of memory!"); |
844 | 863 | free(perm_id); |
845 | 864 | free(perm); |
846 | goto cleanup; | |
865 | return -1; | |
847 | 866 | } |
848 | 867 | perm->s.value = datum->permissions.nprim + 1; |
849 | 868 | } |
850 | 869 | |
851 | 870 | if (add_perm_to_class(perm->s.value, datum->s.value) == -1) { |
852 | 871 | yyerror("Out of memory!"); |
853 | goto cleanup; | |
872 | return -1; | |
854 | 873 | } |
855 | 874 | |
856 | 875 | /* Update number of primitives if we allocated one. */ |
858 | 877 | datum->permissions.nprim++; |
859 | 878 | } |
860 | 879 | return 0; |
861 | cleanup: | |
862 | return -1; | |
863 | 880 | } |
864 | 881 | |
865 | 882 | static int require_role_or_attribute(int pass, unsigned char isattr) |
866 | 883 | { |
867 | char *id = queue_remove(id_queue); | |
884 | char *key = NULL; | |
868 | 885 | role_datum_t *role = NULL; |
869 | int retval; | |
886 | int ret; | |
887 | ||
870 | 888 | if (pass == 2) { |
871 | free(id); | |
889 | free(queue_remove(id_queue)); | |
872 | 890 | return 0; |
873 | 891 | } |
874 | if (id == NULL) { | |
875 | yyerror("no role name"); | |
876 | return -1; | |
877 | } | |
878 | if ((role = malloc(sizeof(*role))) == NULL) { | |
879 | free(id); | |
880 | yyerror("Out of memory!"); | |
881 | return -1; | |
882 | } | |
883 | role_datum_init(role); | |
884 | role->flavor = isattr ? ROLE_ATTRIB : ROLE_ROLE; | |
885 | retval = | |
886 | require_symbol(SYM_ROLES, id, (hashtab_datum_t *) role, | |
887 | &role->s.value, &role->s.value); | |
888 | if (retval != 0) { | |
889 | free(id); | |
892 | ||
893 | ret = create_role(SCOPE_REQ, isattr, &role, &key); | |
894 | if (ret < 0) { | |
895 | return -1; | |
896 | } | |
897 | ||
898 | free(key); | |
899 | ||
900 | if (ret == 0) { | |
901 | ret = ebitmap_set_bit(&role->dominates, role->s.value - 1, 1); | |
902 | if (ret != 0) { | |
903 | yyerror("Out of memory"); | |
904 | return -1; | |
905 | } | |
906 | } else { | |
890 | 907 | role_datum_destroy(role); |
891 | 908 | free(role); |
892 | 909 | } |
893 | switch (retval) { | |
894 | case -3:{ | |
895 | yyerror("Out of memory!"); | |
896 | return -1; | |
897 | } | |
898 | case -2:{ | |
899 | yyerror("duplicate declaration of role"); | |
900 | return -1; | |
901 | } | |
902 | case -1:{ | |
903 | yyerror("could not require role here"); | |
904 | return -1; | |
905 | } | |
906 | case 0:{ | |
907 | /* all roles dominate themselves */ | |
908 | if (ebitmap_set_bit | |
909 | (&role->dominates, role->s.value - 1, 1)) { | |
910 | yyerror("Out of memory"); | |
911 | return -1; | |
912 | } | |
913 | return 0; | |
914 | } | |
915 | case 1:{ | |
916 | return 0; /* role already required */ | |
917 | } | |
918 | default:{ | |
919 | abort(); /* should never get here */ | |
920 | } | |
921 | } | |
910 | ||
911 | return 0; | |
922 | 912 | } |
923 | 913 | |
924 | 914 | int require_role(int pass) |
933 | 923 | |
934 | 924 | static int require_type_or_attribute(int pass, unsigned char isattr) |
935 | 925 | { |
936 | char *id = queue_remove(id_queue); | |
937 | 926 | type_datum_t *type = NULL; |
938 | int retval; | |
927 | int ret; | |
928 | ||
939 | 929 | if (pass == 2) { |
940 | free(id); | |
930 | free(queue_remove(id_queue)); | |
941 | 931 | return 0; |
942 | 932 | } |
943 | if (id == NULL) { | |
944 | yyerror("no type name"); | |
945 | return -1; | |
946 | } | |
947 | if ((type = malloc(sizeof(*type))) == NULL) { | |
948 | free(id); | |
949 | yyerror("Out of memory!"); | |
950 | return -1; | |
951 | } | |
952 | type_datum_init(type); | |
953 | type->primary = 1; | |
954 | type->flavor = isattr ? TYPE_ATTRIB : TYPE_TYPE; | |
955 | retval = | |
956 | require_symbol(SYM_TYPES, id, (hashtab_datum_t *) type, | |
957 | &type->s.value, &type->s.value); | |
958 | if (retval != 0) { | |
959 | free(id); | |
960 | free(type); | |
961 | } | |
962 | switch (retval) { | |
963 | case -3:{ | |
964 | yyerror("Out of memory!"); | |
965 | return -1; | |
966 | } | |
967 | case -2:{ | |
968 | yyerror("duplicate declaration of type/attribute"); | |
969 | return -1; | |
970 | } | |
971 | case -1:{ | |
972 | yyerror("could not require type/attribute here"); | |
973 | return -1; | |
974 | } | |
975 | case 0:{ | |
976 | return 0; | |
977 | } | |
978 | case 1:{ | |
979 | return 0; /* type already required */ | |
980 | } | |
981 | default:{ | |
982 | abort(); /* should never get here */ | |
983 | } | |
984 | } | |
933 | ||
934 | ret = create_type(SCOPE_REQ, isattr, &type); | |
935 | ||
936 | if (ret < 0) { | |
937 | return -1; | |
938 | } | |
939 | ||
940 | return 0; | |
985 | 941 | } |
986 | 942 | |
987 | 943 | int require_type(int pass) |
996 | 952 | |
997 | 953 | int require_user(int pass) |
998 | 954 | { |
999 | char *id = queue_remove(id_queue); | |
955 | char *key = NULL; | |
1000 | 956 | user_datum_t *user = NULL; |
1001 | int retval; | |
957 | int ret; | |
958 | ||
1002 | 959 | if (pass == 1) { |
1003 | free(id); | |
960 | free(queue_remove(id_queue)); | |
1004 | 961 | return 0; |
1005 | 962 | } |
1006 | if (id == NULL) { | |
1007 | yyerror("no user name"); | |
1008 | return -1; | |
1009 | } | |
1010 | if ((user = malloc(sizeof(*user))) == NULL) { | |
1011 | free(id); | |
1012 | yyerror("Out of memory!"); | |
1013 | return -1; | |
1014 | } | |
1015 | user_datum_init(user); | |
1016 | retval = | |
1017 | require_symbol(SYM_USERS, id, (hashtab_datum_t *) user, | |
1018 | &user->s.value, &user->s.value); | |
1019 | if (retval != 0) { | |
1020 | free(id); | |
963 | ||
964 | ret = create_user(SCOPE_REQ, &user, &key); | |
965 | if (ret < 0) { | |
966 | return -1; | |
967 | } | |
968 | ||
969 | free(key); | |
970 | ||
971 | if (ret == 1) { | |
1021 | 972 | user_datum_destroy(user); |
1022 | } | |
1023 | switch (retval) { | |
1024 | case -3:{ | |
1025 | yyerror("Out of memory!"); | |
1026 | return -1; | |
1027 | } | |
1028 | case -2:{ | |
1029 | yyerror("duplicate declaration of user"); | |
1030 | return -1; | |
1031 | } | |
1032 | case -1:{ | |
1033 | yyerror("could not require user here"); | |
1034 | return -1; | |
1035 | } | |
1036 | case 0:{ | |
1037 | return 0; | |
1038 | } | |
1039 | case 1:{ | |
1040 | return 0; /* user already required */ | |
1041 | } | |
1042 | default:{ | |
1043 | abort(); /* should never get here */ | |
1044 | } | |
1045 | } | |
973 | free(user); | |
974 | } | |
975 | ||
976 | return 0; | |
1046 | 977 | } |
1047 | 978 | |
1048 | 979 | static int require_bool_tunable(int pass, int is_tunable) |
1070 | 1001 | &booldatum->s.value, &booldatum->s.value); |
1071 | 1002 | if (retval != 0) { |
1072 | 1003 | cond_destroy_bool(id, booldatum, NULL); |
1073 | } | |
1074 | switch (retval) { | |
1075 | case -3:{ | |
1076 | yyerror("Out of memory!"); | |
1077 | return -1; | |
1078 | } | |
1079 | case -2:{ | |
1080 | yyerror("duplicate declaration of boolean"); | |
1081 | return -1; | |
1082 | } | |
1083 | case -1:{ | |
1084 | yyerror("could not require boolean here"); | |
1085 | return -1; | |
1086 | } | |
1087 | case 0:{ | |
1088 | return 0; | |
1089 | } | |
1090 | case 1:{ | |
1091 | return 0; /* boolean already required */ | |
1092 | } | |
1093 | default:{ | |
1094 | abort(); /* should never get here */ | |
1095 | } | |
1096 | } | |
1004 | if (retval < 0) { | |
1005 | print_error_msg(retval, SYM_BOOLS); | |
1006 | return -1; | |
1007 | } | |
1008 | } | |
1009 | ||
1010 | return 0; | |
1097 | 1011 | } |
1098 | 1012 | |
1099 | 1013 | int require_bool(int pass) |
1143 | 1057 | free(level->level); |
1144 | 1058 | level_datum_destroy(level); |
1145 | 1059 | free(level); |
1146 | } | |
1147 | switch (retval) { | |
1148 | case -3:{ | |
1149 | yyerror("Out of memory!"); | |
1150 | return -1; | |
1151 | } | |
1152 | case -2:{ | |
1153 | yyerror("duplicate declaration of sensitivity"); | |
1154 | return -1; | |
1155 | } | |
1156 | case -1:{ | |
1157 | yyerror("could not require sensitivity here"); | |
1158 | return -1; | |
1159 | } | |
1160 | case 0:{ | |
1161 | return 0; | |
1162 | } | |
1163 | case 1:{ | |
1164 | return 0; /* sensitivity already required */ | |
1165 | } | |
1166 | default:{ | |
1167 | abort(); /* should never get here */ | |
1168 | } | |
1169 | } | |
1060 | if (retval < 0) { | |
1061 | print_error_msg(retval, SYM_LEVELS); | |
1062 | return -1; | |
1063 | } | |
1064 | } | |
1065 | ||
1066 | return 0; | |
1170 | 1067 | } |
1171 | 1068 | |
1172 | 1069 | int require_cat(int pass) |
1196 | 1093 | free(id); |
1197 | 1094 | cat_datum_destroy(cat); |
1198 | 1095 | free(cat); |
1199 | } | |
1200 | switch (retval) { | |
1201 | case -3:{ | |
1202 | yyerror("Out of memory!"); | |
1203 | return -1; | |
1204 | } | |
1205 | case -2:{ | |
1206 | yyerror("duplicate declaration of category"); | |
1207 | return -1; | |
1208 | } | |
1209 | case -1:{ | |
1210 | yyerror("could not require category here"); | |
1211 | return -1; | |
1212 | } | |
1213 | case 0:{ | |
1214 | return 0; | |
1215 | } | |
1216 | case 1:{ | |
1217 | return 0; /* category already required */ | |
1218 | } | |
1219 | default:{ | |
1220 | abort(); /* should never get here */ | |
1221 | } | |
1222 | } | |
1096 | if (retval < 0) { | |
1097 | print_error_msg(retval, SYM_CATS); | |
1098 | return -1; | |
1099 | } | |
1100 | } | |
1101 | ||
1102 | return 0; | |
1223 | 1103 | } |
1224 | 1104 | |
1225 | 1105 | static int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack) |
19 | 19 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. |
20 | 20 | * Copyright (C) 2003 - 2008 Tresys Technology, LLC |
21 | 21 | * Copyright (C) 2007 Red Hat Inc. |
22 | * Copyright (C) 2017 Mellanox Techonologies Inc. | |
22 | 23 | * This program is free software; you can redistribute it and/or modify |
23 | 24 | * it under the terms of the GNU General Public License as published by |
24 | 25 | * the Free Software Foundation, version 2. |
347 | 348 | cladatum = hashtab_search(policydbp->p_classes.table, id); |
348 | 349 | if (!cladatum) { |
349 | 350 | yyerror2("unknown class %s", id); |
350 | return -1; | |
351 | } | |
351 | free(id); | |
352 | return -1; | |
353 | } | |
354 | free(id); | |
352 | 355 | if (ebitmap_set_bit(e_classes, cladatum->s.value - 1, TRUE)) { |
353 | 356 | yyerror("Out of memory"); |
354 | 357 | return -1; |
355 | 358 | } |
356 | free(id); | |
357 | 359 | } |
358 | 360 | return 0; |
359 | 361 | } |
1137 | 1139 | return 0; |
1138 | 1140 | } |
1139 | 1141 | |
1142 | int expand_attrib(void) | |
1143 | { | |
1144 | char *id; | |
1145 | ebitmap_t attrs; | |
1146 | type_datum_t *attr; | |
1147 | ebitmap_node_t *node; | |
1148 | uint32_t i; | |
1149 | int rc = -1; | |
1150 | int flags = 0; | |
1151 | ||
1152 | if (pass == 1) { | |
1153 | for (i = 0; i < 2; i++) { | |
1154 | while ((id = queue_remove(id_queue))) { | |
1155 | free(id); | |
1156 | } | |
1157 | } | |
1158 | return 0; | |
1159 | } | |
1160 | ||
1161 | ebitmap_init(&attrs); | |
1162 | while ((id = queue_remove(id_queue))) { | |
1163 | if (!id) { | |
1164 | yyerror("No attribute name for expandattribute statement?"); | |
1165 | goto exit; | |
1166 | } | |
1167 | ||
1168 | if (!is_id_in_scope(SYM_TYPES, id)) { | |
1169 | yyerror2("attribute %s is not within scope", id); | |
1170 | goto exit; | |
1171 | } | |
1172 | ||
1173 | attr = hashtab_search(policydbp->p_types.table, id); | |
1174 | if (!attr) { | |
1175 | yyerror2("attribute %s is not declared", id); | |
1176 | goto exit; | |
1177 | } | |
1178 | ||
1179 | if (attr->flavor != TYPE_ATTRIB) { | |
1180 | yyerror2("%s is a type, not an attribute", id); | |
1181 | goto exit; | |
1182 | } | |
1183 | ||
1184 | if (attr->flags & TYPE_FLAGS_EXPAND_ATTR) { | |
1185 | yyerror2("%s already has the expandattribute option specified", id); | |
1186 | goto exit; | |
1187 | } | |
1188 | if (ebitmap_set_bit(&attrs, attr->s.value - 1, TRUE)) { | |
1189 | yyerror("Out of memory!"); | |
1190 | goto exit; | |
1191 | } | |
1192 | ||
1193 | free(id); | |
1194 | } | |
1195 | ||
1196 | id = (char *) queue_remove(id_queue); | |
1197 | if (!id) { | |
1198 | yyerror("No option specified for attribute expansion."); | |
1199 | goto exit; | |
1200 | } | |
1201 | ||
1202 | if (!strcmp(id, "T")) { | |
1203 | flags = TYPE_FLAGS_EXPAND_ATTR_TRUE; | |
1204 | } else { | |
1205 | flags = TYPE_FLAGS_EXPAND_ATTR_FALSE; | |
1206 | } | |
1207 | ||
1208 | ebitmap_for_each_bit(&attrs, node, i) { | |
1209 | if (!ebitmap_node_get_bit(node, i)){ | |
1210 | continue; | |
1211 | } | |
1212 | attr = hashtab_search(policydbp->p_types.table, | |
1213 | policydbp->sym_val_to_name[SYM_TYPES][i]); | |
1214 | attr->flags |= flags; | |
1215 | } | |
1216 | ||
1217 | rc = 0; | |
1218 | exit: | |
1219 | ebitmap_destroy(&attrs); | |
1220 | free(id); | |
1221 | return rc; | |
1222 | } | |
1223 | ||
1140 | 1224 | static int add_aliases_to_type(type_datum_t * type) |
1141 | 1225 | { |
1142 | 1226 | char *id; |
1231 | 1315 | free(id); |
1232 | 1316 | return -1; |
1233 | 1317 | } |
1318 | free(id); | |
1234 | 1319 | return add_aliases_to_type(t); |
1235 | 1320 | } |
1236 | 1321 | |
1262 | 1347 | free(id); |
1263 | 1348 | return -1; |
1264 | 1349 | } |
1350 | free(id); | |
1265 | 1351 | |
1266 | 1352 | while ((id = queue_remove(id_queue))) { |
1267 | 1353 | if (!is_id_in_scope(SYM_TYPES, id)) { |
1423 | 1509 | if (!attr) { |
1424 | 1510 | /* treat it as a fatal error */ |
1425 | 1511 | yyerror2("attribute %s is not declared", id); |
1512 | free(id); | |
1426 | 1513 | return -1; |
1427 | 1514 | } |
1428 | 1515 | |
1429 | 1516 | if (attr->flavor != TYPE_ATTRIB) { |
1430 | 1517 | yyerror2("%s is a type, not an attribute", id); |
1518 | free(id); | |
1431 | 1519 | return -1; |
1432 | 1520 | } |
1433 | 1521 | |
1458 | 1546 | type_datum_t *t; |
1459 | 1547 | |
1460 | 1548 | if (strcmp(id, "*") == 0) { |
1549 | free(id); | |
1461 | 1550 | if (!starallowed) { |
1462 | 1551 | yyerror("* not allowed in this type of rule"); |
1463 | 1552 | return -1; |
1464 | 1553 | } |
1465 | 1554 | /* set TYPE_STAR flag */ |
1466 | 1555 | set->flags = TYPE_STAR; |
1467 | free(id); | |
1468 | 1556 | *add = 1; |
1469 | 1557 | return 0; |
1470 | 1558 | } |
1471 | 1559 | |
1472 | 1560 | if (strcmp(id, "~") == 0) { |
1561 | free(id); | |
1473 | 1562 | if (!starallowed) { |
1474 | 1563 | yyerror("~ not allowed in this type of rule"); |
1475 | 1564 | return -1; |
1476 | 1565 | } |
1477 | 1566 | /* complement the set */ |
1478 | 1567 | set->flags = TYPE_COMP; |
1479 | free(id); | |
1480 | 1568 | *add = 1; |
1481 | 1569 | return 0; |
1482 | 1570 | } |
1569 | 1657 | (hashtab_key_t) id); |
1570 | 1658 | if (!datum || datum->flavor == TYPE_ATTRIB) { |
1571 | 1659 | yyerror2("unknown type %s", id); |
1660 | free(id); | |
1572 | 1661 | goto bad; |
1573 | 1662 | } |
1663 | free(id); | |
1574 | 1664 | |
1575 | 1665 | ebitmap_for_each_bit(&tclasses, node, i) { |
1576 | 1666 | if (ebitmap_node_get_bit(node, i)) { |
1703 | 1793 | bool_value = (char *)queue_remove(id_queue); |
1704 | 1794 | if (!bool_value) { |
1705 | 1795 | yyerror("no default value for bool definition?"); |
1706 | free(id); | |
1707 | 1796 | return -1; |
1708 | 1797 | } |
1709 | 1798 | |
1710 | 1799 | datum->state = (int)(bool_value[0] == 'T') ? 1 : 0; |
1800 | free(bool_value); | |
1711 | 1801 | return 0; |
1712 | 1802 | cleanup: |
1713 | 1803 | cond_destroy_bool(id, datum, NULL); |
1916 | 2006 | /* read in ranges to include and omit */ |
1917 | 2007 | if (avrule_read_ioctls(&rangehead)) |
1918 | 2008 | return -1; |
1919 | omit = rangehead->omit; | |
1920 | 2009 | if (rangehead == NULL) { |
1921 | 2010 | yyerror("error processing ioctl commands"); |
1922 | 2011 | return -1; |
1923 | 2012 | } |
2013 | omit = rangehead->omit; | |
1924 | 2014 | /* sort and merge the input ioctls */ |
1925 | 2015 | if (avrule_sort_ioctls(&rangehead)) |
1926 | 2016 | return -1; |
1977 | 2067 | while ((id = queue_remove(id_queue))) { |
1978 | 2068 | if (strcmp(id, "self") == 0) { |
1979 | 2069 | free(id); |
2070 | if (add == 0) { | |
2071 | yyerror("-self is not supported"); | |
2072 | ret = -1; | |
2073 | goto out; | |
2074 | } | |
1980 | 2075 | avrule->flags |= RULE_SELF; |
1981 | 2076 | continue; |
1982 | 2077 | } |
2383 | 2478 | |
2384 | 2479 | id = queue_remove(id_queue); |
2385 | 2480 | if (strcmp(id,"ioctl") == 0) { |
2481 | free(id); | |
2386 | 2482 | if (define_te_avtab_ioctl(avrule_template)) |
2387 | 2483 | return -1; |
2388 | free(id); | |
2389 | 2484 | } else { |
2390 | 2485 | yyerror("only ioctl extended permissions are supported"); |
2486 | free(id); | |
2391 | 2487 | return -1; |
2392 | 2488 | } |
2393 | 2489 | return 0; |
2436 | 2532 | while ((id = queue_remove(id_queue))) { |
2437 | 2533 | if (strcmp(id, "self") == 0) { |
2438 | 2534 | free(id); |
2535 | if (add == 0) { | |
2536 | yyerror("-self is not supported"); | |
2537 | ret = -1; | |
2538 | goto out; | |
2539 | } | |
2439 | 2540 | avrule->flags |= RULE_SELF; |
2440 | 2541 | continue; |
2441 | 2542 | } |
2534 | 2635 | *rule = avrule; |
2535 | 2636 | |
2536 | 2637 | out: |
2638 | if (ret) { | |
2639 | avrule_destroy(avrule); | |
2640 | free(avrule); | |
2641 | } | |
2537 | 2642 | return ret; |
2538 | 2643 | |
2539 | 2644 | } |
2715 | 2820 | free(id); |
2716 | 2821 | return -1; |
2717 | 2822 | } |
2823 | free(id); | |
2718 | 2824 | |
2719 | 2825 | while ((id = queue_remove(id_queue))) { |
2720 | 2826 | if (!is_id_in_scope(SYM_ROLES, id)) { |
3079 | 3185 | role = hashtab_search(policydbp->p_roles.table, id); |
3080 | 3186 | if (!role) { |
3081 | 3187 | yyerror2("unknown role %s used in transition definition", id); |
3188 | free(id); | |
3082 | 3189 | goto bad; |
3083 | 3190 | } |
3084 | 3191 | |
3085 | 3192 | if (role->flavor != ROLE_ROLE) { |
3086 | 3193 | yyerror2("the new role %s must be a regular role", id); |
3194 | free(id); | |
3087 | 3195 | goto bad; |
3088 | 3196 | } |
3197 | free(id); | |
3089 | 3198 | |
3090 | 3199 | /* This ebitmap business is just to ensure that there are not conflicting role_trans rules */ |
3091 | 3200 | if (role_set_expand(&roles, &e_roles, policydbp, NULL, NULL)) |
3209 | 3318 | ebitmap_t e_tclasses; |
3210 | 3319 | ebitmap_node_t *snode, *tnode, *cnode; |
3211 | 3320 | filename_trans_t *ft; |
3321 | filename_trans_datum_t *ftdatum; | |
3212 | 3322 | filename_trans_rule_t *ftr; |
3213 | 3323 | type_datum_t *typdatum; |
3214 | 3324 | uint32_t otype; |
3215 | 3325 | unsigned int c, s, t; |
3216 | int add; | |
3326 | int add, rc; | |
3217 | 3327 | |
3218 | 3328 | if (pass == 1) { |
3219 | 3329 | /* stype */ |
3234 | 3344 | return 0; |
3235 | 3345 | } |
3236 | 3346 | |
3347 | type_set_init(&stypes); | |
3348 | type_set_init(&ttypes); | |
3349 | ebitmap_init(&e_stypes); | |
3350 | ebitmap_init(&e_ttypes); | |
3351 | ebitmap_init(&e_tclasses); | |
3237 | 3352 | |
3238 | 3353 | add = 1; |
3239 | type_set_init(&stypes); | |
3240 | 3354 | while ((id = queue_remove(id_queue))) { |
3241 | 3355 | if (set_types(&stypes, id, &add, 0)) |
3242 | 3356 | goto bad; |
3243 | 3357 | } |
3244 | 3358 | |
3245 | 3359 | add =1; |
3246 | type_set_init(&ttypes); | |
3247 | 3360 | while ((id = queue_remove(id_queue))) { |
3248 | 3361 | if (set_types(&ttypes, id, &add, 0)) |
3249 | 3362 | goto bad; |
3250 | 3363 | } |
3251 | 3364 | |
3252 | ebitmap_init(&e_tclasses); | |
3253 | 3365 | if (read_classes(&e_tclasses)) |
3254 | 3366 | goto bad; |
3255 | 3367 | |
3266 | 3378 | typdatum = hashtab_search(policydbp->p_types.table, id); |
3267 | 3379 | if (!typdatum) { |
3268 | 3380 | yyerror2("unknown type %s used in transition definition", id); |
3381 | free(id); | |
3269 | 3382 | goto bad; |
3270 | 3383 | } |
3271 | 3384 | free(id); |
3280 | 3393 | /* We expand the class set into seperate rules. We expand the types |
3281 | 3394 | * just to make sure there are not duplicates. They will get turned |
3282 | 3395 | * into seperate rules later */ |
3283 | ebitmap_init(&e_stypes); | |
3284 | 3396 | if (type_set_expand(&stypes, &e_stypes, policydbp, 1)) |
3285 | 3397 | goto bad; |
3286 | 3398 | |
3287 | ebitmap_init(&e_ttypes); | |
3288 | 3399 | if (type_set_expand(&ttypes, &e_ttypes, policydbp, 1)) |
3289 | 3400 | goto bad; |
3290 | 3401 | |
3297 | 3408 | ebitmap_for_each_bit(&e_ttypes, tnode, t) { |
3298 | 3409 | if (!ebitmap_node_get_bit(tnode, t)) |
3299 | 3410 | continue; |
3300 | ||
3301 | for (ft = policydbp->filename_trans; ft; ft = ft->next) { | |
3302 | if (ft->stype == (s + 1) && | |
3303 | ft->ttype == (t + 1) && | |
3304 | ft->tclass == (c + 1) && | |
3305 | !strcmp(ft->name, name)) { | |
3306 | yyerror2("duplicate filename transition for: filename_trans %s %s %s:%s", | |
3307 | name, | |
3308 | policydbp->p_type_val_to_name[s], | |
3309 | policydbp->p_type_val_to_name[t], | |
3310 | policydbp->p_class_val_to_name[c]); | |
3311 | goto bad; | |
3312 | } | |
3313 | } | |
3314 | ||
3315 | ft = malloc(sizeof(*ft)); | |
3411 | ||
3412 | ft = calloc(1, sizeof(*ft)); | |
3316 | 3413 | if (!ft) { |
3317 | 3414 | yyerror("out of memory"); |
3318 | 3415 | goto bad; |
3319 | 3416 | } |
3320 | memset(ft, 0, sizeof(*ft)); | |
3321 | ||
3322 | ft->next = policydbp->filename_trans; | |
3323 | policydbp->filename_trans = ft; | |
3324 | ||
3417 | ft->stype = s+1; | |
3418 | ft->ttype = t+1; | |
3419 | ft->tclass = c+1; | |
3325 | 3420 | ft->name = strdup(name); |
3326 | 3421 | if (!ft->name) { |
3327 | 3422 | yyerror("out of memory"); |
3328 | 3423 | goto bad; |
3329 | 3424 | } |
3330 | ft->stype = s + 1; | |
3331 | ft->ttype = t + 1; | |
3332 | ft->tclass = c + 1; | |
3333 | ft->otype = otype; | |
3425 | ||
3426 | ftdatum = hashtab_search(policydbp->filename_trans, | |
3427 | (hashtab_key_t)ft); | |
3428 | if (ftdatum) { | |
3429 | yyerror2("duplicate filename transition for: filename_trans %s %s %s:%s", | |
3430 | name, | |
3431 | policydbp->p_type_val_to_name[s], | |
3432 | policydbp->p_type_val_to_name[t], | |
3433 | policydbp->p_class_val_to_name[c]); | |
3434 | goto bad; | |
3435 | } | |
3436 | ||
3437 | ftdatum = calloc(1, sizeof(*ftdatum)); | |
3438 | if (!ftdatum) { | |
3439 | yyerror("out of memory"); | |
3440 | goto bad; | |
3441 | } | |
3442 | rc = hashtab_insert(policydbp->filename_trans, | |
3443 | (hashtab_key_t)ft, | |
3444 | ftdatum); | |
3445 | if (rc) { | |
3446 | yyerror("out of memory"); | |
3447 | goto bad; | |
3448 | } | |
3334 | 3449 | } |
3335 | 3450 | } |
3336 | 3451 | |
3360 | 3475 | ebitmap_destroy(&e_stypes); |
3361 | 3476 | ebitmap_destroy(&e_ttypes); |
3362 | 3477 | ebitmap_destroy(&e_tclasses); |
3478 | type_set_destroy(&stypes); | |
3479 | type_set_destroy(&ttypes); | |
3363 | 3480 | |
3364 | 3481 | return 0; |
3365 | 3482 | |
3366 | 3483 | bad: |
3367 | 3484 | free(name); |
3485 | ebitmap_destroy(&e_stypes); | |
3486 | ebitmap_destroy(&e_ttypes); | |
3487 | ebitmap_destroy(&e_tclasses); | |
3488 | type_set_destroy(&stypes); | |
3489 | type_set_destroy(&ttypes); | |
3368 | 3490 | return -1; |
3369 | 3491 | } |
3370 | 3492 | |
4883 | 5005 | protocol = IPPROTO_DCCP; |
4884 | 5006 | } else { |
4885 | 5007 | yyerror2("unrecognized protocol %s", id); |
4886 | free(newc); | |
4887 | return -1; | |
5008 | goto bad; | |
4888 | 5009 | } |
4889 | 5010 | |
4890 | 5011 | newc->u.port.protocol = protocol; |
4893 | 5014 | |
4894 | 5015 | if (low > high) { |
4895 | 5016 | yyerror2("low port %d exceeds high port %d", low, high); |
4896 | free(newc); | |
4897 | return -1; | |
5017 | goto bad; | |
4898 | 5018 | } |
4899 | 5019 | |
4900 | 5020 | if (parse_security_context(&newc->context[0])) { |
4901 | free(newc); | |
4902 | return -1; | |
5021 | goto bad; | |
4903 | 5022 | } |
4904 | 5023 | |
4905 | 5024 | /* Preserve the matching order specified in the configuration. */ |
4929 | 5048 | else |
4930 | 5049 | policydbp->ocontexts[OCON_PORT] = newc; |
4931 | 5050 | |
5051 | free(id); | |
4932 | 5052 | return 0; |
4933 | 5053 | |
4934 | 5054 | bad: |
5055 | free(id); | |
4935 | 5056 | free(newc); |
4936 | 5057 | return -1; |
5058 | } | |
5059 | ||
5060 | int define_ibpkey_context(unsigned int low, unsigned int high) | |
5061 | { | |
5062 | ocontext_t *newc, *c, *l, *head; | |
5063 | struct in6_addr subnet_prefix; | |
5064 | char *id; | |
5065 | int rc = 0; | |
5066 | ||
5067 | if (policydbp->target_platform != SEPOL_TARGET_SELINUX) { | |
5068 | yyerror("ibpkeycon not supported for target"); | |
5069 | return -1; | |
5070 | } | |
5071 | ||
5072 | if (pass == 1) { | |
5073 | id = (char *)queue_remove(id_queue); | |
5074 | free(id); | |
5075 | parse_security_context(NULL); | |
5076 | return 0; | |
5077 | } | |
5078 | ||
5079 | newc = malloc(sizeof(*newc)); | |
5080 | if (!newc) { | |
5081 | yyerror("out of memory"); | |
5082 | return -1; | |
5083 | } | |
5084 | memset(newc, 0, sizeof(*newc)); | |
5085 | ||
5086 | id = queue_remove(id_queue); | |
5087 | if (!id) { | |
5088 | yyerror("failed to read the subnet prefix"); | |
5089 | rc = -1; | |
5090 | goto out; | |
5091 | } | |
5092 | ||
5093 | rc = inet_pton(AF_INET6, id, &subnet_prefix); | |
5094 | free(id); | |
5095 | if (rc < 1) { | |
5096 | yyerror("failed to parse the subnet prefix"); | |
5097 | if (rc == 0) | |
5098 | rc = -1; | |
5099 | goto out; | |
5100 | } | |
5101 | ||
5102 | if (subnet_prefix.s6_addr[2] || subnet_prefix.s6_addr[3]) { | |
5103 | yyerror("subnet prefix should be 0's in the low order 64 bits."); | |
5104 | rc = -1; | |
5105 | goto out; | |
5106 | } | |
5107 | ||
5108 | if (low > 0xffff || high > 0xffff) { | |
5109 | yyerror("pkey value too large, pkeys are 16 bits."); | |
5110 | rc = -1; | |
5111 | goto out; | |
5112 | } | |
5113 | ||
5114 | memcpy(&newc->u.ibpkey.subnet_prefix, &subnet_prefix.s6_addr[0], | |
5115 | sizeof(newc->u.ibpkey.subnet_prefix)); | |
5116 | ||
5117 | newc->u.ibpkey.low_pkey = low; | |
5118 | newc->u.ibpkey.high_pkey = high; | |
5119 | ||
5120 | if (low > high) { | |
5121 | yyerror2("low pkey %d exceeds high pkey %d", low, high); | |
5122 | rc = -1; | |
5123 | goto out; | |
5124 | } | |
5125 | ||
5126 | rc = parse_security_context(&newc->context[0]); | |
5127 | if (rc) | |
5128 | goto out; | |
5129 | ||
5130 | /* Preserve the matching order specified in the configuration. */ | |
5131 | head = policydbp->ocontexts[OCON_IBPKEY]; | |
5132 | for (l = NULL, c = head; c; l = c, c = c->next) { | |
5133 | unsigned int low2, high2; | |
5134 | ||
5135 | low2 = c->u.ibpkey.low_pkey; | |
5136 | high2 = c->u.ibpkey.high_pkey; | |
5137 | ||
5138 | if (low == low2 && high == high2 && | |
5139 | c->u.ibpkey.subnet_prefix == newc->u.ibpkey.subnet_prefix) { | |
5140 | yyerror2("duplicate ibpkeycon entry for %d-%d ", | |
5141 | low, high); | |
5142 | rc = -1; | |
5143 | goto out; | |
5144 | } | |
5145 | if (low2 <= low && high2 >= high && | |
5146 | c->u.ibpkey.subnet_prefix == newc->u.ibpkey.subnet_prefix) { | |
5147 | yyerror2("ibpkeycon entry for %d-%d hidden by earlier entry for %d-%d", | |
5148 | low, high, low2, high2); | |
5149 | rc = -1; | |
5150 | goto out; | |
5151 | } | |
5152 | } | |
5153 | ||
5154 | if (l) | |
5155 | l->next = newc; | |
5156 | else | |
5157 | policydbp->ocontexts[OCON_IBPKEY] = newc; | |
5158 | ||
5159 | return 0; | |
5160 | ||
5161 | out: | |
5162 | free(newc); | |
5163 | return rc; | |
5164 | } | |
5165 | ||
5166 | int define_ibendport_context(unsigned int port) | |
5167 | { | |
5168 | ocontext_t *newc, *c, *l, *head; | |
5169 | char *id; | |
5170 | int rc = 0; | |
5171 | ||
5172 | if (policydbp->target_platform != SEPOL_TARGET_SELINUX) { | |
5173 | yyerror("ibendportcon not supported for target"); | |
5174 | return -1; | |
5175 | } | |
5176 | ||
5177 | if (pass == 1) { | |
5178 | id = (char *)queue_remove(id_queue); | |
5179 | free(id); | |
5180 | parse_security_context(NULL); | |
5181 | return 0; | |
5182 | } | |
5183 | ||
5184 | if (port > 0xff || port == 0) { | |
5185 | yyerror("Invalid ibendport port number, should be 0 < port < 256"); | |
5186 | return -1; | |
5187 | } | |
5188 | ||
5189 | newc = malloc(sizeof(*newc)); | |
5190 | if (!newc) { | |
5191 | yyerror("out of memory"); | |
5192 | return -1; | |
5193 | } | |
5194 | memset(newc, 0, sizeof(*newc)); | |
5195 | ||
5196 | newc->u.ibendport.dev_name = queue_remove(id_queue); | |
5197 | if (!newc->u.ibendport.dev_name) { | |
5198 | yyerror("failed to read infiniband device name."); | |
5199 | rc = -1; | |
5200 | goto out; | |
5201 | } | |
5202 | ||
5203 | if (strlen(newc->u.ibendport.dev_name) > IB_DEVICE_NAME_MAX - 1) { | |
5204 | yyerror("infiniband device name exceeds max length of 63."); | |
5205 | rc = -1; | |
5206 | goto out; | |
5207 | } | |
5208 | ||
5209 | newc->u.ibendport.port = port; | |
5210 | ||
5211 | if (parse_security_context(&newc->context[0])) { | |
5212 | free(newc); | |
5213 | return -1; | |
5214 | } | |
5215 | ||
5216 | /* Preserve the matching order specified in the configuration. */ | |
5217 | head = policydbp->ocontexts[OCON_IBENDPORT]; | |
5218 | for (l = NULL, c = head; c; l = c, c = c->next) { | |
5219 | unsigned int port2; | |
5220 | ||
5221 | port2 = c->u.ibendport.port; | |
5222 | ||
5223 | if (port == port2 && | |
5224 | !strcmp(c->u.ibendport.dev_name, | |
5225 | newc->u.ibendport.dev_name)) { | |
5226 | yyerror2("duplicate ibendportcon entry for %s port %u", | |
5227 | newc->u.ibendport.dev_name, port); | |
5228 | rc = -1; | |
5229 | goto out; | |
5230 | } | |
5231 | } | |
5232 | ||
5233 | if (l) | |
5234 | l->next = newc; | |
5235 | else | |
5236 | policydbp->ocontexts[OCON_IBENDPORT] = newc; | |
5237 | ||
5238 | return 0; | |
5239 | ||
5240 | out: | |
5241 | free(newc->u.ibendport.dev_name); | |
5242 | free(newc); | |
5243 | return rc; | |
4937 | 5244 | } |
4938 | 5245 | |
4939 | 5246 | int define_netif_context(void) |
5139 | 5446 | } |
5140 | 5447 | |
5141 | 5448 | memset(newc, 0, sizeof(ocontext_t)); |
5142 | ||
5143 | #ifdef __APPLE__ | |
5144 | 5449 | memcpy(&newc->u.node6.addr[0], &addr.s6_addr[0], 16); |
5145 | 5450 | memcpy(&newc->u.node6.mask[0], &mask.s6_addr[0], 16); |
5146 | #else | |
5147 | memcpy(&newc->u.node6.addr[0], &addr.s6_addr32[0], 16); | |
5148 | memcpy(&newc->u.node6.mask[0], &mask.s6_addr32[0], 16); | |
5149 | #endif | |
5150 | 5451 | |
5151 | 5452 | if (parse_security_context(&newc->context[0])) { |
5152 | 5453 | free(newc); |
5267 | 5568 | else |
5268 | 5569 | policydbp->genfs = newgenfs; |
5269 | 5570 | genfs = newgenfs; |
5571 | } else { | |
5572 | free(fstype); | |
5573 | fstype = NULL; | |
5270 | 5574 | } |
5271 | 5575 | |
5272 | 5576 | newc = (ocontext_t *) malloc(sizeof(ocontext_t)); |
5324 | 5628 | (!newc->v.sclass || !c->v.sclass |
5325 | 5629 | || newc->v.sclass == c->v.sclass)) { |
5326 | 5630 | yyerror2("duplicate entry for genfs entry (%s, %s)", |
5327 | fstype, newc->u.name); | |
5631 | genfs->fstype, newc->u.name); | |
5328 | 5632 | goto fail; |
5329 | 5633 | } |
5330 | 5634 | len = strlen(newc->u.name); |
5338 | 5642 | p->next = newc; |
5339 | 5643 | else |
5340 | 5644 | genfs->head = newc; |
5645 | free(type); | |
5341 | 5646 | return 0; |
5342 | 5647 | fail: |
5343 | 5648 | if (type) |
42 | 42 | int define_netif_context(void); |
43 | 43 | int define_permissive(void); |
44 | 44 | int define_polcap(void); |
45 | int define_ibpkey_context(unsigned int low, unsigned int high); | |
46 | int define_ibendport_context(unsigned int port); | |
45 | 47 | int define_port_context(unsigned int low, unsigned int high); |
46 | 48 | int define_pirq_context(unsigned int pirq); |
47 | 49 | int define_iomem_context(uint64_t low, uint64_t high); |
64 | 66 | int define_type(int alias); |
65 | 67 | int define_user(void); |
66 | 68 | int define_validatetrans(constraint_expr_t *expr); |
69 | int expand_attrib(void); | |
67 | 70 | int insert_id(const char *id,int push); |
68 | 71 | int insert_separator(int push); |
69 | 72 | role_datum_t *define_role_dom(role_datum_t *r); |
20 | 20 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. |
21 | 21 | * Copyright (C) 2003 - 2008 Tresys Technology, LLC |
22 | 22 | * Copyright (C) 2007 Red Hat Inc. |
23 | * Copyright (C) 2017 Mellanox Technologies Inc. | |
23 | 24 | * This program is free software; you can redistribute it and/or modify |
24 | 25 | * it under the terms of the GNU General Public License as published by |
25 | 26 | * the Free Software Foundation, version 2. |
102 | 103 | %token TYPES |
103 | 104 | %token ALIAS |
104 | 105 | %token ATTRIBUTE |
106 | %token EXPANDATTRIBUTE | |
105 | 107 | %token BOOL |
106 | 108 | %token TUNABLE |
107 | 109 | %token IF |
133 | 135 | %token TARGET |
134 | 136 | %token SAMEUSER |
135 | 137 | %token FSCON PORTCON NETIFCON NODECON |
138 | %token IBPKEYCON | |
139 | %token IBENDPORTCON | |
136 | 140 | %token PIRQCON IOMEMCON IOPORTCON PCIDEVICECON DEVICETREECON |
137 | 141 | %token FSUSEXATTR FSUSETASK FSUSETRANS |
138 | 142 | %token GENFSCON |
168 | 172 | opt_default_rules opt_mls te_rbac users opt_constraints |
169 | 173 | { if (pass == 1) { if (policydb_index_bools(policydbp)) return -1;} |
170 | 174 | else if (pass == 2) { if (policydb_index_others(NULL, policydbp, 0)) return -1;}} |
171 | initial_sid_contexts opt_fs_contexts opt_fs_uses opt_genfs_contexts net_contexts opt_dev_contexts | |
175 | initial_sid_contexts opt_fs_contexts opt_fs_uses opt_genfs_contexts net_contexts opt_dev_contexts opt_ibpkey_contexts opt_ibendport_contexts | |
172 | 176 | ; |
173 | 177 | classes : class_def |
174 | 178 | | classes class_def |
313 | 317 | | role_attr_def |
314 | 318 | ; |
315 | 319 | te_decl : attribute_def |
320 | | expandattribute_def | |
316 | 321 | | type_def |
317 | 322 | | typealias_def |
318 | 323 | | typeattribute_def |
326 | 331 | ; |
327 | 332 | attribute_def : ATTRIBUTE identifier ';' |
328 | 333 | { if (define_attrib()) return -1;} |
334 | ; | |
335 | expandattribute_def : EXPANDATTRIBUTE names bool_val ';' | |
336 | { if (expand_attrib()) return -1;} | |
329 | 337 | ; |
330 | 338 | type_def : TYPE identifier alias_def opt_attr_list ';' |
331 | 339 | {if (define_type(1)) return -1;} |
694 | 702 | fs_context_def : FSCON number number security_context_def security_context_def |
695 | 703 | {if (define_fs_context($2,$3)) return -1;} |
696 | 704 | ; |
697 | net_contexts : opt_port_contexts opt_netif_contexts opt_node_contexts | |
705 | net_contexts : opt_port_contexts opt_netif_contexts opt_node_contexts | |
698 | 706 | ; |
699 | 707 | opt_port_contexts : port_contexts |
700 | 708 | | |
707 | 715 | | PORTCON identifier number '-' number security_context_def |
708 | 716 | {if (define_port_context($3,$5)) return -1;} |
709 | 717 | ; |
718 | opt_ibpkey_contexts : ibpkey_contexts | |
719 | | | |
720 | ; | |
721 | ibpkey_contexts : ibpkey_context_def | |
722 | | ibpkey_contexts ibpkey_context_def | |
723 | ; | |
724 | ibpkey_context_def : IBPKEYCON ipv6_addr number security_context_def | |
725 | {if (define_ibpkey_context($3,$3)) return -1;} | |
726 | | IBPKEYCON ipv6_addr number '-' number security_context_def | |
727 | {if (define_ibpkey_context($3,$5)) return -1;} | |
728 | ; | |
729 | opt_ibendport_contexts : ibendport_contexts | |
730 | | | |
731 | ; | |
732 | ibendport_contexts : ibendport_context_def | |
733 | | ibendport_contexts ibendport_context_def | |
734 | ; | |
735 | ibendport_context_def : IBENDPORTCON identifier number security_context_def | |
736 | {if (define_ibendport_context($3)) return -1;} | |
737 | ; | |
710 | 738 | opt_netif_contexts : netif_contexts |
711 | 739 | | |
712 | 740 | ; |
11 | 11 | * Added support for binary policy modules |
12 | 12 | * |
13 | 13 | * Copyright (C) 2003-5 Tresys Technology, LLC |
14 | * Copyright (C) 2017 Mellanox Technologies Inc. | |
14 | 15 | * This program is free software; you can redistribute it and/or modify |
15 | 16 | * it under the terms of the GNU General Public License as published by |
16 | 17 | * the Free Software Foundation, version 2. |
105 | 106 | alias { return(ALIAS); } |
106 | 107 | ATTRIBUTE | |
107 | 108 | attribute { return(ATTRIBUTE); } |
109 | EXPANDATTRIBUTE | | |
110 | expandattribute { return(EXPANDATTRIBUTE); } | |
108 | 111 | TYPE_TRANSITION | |
109 | 112 | type_transition { return(TYPE_TRANSITION); } |
110 | 113 | TYPE_MEMBER | |
180 | 183 | incomp { return(INCOMP);} |
181 | 184 | fscon | |
182 | 185 | FSCON { return(FSCON);} |
186 | ibpkeycon | | |
187 | IBPKEYCON { return(IBPKEYCON);} | |
188 | ibendportcon | | |
189 | IBENDPORTCON { return(IBENDPORTCON);} | |
183 | 190 | portcon | |
184 | 191 | PORTCON { return(PORTCON);} |
185 | 192 | netifcon | |
112 | 112 | |
113 | 113 | p = q->head; |
114 | 114 | while (p != NULL) { |
115 | free(p->element); | |
115 | 116 | temp = p; |
116 | 117 | p = p->next; |
117 | 118 | free(temp); |
4 | 4 | BINDIR=$(PREFIX)/bin |
5 | 5 | LIBDIR ?= $(PREFIX)/lib |
6 | 6 | INCLUDEDIR ?= $(PREFIX)/include |
7 | LIBSEPOLA ?= $(LIBDIR)/libsepol.a | |
7 | 8 | |
8 | 9 | CFLAGS ?= -g -Wall -W -Werror -O2 -pipe |
9 | override CFLAGS += -I$(INCLUDEDIR) | |
10 | ||
11 | LDLIBS=-lfl $(LIBDIR)/libsepol.a -L$(LIBDIR) | |
12 | 10 | |
13 | 11 | all: dispol dismod |
14 | 12 | |
15 | dispol: dispol.o | |
13 | dispol: dispol.o $(LIBSEPOLA) | |
16 | 14 | |
17 | dismod: dismod.o | |
15 | dismod: dismod.o $(LIBSEPOLA) | |
18 | 16 | |
19 | 17 | clean: |
20 | 18 | -rm -f dispol dismod *.o |
64 | 64 | "levels ", "cats ", "attribs" |
65 | 65 | }; |
66 | 66 | |
67 | void usage(const char *progname) | |
67 | static __attribute__((__noreturn__)) void usage(const char *progname) | |
68 | 68 | { |
69 | 69 | printf("usage: %s binary_pol_file\n\n", progname); |
70 | 70 | exit(1); |
242 | 242 | } |
243 | 243 | } else if (avrule->specified & AVRULE_NEVERALLOW) { |
244 | 244 | fprintf(fp, " neverallow"); |
245 | } else if (avrule->specified & AVRULE_XPERMS) { | |
246 | if (avrule->specified & AVRULE_XPERMS_ALLOWED) | |
247 | fprintf(fp, "allowxperm "); | |
248 | else if (avrule->specified & AVRULE_XPERMS_AUDITALLOW) | |
249 | fprintf(fp, "auditallowxperm "); | |
250 | else if (avrule->specified & AVRULE_XPERMS_DONTAUDIT) | |
251 | fprintf(fp, "dontauditxperm "); | |
245 | 252 | } else { |
246 | 253 | fprintf(fp, " ERROR: no valid rule type specified\n"); |
247 | 254 | return -1; |
281 | 288 | policy, fp); |
282 | 289 | } else if (avrule->specified & AVRULE_TYPE) { |
283 | 290 | display_id(policy, fp, SYM_TYPES, avrule->perms->data - 1, ""); |
291 | } else if (avrule->specified & AVRULE_XPERMS) { | |
292 | avtab_extended_perms_t xperms; | |
293 | int i; | |
294 | ||
295 | if (avrule->xperms->specified == AVRULE_XPERMS_IOCTLFUNCTION) | |
296 | xperms.specified = AVTAB_XPERMS_IOCTLFUNCTION; | |
297 | else if (avrule->xperms->specified == AVRULE_XPERMS_IOCTLDRIVER) | |
298 | xperms.specified = AVTAB_XPERMS_IOCTLDRIVER; | |
299 | else { | |
300 | fprintf(fp, " ERROR: no valid xperms specified\n"); | |
301 | return -1; | |
302 | } | |
303 | ||
304 | xperms.driver = avrule->xperms->driver; | |
305 | for (i = 0; i < EXTENDED_PERMS_LEN; i++) | |
306 | xperms.perms[i] = avrule->xperms->perms[i]; | |
307 | ||
308 | fprintf(fp, "%s", sepol_extended_perms_to_string(&xperms)); | |
284 | 309 | } |
285 | 310 | |
286 | 311 | fprintf(fp, ";\n"); |
35 | 35 | |
36 | 36 | static policydb_t policydb; |
37 | 37 | |
38 | void usage(const char *progname) | |
38 | static __attribute__((__noreturn__)) void usage(const char *progname) | |
39 | 39 | { |
40 | 40 | printf("usage: %s binary_pol_file\n\n", progname); |
41 | 41 | exit(1); |
329 | 329 | } |
330 | 330 | } |
331 | 331 | |
332 | struct filenametr_display_args { | |
333 | policydb_t *p; | |
334 | FILE *fp; | |
335 | }; | |
336 | ||
337 | static int filenametr_display(hashtab_key_t key, | |
338 | hashtab_datum_t datum, | |
339 | void *ptr) | |
340 | { | |
341 | struct filename_trans *ft = (struct filename_trans *)key; | |
342 | struct filename_trans_datum *ftdatum = datum; | |
343 | struct filenametr_display_args *args = ptr; | |
344 | policydb_t *p = args->p; | |
345 | FILE *fp = args->fp; | |
346 | ||
347 | display_id(p, fp, SYM_TYPES, ft->stype - 1, ""); | |
348 | display_id(p, fp, SYM_TYPES, ft->ttype - 1, ""); | |
349 | display_id(p, fp, SYM_CLASSES, ft->tclass - 1, ":"); | |
350 | display_id(p, fp, SYM_TYPES, ftdatum->otype - 1, ""); | |
351 | fprintf(fp, " %s\n", ft->name); | |
352 | return 0; | |
353 | } | |
354 | ||
355 | ||
332 | 356 | static void display_filename_trans(policydb_t *p, FILE *fp) |
333 | 357 | { |
334 | filename_trans_t *ft; | |
358 | struct filenametr_display_args args; | |
335 | 359 | |
336 | 360 | fprintf(fp, "filename_trans rules:\n"); |
337 | for (ft = p->filename_trans; ft; ft = ft->next) { | |
338 | display_id(p, fp, SYM_TYPES, ft->stype - 1, ""); | |
339 | display_id(p, fp, SYM_TYPES, ft->ttype - 1, ""); | |
340 | display_id(p, fp, SYM_CLASSES, ft->tclass - 1, ":"); | |
341 | display_id(p, fp, SYM_TYPES, ft->otype - 1, ""); | |
342 | fprintf(fp, " %s\n", ft->name); | |
343 | } | |
361 | args.p = p; | |
362 | args.fp = fp; | |
363 | hashtab_map(p->filename_trans, filenametr_display, &args); | |
344 | 364 | } |
345 | 365 | |
346 | 366 | int menu(void) |