• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
usage(const char * progname)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 
string_to_mode(char * s)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 
main(int argc,char ** argv)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