Proposed patch for policycoreutils/sestatus

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

I have refactored sestatus.c and attached the patch for
policycoreutils-2.0.46.

However, the latter part of the patch is a bit unreadable due to the
extensive changes in the code layout. In fact the line count of the
patch is larger than sestatus.c itself.

The following has been done:

* Refactoring: moved lots of code from main() to static functions
* Error reporting: some system related error messages are now printed to stderr instead of stdout
* Usage message now includes the "-b" option as well
* Fixed some memory leaks (pc[] and fc[])
* More error checking
* Removed dead code
* Replaced sprintf() calls with snprintf()
* Replaced magic numbers with symbolic constants

I hope I didn't break anything, so if you have the time, please check out
the code and test it too. Yes, the program is trivial, but some errors
may have crept in nevertheless...


If you prefer to read the new sestatus.c instead of the patch,
please go to:


  http://www.helsinki.fi/~vmkari/sel


Basically I have tried to preserve the old functionality as is,
so there should be practically no user-visible changes.

However, at least the following changes are visible to the user:

1) When reporting controlling tty security context, I have
   added checks for NULL return value from ttyname().
   The older version just passed NULL along and the emitted error
   message was then a little bit different.

2) Some error messages are now sent to stderr instead of stdout

Best regards,
vmk
-- 
************************************************************************
               Tietotekniikkaosasto / Helsingin yliopisto
                 IT Department / University of Helsinki
************************************************************************
--- policycoreutils-2.0.46/sestatus/sestatus.c	2008-03-18 22:57:01.000000000 +0200
+++ policycoreutils-2.0.46-vmk/sestatus/sestatus.c	2008-07-16 16:20:56.000000000 +0300
@@ -3,248 +3,215 @@
  * Distributed under the terms of the GNU General Public License v2
  * $Header: /home/cvsroot/gentoo-projects/hardened/policycoreutils-extra/src/sestatus.c,v 1.10 2004/03/26 19:25:52 pebenito Exp $
  * Patch provided by Steve Grubb
+ *
+ * 2008 Refactored by Vesa-Matti Kari
+ * 
  */
 
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <libgen.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
-#include <selinux/selinux.h>
-#include <selinux/get_default_type.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
 #include <unistd.h>
-#include <libgen.h>
-#include <ctype.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <selinux/get_default_type.h>
+#include <selinux/selinux.h>
+
 
 #define PROC_BASE "/proc"
 #define MAX_CHECK 50
 #define CONF "/etc/sestatus.conf"
+#define INIT_PROC_PID (pid_t)1
 
 /* conf file sections */
 #define PROCS "[process]"
 #define FILES "[files]"
 
-/* buffer size for cmp_cmdline */
+/* buffer size for cmp_cmdline() and load_checks() */
 #define BUFSIZE 255
 
+
 /* column to put the output (must be a multiple of 8) */
 static unsigned int COL = 32;
 
 extern char *selinux_mnt;
 
-int cmp_cmdline(const char *command, int pid)
-{
 
+static int cmp_cmdline(const char *command, pid_t pid)
+{
 	char buf[BUFSIZE];
 	char filename[BUFSIZE];
 
-	memset(buf, '\0', BUFSIZE);
+	memset(buf, '\0', sizeof buf);
 
-	/* first read the proc entry */
-	sprintf(filename, "%s/%d/exe", PROC_BASE, pid);
+	snprintf(filename, sizeof filename, "%s/%d/exe", PROC_BASE, pid);
 
-	if (readlink(filename, buf, BUFSIZE) < 0)
+	if (readlink(filename, buf, sizeof buf) < 0)
 		return 0;
 
-	if (buf[BUFSIZE - 1] != '\0')
-		buf[BUFSIZE - 1] = '\0';
+	if (buf[sizeof buf - 1] != '\0')
+		buf[sizeof buf - 1] = '\0';
 
-	/* check if this is the command we're looking for. */
-	if (strcmp(command, buf) == 0)
-		return 1;
-	else
-		return 0;
+	return !strcmp(command, buf);
 }
 
-int pidof(const char *command)
+static int pidof(const char *command, pid_t *pid)
 {
-/* inspired by killall5.c from psmisc */
 	DIR *dir;
 	struct dirent *de;
-	int pid, ret = -1, self = getpid();
+	pid_t self;
+	int rc;
+
+	rc = -1;
 
-	if (!(dir = opendir(PROC_BASE))) {
-		perror(PROC_BASE);
-		return -1;
+	dir = opendir(PROC_BASE);
+	if (!dir) {
+		fprintf(stderr, "Unable to open %s: %s", PROC_BASE, strerror(errno));
+		return rc;
 	}
 
-	while ((de = readdir(dir)) != NULL) {
+	self = getpid();
+	while ((de = readdir(dir))) {
 		errno = 0;
-		pid = (int)strtol(de->d_name, (char **)NULL, 10);
-		if (errno || pid == 0 || pid == self)
+		*pid = (pid_t)strtol(de->d_name, NULL, 10);
+		if (errno || *pid == 0 || *pid == self)
 			continue;
-		if (cmp_cmdline(command, pid)) {
-			ret = pid;
+		if (cmp_cmdline(command, *pid)) {
+			rc = 0;
 			break;
 		}
 	}
 
 	closedir(dir);
-	return ret;
+	return rc;
 }
 
-void load_checks(char *pc[], int *npc, char *fc[], int *nfc)
+static void load_checks(char *pc[], int *npc, char *fc[], int *nfc)
 {
-
-	FILE *fp = fopen(CONF, "r");
-	char buf[255], *bufp;
-	int buf_len, section = -1;
-	int proclen = strlen(PROCS);
-	int filelen = strlen(FILES);
-
-	if (fp == NULL) {
-		printf("\nUnable to open %s.\n", CONF);
+	FILE *fp;
+	char buf[BUFSIZE];
+	char *bufp;
+	int buflen, section;
+	int i;
+
+	fp = fopen(CONF, "r");
+	if (!fp) {
+		fprintf(stderr, "\nUnable to open %s: %s\n", CONF, strerror(errno));
 		return;
 	}
 
-	while (!feof(fp)) {
-		if (!fgets(buf, sizeof buf, fp))
-			break;
+	section = -1;
+
+	while (fgets(buf, sizeof buf, fp)) {
 
-		buf_len = strlen(buf);
-		if (buf[buf_len - 1] == '\n')
-			buf[buf_len - 1] = 0;
+		buflen = strlen(buf);
+		if (buf[buflen - 1] == '\n')
+			buf[buflen - 1] = '\0';
 
 		bufp = buf;
-		while (*bufp && isspace(*bufp)) {
+		while (*bufp && isspace(*bufp))
 			bufp++;
-			buf_len--;
-		}
 
-		if (*bufp == '#')
-			/* skip comments */
+		if (*bufp == '#' || *bufp == '\0')
 			continue;
 
-		if (*bufp) {
-			if (!(*bufp))
-				goto out;
-
-			if (strncmp(bufp, PROCS, proclen) == 0)
-				section = 0;
-			else if (strncmp(bufp, FILES, filelen) == 0)
-				section = 1;
-			else {
-				switch (section) {
-				case 0:
-					if (*npc >= MAX_CHECK)
-						break;
-					pc[*npc] =
-					    (char *)malloc((buf_len) *
-							   sizeof(char));
-					memcpy(pc[*npc], bufp, buf_len);
-					(*npc)++;
-					bufp = NULL;
+		if (!strncmp(bufp, PROCS, sizeof PROCS))
+			section = 0;
+		else if (!strncmp(bufp, FILES, sizeof FILES))
+			section = 1;
+		else {
+			switch (section) {
+			case 0:
+				if (*npc >= MAX_CHECK)
 					break;
-				case 1:
-					if (*nfc >= MAX_CHECK)
-						break;
-					fc[*nfc] =
-					    (char *)malloc((buf_len) *
-							   sizeof(char));
-					memcpy(fc[*nfc], bufp, buf_len);
-					(*nfc)++;
-					bufp = NULL;
+				pc[*npc] = strdup(bufp);
+				if (!pc[*npc])
+					goto outfree;
+				(*npc)++;
+				break;
+			case 1:
+				if (*nfc >= MAX_CHECK)
 					break;
-				default:
-					/* ignore lines before a section */
-					printf("Line not in a section: %s.\n",
-					       buf);
-					break;
-				}
+				fc[*nfc] = strdup(bufp);
+				if (!fc[*nfc]) 
+					goto outfree;
+				(*nfc)++;
+				break;
+			default:
+				/* ignore lines before a section */
+				printf("Line not in a section: %s.\n", buf);
+				break;
 			}
 		}
 	}
-      out:
+
+	if (ferror(fp)) {
+		fprintf(stderr, "\nError while reading %s: %s\n", CONF, strerror(errno));
+		goto outfree;
+	}
+
+out:
 	fclose(fp);
 	return;
+
+outfree:
+	for (i = 0; i < *npc && i < MAX_CHECK; i++)
+		free(pc[i]);
+	for (i = 0; i < *nfc && i < MAX_CHECK; i++)
+		free(fc[i]);
+	goto out;
 }
 
-void printf_tab(const char *outp)
+static void printf_tab(const char *outp)
 {
 	char buf[20];
-	snprintf(buf, sizeof(buf), "%%-%us", COL);
+	snprintf(buf, sizeof buf, "%%-%us", COL);
 	printf(buf, outp);
 
 }
 
-int main(int argc, char **argv)
+static int status_show(void)
 {
-	/* these vars are reused several times */
-	int rc, opt, i, c;
-	char *context;
-
-	/* files that need context checks */
-	char *fc[MAX_CHECK];
-	char *cterm = ttyname(0);
-	int nfc = 0;
-	struct stat m;
-
-	/* processes that need context checks */
-	char *pc[MAX_CHECK];
-	int npc = 0;
-
-	/* booleans */
-	char **bools;
-	int nbool;
-
-	int verbose = 0;
-	int show_bools = 0;
-
-	/* policy */
-	const char *pol_name;
-	char *pol_path;
-
-	while (1) {
-		opt = getopt(argc, argv, "vb");
-		if (opt == -1)
-			break;
-		switch (opt) {
-		case 'v':
-			verbose = 1;
-			break;
-		case 'b':
-			show_bools = 1;
-			break;
-		default:
-			/* invalid option */
-			printf("\nUsage: %s [OPTION]\n\n", basename(argv[0]));
-			printf
-			    ("  -v  Verbose check of process and file contexts.\n");
-			printf("\nWithout options, show SELinux status.\n");
-			return -1;
-		}
-	}
 	printf_tab("SELinux status:");
-	rc = is_selinux_enabled();
 
-	switch (rc) {
+	switch (is_selinux_enabled()) {
 	case 1:
 		printf("enabled\n");
+		return 1;
 		break;
 	case 0:
 		printf("disabled\n");
 		return 0;
 		break;
 	default:
-		printf("unknown (%s)\n", strerror(errno));
+		printf("unknown (%s)\n", strerror(errno)); 
 		return 0;
 		break;
 	}
+}
 
+static int mount_show(const char *mnt)
+{
 	printf_tab("SELinuxfs mount:");
-	if (selinux_mnt != NULL) {
-		printf("%s\n", selinux_mnt);
-	} else {
-		printf("not mounted\n\n");
-		printf("Please mount selinuxfs for proper results.\n");
-		return -1;
-	}
 
+	if (mnt) {
+		printf("%s\n", mnt);
+		return 0;
+	} 
+
+	return -1;
+}
+
+static void mode_show(void)
+{
 	printf_tab("Current mode:");
-	rc = security_getenforce();
-	switch (rc) {
+
+	switch (security_getenforce()) {
 	case 1:
 		printf("enforcing\n");
 		break;
@@ -255,8 +222,14 @@
 		printf("unknown (%s)\n", strerror(errno));
 		break;
 	}
+}
+
+static void confmode_show(void)
+{
+	int rc;
 
 	printf_tab("Mode from config file:");
+
 	if (selinux_getenforcemode(&rc) == 0) {
 		switch (rc) {
 		case 1:
@@ -269,81 +242,99 @@
 			printf("disabled\n");
 			break;
 		}
-	} else {
+	} else
 		printf("error (%s)\n", strerror(errno));
-	}
+}
+
+static void policyvers_show(void)
+{
+	int rc;
 
-	rc = security_policyvers();
 	printf_tab("Policy version:");
+
+	rc = security_policyvers();
 	if (rc < 0)
 		printf("unknown (%s)\n", strerror(errno));
 	else
 		printf("%d\n", rc);
+}
+
+static void confpolicyvers_show(void)
+{
+	const char *pol_name;
+	char *pol_path;
 
-	/* Dump all the path information */
 	printf_tab("Policy from config file:");
+
 	pol_path = strdup(selinux_policy_root());
-	if (pol_path) {
-		pol_name = basename(pol_path);
-		puts(pol_name);
-		free(pol_path);
-	} else {
+	if (!pol_path) {
 		printf("error (%s)\n", strerror(errno));
+		return;
 	}
 
-	if (show_bools) {
-		/* show booleans */
-		if (security_get_boolean_names(&bools, &nbool) >= 0) {
-			printf("\nPolicy booleans:\n");
-
-			for (i = 0; i < nbool; i++) {
-				if (strlen(bools[i]) + 1 > COL)
-					COL = strlen(bools[i]) + 1;
-			}
-			for (i = 0; i < nbool; i++) {
-				printf_tab(bools[i]);
+	pol_name = basename(pol_path);
+	puts(pol_name);
+	free(pol_path);
+}
 
-				rc = security_get_boolean_active(bools[i]);
-				switch (rc) {
+static void bools_show(unsigned int *column)
+{
+	char **bools;
+	int nbool;
+	int c, i, rc;
+
+	rc = security_get_boolean_names(&bools, &nbool);
+	if (rc < 0)
+		return;
+
+	printf("Policy booleans:\n");
+
+		for (i = 0; i < nbool; i++)
+			if (strlen(bools[i]) + 1 > *column)
+				*column = strlen(bools[i]) + 1;
+		
+		for (i = 0; i < nbool; i++) {
+			printf_tab(bools[i]);
+
+			rc = security_get_boolean_active(bools[i]);
+			switch (rc) {
+			case 1:
+				printf("on");
+				break;
+			case 0:
+				printf("off");
+				break;
+			default:
+				printf("unknown (%s)", strerror(errno));
+				break;
+			}
+			c = security_get_boolean_pending(bools[i]);
+			if (c != rc)
+				switch (c) {
 				case 1:
-					printf("on");
+					printf(" (activate pending)");
 					break;
 				case 0:
-					printf("off");
+					printf(" (inactivate pending)");
 					break;
 				default:
-					printf("unknown (%s)", strerror(errno));
+					printf(" (pending error: %s)", strerror(errno));
 					break;
 				}
-				c = security_get_boolean_pending(bools[i]);
-				if (c != rc)
-					switch (c) {
-					case 1:
-						printf(" (activate pending)");
-						break;
-					case 0:
-						printf(" (inactivate pending)");
-						break;
-					default:
-						printf(" (pending error: %s)",
-						       strerror(errno));
-						break;
-					}
-				printf("\n");
+			printf("\n");
 
-				/* free up the booleans */
-				free(bools[i]);
-			}
-			free(bools);
+			free(bools[i]);
 		}
-	}
-	/* only show contexts if -v is given */
-	if (!verbose)
-		return 0;
+		free(bools);
+}
 
-	load_checks(pc, &npc, fc, &nfc);
+static void proccon_show(char *pc[], int npc)
+{
+	char *context;
+	pid_t pid;
+	int i, rc;
 
-	printf("\nProcess contexts:\n");
+	printf("Process contexts:\n");
 
 	printf_tab("Current context:");
 	if (getcon(&context) >= 0) {
@@ -353,48 +344,64 @@
 		printf("unknown (%s)\n", strerror(errno));
 
 	printf_tab("Init context:");
-	if (getpidcon(1, &context) >= 0) {
+	if (getpidcon(INIT_PROC_PID, &context) >= 0) {
 		printf("%s\n", context);
 		freecon(context);
 	} else
 		printf("unknown (%s)\n", strerror(errno));
 
 	for (i = 0; i < npc; i++) {
-		rc = pidof(pc[i]);
-		if (rc > 0) {
-			if (getpidcon(rc, &context) < 0)
-				continue;
+		rc = pidof(pc[i], &pid);
 
-			printf_tab(pc[i]);
-			printf("%s\n", context);
-			freecon(context);
-		}
-	}
+		if (rc < 0)
+			continue;
 
-	printf("\nFile contexts:\n");
+		if (getpidcon(pid, &context) < 0)
+			continue;
 
-	/* controlling term */
-	printf_tab("Controlling term:");
-	if (lgetfilecon(cterm, &context) >= 0) {
+		printf_tab(pc[i]);
 		printf("%s\n", context);
 		freecon(context);
-	} else {
-		printf("unknown (%s)\n", strerror(errno));
 	}
 
+	for (i = 0; i < npc; i++)
+		free(pc[i]);
+}
+
+static void filecon_show(char *fc[], int nfc)
+{
+	struct stat st;
+	char *context;
+	char *ctrlterm;
+	int i;
+
+	printf("File contexts:\n");
+
+	printf_tab("Controlling term:");
+
+	ctrlterm = ttyname(STDIN_FILENO);
+	if (ctrlterm) {
+		if (lgetfilecon(ctrlterm, &context) >= 0) {
+			printf("%s\n", context);
+			freecon(context);
+		} else {
+			printf("unknown (%s)\n", strerror(errno));
+		}
+	} else
+		printf("error: %s\n", strerror(errno));
+
 	for (i = 0; i < nfc; i++) {
 		if (lgetfilecon(fc[i], &context) >= 0) {
 			printf_tab(fc[i]);
 
 			/* check if this is a symlink */
-			if (lstat(fc[i], &m)) {
-				printf
-				    ("%s (could not check link status (%s)!)\n",
+			if (lstat(fc[i], &st)) {
+				printf ("%s (could not check link status (%s)!)\n",
 				     context, strerror(errno));
 				freecon(context);
 				continue;
 			}
-			if (S_ISLNK(m.st_mode)) {
+			if (S_ISLNK(st.st_mode)) {
 				/* print link target context */
 				printf("%s -> ", context);
 				freecon(context);
@@ -402,16 +409,81 @@
 				if (getfilecon(fc[i], &context) >= 0) {
 					printf("%s\n", context);
 					freecon(context);
-				} else {
-					printf("unknown (%s)\n",
-					       strerror(errno));
-				}
+				} else 
+					printf("unknown (%s)\n", strerror(errno));
 			} else {
 				printf("%s\n", context);
 				freecon(context);
 			}
+		} 
+	}
+
+	for (i = 0; i < nfc; i++)
+		free(fc[i]);
+}
+
+int main(int argc, char *argv[])
+{
+	char *pc[MAX_CHECK]; /* processes that need context checks */
+	char *fc[MAX_CHECK]; /* files that need context checks */
+	int npc, nfc;
+	int verbose, bools;
+	int rc, opt;
+
+	npc = nfc = 0;
+	verbose = bools = 0;
+
+	while (1) {
+		opt = getopt(argc, argv, "vb");
+		if (opt == -1)
+			break;
+		switch (opt) {
+		case 'v':
+			verbose = 1;
+			break;
+		case 'b':
+			bools = 1;
+			break;
+		default:
+			fprintf(stderr, "\nUsage: %s [OPTION]\n\n", basename(argv[0]));
+			fprintf(stderr, "  -b  Display the current state of booleans.\n");
+			fprintf(stderr, "  -v  Verbose check of process and file contexts.\n");
+			fprintf(stderr, "\nWithout options, show SELinux status.\n");
+			return -1;
 		}
 	}
 
+	rc = status_show();
+	if (rc < 1) {
+		return rc;
+	}
+
+	rc = mount_show(selinux_mnt);
+	if (rc < 0) {
+		fprintf(stderr, "not mounted\n\nPlease mount selinuxfs for proper results.\n");
+		return rc;
+	}
+
+	mode_show();
+	confmode_show();
+	policyvers_show();
+	confpolicyvers_show();
+
+	if (bools) {
+		putchar('\n');
+		bools_show(&COL);
+	}
+
+	if (!verbose)
+		return 0;
+
+	load_checks(pc, &npc, fc, &nfc);
+
+	putchar('\n');
+	proccon_show(pc, npc);
+
+	putchar('\n');
+	filecon_show(fc, nfc);
+
 	return 0;
 }

[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux