• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Authors: Karl MacMillan <kmacmillan@tresys.com>
2  *          Joshua Brindle <jbrindle@tresys.com>
3  *          Jason Tang <jtang@tresys.com>
4  *
5  * Copyright (C) 2004-2005 Tresys Technology, LLC
6  *      This program is free software; you can redistribute it and/or
7  *      modify it under the terms of the GNU General Public License as
8  *      published by the Free Software Foundation, version 2.
9  */
10 
11 #include <fcntl.h>
12 #include <getopt.h>
13 #include <signal.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <errno.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <sys/mman.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <libgen.h>
23 #include <limits.h>
24 
25 #include <sepol/cil/cil.h>
26 #include <semanage/modules.h>
27 
28 enum client_modes {
29 	NO_MODE, INSTALL_M, REMOVE_M, EXTRACT_M, CIL_M, HLL_M,
30 	LIST_M, RELOAD, PRIORITY_M, ENABLE_M, DISABLE_M
31 };
32 /* list of modes in which one ought to commit afterwards */
33 static const int do_commit[] = {
34 	0, 1, 1, 0, 0, 0,
35 	0, 0, 0, 1, 1,
36 };
37 
38 struct command {
39 	enum client_modes mode;
40 	char *arg;
41 };
42 static struct command *commands = NULL;
43 static int num_commands = 0;
44 
45 /* options given on command line */
46 static int verbose;
47 static int reload;
48 static int no_reload;
49 static int build;
50 static int disable_dontaudit;
51 static int preserve_tunables;
52 static int ignore_module_cache;
53 static uint16_t priority;
54 static int priority_set = 0;
55 
56 static semanage_handle_t *sh = NULL;
57 static char *store;
58 static char *store_root;
59 int extract_cil = 0;
60 
61 extern char *optarg;
62 extern int optind;
63 
cleanup(void)64 static void cleanup(void)
65 {
66 	while (--num_commands >= 0) {
67 		free(commands[num_commands].arg);
68 	}
69 	free(commands);
70 }
71 
72 /* Signal handlers. */
handle_signal(int sig_num)73 static void handle_signal(int sig_num)
74 {
75 	if (sig_num == SIGINT || sig_num == SIGQUIT || sig_num == SIGTERM) {
76 		/* catch these signals, and then drop them */
77 	}
78 }
79 
set_store(char * storename)80 static void set_store(char *storename)
81 {
82 	/* For now this only supports a store name, later on this
83 	 * should support an address for a remote connection */
84 
85 	if ((store = strdup(storename)) == NULL) {
86 		fprintf(stderr, "Out of memory!\n");
87 		goto bad;
88 	}
89 
90 	return;
91 
92       bad:
93 	cleanup();
94 	exit(1);
95 }
96 
set_store_root(char * path)97 static void set_store_root(char *path)
98 {
99 	if ((store_root = strdup(path)) == NULL) {
100 		fprintf(stderr, "Out of memory!\n");
101 		goto bad;
102 	}
103 
104 	return;
105 
106       bad:
107 	cleanup();
108 	exit(1);
109 }
110 
111 /* Establish signal handlers for the process. */
create_signal_handlers(void)112 static void create_signal_handlers(void)
113 {
114 	if (signal(SIGINT, handle_signal) == SIG_ERR ||
115 	    signal(SIGQUIT, handle_signal) == SIG_ERR ||
116 	    signal(SIGTERM, handle_signal) == SIG_ERR) {
117 		fprintf(stderr, "Could not set up signal handler.\n");
118 		exit(255);
119 	}
120 }
121 
usage(char * progname)122 static void usage(char *progname)
123 {
124 	printf("usage:  %s [option]... MODE...\n", progname);
125 	printf("Manage SELinux policy modules.\n");
126 	printf("MODES:\n");
127 	printf("  -R, --reload		    reload policy\n");
128 	printf("  -B, --build		    build and reload policy\n");
129 	printf("  -D,--disable_dontaudit    Remove dontaudits from policy\n");
130 	printf("  -i,--install=MODULE_PKG   install a new module\n");
131 	printf("  -r,--remove=MODULE_NAME   remove existing module at desired priority\n");
132 	printf("  -l[KIND],--list-modules[=KIND]  display list of installed modules\n");
133 	printf("     KIND:  standard  list highest priority, enabled modules\n");
134 	printf("            full      list all modules\n");
135 	printf("  -X,--priority=PRIORITY    set priority for following operations (1-999)\n");
136 	printf("  -e,--enable=MODULE_NAME   enable module\n");
137 	printf("  -d,--disable=MODULE_NAME  disable module\n");
138 	printf("  -E,--extract=MODULE_NAME  extract module\n");
139 	printf("Options:\n");
140 	printf("  -s,--store	   name of the store to operate on\n");
141 	printf("  -N,-n,--noreload do not reload policy after commit\n");
142 	printf("  -h,--help        print this message and quit\n");
143 	printf("  -v,--verbose     be verbose\n");
144 	printf("  -P,--preserve_tunables	Preserve tunables in policy\n");
145 	printf("  -C,--ignore-module-cache	Rebuild CIL modules compiled from HLL files\n");
146 	printf("  -p,--path        use an alternate path for the policy root\n");
147 	printf("  -S,--store-path  use an alternate path for the policy store root\n");
148 	printf("  -c, --cil extract module as cil. This only affects module extraction.\n");
149 	printf("  -H, --hll extract module as hll. This only affects module extraction.\n");
150 }
151 
152 /* Sets the global mode variable to new_mode, but only if no other
153  * mode has been given. */
set_mode(enum client_modes new_mode,char * arg)154 static void set_mode(enum client_modes new_mode, char *arg)
155 {
156 	struct command *c;
157 	char *s;
158 	if ((c = realloc(commands, sizeof(*c) * (num_commands + 1))) == NULL) {
159 		fprintf(stderr, "Out of memory!\n");
160 		cleanup();
161 		exit(1);
162 	}
163 	commands = c;
164 	commands[num_commands].mode = new_mode;
165 	commands[num_commands].arg = NULL;
166 	num_commands++;
167 	if (arg != NULL) {
168 		if ((s = strdup(arg)) == NULL) {
169 			fprintf(stderr, "Out of memory!\n");
170 			cleanup();
171 			exit(1);
172 		}
173 		commands[num_commands - 1].arg = s;
174 	}
175 }
176 
177 /* Parse command line and set global options. */
parse_command_line(int argc,char ** argv)178 static void parse_command_line(int argc, char **argv)
179 {
180 	static struct option opts[] = {
181 		{"store", required_argument, NULL, 's'},
182 		{"base", required_argument, NULL, 'b'},
183 		{"help", 0, NULL, 'h'},
184 		{"install", required_argument, NULL, 'i'},
185 		{"extract", required_argument, NULL, 'E'},
186 		{"cil", 0, NULL, 'c'},
187 		{"hll", 0, NULL, 'H'},
188 		{"list-modules", optional_argument, NULL, 'l'},
189 		{"verbose", 0, NULL, 'v'},
190 		{"remove", required_argument, NULL, 'r'},
191 		{"upgrade", required_argument, NULL, 'u'},
192 		{"reload", 0, NULL, 'R'},
193 		{"noreload", 0, NULL, 'n'},
194 		{"build", 0, NULL, 'B'},
195 		{"disable_dontaudit", 0, NULL, 'D'},
196 		{"preserve_tunables", 0, NULL, 'P'},
197 		{"ignore-module-cache", 0, NULL, 'C'},
198 		{"priority", required_argument, NULL, 'X'},
199 		{"enable", required_argument, NULL, 'e'},
200 		{"disable", required_argument, NULL, 'd'},
201 		{"path", required_argument, NULL, 'p'},
202 		{"store-path", required_argument, NULL, 'S'},
203 		{NULL, 0, NULL, 0}
204 	};
205 	int extract_selected = 0;
206 	int cil_hll_set = 0;
207 	int i;
208 	verbose = 0;
209 	reload = 0;
210 	no_reload = 0;
211 	priority = 400;
212 	while ((i =
213 		getopt_long(argc, argv, "s:b:hi:l::vr:u:RnNBDCPX:e:d:p:S:E:cH", opts,
214 			    NULL)) != -1) {
215 		switch (i) {
216 		case 'b':
217 			fprintf(stderr, "The --base option is deprecated. Use --install instead.\n");
218 			set_mode(INSTALL_M, optarg);
219 			break;
220 		case 'h':
221 			usage(argv[0]);
222 			exit(0);
223 		case 'i':
224 			set_mode(INSTALL_M, optarg);
225 			break;
226 		case 'E':
227 			set_mode(EXTRACT_M, optarg);
228 			extract_selected = 1;
229 			break;
230 		case 'c':
231 			set_mode(CIL_M, NULL);
232 			cil_hll_set = 1;
233 			break;
234 		case 'H':
235 			set_mode(HLL_M, NULL);
236 			cil_hll_set = 1;
237 			break;
238 		case 'l':
239 			set_mode(LIST_M, optarg);
240 			break;
241 		case 'v':
242 			verbose++;
243 			break;
244 		case 'r':
245 			set_mode(REMOVE_M, optarg);
246 			break;
247 		case 'u':
248 			fprintf(stderr, "The --upgrade option is deprecated. Use --install instead.\n");
249 			set_mode(INSTALL_M, optarg);
250 			break;
251 		case 's':
252 			set_store(optarg);
253 			break;
254 		case 'p':
255 			semanage_set_root(optarg);
256 			break;
257 		case 'S':
258 			set_store_root(optarg);
259 			break;
260 		case 'R':
261 			reload = 1;
262 			break;
263 		case 'n':
264 			no_reload = 1;
265 			break;
266 		case 'N':
267 			no_reload = 1;
268 			break;
269 		case 'B':
270 			build = 1;
271 			break;
272 		case 'D':
273 			disable_dontaudit = 1;
274 			break;
275 		case 'P':
276 			preserve_tunables = 1;
277 			break;
278 		case 'C':
279 			ignore_module_cache = 1;
280 			break;
281 		case 'X':
282 			set_mode(PRIORITY_M, optarg);
283 			break;
284 		case 'e':
285 			set_mode(ENABLE_M, optarg);
286 			break;
287 		case 'd':
288 			set_mode(DISABLE_M, optarg);
289 			break;
290 		case '?':
291 		default:{
292 				usage(argv[0]);
293 				exit(1);
294 			}
295 		}
296 	}
297 	if ((build || reload) && num_commands) {
298 		fprintf(stderr,
299 			"build or reload should not be used with other commands\n");
300 		usage(argv[0]);
301 		exit(1);
302 	}
303 	if (num_commands == 0 && reload == 0 && build == 0) {
304 		fprintf(stderr, "At least one mode must be specified.\n");
305 		usage(argv[0]);
306 		exit(1);
307 	}
308 	if (extract_selected == 0 && cil_hll_set == 1) {
309 		fprintf(stderr, "--cil and --hll require a module to export with the --extract option.\n");
310 		usage(argv[0]);
311 		exit(1);
312 	}
313 
314 	if (optind < argc) {
315 		int mode = commands ? (int) commands[num_commands - 1].mode : -1;
316 		/* if -i/u/r/E was the last command treat any remaining
317 		 * arguments as args. Will allow 'semodule -i *.pp' to
318 		 * work as expected.
319 		 */
320 
321 		switch (mode) {
322 			case INSTALL_M:
323 			case REMOVE_M:
324 			case EXTRACT_M:
325 			case ENABLE_M:
326 			case DISABLE_M:
327 				while (optind < argc)
328 					set_mode(mode, argv[optind++]);
329 				break;
330 			default:
331 				fprintf(stderr, "unknown additional arguments:\n");
332 				while (optind < argc)
333 					fprintf(stderr, " %s", argv[optind++]);
334 				fprintf(stderr, "\n\n");
335 				usage(argv[0]);
336 				exit(1);
337 		}
338 	}
339 }
340 
main(int argc,char * argv[])341 int main(int argc, char *argv[])
342 {
343 	int i, commit = 0;
344 	int result;
345 	int status = EXIT_FAILURE;
346 	const char *genhomedirconargv[] = { "genhomedircon", "-B", "-n" };
347 	create_signal_handlers();
348 	if (strcmp(basename(argv[0]), "genhomedircon") == 0) {
349 		argc = 3;
350 		argv = (char **)genhomedirconargv;
351 	}
352 	parse_command_line(argc, argv);
353 
354 	cil_set_log_level(CIL_ERR + verbose);
355 
356 	if (build)
357 		commit = 1;
358 
359 	sh = semanage_handle_create();
360 	if (!sh) {
361 		fprintf(stderr, "%s:  Could not create semanage handle\n",
362 			argv[0]);
363 		goto cleanup_nohandle;
364 	}
365 
366 	if (store) {
367 		/* Set the store we want to connect to, before connecting.
368 		 * this will always set a direct connection now, an additional
369 		 * option will need to be used later to specify a policy server
370 		 * location */
371 		semanage_select_store(sh, store, SEMANAGE_CON_DIRECT);
372 	}
373 
374 	if (store_root) {
375 		semanage_set_store_root(sh, store_root);
376 	}
377 
378 	/* create store if necessary, for bootstrapping */
379 	semanage_set_create_store(sh, 1);
380 
381 	if ((result = semanage_connect(sh)) < 0) {
382 		fprintf(stderr, "%s:  Could not connect to policy handler\n",
383 			argv[0]);
384 		goto cleanup;
385 	}
386 
387 	if (reload) {
388 		if ((result = semanage_reload_policy(sh)) < 0) {
389 			fprintf(stderr, "%s:  Could not reload policy\n",
390 				argv[0]);
391 			goto cleanup;
392 		}
393 	}
394 
395 	if (build) {
396 		if ((result = semanage_begin_transaction(sh)) < 0) {
397 			fprintf(stderr, "%s:  Could not begin transaction:  %s\n",
398 				argv[0], errno ? strerror(errno) : "");
399 			goto cleanup;
400 		}
401 	}
402 
403 	if ((result = semanage_set_default_priority(sh, priority)) != 0) {
404 		fprintf(stderr,
405 			"%s: Invalid priority %d (needs to be between 1 and 999)\n",
406 			argv[0],
407 			priority);
408 		goto cleanup;
409 	}
410 
411 	for (i = 0; i < num_commands; i++) {
412 		enum client_modes mode = commands[i].mode;
413 		char *mode_arg = commands[i].arg;
414 
415 		switch (mode) {
416 		case INSTALL_M:{
417 				if (verbose) {
418 					printf
419 					    ("Attempting to install module '%s':\n",
420 					     mode_arg);
421 				}
422 				result =
423 				    semanage_module_install_file(sh, mode_arg);
424 				break;
425 			}
426 		case EXTRACT_M:{
427 				semanage_module_info_t *extract_info = NULL;
428 				semanage_module_key_t *modkey = NULL;
429 				uint16_t curr_priority;
430 				void *data = NULL;
431 				size_t data_len = 0;
432 				char output_path[PATH_MAX];
433 				const char *output_name = NULL;
434 				const char *lang_ext = NULL;
435 				int rlen;
436 				FILE *output_fd = NULL;
437 
438 				result = semanage_module_key_create(sh, &modkey);
439 				if (result != 0) {
440 					goto cleanup_extract;
441 				}
442 
443 				result = semanage_module_key_set_name(sh, modkey, mode_arg);
444 				if (result != 0) {
445 					goto cleanup_extract;
446 				}
447 
448 				if (priority_set == 0) {
449 					result = semanage_module_get_module_info(sh, modkey, &extract_info);
450 					if (result != 0) {
451 						goto cleanup_extract;
452 					}
453 
454 					semanage_module_info_get_priority(sh, extract_info, &curr_priority);
455 					printf("Module '%s' does not exist at the default priority '%d'. "
456 							"Extracting at highest existing priority '%d'.\n", mode_arg, priority, curr_priority);
457 					priority = curr_priority;
458 				}
459 
460 				result  = semanage_module_key_set_priority(sh, modkey, priority);
461 				if (result != 0) {
462 					goto cleanup_extract;
463 				}
464 
465 				if (verbose) {
466 					printf
467 						("Attempting to extract module '%s':\n",
468 							mode_arg);
469 				}
470 				result = semanage_module_extract(sh, modkey, extract_cil, &data, &data_len, &extract_info);
471 				if (result != 0) {
472 					goto cleanup_extract;
473 				}
474 
475 				if (extract_cil) {
476 					lang_ext = "cil";
477 				} else {
478 					result = semanage_module_info_get_lang_ext(sh, extract_info, &lang_ext);
479 					if (result != 0) {
480 						goto cleanup_extract;
481 					}
482 				}
483 
484 				result = semanage_module_info_get_name(sh, extract_info, &output_name);
485 				if (result != 0) {
486 					goto cleanup_extract;
487 				}
488 
489 				rlen = snprintf(output_path, PATH_MAX, "%s.%s", output_name, lang_ext);
490 				if (rlen < 0 || rlen >= PATH_MAX) {
491 					fprintf(stderr, "%s: Failed to generate output path.\n", argv[0]);
492 					result = -1;
493 					goto cleanup_extract;
494 				}
495 
496 				if (access(output_path, F_OK) == 0) {
497 					fprintf(stderr, "%s: %s is already extracted with extension %s.\n", argv[0], mode_arg, lang_ext);
498 					result = -1;
499 					goto cleanup_extract;
500 				}
501 
502 				output_fd = fopen(output_path, "w");
503 				if (output_fd == NULL) {
504 					fprintf(stderr, "%s: Unable to open %s\n", argv[0], output_path);
505 					result = -1;
506 					goto cleanup_extract;
507 				}
508 
509 				if (fwrite(data, 1, data_len, output_fd) < data_len) {
510 					fprintf(stderr, "%s: Unable to write to %s\n", argv[0], output_path);
511 					result = -1;
512 					goto cleanup_extract;
513 				}
514 cleanup_extract:
515 				if (output_fd != NULL) {
516 					fclose(output_fd);
517 				}
518 				if (data_len > 0) {
519 					munmap(data, data_len);
520 				}
521 				semanage_module_info_destroy(sh, extract_info);
522 				free(extract_info);
523 				semanage_module_key_destroy(sh, modkey);
524 				free(modkey);
525 				break;
526 			}
527 		case CIL_M:
528 				extract_cil = 1;
529 				break;
530 		case HLL_M:
531 				extract_cil = 0;
532 				break;
533 		case REMOVE_M:{
534 				if (verbose) {
535 					printf
536 					    ("Attempting to remove module '%s':\n",
537 					     mode_arg);
538 				}
539 				result = semanage_module_remove(sh, mode_arg);
540 				if ( result == -2 ) {
541 					continue;
542 				}
543 				break;
544 			}
545 		case LIST_M:{
546 				semanage_module_info_t *modinfos = NULL;
547 				int modinfos_len = 0;
548 				semanage_module_info_t *m = NULL;
549 				int j = 0;
550 
551 				if (verbose) {
552 					printf
553 					    ("Attempting to list active modules:\n");
554 				}
555 
556 				if (mode_arg == NULL || strcmp(mode_arg, "standard") == 0) {
557 					result = semanage_module_list(sh,
558 								      &modinfos,
559 								      &modinfos_len);
560 					if (result < 0) goto cleanup_list;
561 
562 					if (modinfos_len == 0) {
563 						printf("No modules.\n");
564 					}
565 
566 					const char *name = NULL;
567 
568 					for (j = 0; j < modinfos_len; j++) {
569 						m = semanage_module_list_nth(modinfos, j);
570 
571 						result = semanage_module_info_get_name(sh, m, &name);
572 						if (result != 0) goto cleanup_list;
573 
574 						printf("%s\n", name);
575 					}
576 				}
577 				else if (strcmp(mode_arg, "full") == 0) {
578 					/* get the modules */
579 					result = semanage_module_list_all(sh,
580 									  &modinfos,
581 									  &modinfos_len);
582 					if (result != 0) goto cleanup_list;
583 
584 					if (modinfos_len == 0) {
585 						printf("No modules.\n");
586 					}
587 
588 					/* calculate column widths */
589 					size_t column[4] = { 0, 0, 0, 0 };
590 
591 					/* fixed width columns */
592 					column[0] = sizeof("000") - 1;
593 					column[3] = sizeof("disabled") - 1;
594 
595 					/* variable width columns */
596 					const char *tmp = NULL;
597 					size_t size;
598 					for (j = 0; j < modinfos_len; j++) {
599 						m = semanage_module_list_nth(modinfos, j);
600 
601 						result = semanage_module_info_get_name(sh, m, &tmp);
602 						if (result != 0) goto cleanup_list;
603 
604 						size = strlen(tmp);
605 						if (size > column[1]) column[1] = size;
606 
607 						result = semanage_module_info_get_lang_ext(sh, m, &tmp);
608 						if (result != 0) goto cleanup_list;
609 
610 						size = strlen(tmp);
611 						if (size > column[3]) column[3] = size;
612 					}
613 
614 					/* print out each module */
615 					for (j = 0; j < modinfos_len; j++) {
616 						uint16_t pri = 0;
617 						const char *name = NULL;
618 						int enabled = 0;
619 						const char *lang_ext = NULL;
620 
621 						m = semanage_module_list_nth(modinfos, j);
622 
623 						result = semanage_module_info_get_priority(sh, m, &pri);
624 						if (result != 0) goto cleanup_list;
625 
626 						result = semanage_module_info_get_name(sh, m, &name);
627 						if (result != 0) goto cleanup_list;
628 
629 						result = semanage_module_info_get_enabled(sh, m, &enabled);
630 						if (result != 0) goto cleanup_list;
631 
632 						result = semanage_module_info_get_lang_ext(sh, m, &lang_ext);
633 						if (result != 0) goto cleanup_list;
634 
635 						printf("%0*u %-*s %-*s %-*s\n",
636 							(int)column[0], pri,
637 							(int)column[1], name,
638 							(int)column[2], lang_ext,
639 							(int)column[3], enabled ? "" : "disabled");
640 					}
641 				}
642 				else {
643 					result = -1;
644 				}
645 
646 cleanup_list:
647 				for (j = 0; j < modinfos_len; j++) {
648 					m = semanage_module_list_nth(modinfos, j);
649 					semanage_module_info_destroy(sh, m);
650 				}
651 
652 				free(modinfos);
653 
654 				break;
655 			}
656 		case PRIORITY_M:{
657 				char *endptr = NULL;
658 				priority = (uint16_t)strtoul(mode_arg, &endptr, 10);
659 				priority_set = 1;
660 
661 				if ((result = semanage_set_default_priority(sh, priority)) != 0) {
662 					fprintf(stderr,
663 						"%s: Invalid priority %d (needs to be between 1 and 999)\n",
664 						argv[0],
665 						priority);
666 					goto cleanup;
667 				}
668 
669 				break;
670 			}
671 		case ENABLE_M:{
672 				if (verbose) {
673 					printf
674 					    ("Attempting to enable module '%s':\n",
675 					     mode_arg);
676 				}
677 
678 				semanage_module_key_t *modkey = NULL;
679 
680 				result = semanage_module_key_create(sh, &modkey);
681 				if (result != 0) goto cleanup_enable;
682 
683 				result = semanage_module_key_set_name(sh, modkey, mode_arg);
684 				if (result != 0) goto cleanup_enable;
685 
686 				result = semanage_module_set_enabled(sh, modkey, 1);
687 				if (result != 0) goto cleanup_enable;
688 
689 cleanup_enable:
690 				semanage_module_key_destroy(sh, modkey);
691 				free(modkey);
692 
693 				break;
694 			}
695 		case DISABLE_M:{
696 				if (verbose) {
697 					printf
698 					    ("Attempting to disable module '%s':\n",
699 					     mode_arg);
700 				}
701 
702 				semanage_module_key_t *modkey = NULL;
703 
704 				result = semanage_module_key_create(sh, &modkey);
705 				if (result != 0) goto cleanup_disable;
706 
707 				result = semanage_module_key_set_name(sh, modkey, mode_arg);
708 				if (result != 0) goto cleanup_disable;
709 
710 				result = semanage_module_set_enabled(sh, modkey, 0);
711 				if (result != 0) goto cleanup_disable;
712 
713 cleanup_disable:
714 				semanage_module_key_destroy(sh, modkey);
715 				free(modkey);
716 
717 				break;
718 			}
719 		default:{
720 				fprintf(stderr,
721 					"%s:  Unknown mode specified.\n",
722 					argv[0]);
723 				usage(argv[0]);
724 				goto cleanup;
725 			}
726 		}
727 		commit += do_commit[mode];
728 		if (result < 0) {
729 			fprintf(stderr, "%s:  Failed on %s!\n", argv[0],
730 				mode_arg ? : "list");
731 			goto cleanup;
732 		} else if (verbose) {
733 			printf("Ok: return value of %d.\n", result);
734 		}
735 	}
736 
737 	if (commit) {
738 		if (verbose)
739 			printf("Committing changes:\n");
740 		if (no_reload)
741 			semanage_set_reload(sh, 0);
742 		if (build)
743 			semanage_set_rebuild(sh, 1);
744 		if (disable_dontaudit)
745 			semanage_set_disable_dontaudit(sh, 1);
746 		else if (build)
747 			semanage_set_disable_dontaudit(sh, 0);
748 		if (preserve_tunables)
749 			semanage_set_preserve_tunables(sh, 1);
750 		if (ignore_module_cache)
751 			semanage_set_ignore_module_cache(sh, 1);
752 
753 		result = semanage_commit(sh);
754 	}
755 
756 	if (result < 0) {
757 		fprintf(stderr, "%s:  Failed!\n", argv[0]);
758 		goto cleanup;
759 	} else if (commit && verbose) {
760 		printf("Ok: transaction number %d.\n", result);
761 	}
762 
763 	if (semanage_disconnect(sh) < 0) {
764 		fprintf(stderr, "%s:  Error disconnecting\n", argv[0]);
765 		goto cleanup;
766 	}
767 	status = EXIT_SUCCESS;
768 
769       cleanup:
770 	if (semanage_is_connected(sh)) {
771 		if (semanage_disconnect(sh) < 0) {
772 			fprintf(stderr, "%s:  Error disconnecting\n", argv[0]);
773 		}
774 	}
775 	semanage_handle_destroy(sh);
776 
777       cleanup_nohandle:
778 	cleanup();
779 	exit(status);
780 }
781