Codebase list checkpolicy / fd48bc0
New upstream version 2.7~rc2 Laurent Bigonville 6 years ago
15 changed file(s) with 1019 addition(s) and 1179 deletion(s). Raw diff Collapse all Expand all
+0
-493
ChangeLog less more
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
55 MANDIR ?= $(PREFIX)/share/man
66 LIBDIR ?= $(PREFIX)/lib
77 INCLUDEDIR ?= $(PREFIX)/include
8 LIBSEPOLA ?= $(LIBDIR)/libsepol.a
89 TARGETS = checkpolicy checkmodule
910
1011 LEX = flex
1213
1314 CFLAGS ?= -g -Wall -Werror -Wshadow -O2 -pipe -fno-strict-aliasing
1415
15 override CFLAGS += -I. -I${INCLUDEDIR}
16 override CFLAGS += -I.
1617
1718 CHECKOBJS = y.tab.o lex.yy.o queue.o module_compiler.o parse_util.o \
1819 policy_define.o
1920 CHECKPOLOBJS = $(CHECKOBJS) checkpolicy.o
2021 CHECKMODOBJS = $(CHECKOBJS) checkmodule.o
2122
22 LDLIBS=$(LIBDIR)/libsepol.a -lfl
23
2423 GENERATED=lex.yy.c y.tab.c y.tab.h
2524
2625 all: $(TARGETS)
2726 $(MAKE) -C test
2827
29 checkpolicy: $(CHECKPOLOBJS)
28 checkpolicy: $(CHECKPOLOBJS) $(LIBSEPOLA)
3029
31 checkmodule: $(CHECKMODOBJS)
30 checkmodule: $(CHECKMODOBJS) $(LIBSEPOLA)
3231
3332 %.o: %.c
3433 $(CC) $(CFLAGS) -o $@ -c $<
0 2.6
0 2.7-rc2
123123 return policydb_write(p, &pf);
124124 }
125125
126 static void usage(char *progname)
126 static __attribute__((__noreturn__)) void usage(const char *progname)
127127 {
128128 printf("usage: %s [-h] [-V] [-b] [-C] [-U handle_unknown] [-m] [-M] [-o FILE] [INPUT]\n", progname);
129129 printf("Build base and policy modules.\n");
22 checkpolicy \- SELinux policy compiler
33 .SH SYNOPSIS
44 .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]"
66 .br
77 .SH "DESCRIPTION"
88 This manual page describes the
2525 .TP
2626 .B \-d,\-\-debug
2727 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.
2831 .TP
2932 .B \-M,\-\-mls
3033 Enable the MLS policy when checking and compiling the policy.
2121 *
2222 * Policy Module support.
2323 *
24 * Copyright (C) 2017 Mellanox Technologies Inc.
2425 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
2526 * Copyright (C) 2003 - 2005 Tresys Technology, LLC
2627 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
5657 * booleans or conditional rules are thrown away a warning is printed.
5758 */
5859
60 #include <ctype.h>
5961 #include <getopt.h>
6062 #include <unistd.h>
6163 #include <stdlib.h>
7274 #include <errno.h>
7375 #include <sys/mman.h>
7476
75 #ifdef __APPLE__
76 #include <ctype.h>
77 #endif
78
7977 #include <sepol/module_to_cil.h>
78 #include <sepol/kernel_to_cil.h>
79 #include <sepol/kernel_to_conf.h>
8080 #include <sepol/policydb/policydb.h>
8181 #include <sepol/policydb/services.h>
8282 #include <sepol/policydb/conditional.h>
104104
105105 unsigned int policyvers = POLICYDB_VERSION_MAX;
106106
107 void usage(char *progname)
107 static __attribute__((__noreturn__)) void usage(const char *progname)
108108 {
109109 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]"
111111 "[-c policyvers (%d-%d)] [-o output_file] [-t target_platform (selinux,xen)]"
112112 "[input_file]\n",
113113 progname, POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
390390 size_t scontext_len, pathlen;
391391 unsigned int i;
392392 unsigned int protocol, port;
393 unsigned int binary = 0, debug = 0, cil = 0;
393 unsigned int binary = 0, debug = 0, cil = 0, conf = 0;
394394 struct val_to_name v;
395395 int ret, ch, fd, target = SEPOL_TARGET_SELINUX;
396396 unsigned int nel, uret;
413413 {"handle-unknown", required_argument, NULL, 'U'},
414414 {"mls", no_argument, NULL, 'M'},
415415 {"cil", no_argument, NULL, 'C'},
416 {"conf",no_argument, NULL, 'F'},
416417 {"help", no_argument, NULL, 'h'},
417418 {NULL, 0, NULL, 0}
418419 };
419420
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) {
421422 switch (ch) {
422423 case 'o':
423424 outfile = optarg;
462463 break;
463464 case 'C':
464465 cil = 1;
466 break;
467 case 'F':
468 conf = 1;
465469 break;
466470 case 'c':{
467471 long int n;
512516 sepol_set_policydb(&policydb);
513517 sepol_set_sidtab(&sidtab);
514518
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
515524 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 }
521525 fd = open(file, O_RDONLY);
522526 if (fd < 0) {
523527 fprintf(stderr, "Can't open '%s': %s\n",
570574 }
571575 }
572576 } else {
577 if (conf) {
578 fprintf(stderr, "Can only generate policy.conf from binary policy\n");
579 exit(1);
580 }
573581 if (policydb_init(&parse_policy))
574582 exit(1);
575583 /* We build this as a base policy first since that is all the parser understands */
623631 policydb.policyvers = policyvers;
624632
625633 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 }
635648 if (ret) {
636649 fprintf(stderr, "%s: error writing %s\n",
637650 argv[0], outfile);
639652 }
640653 } else {
641654 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 }
643660 if (ret) {
644661 fprintf(stderr, "%s: error writing %s\n", argv[0], outfile);
645662 exit(1);
656673
657674 if (!debug) {
658675 policydb_destroy(&policydb);
676 sepol_sidtab_destroy(&sidtab);
659677 exit(0);
660678 }
661679
681699 printf("h) change a boolean value\n");
682700 printf("i) display constraint expressions\n");
683701 printf("j) display validatetrans expressions\n");
702 printf("k) Call ibpkey_sid\n");
703 printf("l) Call ibendport_sid\n");
684704 #ifdef EQUIVTYPES
685705 printf("z) Show equivalent types\n");
686706 #endif
12021222 "\nNo validatetrans expressions found.\n");
12031223 }
12041224 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;
12051269 #ifdef EQUIVTYPES
12061270 case 'z':
12071271 identify_equiv_types();
4949 static scope_stack_t *stack_top = NULL;
5050 static avrule_block_t *last_block;
5151 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 }
5280
5381 int define_policy(int pass, int module_header_given)
5482 {
101129 return 0;
102130 }
103131
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
107135 * current scope stack then this would return a 0.
108136 */
109 static int is_declaration_allowed(void)
137 static int is_creation_allowed(void)
110138 {
111139 if (stack_top->type != 1 || stack_top->in_else) {
112140 return 0;
113141 }
114142 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;
115184 }
116185
117186 /* Attempt to declare a symbol within the current declaration. If
128197 uint32_t * dest_value, uint32_t * datum_value)
129198 {
130199 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)) {
154208 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;
164212 }
165213
166214 static int role_implicit_bounds(hashtab_t roles_tab,
200248 return 0;
201249 }
202250
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;
208256 uint32_t value;
257
258 *role = NULL;
259 *key = NULL;
260 isattr = isattr ? ROLE_ATTRIB : ROLE_ROLE;
209261
210262 if (id == NULL) {
211263 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) {
212324 return NULL;
213325 }
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) {
251342 yyerror("Out of memory!");
252 free(dest_id);
343 free(key);
253344 return NULL;
254345 }
255346 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;
271349 } 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) {
279361 yyerror("Out of memory!");
362 free(key);
363 role_datum_destroy(dest_role);
364 free(dest_role);
280365 return NULL;
281366 }
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");
284379 return NULL;
285380 }
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)
308387 {
309388 char *id;
310 type_datum_t *typdatum;
311 int retval;
389 type_datum_t *datum;
390 int ret;
312391 uint32_t value = 0;
392
393 *type = NULL;
394 isattr = isattr ? TYPE_ATTRIB : TYPE_TYPE;
313395
314396 id = (char *)queue_remove(id_queue);
315397 if (!id) {
316398 yyerror("no type/attribute name?");
317 return NULL;
399 return -1;
318400 }
319401 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) {
328409 yyerror("Out of memory!");
329410 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;
368457 }
369458
370459 static int user_implicit_bounds(hashtab_t users_tab,
404493 return 0;
405494 }
406495
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;
413505
414506 if (id == NULL) {
415507 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) {
416558 return NULL;
417559 }
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) {
456576 yyerror("Out of memory!");
457 free(dest_id);
577 free(key);
458578 return NULL;
459579 }
460580 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;
475582 } 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) {
483594 yyerror("Out of memory!");
595 free(key);
596 user_datum_destroy(dest_user);
597 free(dest_user);
484598 return NULL;
485599 }
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;
504609 }
505610
506611 /* Return a type_datum_t for the local avrule_decl with the given ID.
596701 }
597702
598703 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;
611704 }
612705
613706 /* Attempt to require a symbol within the current scope. If currently
623716 uint32_t * dest_value, uint32_t * datum_value)
624717 {
625718 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)) {
681727 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
690730 stack_top->require_given = 1;
691 return retval;
731 return ret;
692732 }
693733
694734 int add_perm_to_class(uint32_t perm_value, uint32_t class_value)
761801 if ((datum = calloc(1, sizeof(*datum))) == NULL ||
762802 symtab_init(&datum->permissions, PERM_SYMTAB_SIZE)) {
763803 yyerror("Out of memory!");
764 goto cleanup;
804 return -1;
765805 }
766806 ret =
767807 require_symbol(SYM_CLASSES, class_id, datum, &datum->s.value,
768808 &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)) {
771819 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);
808827 }
809828
810829 /* now add each of the permissions to this class's requirements */
827846 ("Base policy - require of permission %s without prior declaration.",
828847 perm_id);
829848 free(perm_id);
830 goto cleanup;
849 return -1;
831850 }
832851 allocated = 1;
833852 if ((perm = malloc(sizeof(*perm))) == NULL) {
834853 yyerror("Out of memory!");
835854 free(perm_id);
836 goto cleanup;
855 return -1;
837856 }
838857 memset(perm, 0, sizeof(*perm));
839858 ret =
843862 yyerror("Out of memory!");
844863 free(perm_id);
845864 free(perm);
846 goto cleanup;
865 return -1;
847866 }
848867 perm->s.value = datum->permissions.nprim + 1;
849868 }
850869
851870 if (add_perm_to_class(perm->s.value, datum->s.value) == -1) {
852871 yyerror("Out of memory!");
853 goto cleanup;
872 return -1;
854873 }
855874
856875 /* Update number of primitives if we allocated one. */
858877 datum->permissions.nprim++;
859878 }
860879 return 0;
861 cleanup:
862 return -1;
863880 }
864881
865882 static int require_role_or_attribute(int pass, unsigned char isattr)
866883 {
867 char *id = queue_remove(id_queue);
884 char *key = NULL;
868885 role_datum_t *role = NULL;
869 int retval;
886 int ret;
887
870888 if (pass == 2) {
871 free(id);
889 free(queue_remove(id_queue));
872890 return 0;
873891 }
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 {
890907 role_datum_destroy(role);
891908 free(role);
892909 }
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;
922912 }
923913
924914 int require_role(int pass)
933923
934924 static int require_type_or_attribute(int pass, unsigned char isattr)
935925 {
936 char *id = queue_remove(id_queue);
937926 type_datum_t *type = NULL;
938 int retval;
927 int ret;
928
939929 if (pass == 2) {
940 free(id);
930 free(queue_remove(id_queue));
941931 return 0;
942932 }
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;
985941 }
986942
987943 int require_type(int pass)
996952
997953 int require_user(int pass)
998954 {
999 char *id = queue_remove(id_queue);
955 char *key = NULL;
1000956 user_datum_t *user = NULL;
1001 int retval;
957 int ret;
958
1002959 if (pass == 1) {
1003 free(id);
960 free(queue_remove(id_queue));
1004961 return 0;
1005962 }
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) {
1021972 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;
1046977 }
1047978
1048979 static int require_bool_tunable(int pass, int is_tunable)
10701001 &booldatum->s.value, &booldatum->s.value);
10711002 if (retval != 0) {
10721003 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;
10971011 }
10981012
10991013 int require_bool(int pass)
11431057 free(level->level);
11441058 level_datum_destroy(level);
11451059 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;
11701067 }
11711068
11721069 int require_cat(int pass)
11961093 free(id);
11971094 cat_datum_destroy(cat);
11981095 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;
12231103 }
12241104
12251105 static int is_scope_in_stack(scope_datum_t * scope, scope_stack_t * stack)
1919 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
2020 * Copyright (C) 2003 - 2008 Tresys Technology, LLC
2121 * Copyright (C) 2007 Red Hat Inc.
22 * Copyright (C) 2017 Mellanox Techonologies Inc.
2223 * This program is free software; you can redistribute it and/or modify
2324 * it under the terms of the GNU General Public License as published by
2425 * the Free Software Foundation, version 2.
347348 cladatum = hashtab_search(policydbp->p_classes.table, id);
348349 if (!cladatum) {
349350 yyerror2("unknown class %s", id);
350 return -1;
351 }
351 free(id);
352 return -1;
353 }
354 free(id);
352355 if (ebitmap_set_bit(e_classes, cladatum->s.value - 1, TRUE)) {
353356 yyerror("Out of memory");
354357 return -1;
355358 }
356 free(id);
357359 }
358360 return 0;
359361 }
11371139 return 0;
11381140 }
11391141
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
11401224 static int add_aliases_to_type(type_datum_t * type)
11411225 {
11421226 char *id;
12311315 free(id);
12321316 return -1;
12331317 }
1318 free(id);
12341319 return add_aliases_to_type(t);
12351320 }
12361321
12621347 free(id);
12631348 return -1;
12641349 }
1350 free(id);
12651351
12661352 while ((id = queue_remove(id_queue))) {
12671353 if (!is_id_in_scope(SYM_TYPES, id)) {
14231509 if (!attr) {
14241510 /* treat it as a fatal error */
14251511 yyerror2("attribute %s is not declared", id);
1512 free(id);
14261513 return -1;
14271514 }
14281515
14291516 if (attr->flavor != TYPE_ATTRIB) {
14301517 yyerror2("%s is a type, not an attribute", id);
1518 free(id);
14311519 return -1;
14321520 }
14331521
14581546 type_datum_t *t;
14591547
14601548 if (strcmp(id, "*") == 0) {
1549 free(id);
14611550 if (!starallowed) {
14621551 yyerror("* not allowed in this type of rule");
14631552 return -1;
14641553 }
14651554 /* set TYPE_STAR flag */
14661555 set->flags = TYPE_STAR;
1467 free(id);
14681556 *add = 1;
14691557 return 0;
14701558 }
14711559
14721560 if (strcmp(id, "~") == 0) {
1561 free(id);
14731562 if (!starallowed) {
14741563 yyerror("~ not allowed in this type of rule");
14751564 return -1;
14761565 }
14771566 /* complement the set */
14781567 set->flags = TYPE_COMP;
1479 free(id);
14801568 *add = 1;
14811569 return 0;
14821570 }
15691657 (hashtab_key_t) id);
15701658 if (!datum || datum->flavor == TYPE_ATTRIB) {
15711659 yyerror2("unknown type %s", id);
1660 free(id);
15721661 goto bad;
15731662 }
1663 free(id);
15741664
15751665 ebitmap_for_each_bit(&tclasses, node, i) {
15761666 if (ebitmap_node_get_bit(node, i)) {
17031793 bool_value = (char *)queue_remove(id_queue);
17041794 if (!bool_value) {
17051795 yyerror("no default value for bool definition?");
1706 free(id);
17071796 return -1;
17081797 }
17091798
17101799 datum->state = (int)(bool_value[0] == 'T') ? 1 : 0;
1800 free(bool_value);
17111801 return 0;
17121802 cleanup:
17131803 cond_destroy_bool(id, datum, NULL);
19162006 /* read in ranges to include and omit */
19172007 if (avrule_read_ioctls(&rangehead))
19182008 return -1;
1919 omit = rangehead->omit;
19202009 if (rangehead == NULL) {
19212010 yyerror("error processing ioctl commands");
19222011 return -1;
19232012 }
2013 omit = rangehead->omit;
19242014 /* sort and merge the input ioctls */
19252015 if (avrule_sort_ioctls(&rangehead))
19262016 return -1;
19772067 while ((id = queue_remove(id_queue))) {
19782068 if (strcmp(id, "self") == 0) {
19792069 free(id);
2070 if (add == 0) {
2071 yyerror("-self is not supported");
2072 ret = -1;
2073 goto out;
2074 }
19802075 avrule->flags |= RULE_SELF;
19812076 continue;
19822077 }
23832478
23842479 id = queue_remove(id_queue);
23852480 if (strcmp(id,"ioctl") == 0) {
2481 free(id);
23862482 if (define_te_avtab_ioctl(avrule_template))
23872483 return -1;
2388 free(id);
23892484 } else {
23902485 yyerror("only ioctl extended permissions are supported");
2486 free(id);
23912487 return -1;
23922488 }
23932489 return 0;
24362532 while ((id = queue_remove(id_queue))) {
24372533 if (strcmp(id, "self") == 0) {
24382534 free(id);
2535 if (add == 0) {
2536 yyerror("-self is not supported");
2537 ret = -1;
2538 goto out;
2539 }
24392540 avrule->flags |= RULE_SELF;
24402541 continue;
24412542 }
25342635 *rule = avrule;
25352636
25362637 out:
2638 if (ret) {
2639 avrule_destroy(avrule);
2640 free(avrule);
2641 }
25372642 return ret;
25382643
25392644 }
27152820 free(id);
27162821 return -1;
27172822 }
2823 free(id);
27182824
27192825 while ((id = queue_remove(id_queue))) {
27202826 if (!is_id_in_scope(SYM_ROLES, id)) {
30793185 role = hashtab_search(policydbp->p_roles.table, id);
30803186 if (!role) {
30813187 yyerror2("unknown role %s used in transition definition", id);
3188 free(id);
30823189 goto bad;
30833190 }
30843191
30853192 if (role->flavor != ROLE_ROLE) {
30863193 yyerror2("the new role %s must be a regular role", id);
3194 free(id);
30873195 goto bad;
30883196 }
3197 free(id);
30893198
30903199 /* This ebitmap business is just to ensure that there are not conflicting role_trans rules */
30913200 if (role_set_expand(&roles, &e_roles, policydbp, NULL, NULL))
32093318 ebitmap_t e_tclasses;
32103319 ebitmap_node_t *snode, *tnode, *cnode;
32113320 filename_trans_t *ft;
3321 filename_trans_datum_t *ftdatum;
32123322 filename_trans_rule_t *ftr;
32133323 type_datum_t *typdatum;
32143324 uint32_t otype;
32153325 unsigned int c, s, t;
3216 int add;
3326 int add, rc;
32173327
32183328 if (pass == 1) {
32193329 /* stype */
32343344 return 0;
32353345 }
32363346
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);
32373352
32383353 add = 1;
3239 type_set_init(&stypes);
32403354 while ((id = queue_remove(id_queue))) {
32413355 if (set_types(&stypes, id, &add, 0))
32423356 goto bad;
32433357 }
32443358
32453359 add =1;
3246 type_set_init(&ttypes);
32473360 while ((id = queue_remove(id_queue))) {
32483361 if (set_types(&ttypes, id, &add, 0))
32493362 goto bad;
32503363 }
32513364
3252 ebitmap_init(&e_tclasses);
32533365 if (read_classes(&e_tclasses))
32543366 goto bad;
32553367
32663378 typdatum = hashtab_search(policydbp->p_types.table, id);
32673379 if (!typdatum) {
32683380 yyerror2("unknown type %s used in transition definition", id);
3381 free(id);
32693382 goto bad;
32703383 }
32713384 free(id);
32803393 /* We expand the class set into seperate rules. We expand the types
32813394 * just to make sure there are not duplicates. They will get turned
32823395 * into seperate rules later */
3283 ebitmap_init(&e_stypes);
32843396 if (type_set_expand(&stypes, &e_stypes, policydbp, 1))
32853397 goto bad;
32863398
3287 ebitmap_init(&e_ttypes);
32883399 if (type_set_expand(&ttypes, &e_ttypes, policydbp, 1))
32893400 goto bad;
32903401
32973408 ebitmap_for_each_bit(&e_ttypes, tnode, t) {
32983409 if (!ebitmap_node_get_bit(tnode, t))
32993410 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));
33163413 if (!ft) {
33173414 yyerror("out of memory");
33183415 goto bad;
33193416 }
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;
33253420 ft->name = strdup(name);
33263421 if (!ft->name) {
33273422 yyerror("out of memory");
33283423 goto bad;
33293424 }
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 }
33343449 }
33353450 }
33363451
33603475 ebitmap_destroy(&e_stypes);
33613476 ebitmap_destroy(&e_ttypes);
33623477 ebitmap_destroy(&e_tclasses);
3478 type_set_destroy(&stypes);
3479 type_set_destroy(&ttypes);
33633480
33643481 return 0;
33653482
33663483 bad:
33673484 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);
33683490 return -1;
33693491 }
33703492
48835005 protocol = IPPROTO_DCCP;
48845006 } else {
48855007 yyerror2("unrecognized protocol %s", id);
4886 free(newc);
4887 return -1;
5008 goto bad;
48885009 }
48895010
48905011 newc->u.port.protocol = protocol;
48935014
48945015 if (low > high) {
48955016 yyerror2("low port %d exceeds high port %d", low, high);
4896 free(newc);
4897 return -1;
5017 goto bad;
48985018 }
48995019
49005020 if (parse_security_context(&newc->context[0])) {
4901 free(newc);
4902 return -1;
5021 goto bad;
49035022 }
49045023
49055024 /* Preserve the matching order specified in the configuration. */
49295048 else
49305049 policydbp->ocontexts[OCON_PORT] = newc;
49315050
5051 free(id);
49325052 return 0;
49335053
49345054 bad:
5055 free(id);
49355056 free(newc);
49365057 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;
49375244 }
49385245
49395246 int define_netif_context(void)
51395446 }
51405447
51415448 memset(newc, 0, sizeof(ocontext_t));
5142
5143 #ifdef __APPLE__
51445449 memcpy(&newc->u.node6.addr[0], &addr.s6_addr[0], 16);
51455450 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
51505451
51515452 if (parse_security_context(&newc->context[0])) {
51525453 free(newc);
52675568 else
52685569 policydbp->genfs = newgenfs;
52695570 genfs = newgenfs;
5571 } else {
5572 free(fstype);
5573 fstype = NULL;
52705574 }
52715575
52725576 newc = (ocontext_t *) malloc(sizeof(ocontext_t));
53245628 (!newc->v.sclass || !c->v.sclass
53255629 || newc->v.sclass == c->v.sclass)) {
53265630 yyerror2("duplicate entry for genfs entry (%s, %s)",
5327 fstype, newc->u.name);
5631 genfs->fstype, newc->u.name);
53285632 goto fail;
53295633 }
53305634 len = strlen(newc->u.name);
53385642 p->next = newc;
53395643 else
53405644 genfs->head = newc;
5645 free(type);
53415646 return 0;
53425647 fail:
53435648 if (type)
4242 int define_netif_context(void);
4343 int define_permissive(void);
4444 int define_polcap(void);
45 int define_ibpkey_context(unsigned int low, unsigned int high);
46 int define_ibendport_context(unsigned int port);
4547 int define_port_context(unsigned int low, unsigned int high);
4648 int define_pirq_context(unsigned int pirq);
4749 int define_iomem_context(uint64_t low, uint64_t high);
6466 int define_type(int alias);
6567 int define_user(void);
6668 int define_validatetrans(constraint_expr_t *expr);
69 int expand_attrib(void);
6770 int insert_id(const char *id,int push);
6871 int insert_separator(int push);
6972 role_datum_t *define_role_dom(role_datum_t *r);
2020 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
2121 * Copyright (C) 2003 - 2008 Tresys Technology, LLC
2222 * Copyright (C) 2007 Red Hat Inc.
23 * Copyright (C) 2017 Mellanox Technologies Inc.
2324 * This program is free software; you can redistribute it and/or modify
2425 * it under the terms of the GNU General Public License as published by
2526 * the Free Software Foundation, version 2.
102103 %token TYPES
103104 %token ALIAS
104105 %token ATTRIBUTE
106 %token EXPANDATTRIBUTE
105107 %token BOOL
106108 %token TUNABLE
107109 %token IF
133135 %token TARGET
134136 %token SAMEUSER
135137 %token FSCON PORTCON NETIFCON NODECON
138 %token IBPKEYCON
139 %token IBENDPORTCON
136140 %token PIRQCON IOMEMCON IOPORTCON PCIDEVICECON DEVICETREECON
137141 %token FSUSEXATTR FSUSETASK FSUSETRANS
138142 %token GENFSCON
168172 opt_default_rules opt_mls te_rbac users opt_constraints
169173 { if (pass == 1) { if (policydb_index_bools(policydbp)) return -1;}
170174 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
172176 ;
173177 classes : class_def
174178 | classes class_def
313317 | role_attr_def
314318 ;
315319 te_decl : attribute_def
320 | expandattribute_def
316321 | type_def
317322 | typealias_def
318323 | typeattribute_def
326331 ;
327332 attribute_def : ATTRIBUTE identifier ';'
328333 { if (define_attrib()) return -1;}
334 ;
335 expandattribute_def : EXPANDATTRIBUTE names bool_val ';'
336 { if (expand_attrib()) return -1;}
329337 ;
330338 type_def : TYPE identifier alias_def opt_attr_list ';'
331339 {if (define_type(1)) return -1;}
694702 fs_context_def : FSCON number number security_context_def security_context_def
695703 {if (define_fs_context($2,$3)) return -1;}
696704 ;
697 net_contexts : opt_port_contexts opt_netif_contexts opt_node_contexts
705 net_contexts : opt_port_contexts opt_netif_contexts opt_node_contexts
698706 ;
699707 opt_port_contexts : port_contexts
700708 |
707715 | PORTCON identifier number '-' number security_context_def
708716 {if (define_port_context($3,$5)) return -1;}
709717 ;
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 ;
710738 opt_netif_contexts : netif_contexts
711739 |
712740 ;
1111 * Added support for binary policy modules
1212 *
1313 * Copyright (C) 2003-5 Tresys Technology, LLC
14 * Copyright (C) 2017 Mellanox Technologies Inc.
1415 * This program is free software; you can redistribute it and/or modify
1516 * it under the terms of the GNU General Public License as published by
1617 * the Free Software Foundation, version 2.
105106 alias { return(ALIAS); }
106107 ATTRIBUTE |
107108 attribute { return(ATTRIBUTE); }
109 EXPANDATTRIBUTE |
110 expandattribute { return(EXPANDATTRIBUTE); }
108111 TYPE_TRANSITION |
109112 type_transition { return(TYPE_TRANSITION); }
110113 TYPE_MEMBER |
180183 incomp { return(INCOMP);}
181184 fscon |
182185 FSCON { return(FSCON);}
186 ibpkeycon |
187 IBPKEYCON { return(IBPKEYCON);}
188 ibendportcon |
189 IBENDPORTCON { return(IBENDPORTCON);}
183190 portcon |
184191 PORTCON { return(PORTCON);}
185192 netifcon |
112112
113113 p = q->head;
114114 while (p != NULL) {
115 free(p->element);
115116 temp = p;
116117 p = p->next;
117118 free(temp);
44 BINDIR=$(PREFIX)/bin
55 LIBDIR ?= $(PREFIX)/lib
66 INCLUDEDIR ?= $(PREFIX)/include
7 LIBSEPOLA ?= $(LIBDIR)/libsepol.a
78
89 CFLAGS ?= -g -Wall -W -Werror -O2 -pipe
9 override CFLAGS += -I$(INCLUDEDIR)
10
11 LDLIBS=-lfl $(LIBDIR)/libsepol.a -L$(LIBDIR)
1210
1311 all: dispol dismod
1412
15 dispol: dispol.o
13 dispol: dispol.o $(LIBSEPOLA)
1614
17 dismod: dismod.o
15 dismod: dismod.o $(LIBSEPOLA)
1816
1917 clean:
2018 -rm -f dispol dismod *.o
6464 "levels ", "cats ", "attribs"
6565 };
6666
67 void usage(const char *progname)
67 static __attribute__((__noreturn__)) void usage(const char *progname)
6868 {
6969 printf("usage: %s binary_pol_file\n\n", progname);
7070 exit(1);
242242 }
243243 } else if (avrule->specified & AVRULE_NEVERALLOW) {
244244 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 ");
245252 } else {
246253 fprintf(fp, " ERROR: no valid rule type specified\n");
247254 return -1;
281288 policy, fp);
282289 } else if (avrule->specified & AVRULE_TYPE) {
283290 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));
284309 }
285310
286311 fprintf(fp, ";\n");
3535
3636 static policydb_t policydb;
3737
38 void usage(const char *progname)
38 static __attribute__((__noreturn__)) void usage(const char *progname)
3939 {
4040 printf("usage: %s binary_pol_file\n\n", progname);
4141 exit(1);
329329 }
330330 }
331331
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
332356 static void display_filename_trans(policydb_t *p, FILE *fp)
333357 {
334 filename_trans_t *ft;
358 struct filenametr_display_args args;
335359
336360 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);
344364 }
345365
346366 int menu(void)