Home | History | Annotate | Download | only in utils
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <getopt.h>
      5 #include <errno.h>
      6 #include <sys/stat.h>
      7 #include <selinux/selinux.h>
      8 #include <selinux/label.h>
      9 
     10 static __attribute__ ((__noreturn__)) void usage(const char *progname)
     11 {
     12 	fprintf(stderr,
     13 		"usage: %s [-v] [-r] -p path [-m mode] [-f file] [link...]\n\n"
     14 		"Where:\n\t"
     15 		"-v     Validate file_contxts entries against loaded policy.\n\t"
     16 		"-r     Use \"raw\" function.\n\t"
     17 		"-p     Path to check for best match using the link(s) provided.\n\t"
     18 		"-m     Optional mode (b, c, d, p, l, s or f) Defaults to 0.\n\t"
     19 		"-f     Optional file containing the specs (defaults to\n\t"
     20 		"       those used by loaded policy).\n\t"
     21 		"link   Zero or more links to check against, the order of\n\t"
     22 		"       precedence for best match is:\n\t\t"
     23 		"   1) An exact match for the real path (if no links), or\n\t\t"
     24 		"   2) An exact match for any of the links (aliases), or\n\t\t"
     25 		"   3) The longest fixed prefix match.\n\n"
     26 		"Example:\n\t"
     27 		"%s -p /dev/initctl /run/systemd/initctl/fifo\n\t"
     28 		"   Find best matching context for the specified path using one link.\n\n",
     29 		progname, progname);
     30 	exit(1);
     31 }
     32 
     33 static mode_t string_to_mode(char *s)
     34 {
     35 	switch (s[0]) {
     36 	case 'b':
     37 		return S_IFBLK;
     38 	case 'c':
     39 		return S_IFCHR;
     40 	case 'd':
     41 		return S_IFDIR;
     42 	case 'p':
     43 		return S_IFIFO;
     44 	case 'l':
     45 		return S_IFLNK;
     46 	case 's':
     47 		return S_IFSOCK;
     48 	case 'f':
     49 		return S_IFREG;
     50 	};
     51 	return 0;
     52 }
     53 
     54 int main(int argc, char **argv)
     55 {
     56 	int raw = 0, mode = 0, rc, opt, i, num_links, string_len;
     57 	char *validate = NULL, *path = NULL, *context = NULL, *file = NULL;
     58 	char **links = NULL;
     59 
     60 	struct selabel_handle *hnd;
     61 	struct selinux_opt options[] = {
     62 		{ SELABEL_OPT_PATH, file },
     63 		{ SELABEL_OPT_VALIDATE, validate }
     64 	};
     65 
     66 	if (argc < 3)
     67 		usage(argv[0]);
     68 
     69 	while ((opt = getopt(argc, argv, "f:vrp:m:")) > 0) {
     70 		switch (opt) {
     71 		case 'f':
     72 			file = optarg;
     73 			break;
     74 		case 'v':
     75 			validate = (char *)1;
     76 			break;
     77 		case 'r':
     78 			raw = 1;
     79 			break;
     80 		case 'p':
     81 			path = optarg;
     82 			break;
     83 		case 'm':
     84 			mode = string_to_mode(optarg);
     85 			break;
     86 		default:
     87 			usage(argv[0]);
     88 		}
     89 	}
     90 
     91 	/* Count links */
     92 	for (i = optind, num_links = 0; i < argc; i++, num_links++)
     93 		;
     94 
     95 	if (num_links) {
     96 		links = calloc(num_links + 1, sizeof(char *));
     97 
     98 		if (!links) {
     99 			fprintf(stderr, "ERROR: calloc failed.\n");
    100 			exit(1);
    101 		}
    102 
    103 		for (i = optind, num_links = 0; i < argc; i++, num_links++) {
    104 			string_len = strlen(argv[i]) + 1;
    105 			links[num_links] = malloc(string_len);
    106 			if (!links[num_links]) {
    107 				fprintf(stderr, "ERROR: malloc failed.\n");
    108 				exit(1);
    109 			}
    110 			strcpy(links[num_links], argv[i]);
    111 		}
    112 	}
    113 
    114 	options[0].value = file;
    115 	options[1].value = validate;
    116 
    117 	hnd = selabel_open(SELABEL_CTX_FILE, options, 2);
    118 	if (!hnd) {
    119 		fprintf(stderr, "ERROR: selabel_open - Could not obtain "
    120 							     "handle.\n");
    121 		rc = -1;
    122 		goto out;
    123 	}
    124 
    125 	if (raw)
    126 		rc = selabel_lookup_best_match_raw(hnd, &context, path,
    127 					    (const char **)links, mode);
    128 	else
    129 		rc = selabel_lookup_best_match(hnd, &context, path,
    130 					    (const char **)links, mode);
    131 
    132 	selabel_close(hnd);
    133 
    134 	if (rc) {
    135 		switch (errno) {
    136 		case ENOENT:
    137 			fprintf(stderr, "ERROR: selabel_lookup_best_match "
    138 				    "failed to find a valid context.\n");
    139 			break;
    140 		case EINVAL:
    141 			fprintf(stderr, "ERROR: selabel_lookup_best_match "
    142 				"failed to validate context, or path / mode "
    143 				"are invalid.\n");
    144 			break;
    145 		default:
    146 			fprintf(stderr, "selabel_lookup_best_match ERROR: "
    147 					    "%s\n", strerror(errno));
    148 		}
    149 	} else {
    150 		printf("Best match context: %s\n", context);
    151 		freecon(context);
    152 	}
    153 
    154 out:
    155 	if (links) {
    156 		for (i = 0; links[i]; i++)
    157 			free(links[i]);
    158 		free(links);
    159 	}
    160 
    161 	return rc;
    162 }
    163