* Proposed patch for policycoreutils/sestatus
@ 2008-07-16 15:02 Vesa-Matti J Kari
2008-07-16 15:28 ` Buggy patch (Re: Proposed patch for policycoreutils/sestatus) Vesa-Matti J Kari
2008-07-17 11:15 ` Proposed patch for policycoreutils/sestatus Joshua Brindle
0 siblings, 2 replies; 4+ messages in thread
From: Vesa-Matti J Kari @ 2008-07-16 15:02 UTC (permalink / raw)
To: selinux
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1748 bytes --]
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
************************************************************************
[-- Attachment #2: patch for policycoreutils-2.0.46 --]
[-- Type: TEXT/PLAIN, Size: 15499 bytes --]
--- 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;
}
^ permalink raw reply [flat|nested] 4+ messages in thread
* Buggy patch (Re: Proposed patch for policycoreutils/sestatus)
2008-07-16 15:02 Proposed patch for policycoreutils/sestatus Vesa-Matti J Kari
@ 2008-07-16 15:28 ` Vesa-Matti J Kari
2008-07-17 11:15 ` Proposed patch for policycoreutils/sestatus Joshua Brindle
1 sibling, 0 replies; 4+ messages in thread
From: Vesa-Matti J Kari @ 2008-07-16 15:28 UTC (permalink / raw)
To: selinux
[-- Attachment #1: Type: TEXT/PLAIN, Size: 959 bytes --]
Hello,
On Wed, 16 Jul 2008, Vesa-Matti J Kari wrote:
> 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...
I am very sorry for being hasty with sending the patch.
My sestatus.diff indeed contains a bug that makes double free() possible.
If strdup() fails to allocate memory, then load_checks() free():s all
the memory allocated so far, but it does not reset *npc and *nfc to zero.
Hence proccon_show() and filecon_show() might free() the memory that
has already been free():d by load_checks().
The fix patch is attached.
Apologies again.
Best regards,
vmk
--
************************************************************************
Tietotekniikkaosasto / Helsingin yliopisto
IT Department / University of Helsinki
************************************************************************
[-- Attachment #2: fix to prevent double free():ing --]
[-- Type: TEXT/PLAIN, Size: 250 bytes --]
--- sestatus.c.old 2008-07-16 16:20:56.000000000 +0300
+++ sestatus.c 2008-07-16 18:10:52.000000000 +0300
@@ -164,6 +164,7 @@
free(pc[i]);
for (i = 0; i < *nfc && i < MAX_CHECK; i++)
free(fc[i]);
+ *npc = *nfc = 0;
goto out;
}
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Proposed patch for policycoreutils/sestatus
2008-07-16 15:02 Proposed patch for policycoreutils/sestatus Vesa-Matti J Kari
2008-07-16 15:28 ` Buggy patch (Re: Proposed patch for policycoreutils/sestatus) Vesa-Matti J Kari
@ 2008-07-17 11:15 ` Joshua Brindle
2008-07-17 16:12 ` Vesa-Matti J Kari
1 sibling, 1 reply; 4+ messages in thread
From: Joshua Brindle @ 2008-07-17 11:15 UTC (permalink / raw)
To: Vesa-Matti J Kari; +Cc: selinux
Vesa-Matti J Kari wrote:
> 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.
>
split the layout changes from the functional changes and submit 2 patches please.
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Proposed patch for policycoreutils/sestatus
2008-07-17 11:15 ` Proposed patch for policycoreutils/sestatus Joshua Brindle
@ 2008-07-17 16:12 ` Vesa-Matti J Kari
0 siblings, 0 replies; 4+ messages in thread
From: Vesa-Matti J Kari @ 2008-07-17 16:12 UTC (permalink / raw)
To: Joshua Brindle; +Cc: selinux
[-- Attachment #1: Type: TEXT/PLAIN, Size: 578 bytes --]
Hello,
On Thu, 17 Jul 2008, Joshua Brindle wrote:
> split the layout changes from the functional changes and
> submit 2 patches please.
All right, here they come, I hope they are okay now.
Please apply the patches in this order:
1) sestatus-layout.patch
2) sestatus-functionality.patch
Best regards,
vmk
--
************************************************************************
Tietotekniikkaosasto / Helsingin yliopisto
IT Department / University of Helsinki
************************************************************************
[-- Attachment #2: refactored main() --]
[-- Type: TEXT/PLAIN, Size: 9275 bytes --]
--- 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-17 18:46:39.000000000 +0300
@@ -3,20 +3,22 @@
* 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
+ * 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
@@ -60,7 +62,6 @@
int pidof(const char *command)
{
-/* inspired by killall5.c from psmisc */
DIR *dir;
struct dirent *de;
int pid, ret = -1, self = getpid();
@@ -169,82 +170,44 @@
}
-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;
+ }
+
+ fprintf(stderr, "not mounted\n\nPlease mount selinuxfs for proper results.\n");
+ 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 +218,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 +238,98 @@
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;
+ int i, rc;
- printf("\nProcess contexts:\n");
+ printf("Process contexts:\n");
printf_tab("Current context:");
if (getcon(&context) >= 0) {
@@ -371,10 +357,22 @@
}
}
- printf("\nFile contexts:\n");
+ for (i = 0; i < npc; i++)
+ free(pc[i]);
+}
+
+static void filecon_show(char *fc[], int nfc)
+{
+ struct stat st;
+ char *context;
+ char *cterm;
+ int i;
+
+ printf("File contexts:\n");
- /* controlling term */
printf_tab("Controlling term:");
+
+ cterm = ttyname(0);
if (lgetfilecon(cterm, &context) >= 0) {
printf("%s\n", context);
freecon(context);
@@ -387,14 +385,13 @@
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 +399,79 @@
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, " -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) {
+ 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;
}
[-- Attachment #3: the other changes --]
[-- Type: TEXT/PLAIN, Size: 7549 bytes --]
--- policycoreutils-2.0.46/sestatus/sestatus.c 2008-07-17 18:51:41.000000000 +0300
+++ policycoreutils-2.0.46-vmk/sestatus/sestatus.c 2008-07-17 18:45:11.000000000 +0300
@@ -20,152 +20,156 @@
#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)
{
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;
+ char buf[BUFSIZE];
+ char *bufp;
+ int buflen, section;
+ int i;
- 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);
+ 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;
- 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;
+ 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;
- default:
- /* ignore lines before a section */
- printf("Line not in a section: %s.\n",
- buf);
+ pc[*npc] = strdup(bufp);
+ if (!pc[*npc])
+ goto outfree;
+ (*npc)++;
+ break;
+ case 1:
+ if (*nfc >= MAX_CHECK)
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]);
+ *npc = *nfc = 0;
+ 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);
}
@@ -327,6 +331,7 @@
static void proccon_show(char *pc[], int npc)
{
char *context;
+ pid_t pid;
int i, rc;
printf("Process contexts:\n");
@@ -339,22 +344,24 @@
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;
+
+ if (getpidcon(pid, &context) < 0)
+ continue;
+
+ printf_tab(pc[i]);
+ printf("%s\n", context);
+ freecon(context);
}
for (i = 0; i < npc; i++)
@@ -365,20 +372,23 @@
{
struct stat st;
char *context;
- char *cterm;
+ char *ctrlterm;
int i;
printf("File contexts:\n");
printf_tab("Controlling term:");
- cterm = ttyname(0);
- if (lgetfilecon(cterm, &context) >= 0) {
- printf("%s\n", context);
- freecon(context);
- } else {
- printf("unknown (%s)\n", strerror(errno));
- }
+ 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) {
@@ -436,6 +446,7 @@
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;
[-- Attachment #4: bash script for testing sestatus --]
[-- Type: TEXT/PLAIN, Size: 414 bytes --]
#!/bin/bash
#
# PURPOSE: compare old and new sestatus output
# NOTE: run this in policycoreutils-X-Y-ZZ/sestatus
OLD=/usr/sbin/sestatus
NEW=$PWD/sestatus
OOUT=/tmp/old
NOUT=/tmp/new
i=0
for arg in '' '-b' '-v' '-vb'; do
((i++))
echo -n "$OLD $arg => "
$OLD $arg > $OOUT &&
$NEW $arg > $NOUT &&
diff $OOUT $NOUT &&
echo test $i okay ||
echo test $i failed
done
rm -f $OOUT $NOUT
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2008-07-17 16:12 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-16 15:02 Proposed patch for policycoreutils/sestatus Vesa-Matti J Kari
2008-07-16 15:28 ` Buggy patch (Re: Proposed patch for policycoreutils/sestatus) Vesa-Matti J Kari
2008-07-17 11:15 ` Proposed patch for policycoreutils/sestatus Joshua Brindle
2008-07-17 16:12 ` Vesa-Matti J Kari
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.