1
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <assert.h>
5
6 #include <string.h>
7
8 #define xstreq(x, y) !strcmp(x, y)
9
10 #include <err.h>
11
12 #include <getopt.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15 #include <selinux/selinux.h>
16 #include <selinux/context.h>
17
18 #define TRUE 1
19 #define FALSE 0
20
21 #define SECON_CONF_PROG_NAME "secon" /* default program name */
22 #define SECON_OPTS_SM "hVurtscmPRCfLp" /* small options available, print */
23 #define SECON_OPTS_GO "hVurtlscmPRCf:L:p:" /* small options available, getopt */
24
25 #define OPTS_FROM_ARG 0
26 #define OPTS_FROM_FILE 1
27 #define OPTS_FROM_LINK 2
28 #define OPTS_FROM_STDIN 3
29 #define OPTS_FROM_CUR 4
30 #define OPTS_FROM_CUREXE 5
31 #define OPTS_FROM_CURFS 6
32 #define OPTS_FROM_CURKEY 7
33 #define OPTS_FROM_PROC 8
34 #define OPTS_FROM_PROCEXE 9
35 #define OPTS_FROM_PROCFS 10
36 #define OPTS_FROM_PROCKEY 11
37
38 struct context_color_t {
39 unsigned int valid;
40
41 char *user_fg;
42 char *user_bg;
43 char *role_fg;
44 char *role_bg;
45 char *type_fg;
46 char *type_bg;
47 char *range_fg;
48 char *range_bg;
49 };
50
51 struct {
52 unsigned int disp_user:1;
53 unsigned int disp_role:1;
54 unsigned int disp_type:1;
55 unsigned int disp_sen:1;
56 unsigned int disp_clr:1;
57 unsigned int disp_mlsr:1;
58
59 unsigned int disp_raw:1;
60 unsigned int disp_color:1;
61
62 unsigned int disp_prompt:1; /* no return, use : to sep */
63
64 unsigned int from_type:8; /* 16 bits, uses 4 bits */
65
66 union {
67 pid_t pid;
68 const char *file;
69 const char *link;
70 const char *arg;
71 } f;
72 } opts[1] = { {
73 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
74 FALSE, FALSE, FALSE, OPTS_FROM_ARG, {0} } };
75
usage(const char * name,int exit_code)76 static __attribute__((__noreturn__)) void usage(const char *name, int exit_code)
77 {
78 fprintf(exit_code ? stderr : stdout,
79 " Usage: %s [-%s] [ context | - ]\n"
80 " --help -h Show this message.\n"
81 " --version -V Show the version.\n"
82 " --prompt -P Output in a format good for a prompt.\n"
83 " --user -u Show the user of the context.\n"
84 " --role -r Show the role of the context.\n"
85 " --type -t Show the type of the context.\n"
86 " --sensitivity -s Show the sensitivity level of the context.\n"
87 " --clearance -c Show the clearance level of the context.\n"
88 " --mls-range -m Show the sensitivity to clearance range of \n"
89 " the context.\n"
90 " --raw -R Show the context in \"raw\" format.\n"
91 " --color -C Output using ANSI color codes (requires -P).\n"
92 " --current, --self Get the context for the current process.\n"
93 " --current-exec, --self-exec Get the exec context for the current process.\n"
94 " --current-fs, --self-fs Get the fs context for the current process.\n"
95 " --current-key, --self-key Get the key context for the current process.\n"
96 " --parent Get the context for the parent process.\n"
97 " --parent-exec Get the exec context for the parent process.\n"
98 " --parent-fs Get the fs context for the parent process.\n"
99 " --parent-key Get the key context for the parent process.\n"
100 " --pid -p <arg> Use the context from the specified pid.\n"
101 " --pid-exec <arg> Use the exec context from the specified pid.\n"
102 " --pid-fs <arg> Use the fs context from the specified pid.\n"
103 " --pid-key <arg> Use the key context from the specified pid.\n"
104 " --file -f <arg> Use the context from the specified file.\n"
105 " --link -L <arg> Use the context from the specified link.\n",
106 name, SECON_OPTS_SM);
107
108 exit(exit_code);
109 }
110
opt_program_name(const char * argv0,const char * def)111 static const char *opt_program_name(const char *argv0, const char *def)
112 {
113 if (argv0) {
114 if ((def = strrchr(argv0, '/')))
115 ++def;
116 else
117 def = argv0;
118
119 /* hack for libtool */
120 if ((strlen(def) > strlen("lt-"))
121 && !memcmp("lt-", def, strlen("lt-")))
122 def += 3;
123 }
124
125 return (def);
126 }
127
disp_num(void)128 static int disp_num(void)
129 {
130 int num = 0;
131
132 num += opts->disp_user;
133 num += opts->disp_role;
134 num += opts->disp_type;
135 num += opts->disp_sen;
136 num += opts->disp_clr;
137 num += opts->disp_mlsr;
138
139 return (num);
140 }
141
disp_none(void)142 static int disp_none(void)
143 {
144 return (!disp_num());
145 }
146
disp_multi(void)147 static int disp_multi(void)
148 {
149 return (disp_num() > 1);
150 }
151
cmd_line(int argc,char * argv[])152 static void cmd_line(int argc, char *argv[])
153 {
154 int optchar = 0;
155 const char *program_name = NULL;
156 struct option long_options[] = {
157 {"help", no_argument, NULL, 'h'},
158 {"version", no_argument, NULL, 'V'},
159
160 {"prompt", no_argument, NULL, 'P'},
161
162 {"user", no_argument, NULL, 'u'},
163 {"role", no_argument, NULL, 'r'},
164 {"type", no_argument, NULL, 't'},
165 {"level", no_argument, NULL, 'l'}, /* compat. */
166 {"sensitivity", no_argument, NULL, 's'},
167 {"range", no_argument, NULL, 'm'},
168 {"clearance", no_argument, NULL, 'c'},
169 {"mls-range", no_argument, NULL, 'm'},
170
171 {"raw", no_argument, NULL, 'R'},
172 {"color", no_argument, NULL, 'C'},
173
174 {"current", no_argument, NULL, 1},
175 {"self", no_argument, NULL, 1},
176 {"current-exec", no_argument, NULL, 2},
177 {"self-exec", no_argument, NULL, 2},
178 {"current-fs", no_argument, NULL, 3},
179 {"self-fs", no_argument, NULL, 3},
180 {"current-key", no_argument, NULL, 4},
181 {"self-key", no_argument, NULL, 4},
182
183 {"parent", no_argument, NULL, 5},
184 {"parent-exec", no_argument, NULL, 6},
185 {"parent-fs", no_argument, NULL, 7},
186 {"parent-key", no_argument, NULL, 8},
187
188 {"file", required_argument, NULL, 'f'},
189 {"link", required_argument, NULL, 'L'},
190 {"pid", required_argument, NULL, 'p'},
191 {"pid-exec", required_argument, NULL, 9},
192 {"pid-fs", required_argument, NULL, 10},
193 {"pid-key", required_argument, NULL, 11},
194
195 {NULL, 0, NULL, 0}
196 };
197 int done = FALSE;
198
199 program_name = opt_program_name(argv[0], SECON_CONF_PROG_NAME);
200
201 while ((optchar = getopt_long(argc, argv, SECON_OPTS_GO,
202 long_options, NULL)) != -1) {
203 switch (optchar) {
204 case '?':
205 usage(program_name, EXIT_FAILURE);
206 case 'h':
207 usage(program_name, EXIT_SUCCESS);
208 case 'V':
209 fprintf(stdout,
210 " %s version %s.\n", program_name, VERSION);
211 exit(EXIT_SUCCESS);
212
213 case 'u':
214 done = TRUE;
215 opts->disp_user = !opts->disp_user;
216 break;
217 case 'r':
218 done = TRUE;
219 opts->disp_role = !opts->disp_role;
220 break;
221 case 't':
222 done = TRUE;
223 opts->disp_type = !opts->disp_type;
224 break;
225 case 'l':
226 done = TRUE;
227 opts->disp_sen = !opts->disp_sen;
228 break;
229 case 's':
230 done = TRUE;
231 opts->disp_sen = !opts->disp_sen;
232 break;
233 case 'c':
234 done = TRUE;
235 opts->disp_clr = !opts->disp_clr;
236 break;
237 case 'm':
238 done = TRUE;
239 opts->disp_mlsr = !opts->disp_mlsr;
240 break;
241
242 case 'P':
243 opts->disp_prompt = !opts->disp_prompt;
244 break;
245
246 case 'R':
247 opts->disp_raw = !opts->disp_raw;
248 break;
249 case 'C':
250 opts->disp_color = !opts->disp_color;
251 break;
252 case 1:
253 opts->from_type = OPTS_FROM_CUR;
254 break;
255 case 2:
256 opts->from_type = OPTS_FROM_CUREXE;
257 break;
258 case 3:
259 opts->from_type = OPTS_FROM_CURFS;
260 break;
261 case 4:
262 opts->from_type = OPTS_FROM_CURKEY;
263 break;
264
265 case 5:
266 opts->from_type = OPTS_FROM_PROC;
267 opts->f.pid = getppid();
268 break;
269 case 6:
270 opts->from_type = OPTS_FROM_PROCEXE;
271 opts->f.pid = getppid();
272 break;
273 case 7:
274 opts->from_type = OPTS_FROM_PROCFS;
275 opts->f.pid = getppid();
276 break;
277 case 8:
278 opts->from_type = OPTS_FROM_PROCKEY;
279 opts->f.pid = getppid();
280 break;
281
282 case 'f':
283 opts->from_type = OPTS_FROM_FILE;
284 opts->f.file = optarg;
285 break;
286 case 'L':
287 opts->from_type = OPTS_FROM_LINK;
288 opts->f.link = optarg;
289 break;
290 case 'p':
291 opts->from_type = OPTS_FROM_PROC;
292 opts->f.pid = atoi(optarg);
293 break;
294 case 9:
295 opts->from_type = OPTS_FROM_PROCEXE;
296 opts->f.pid = atoi(optarg);
297 break;
298 case 10:
299 opts->from_type = OPTS_FROM_PROCFS;
300 opts->f.pid = atoi(optarg);
301 break;
302 case 11:
303 opts->from_type = OPTS_FROM_PROCKEY;
304 opts->f.pid = atoi(optarg);
305 break;
306
307 default:
308 assert(FALSE);
309 }
310 }
311
312 if (!done) { /* default, if nothing specified */
313 opts->disp_user = TRUE;
314 opts->disp_role = TRUE;
315 opts->disp_type = TRUE;
316 if (!opts->disp_prompt) { /* when displaying prompt, just output "normal" by default */
317 opts->disp_sen = TRUE;
318 opts->disp_clr = TRUE;
319 }
320 opts->disp_mlsr = TRUE;
321 }
322
323 if (disp_none())
324 err(EXIT_FAILURE, " Nothing to display");
325
326 argc -= optind;
327 argv += optind;
328
329 if (!argc && (opts->from_type == OPTS_FROM_ARG)
330 && !isatty(STDIN_FILENO))
331 opts->from_type = OPTS_FROM_STDIN;
332 if (!argc && (opts->from_type == OPTS_FROM_ARG))
333 opts->from_type = OPTS_FROM_CUR;
334
335 if (opts->from_type == OPTS_FROM_ARG) {
336 opts->f.arg = argv[0];
337
338 if (xstreq(argv[0], "-"))
339 opts->from_type = OPTS_FROM_STDIN;
340 } else if (!is_selinux_enabled())
341 errx(EXIT_FAILURE, "SELinux is not enabled");
342 }
343
my_getXcon_raw(pid_t pid,security_context_t * con,const char * val)344 static int my_getXcon_raw(pid_t pid, security_context_t * con, const char *val)
345 {
346 char buf[4096];
347 FILE *fp = NULL;
348 const char *ptr = NULL;
349
350 snprintf(buf, sizeof(buf), "%s/%ld/attr/%s", "/proc", (long int)pid,
351 val);
352
353 if (!(fp = fopen(buf, "rb")))
354 return (-1);
355
356 ptr = fgets(buf, sizeof(buf), fp);
357
358 fclose(fp);
359
360 *con = NULL;
361 if (ptr) { /* return *con = NULL, when proc file is empty */
362 char *tmp = strchr(ptr, '\n');
363
364 if (tmp)
365 *tmp = 0;
366
367 if (*ptr && !(*con = strdup(ptr)))
368 return (-1);
369 }
370
371 return (0);
372 }
373
my_getpidexeccon_raw(pid_t pid,security_context_t * con)374 static int my_getpidexeccon_raw(pid_t pid, security_context_t * con)
375 {
376 return (my_getXcon_raw(pid, con, "exec"));
377 }
my_getpidfscreatecon_raw(pid_t pid,security_context_t * con)378 static int my_getpidfscreatecon_raw(pid_t pid, security_context_t * con)
379 {
380 return (my_getXcon_raw(pid, con, "fscreate"));
381 }
my_getpidkeycreatecon_raw(pid_t pid,security_context_t * con)382 static int my_getpidkeycreatecon_raw(pid_t pid, security_context_t * con)
383 {
384 return (my_getXcon_raw(pid, con, "keycreate"));
385 }
386
get_scon(void)387 static security_context_t get_scon(void)
388 {
389 static char dummy_NIL[1] = "";
390 security_context_t con = NULL, con_tmp;
391 int ret = -1;
392
393 switch (opts->from_type) {
394 case OPTS_FROM_ARG:
395 if (!(con_tmp = strdup(opts->f.arg)))
396 err(EXIT_FAILURE,
397 " Couldn't allocate security context");
398 if (selinux_trans_to_raw_context(con_tmp, &con) < 0)
399 err(EXIT_FAILURE,
400 " Couldn't translate security context");
401 freecon(con_tmp);
402 break;
403
404 case OPTS_FROM_STDIN:
405 {
406 char buf[4096] = "";
407 char *ptr = buf;
408
409 while (!*ptr) {
410 if (!(ptr = fgets(buf, sizeof(buf), stdin)))
411 err(EXIT_FAILURE,
412 " Couldn't read security context");
413
414 ptr += strspn(ptr, " \n\t");
415 ptr[strcspn(ptr, " \n\t")] = 0;
416 }
417
418 if (!(con_tmp = strdup(ptr)))
419 err(EXIT_FAILURE,
420 " Couldn't allocate security context");
421 if (selinux_trans_to_raw_context(con_tmp, &con) < 0)
422 err(EXIT_FAILURE,
423 " Couldn't translate security context");
424 freecon(con_tmp);
425 break;
426 }
427
428 case OPTS_FROM_CUR:
429 ret = getcon_raw(&con);
430
431 if (ret == -1)
432 err(EXIT_FAILURE,
433 " Couldn't get current security context");
434 break;
435 case OPTS_FROM_CUREXE:
436 ret = getexeccon_raw(&con);
437
438 if (ret == -1)
439 err(EXIT_FAILURE,
440 " Couldn't get current exec security context");
441
442 if (!con)
443 con = strdup(dummy_NIL);
444 break;
445 case OPTS_FROM_CURFS:
446 ret = getfscreatecon_raw(&con);
447
448 if (ret == -1)
449 err(EXIT_FAILURE,
450 " Couldn't get current fs security context");
451
452 if (!con)
453 con = strdup(dummy_NIL);
454 break;
455 case OPTS_FROM_CURKEY:
456 ret = getkeycreatecon_raw(&con);
457
458 if (ret == -1)
459 err(EXIT_FAILURE,
460 " Couldn't get current key security context");
461
462 if (!con)
463 con = strdup(dummy_NIL);
464 break;
465
466 case OPTS_FROM_PROC:
467 ret = getpidcon_raw(opts->f.pid, &con);
468
469 if (ret == -1)
470 err(EXIT_FAILURE,
471 " Couldn't get security context for pid %lu",
472 (unsigned long)opts->f.pid);
473 break;
474 case OPTS_FROM_PROCEXE:
475 ret = my_getpidexeccon_raw(opts->f.pid, &con);
476
477 if (ret == -1)
478 err(EXIT_FAILURE,
479 " Couldn't get security context for pid %lu",
480 (unsigned long)opts->f.pid);
481
482 if (!con)
483 con = strdup(dummy_NIL);
484 break;
485 case OPTS_FROM_PROCFS:
486 ret = my_getpidfscreatecon_raw(opts->f.pid, &con);
487
488 if (ret == -1)
489 err(EXIT_FAILURE,
490 " Couldn't get security context for pid %lu",
491 (unsigned long)opts->f.pid);
492
493 if (!con)
494 con = strdup(dummy_NIL);
495 /* disabled -- override with normal context ...
496 {
497 opts->from_type = OPTS_FROM_PROC;
498 return (get_scon());
499 } */
500 break;
501 case OPTS_FROM_PROCKEY:
502 ret = my_getpidkeycreatecon_raw(opts->f.pid, &con);
503
504 if (ret == -1)
505 err(EXIT_FAILURE,
506 " Couldn't get security context for pid %lu",
507 (unsigned long)opts->f.pid);
508
509 if (!con)
510 con = strdup(dummy_NIL);
511 break;
512
513 case OPTS_FROM_FILE:
514 ret = getfilecon_raw(opts->f.file, &con);
515
516 if (ret == -1)
517 err(EXIT_FAILURE,
518 " Couldn't get security context for file %s",
519 opts->f.file);
520 break;
521
522 case OPTS_FROM_LINK:
523 ret = lgetfilecon_raw(opts->f.link, &con);
524
525 if (ret == -1)
526 err(EXIT_FAILURE,
527 " Couldn't get security context for symlink %s",
528 opts->f.link);
529 break;
530
531 default:
532 assert(FALSE);
533 }
534
535 return (con);
536 }
537
disp__color_to_ansi(const char * color_str)538 static unsigned int disp__color_to_ansi(const char *color_str)
539 {
540 int val = 30;
541
542 /* NOTE: ansi black is 30 for foreground colors */
543
544 /* red */
545 if (strncasecmp(&color_str[1], "7f", 2) >= 0)
546 val += 1;
547 /* green */
548 if (strncasecmp(&color_str[3], "7f", 2) >= 0)
549 val += 2;
550 /* blue */
551 if (strncasecmp(&color_str[5], "7f", 2) >= 0)
552 val += 4;
553
554 return val;
555 }
556
disp__con_color_ansi(const char * name,struct context_color_t * color)557 static char *disp__con_color_ansi(const char *name,
558 struct context_color_t *color)
559 {
560 unsigned int fg, bg;
561 char *ansi;
562 int ansi_len = strlen("\e[99;99m") + 1;
563
564 /* NOTE: ansi background codes are the same as foreground codes +10 */
565
566 if (xstreq("user", name)) {
567 fg = disp__color_to_ansi(color->user_fg);
568 bg = disp__color_to_ansi(color->user_bg) + 10;
569 } else if (xstreq("role", name)) {
570 fg = disp__color_to_ansi(color->role_fg);
571 bg = disp__color_to_ansi(color->role_bg) + 10;
572 } else if (xstreq("type", name)) {
573 fg = disp__color_to_ansi(color->type_fg);
574 bg = disp__color_to_ansi(color->type_bg) + 10;
575 } else if (xstreq("sensitivity", name) ||
576 xstreq("clearance", name) ||
577 xstreq("mls-range", name)) {
578 fg = disp__color_to_ansi(color->range_fg);
579 bg = disp__color_to_ansi(color->range_bg) + 10;
580 } else
581 err(EXIT_FAILURE, " No color information for context field");
582
583 if (!(ansi = malloc(ansi_len)))
584 err(EXIT_FAILURE, " Unable to allocate memory");
585 if (snprintf(ansi, ansi_len, "\e[%d;%dm", fg, bg) > ansi_len)
586 err(EXIT_FAILURE, " Unable to convert colors to ANSI codes");
587
588 return ansi;
589 }
590
disp__con_val(const char * name,const char * val,struct context_color_t * color)591 static void disp__con_val(const char *name, const char *val,
592 struct context_color_t *color)
593 {
594 static int done = FALSE;
595
596 assert(name);
597 assert(color);
598
599 if (!val)
600 val = ""; /* targeted has no "level" etc.,
601 any errors should happen at context_new() time */
602
603 if (opts->disp_prompt) {
604 if (xstreq("mls-range", name) && !*val)
605 return; /* skip, mls-range if it's empty */
606
607 if (opts->disp_color && color->valid) {
608 char *ansi = disp__con_color_ansi(name, color);
609 fprintf(stdout, "%s", ansi);
610 free(ansi);
611 }
612 fprintf(stdout, "%s%s", done ? ":" : "", val);
613 if (opts->disp_color && color->valid)
614 fprintf(stdout, "\e[0m");
615 } else if (disp_multi())
616 fprintf(stdout, "%s: %s\n", name, val);
617 else
618 fprintf(stdout, "%s\n", val);
619
620 done = TRUE;
621 }
622
disp_con(security_context_t scon_raw)623 static void disp_con(security_context_t scon_raw)
624 {
625 security_context_t scon_trans, scon;
626 context_t con = NULL;
627 char *color_str = NULL;
628 struct context_color_t color = { .valid = 0 };
629
630 selinux_raw_to_trans_context(scon_raw, &scon_trans);
631 if (opts->disp_raw)
632 scon = scon_raw;
633 else
634 scon = scon_trans;
635
636 if (!*scon) { /* --self-exec and --self-fs etc. */
637 if (opts->disp_user)
638 disp__con_val("user", NULL, &color);
639 if (opts->disp_role)
640 disp__con_val("role", NULL, &color);
641 if (opts->disp_type)
642 disp__con_val("type", NULL, &color);
643 if (opts->disp_sen)
644 disp__con_val("sensitivity", NULL, &color);
645 if (opts->disp_clr)
646 disp__con_val("clearance", NULL, &color);
647 if (opts->disp_mlsr)
648 disp__con_val("mls-range", NULL, &color);
649 freecon(scon_trans);
650 return;
651 }
652
653 if (opts->disp_color) {
654 if (selinux_raw_context_to_color(scon_raw, &color_str) < 0)
655 errx(EXIT_FAILURE, "Couldn't determine colors for: %s",
656 scon);
657
658 color.user_fg = strtok(color_str, " ");
659 if (!color.user_fg)
660 errx(EXIT_FAILURE, "Invalid color string");
661 color.user_bg = strtok(NULL, " ");
662 if (!color.user_bg)
663 errx(EXIT_FAILURE, "Invalid color string");
664
665 color.role_fg = strtok(NULL, " ");
666 if (!color.role_fg)
667 errx(EXIT_FAILURE, "Invalid color string");
668 color.role_bg = strtok(NULL, " ");
669 if (!color.role_bg)
670 errx(EXIT_FAILURE, "Invalid color string");
671
672 color.type_fg = strtok(NULL, " ");
673 if (!color.type_fg)
674 errx(EXIT_FAILURE, "Invalid color string");
675 color.type_bg = strtok(NULL, " ");
676 if (!color.type_bg)
677 errx(EXIT_FAILURE, "Invalid color string");
678
679 color.range_fg = strtok(NULL, " ");
680 if (!color.range_fg)
681 errx(EXIT_FAILURE, "Invalid color string");
682 color.range_bg = strtok(NULL, " ");
683
684 color.valid = 1;
685 };
686
687 if (!(con = context_new(scon)))
688 errx(EXIT_FAILURE, "Couldn't create context from: %s", scon);
689
690 if (opts->disp_user) {
691 disp__con_val("user", context_user_get(con), &color);
692 }
693 if (opts->disp_role) {
694 disp__con_val("role", context_role_get(con), &color);
695 }
696 if (opts->disp_type) {
697 disp__con_val("type", context_type_get(con), &color);
698 }
699 if (opts->disp_sen) {
700 const char *val = NULL;
701 char *tmp = NULL;
702
703 val = context_range_get(con);
704 if (!val)
705 val = ""; /* targeted has no "level" etc.,
706 any errors should happen at context_new() time */
707
708 tmp = strdup(val);
709 if (!tmp)
710 errx(EXIT_FAILURE, "Couldn't create context from: %s",
711 scon);
712 if (strchr(tmp, '-'))
713 *strchr(tmp, '-') = 0;
714
715 disp__con_val("sensitivity", tmp, &color);
716
717 free(tmp);
718 }
719 if (opts->disp_clr) {
720 const char *val = NULL;
721 char *tmp = NULL;
722
723 val = context_range_get(con);
724 if (!val)
725 val = ""; /* targeted has no "level" etc.,
726 any errors should happen at context_new() time */
727
728 tmp = strdup(val);
729 if (!tmp)
730 errx(EXIT_FAILURE, "Couldn't create context from: %s",
731 scon);
732 if (strchr(tmp, '-'))
733 disp__con_val("clearance", strchr(tmp, '-') + 1, &color);
734 else
735 disp__con_val("clearance", tmp, &color);
736
737 free(tmp);
738 }
739
740 if (opts->disp_mlsr)
741 disp__con_val("mls-range", context_range_get(con), &color);
742
743 context_free(con);
744 freecon(scon_trans);
745 if (color_str)
746 free(color_str);
747 }
748
main(int argc,char * argv[])749 int main(int argc, char *argv[])
750 {
751 security_context_t scon_raw = NULL;
752
753 cmd_line(argc, argv);
754
755 scon_raw = get_scon();
756
757 disp_con(scon_raw);
758
759 freecon(scon_raw);
760
761 exit(EXIT_SUCCESS);
762 }
763