• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 1999-2004 Gentoo Technologies, Inc.
3  * Distributed under the terms of the GNU General Public License v2
4  * $Header: /home/cvsroot/gentoo-projects/hardened/policycoreutils-extra/src/sestatus.c,v 1.10 2004/03/26 19:25:52 pebenito Exp $
5  * Patch provided by Steve Grubb
6  */
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <errno.h>
12 #include <selinux/selinux.h>
13 #include <selinux/get_default_type.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <dirent.h>
17 #include <unistd.h>
18 #include <libgen.h>
19 #include <ctype.h>
20 
21 #define PROC_BASE "/proc"
22 #define MAX_CHECK 50
23 #define CONF "/etc/sestatus.conf"
24 
25 /* conf file sections */
26 #define PROCS "[process]"
27 #define FILES "[files]"
28 
29 /* buffer size for cmp_cmdline */
30 #define BUFSIZE 255
31 
32 /* column to put the output (must be a multiple of 8) */
33 static unsigned int COL = 32;
34 
35 extern char *selinux_mnt;
36 
cmp_cmdline(const char * command,int pid)37 int cmp_cmdline(const char *command, int pid)
38 {
39 
40 	char buf[BUFSIZE];
41 	char filename[BUFSIZE];
42 
43 	memset(buf, '\0', BUFSIZE);
44 
45 	/* first read the proc entry */
46 	sprintf(filename, "%s/%d/exe", PROC_BASE, pid);
47 
48 	if (readlink(filename, buf, BUFSIZE) < 0)
49 		return 0;
50 
51 	if (buf[BUFSIZE - 1] != '\0')
52 		buf[BUFSIZE - 1] = '\0';
53 
54 	/* check if this is the command we're looking for. */
55 	if (strcmp(command, buf) == 0)
56 		return 1;
57 	else
58 		return 0;
59 }
60 
pidof(const char * command)61 int pidof(const char *command)
62 {
63 /* inspired by killall5.c from psmisc */
64 	DIR *dir;
65 	struct dirent *de;
66 	int pid, ret = -1, self = getpid();
67 
68 	if (!(dir = opendir(PROC_BASE))) {
69 		perror(PROC_BASE);
70 		return -1;
71 	}
72 
73 	while ((de = readdir(dir)) != NULL) {
74 		errno = 0;
75 		pid = (int)strtol(de->d_name, (char **)NULL, 10);
76 		if (errno || pid == 0 || pid == self)
77 			continue;
78 		if (cmp_cmdline(command, pid)) {
79 			ret = pid;
80 			break;
81 		}
82 	}
83 
84 	closedir(dir);
85 	return ret;
86 }
87 
load_checks(char * pc[],int * npc,char * fc[],int * nfc)88 void load_checks(char *pc[], int *npc, char *fc[], int *nfc)
89 {
90 
91 	FILE *fp = fopen(CONF, "r");
92 	char buf[255], *bufp;
93 	int buf_len, section = -1;
94 	int proclen = strlen(PROCS);
95 	int filelen = strlen(FILES);
96 
97 	if (fp == NULL) {
98 		printf("\nUnable to open %s.\n", CONF);
99 		return;
100 	}
101 
102 	while (!feof(fp)) {
103 		if (!fgets(buf, sizeof buf, fp))
104 			break;
105 
106 		buf_len = strlen(buf);
107 		if (buf[buf_len - 1] == '\n')
108 			buf[buf_len - 1] = 0;
109 
110 		bufp = buf;
111 		while (*bufp && isspace(*bufp)) {
112 			bufp++;
113 			buf_len--;
114 		}
115 
116 		if (*bufp == '#')
117 			/* skip comments */
118 			continue;
119 
120 		if (*bufp) {
121 			if (!(*bufp))
122 				goto out;
123 
124 			if (strncmp(bufp, PROCS, proclen) == 0)
125 				section = 0;
126 			else if (strncmp(bufp, FILES, filelen) == 0)
127 				section = 1;
128 			else {
129 				switch (section) {
130 				case 0:
131 					if (*npc >= MAX_CHECK)
132 						break;
133 					pc[*npc] =
134 					    (char *)malloc((buf_len) *
135 							   sizeof(char));
136 					memcpy(pc[*npc], bufp, buf_len);
137 					(*npc)++;
138 					bufp = NULL;
139 					break;
140 				case 1:
141 					if (*nfc >= MAX_CHECK)
142 						break;
143 					fc[*nfc] =
144 					    (char *)malloc((buf_len) *
145 							   sizeof(char));
146 					memcpy(fc[*nfc], bufp, buf_len);
147 					(*nfc)++;
148 					bufp = NULL;
149 					break;
150 				default:
151 					/* ignore lines before a section */
152 					printf("Line not in a section: %s.\n",
153 					       buf);
154 					break;
155 				}
156 			}
157 		}
158 	}
159       out:
160 	fclose(fp);
161 	return;
162 }
163 
printf_tab(const char * outp)164 void printf_tab(const char *outp)
165 {
166 	char buf[20];
167 	snprintf(buf, sizeof(buf), "%%-%us", COL);
168 	printf(buf, outp);
169 
170 }
171 
main(int argc,char ** argv)172 int main(int argc, char **argv)
173 {
174 	/* these vars are reused several times */
175 	int rc, opt, i, c;
176 	char *context, *root_path;
177 
178 	/* files that need context checks */
179 	char *fc[MAX_CHECK];
180 	char *cterm = ttyname(0);
181 	int nfc = 0;
182 	struct stat m;
183 
184 	/* processes that need context checks */
185 	char *pc[MAX_CHECK];
186 	int npc = 0;
187 
188 	/* booleans */
189 	char **bools;
190 	int nbool;
191 
192 	int verbose = 0;
193 	int show_bools = 0;
194 
195 	/* policy */
196 	const char *pol_name, *root_dir;
197 	char *pol_path;
198 
199 
200 	while (1) {
201 		opt = getopt(argc, argv, "vb");
202 		if (opt == -1)
203 			break;
204 		switch (opt) {
205 		case 'v':
206 			verbose = 1;
207 			break;
208 		case 'b':
209 			show_bools = 1;
210 			break;
211 		default:
212 			/* invalid option */
213 			printf("\nUsage: %s [OPTION]\n\n", basename(argv[0]));
214 			printf("  -v  Verbose check of process and file contexts.\n");
215 			printf("  -b  Display current state of booleans.\n");
216 			printf("\nWithout options, show SELinux status.\n");
217 			return -1;
218 		}
219 	}
220 	printf_tab("SELinux status:");
221 	rc = is_selinux_enabled();
222 
223 	switch (rc) {
224 	case 1:
225 		printf("enabled\n");
226 		break;
227 	case 0:
228 		printf("disabled\n");
229 		return 0;
230 		break;
231 	default:
232 		printf("unknown (%s)\n", strerror(errno));
233 		return 0;
234 		break;
235 	}
236 
237 	printf_tab("SELinuxfs mount:");
238 	if (selinux_mnt != NULL) {
239 		printf("%s\n", selinux_mnt);
240 	} else {
241 		printf("not mounted\n\n");
242 		printf("Please mount selinuxfs for proper results.\n");
243 		return -1;
244 	}
245 
246 	printf_tab("SELinux root directory:");
247 	root_dir = selinux_path();
248 	if (root_dir == NULL) {
249 		printf("error (%s)\n", strerror(errno));
250 		return -1;
251 	}
252 	/* The path has a trailing '/' so duplicate to edit */
253 	root_path = strdup(root_dir);
254 	if (!root_path) {
255 		printf("malloc error (%s)\n", strerror(errno));
256 		return -1;
257 	}
258 	/* actually blank the '/' */
259 	root_path[strlen(root_path) - 1] = '\0';
260 	printf("%s\n", root_path);
261 	free(root_path);
262 
263 	/* Dump all the path information */
264 	printf_tab("Loaded policy name:");
265 	pol_path = strdup(selinux_policy_root());
266 	if (pol_path) {
267 		pol_name = basename(pol_path);
268 		puts(pol_name);
269 		free(pol_path);
270 	} else {
271 		printf("error (%s)\n", strerror(errno));
272 	}
273 
274 	printf_tab("Current mode:");
275 	rc = security_getenforce();
276 	switch (rc) {
277 	case 1:
278 		printf("enforcing\n");
279 		break;
280 	case 0:
281 		printf("permissive\n");
282 		break;
283 	default:
284 		printf("unknown (%s)\n", strerror(errno));
285 		break;
286 	}
287 
288 	printf_tab("Mode from config file:");
289 	if (selinux_getenforcemode(&rc) == 0) {
290 		switch (rc) {
291 		case 1:
292 			printf("enforcing\n");
293 			break;
294 		case 0:
295 			printf("permissive\n");
296 			break;
297 		case -1:
298 			printf("disabled\n");
299 			break;
300 		}
301 	} else {
302 		printf("error (%s)\n", strerror(errno));
303 	}
304 
305 	printf_tab("Policy MLS status:");
306 	rc = is_selinux_mls_enabled();
307 	switch (rc) {
308 		case 0:
309 			printf("disabled\n");
310 			break;
311 		case 1:
312 			printf("enabled\n");
313 			break;
314 		default:
315 			printf("error (%s)\n", strerror(errno));
316 			break;
317 	}
318 
319 	printf_tab("Policy deny_unknown status:");
320 	rc = security_deny_unknown();
321 	switch (rc) {
322 		case 0:
323 			printf("allowed\n");
324 			break;
325 		case 1:
326 			printf("denied\n");
327 			break;
328 		default:
329 			printf("error (%s)\n", strerror(errno));
330 			break;
331 	}
332 
333 	rc = security_policyvers();
334 	printf_tab("Max kernel policy version:");
335 	if (rc < 0)
336 		printf("unknown (%s)\n", strerror(errno));
337 	else
338 		printf("%d\n", rc);
339 
340 
341 	if (show_bools) {
342 		/* show booleans */
343 		if (security_get_boolean_names(&bools, &nbool) >= 0) {
344 			printf("\nPolicy booleans:\n");
345 
346 			for (i = 0; i < nbool; i++) {
347 				if (strlen(bools[i]) + 1 > COL)
348 					COL = strlen(bools[i]) + 1;
349 			}
350 			for (i = 0; i < nbool; i++) {
351 				printf_tab(bools[i]);
352 
353 				rc = security_get_boolean_active(bools[i]);
354 				switch (rc) {
355 				case 1:
356 					printf("on");
357 					break;
358 				case 0:
359 					printf("off");
360 					break;
361 				default:
362 					printf("unknown (%s)", strerror(errno));
363 					break;
364 				}
365 				c = security_get_boolean_pending(bools[i]);
366 				if (c != rc)
367 					switch (c) {
368 					case 1:
369 						printf(" (activate pending)");
370 						break;
371 					case 0:
372 						printf(" (inactivate pending)");
373 						break;
374 					default:
375 						printf(" (pending error: %s)",
376 						       strerror(errno));
377 						break;
378 					}
379 				printf("\n");
380 
381 				/* free up the booleans */
382 				free(bools[i]);
383 			}
384 			free(bools);
385 		}
386 	}
387 	/* only show contexts if -v is given */
388 	if (!verbose)
389 		return 0;
390 
391 	load_checks(pc, &npc, fc, &nfc);
392 
393 	printf("\nProcess contexts:\n");
394 
395 	printf_tab("Current context:");
396 	if (getcon(&context) >= 0) {
397 		printf("%s\n", context);
398 		freecon(context);
399 	} else
400 		printf("unknown (%s)\n", strerror(errno));
401 
402 	printf_tab("Init context:");
403 	if (getpidcon(1, &context) >= 0) {
404 		printf("%s\n", context);
405 		freecon(context);
406 	} else
407 		printf("unknown (%s)\n", strerror(errno));
408 
409 	for (i = 0; i < npc; i++) {
410 		rc = pidof(pc[i]);
411 		if (rc > 0) {
412 			if (getpidcon(rc, &context) < 0)
413 				continue;
414 
415 			printf_tab(pc[i]);
416 			printf("%s\n", context);
417 			freecon(context);
418 		}
419 	}
420 
421 	printf("\nFile contexts:\n");
422 
423 	/* controlling term */
424 	printf_tab("Controlling terminal:");
425 	if (lgetfilecon(cterm, &context) >= 0) {
426 		printf("%s\n", context);
427 		freecon(context);
428 	} else {
429 		printf("unknown (%s)\n", strerror(errno));
430 	}
431 
432 	for (i = 0; i < nfc; i++) {
433 		if (lgetfilecon(fc[i], &context) >= 0) {
434 			printf_tab(fc[i]);
435 
436 			/* check if this is a symlink */
437 			if (lstat(fc[i], &m)) {
438 				printf
439 				    ("%s (could not check link status (%s)!)\n",
440 				     context, strerror(errno));
441 				freecon(context);
442 				continue;
443 			}
444 			if (S_ISLNK(m.st_mode)) {
445 				/* print link target context */
446 				printf("%s -> ", context);
447 				freecon(context);
448 
449 				if (getfilecon(fc[i], &context) >= 0) {
450 					printf("%s\n", context);
451 					freecon(context);
452 				} else {
453 					printf("unknown (%s)\n",
454 					       strerror(errno));
455 				}
456 			} else {
457 				printf("%s\n", context);
458 				freecon(context);
459 			}
460 		}
461 	}
462 
463 	return 0;
464 }
465