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