aboutsummaryrefslogtreecommitdiffstats
path: root/libselinux/utils
diff options
context:
space:
mode:
Diffstat (limited to 'libselinux/utils')
-rw-r--r--libselinux/utils/Makefile32
-rw-r--r--libselinux/utils/avcstat.c234
-rw-r--r--libselinux/utils/compute_av.c55
-rw-r--r--libselinux/utils/compute_create.c36
-rw-r--r--libselinux/utils/compute_member.c36
-rw-r--r--libselinux/utils/compute_relabel.c36
-rw-r--r--libselinux/utils/compute_user.c38
-rw-r--r--libselinux/utils/getconlist.c73
-rw-r--r--libselinux/utils/getdefaultcon.c80
-rw-r--r--libselinux/utils/getenforce.c31
-rw-r--r--libselinux/utils/getfilecon.c27
-rw-r--r--libselinux/utils/getpidcon.c31
-rw-r--r--libselinux/utils/getsebool.c105
-rw-r--r--libselinux/utils/getseuser.c40
-rw-r--r--libselinux/utils/matchpathcon.c143
-rw-r--r--libselinux/utils/policyvers.c18
-rw-r--r--libselinux/utils/selinux_check_securetty_context.c35
-rw-r--r--libselinux/utils/selinuxenabled.c9
-rw-r--r--libselinux/utils/setenforce.c42
-rw-r--r--libselinux/utils/setfilecon.c24
-rw-r--r--libselinux/utils/togglesebool.c97
21 files changed, 1222 insertions, 0 deletions
diff --git a/libselinux/utils/Makefile b/libselinux/utils/Makefile
new file mode 100644
index 00000000..a2c0a53b
--- /dev/null
+++ b/libselinux/utils/Makefile
@@ -0,0 +1,32 @@
+# Installation directories.
+PREFIX ?= $(DESTDIR)/usr
+LIBDIR ?= $(PREFIX)/lib
+BINDIR ?= $(PREFIX)/sbin
+
+CFLAGS ?= -Wall
+override CFLAGS += -I../include -D_GNU_SOURCE $(EMFLAGS)
+LDLIBS += -L../src -lselinux -L$(LIBDIR)
+
+TARGETS=$(patsubst %.c,%,$(wildcard *.c))
+ifeq ($(DISABLE_AVC),y)
+ UNUSED_TARGETS+=compute_av compute_create compute_member compute_relabel
+endif
+ifeq ($(DISABLE_BOOL),y)
+ UNUSED_TARGETS+=getsebool togglesebool
+endif
+TARGETS:= $(filter-out $(UNUSED_TARGETS), $(TARGETS))
+
+all: $(TARGETS)
+
+install: all
+ -mkdir -p $(BINDIR)
+ install -m 755 $(TARGETS) $(BINDIR)
+
+clean:
+ rm -f $(TARGETS) *.o
+
+indent:
+ ../../scripts/Lindent $(wildcard *.[ch])
+
+relabel:
+
diff --git a/libselinux/utils/avcstat.c b/libselinux/utils/avcstat.c
new file mode 100644
index 00000000..772118a1
--- /dev/null
+++ b/libselinux/utils/avcstat.c
@@ -0,0 +1,234 @@
+/*
+ * avcstat - Display SELinux avc statistics.
+ *
+ * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <libgen.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <linux/limits.h>
+
+#define DEF_STAT_FILE "/avc/cache_stats"
+#define DEF_BUF_SIZE 8192
+#define HEADERS "lookups hits misses allocations reclaims frees"
+
+struct avc_cache_stats {
+ unsigned long long lookups;
+ unsigned long long hits;
+ unsigned long long misses;
+ unsigned long long allocations;
+ unsigned long long reclaims;
+ unsigned long long frees;
+};
+
+static int interval;
+static int rows;
+static char *progname;
+static char buf[DEF_BUF_SIZE];
+
+/* selinuxfs mount point */
+extern char *selinux_mnt;
+
+static void die(const char *msg, ...)
+{
+ va_list args;
+
+ fputs("ERROR: ", stderr);
+
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+
+ if (errno)
+ fprintf(stderr, ": %s", strerror(errno));
+
+ fputc('\n', stderr);
+ exit(1);
+}
+
+static void usage(void)
+{
+ printf("\nUsage: %s [-c] [-f status_file] [interval]\n\n", progname);
+ printf
+ ("Display SELinux AVC statistics. If the interval parameter is specified, the\n");
+ printf
+ ("program will loop, displaying updated statistics every \'interval\' seconds.\n");
+ printf
+ ("Relative values are displayed by default. Use the -c option to specify the\n");
+ printf
+ ("display of cumulative values. The -f option specifies the location of the\n");
+ printf("AVC statistics file, defaulting to \'%s%s\'.\n\n", selinux_mnt,
+ DEF_STAT_FILE);
+}
+
+static void set_window_rows(void)
+{
+ int ret;
+ struct winsize ws;
+
+ ret = ioctl(fileno(stdout), TIOCGWINSZ, &ws);
+ if (ret < 0 || ws.ws_row < 3)
+ ws.ws_row = 24;
+ rows = ws.ws_row;
+}
+
+static void sighandler(int num)
+{
+ if (num == SIGWINCH)
+ set_window_rows();
+}
+
+int main(int argc, char **argv)
+{
+ struct avc_cache_stats tot, rel, last;
+ int fd, i, cumulative = 0;
+ struct sigaction sa;
+ char avcstatfile[PATH_MAX];
+ snprintf(avcstatfile, sizeof avcstatfile, "%s%s", selinux_mnt,
+ DEF_STAT_FILE);
+ progname = basename(argv[0]);
+
+ memset(&last, 0, sizeof(last));
+
+ while ((i = getopt(argc, argv, "cf:h?-")) != -1) {
+ switch (i) {
+ case 'c':
+ cumulative = 1;
+ break;
+ case 'f':
+ strncpy(avcstatfile, optarg, sizeof avcstatfile);
+ break;
+ case 'h':
+ case '-':
+ usage();
+ exit(0);
+ default:
+ usage();
+ die("unrecognized parameter", i);
+ }
+ }
+
+ if (optind < argc) {
+ char *arg = argv[optind];
+ unsigned int n = strtoul(arg, NULL, 10);
+
+ if (errno == ERANGE) {
+ usage();
+ die("invalid interval \'%s\'", arg);
+ }
+ if (n == 0) {
+ usage();
+ exit(0);
+ }
+ interval = n;
+ }
+
+ sa.sa_handler = sighandler;
+ sa.sa_flags = SA_RESTART;
+
+ i = sigaction(SIGWINCH, &sa, NULL);
+ if (i < 0)
+ die("sigaction");
+
+ set_window_rows();
+ fd = open(avcstatfile, O_RDONLY);
+ if (fd < 0)
+ die("open: \'%s\'", avcstatfile);
+
+ for (i = 0;; i++) {
+ char *line;
+ ssize_t ret, parsed = 0;
+
+ memset(buf, 0, DEF_BUF_SIZE);
+ ret = read(fd, buf, DEF_BUF_SIZE);
+ if (ret < 0)
+ die("read");
+
+ if (ret == 0)
+ die("read: \'%s\': unexpected end of file",
+ avcstatfile);
+
+ line = strtok(buf, "\n");
+ if (!line)
+ die("unable to parse \'%s\': end of line not found",
+ avcstatfile);
+
+ if (strcmp(line, HEADERS))
+ die("unable to parse \'%s\': invalid headers",
+ avcstatfile);
+
+ if (!i || !(i % (rows - 2)))
+ printf("%10s %10s %10s %10s %10s %10s\n", "lookups",
+ "hits", "misses", "allocs", "reclaims", "frees");
+
+ memset(&tot, 0, sizeof(tot));
+
+ while ((line = strtok(NULL, "\n"))) {
+ struct avc_cache_stats tmp;
+
+ ret = sscanf(line, "%llu %llu %llu %llu %llu %llu",
+ &tmp.lookups,
+ &tmp.hits,
+ &tmp.misses,
+ &tmp.allocations,
+ &tmp.reclaims, &tmp.frees);
+ if (ret != 6)
+ die("unable to parse \'%s\': scan error",
+ avcstatfile);
+
+ tot.lookups += tmp.lookups;
+ tot.hits += tmp.hits;
+ tot.misses += tmp.misses;
+ tot.allocations += tmp.allocations;
+ tot.reclaims += tmp.reclaims;
+ tot.frees += tmp.frees;
+ parsed = 1;
+ }
+
+ if (!parsed)
+ die("unable to parse \'%s\': no data", avcstatfile);
+
+ if (cumulative || (!cumulative && !i))
+ printf("%10Lu %10Lu %10Lu %10Lu %10Lu %10Lu\n",
+ tot.lookups, tot.hits, tot.misses,
+ tot.allocations, tot.reclaims, tot.frees);
+ else {
+ rel.lookups = tot.lookups - last.lookups;
+ rel.hits = tot.hits - last.hits;
+ rel.misses = tot.misses - last.misses;
+ rel.allocations = tot.allocations - last.allocations;
+ rel.reclaims = tot.reclaims - last.reclaims;
+ rel.frees = tot.frees - last.frees;
+ printf("%10Lu %10Lu %10Lu %10Lu %10Lu %10Lu\n",
+ rel.lookups, rel.hits, rel.misses,
+ rel.allocations, rel.reclaims, rel.frees);
+ }
+
+ if (!interval)
+ break;
+
+ memcpy(&last, &tot, sizeof(last));
+ sleep(interval);
+
+ ret = lseek(fd, 0, 0);
+ if (ret < 0)
+ die("lseek");
+ }
+
+ close(fd);
+ return 0;
+}
diff --git a/libselinux/utils/compute_av.c b/libselinux/utils/compute_av.c
new file mode 100644
index 00000000..574fa6ed
--- /dev/null
+++ b/libselinux/utils/compute_av.c
@@ -0,0 +1,55 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <selinux/selinux.h>
+
+int main(int argc, char **argv)
+{
+ struct av_decision avd;
+ security_class_t tclass;
+ int ret;
+
+ if (argc != 4) {
+ fprintf(stderr, "usage: %s scontext tcontext tclass\n",
+ argv[0]);
+ exit(1);
+ }
+
+ tclass = string_to_security_class(argv[3]);
+ if (!tclass) {
+ fprintf(stderr, "%s: invalid class '%s'\n", argv[0], argv[3]);
+ exit(2);
+ }
+
+ ret = security_compute_av(argv[1], argv[2], tclass, 1, &avd);
+ if (ret < 0) {
+ fprintf(stderr, "%s: security_compute_av failed\n", argv[0]);
+ exit(3);
+ }
+
+ printf("allowed=");
+ print_access_vector(tclass, avd.allowed);
+ printf("\n");
+
+ if (avd.decided != ~0U) {
+ printf("decided=");
+ print_access_vector(tclass, avd.decided);
+ printf("\n");
+ }
+
+ if (avd.auditallow) {
+ printf("auditallow=");
+ print_access_vector(tclass, avd.auditallow);
+ printf("\n");
+ }
+
+ if (avd.auditdeny != ~0U) {
+ printf("auditdeny");
+ print_access_vector(tclass, avd.auditdeny);
+ printf("\n");
+ }
+
+ exit(0);
+}
diff --git a/libselinux/utils/compute_create.c b/libselinux/utils/compute_create.c
new file mode 100644
index 00000000..4abc29fb
--- /dev/null
+++ b/libselinux/utils/compute_create.c
@@ -0,0 +1,36 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <selinux/selinux.h>
+
+int main(int argc, char **argv)
+{
+ char *buf;
+ security_class_t tclass;
+ int ret;
+
+ if (argc != 4) {
+ fprintf(stderr, "usage: %s scontext tcontext tclass\n",
+ argv[0]);
+ exit(1);
+ }
+
+ tclass = string_to_security_class(argv[3]);
+ if (!tclass) {
+ fprintf(stderr, "Invalid class '%s'\n", argv[3]);
+ exit(2);
+ }
+
+ ret = security_compute_create(argv[1], argv[2], tclass, &buf);
+ if (ret < 0) {
+ fprintf(stderr, "%s: security_compute_create failed\n",
+ argv[0]);
+ exit(3);
+ }
+
+ printf("%s\n", buf);
+ freecon(buf);
+ exit(0);
+}
diff --git a/libselinux/utils/compute_member.c b/libselinux/utils/compute_member.c
new file mode 100644
index 00000000..14edd451
--- /dev/null
+++ b/libselinux/utils/compute_member.c
@@ -0,0 +1,36 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <selinux/selinux.h>
+
+int main(int argc, char **argv)
+{
+ char *buf;
+ security_class_t tclass;
+ int ret;
+
+ if (argc != 4) {
+ fprintf(stderr, "usage: %s scontext tcontext tclass\n",
+ argv[0]);
+ exit(1);
+ }
+
+ tclass = string_to_security_class(argv[3]);
+ if (!tclass) {
+ fprintf(stderr, "Invalid class '%s'\n", argv[3]);
+ exit(2);
+ }
+
+ ret = security_compute_member(argv[1], argv[2], tclass, &buf);
+ if (ret < 0) {
+ fprintf(stderr, "%s: security_compute_member failed\n",
+ argv[0]);
+ exit(3);
+ }
+
+ printf("%s\n", buf);
+ freecon(buf);
+ exit(0);
+}
diff --git a/libselinux/utils/compute_relabel.c b/libselinux/utils/compute_relabel.c
new file mode 100644
index 00000000..970750e8
--- /dev/null
+++ b/libselinux/utils/compute_relabel.c
@@ -0,0 +1,36 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <selinux/selinux.h>
+
+int main(int argc, char **argv)
+{
+ char *buf;
+ security_class_t tclass;
+ int ret;
+
+ if (argc != 4) {
+ fprintf(stderr, "usage: %s scontext tcontext tclass\n",
+ argv[0]);
+ exit(1);
+ }
+
+ tclass = string_to_security_class(argv[3]);
+ if (!tclass) {
+ fprintf(stderr, "%s: invalid class '%s'\n", argv[0], argv[3]);
+ exit(2);
+ }
+
+ ret = security_compute_relabel(argv[1], argv[2], tclass, &buf);
+ if (ret < 0) {
+ fprintf(stderr, "%s: security_compute_relabel failed\n",
+ argv[0]);
+ exit(3);
+ }
+
+ printf("%s\n", buf);
+ freecon(buf);
+ exit(0);
+}
diff --git a/libselinux/utils/compute_user.c b/libselinux/utils/compute_user.c
new file mode 100644
index 00000000..cae62b26
--- /dev/null
+++ b/libselinux/utils/compute_user.c
@@ -0,0 +1,38 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <selinux/selinux.h>
+
+int main(int argc, char **argv)
+{
+ char **buf, **ptr;
+ int ret;
+
+ if (argc != 3) {
+ fprintf(stderr, "usage: %s context user\n", argv[0]);
+ exit(1);
+ }
+
+ ret = security_compute_user(argv[1], argv[2], &buf);
+ if (ret < 0) {
+ fprintf(stderr, "%s: security_compute_user(%s,%s) failed\n",
+ argv[0], argv[1], argv[2]);
+ exit(2);
+ }
+
+ if (!buf[0]) {
+ printf("none\n");
+ exit(0);
+ }
+
+ for (ptr = buf; *ptr; ptr++) {
+ printf("%s\n", *ptr);
+ }
+ freeconary(buf);
+ exit(0);
+}
diff --git a/libselinux/utils/getconlist.c b/libselinux/utils/getconlist.c
new file mode 100644
index 00000000..4f473e4f
--- /dev/null
+++ b/libselinux/utils/getconlist.c
@@ -0,0 +1,73 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <selinux/selinux.h>
+#include <selinux/get_context_list.h>
+
+void usage(char *name, char *detail, int rc)
+{
+ fprintf(stderr, "usage: %s [-l level] user [context]\n", name);
+ if (detail)
+ fprintf(stderr, "%s: %s\n", name, detail);
+ exit(rc);
+}
+
+int main(int argc, char **argv)
+{
+ security_context_t *list, usercon = NULL, cur_context = NULL;
+ char *user = NULL, *level = NULL;
+ int ret, i, opt;
+
+ while ((opt = getopt(argc, argv, "l:")) > 0) {
+ switch (opt) {
+ case 'l':
+ level = strdup(optarg);
+ break;
+ default:
+ usage(argv[0], "invalid option", 1);
+ }
+ }
+
+ if (((argc - optind) < 1) || ((argc - optind) > 2))
+ usage(argv[0], "invalid number of arguments", 2);
+
+ /* If selinux isn't available, bail out. */
+ if (!is_selinux_enabled()) {
+ fprintf(stderr,
+ "getconlist may be used only on a SELinux kernel.\n");
+ return 1;
+ }
+
+ user = argv[optind];
+
+ /* If a context wasn't passed, use the current context. */
+ if (((argc - optind) < 2)) {
+ if (getcon(&cur_context) < 0) {
+ fprintf(stderr, "Couldn't get current context.\n");
+ return 2;
+ }
+ } else
+ cur_context = argv[optind + 1];
+
+ /* Get the list and print it */
+ if (level)
+ ret =
+ get_ordered_context_list_with_level(user, level,
+ cur_context, &list);
+ else
+ ret = get_ordered_context_list(user, cur_context, &list);
+ if (ret != -1) {
+ for (i = 0; list[i]; i++)
+ puts(list[i]);
+ freeconary(list);
+ }
+
+ free(usercon);
+
+ return 0;
+}
diff --git a/libselinux/utils/getdefaultcon.c b/libselinux/utils/getdefaultcon.c
new file mode 100644
index 00000000..93762c1e
--- /dev/null
+++ b/libselinux/utils/getdefaultcon.c
@@ -0,0 +1,80 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <selinux/selinux.h>
+#include <selinux/get_context_list.h>
+
+void usage(char *name, char *detail, int rc)
+{
+ fprintf(stderr, "usage: %s [-l level] user fromcon\n", name);
+ if (detail)
+ fprintf(stderr, "%s: %s\n", name, detail);
+ exit(rc);
+}
+
+int main(int argc, char **argv)
+{
+ security_context_t usercon = NULL, cur_context = NULL;
+ char *user = NULL, *level = NULL, *role=NULL, *seuser=NULL, *dlevel=NULL;
+ int ret, opt;
+
+ while ((opt = getopt(argc, argv, "l:r:")) > 0) {
+ switch (opt) {
+ case 'l':
+ level = strdup(optarg);
+ break;
+ case 'r':
+ role = strdup(optarg);
+ break;
+ default:
+ usage(argv[0], "invalid option", 1);
+ }
+ }
+
+ if (((argc - optind) < 1) || ((argc - optind) > 2))
+ usage(argv[0], "invalid number of arguments", 2);
+
+ /* If selinux isn't available, bail out. */
+ if (!is_selinux_enabled()) {
+ fprintf(stderr,
+ "%s may be used only on a SELinux kernel.\n", argv[0]);
+ return 1;
+ }
+
+ user = argv[optind];
+
+ /* If a context wasn't passed, use the current context. */
+ if (((argc - optind) < 2)) {
+ if (getcon(&cur_context) < 0) {
+ fprintf(stderr, "Couldn't get current context.\n");
+ return 2;
+ }
+ } else
+ cur_context = argv[optind + 1];
+
+ if ((ret = getseuserbyname(user, &seuser, &dlevel)) == 0) {
+ if (! level) level=dlevel;
+ if (role != NULL && role[0])
+ ret=get_default_context_with_rolelevel(seuser, role, level,cur_context,&usercon);
+ else
+ ret=get_default_context_with_level(seuser, level, cur_context,&usercon);
+ }
+ if (ret < 0)
+ perror(argv[0]);
+ else
+ printf("%s: %s from %s %s %s %s -> %s\n", argv[0], user, cur_context, seuser, role, level, usercon);
+
+
+ free(role);
+ free(seuser);
+ if (level != dlevel) free(level);
+ free(dlevel);
+ free(usercon);
+
+ return 0;
+}
diff --git a/libselinux/utils/getenforce.c b/libselinux/utils/getenforce.c
new file mode 100644
index 00000000..891c7b7e
--- /dev/null
+++ b/libselinux/utils/getenforce.c
@@ -0,0 +1,31 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <selinux/selinux.h>
+
+int main(int argc __attribute__ ((unused)), char **argv)
+{
+ int rc;
+
+ rc = is_selinux_enabled();
+ if (rc < 0) {
+ fputs("getenforce: is_selinux_enabled() failed", stderr);
+ return 2;
+ }
+ if (rc == 1) {
+ rc = security_getenforce();
+ if (rc < 0) {
+ fputs("getenforce: getenforce() failed", stderr);
+ return 2;
+ }
+
+ if (rc)
+ puts("Enforcing");
+ else
+ puts("Permissive");
+ } else {
+ puts("Disabled");
+ }
+
+ return 0;
+}
diff --git a/libselinux/utils/getfilecon.c b/libselinux/utils/getfilecon.c
new file mode 100644
index 00000000..a7a51abb
--- /dev/null
+++ b/libselinux/utils/getfilecon.c
@@ -0,0 +1,27 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <selinux/selinux.h>
+
+int main(int argc, char **argv)
+{
+ char *buf;
+ int rc, i;
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s path...\n", argv[0]);
+ exit(1);
+ }
+
+ for (i = 1; i < argc; i++) {
+ rc = getfilecon(argv[i], &buf);
+ if (rc < 0) {
+ fprintf(stderr, "%s: getfilecon(%s) failed\n", argv[0],
+ argv[i]);
+ exit(2);
+ }
+ printf("%s\t%s\n", argv[i], buf);
+ freecon(buf);
+ }
+ exit(0);
+}
diff --git a/libselinux/utils/getpidcon.c b/libselinux/utils/getpidcon.c
new file mode 100644
index 00000000..3df0da1f
--- /dev/null
+++ b/libselinux/utils/getpidcon.c
@@ -0,0 +1,31 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <selinux/selinux.h>
+
+int main(int argc, char **argv)
+{
+ pid_t pid;
+ char *buf;
+ int rc;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s pid\n", argv[0]);
+ exit(1);
+ }
+
+ if (sscanf(argv[1], "%d", &pid) != 1) {
+ fprintf(stderr, "%s: invalid pid %s\n", argv[0], argv[1]);
+ exit(2);
+ }
+
+ rc = getpidcon(pid, &buf);
+ if (rc < 0) {
+ fprintf(stderr, "%s: getpidcon() failed\n", argv[0]);
+ exit(3);
+ }
+
+ printf("%s\n", buf);
+ freecon(buf);
+ exit(0);
+}
diff --git a/libselinux/utils/getsebool.c b/libselinux/utils/getsebool.c
new file mode 100644
index 00000000..cab2bb9c
--- /dev/null
+++ b/libselinux/utils/getsebool.c
@@ -0,0 +1,105 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <errno.h>
+#include <string.h>
+#include <selinux/selinux.h>
+
+void usage(const char *progname)
+{
+ fprintf(stderr, "usage: %s -a or %s boolean...\n", progname, progname);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ int i, get_all = 0, rc = 0, active, pending, len = 0, opt;
+ char **names;
+
+ while ((opt = getopt(argc, argv, "a")) > 0) {
+ switch (opt) {
+ case 'a':
+ if (argc > 2)
+ usage(argv[0]);
+ if (is_selinux_enabled() <= 0) {
+ fprintf(stderr, "%s: SELinux is disabled\n",
+ argv[0]);
+ return 1;
+ }
+ errno = 0;
+ rc = security_get_boolean_names(&names, &len);
+ if (rc) {
+ fprintf(stderr,
+ "%s: Unable to get boolean names: %s\n",
+ argv[0], strerror(errno));
+ return 1;
+ }
+ if (!len) {
+ printf("No booleans\n");
+ return 0;
+ }
+ get_all = 1;
+ break;
+ default:
+ usage(argv[0]);
+ }
+ }
+
+ if (is_selinux_enabled() <= 0) {
+ fprintf(stderr, "%s: SELinux is disabled\n", argv[0]);
+ return 1;
+ }
+
+ if (!len) {
+ if (argc < 2)
+ usage(argv[0]);
+ len = argc - 1;
+ names = malloc(sizeof(char *) * len);
+ if (!names) {
+ fprintf(stderr, "%s: out of memory\n", argv[0]);
+ return 2;
+ }
+ for (i = 0; i < len; i++) {
+ names[i] = strdup(argv[i + 1]);
+ if (!names[i]) {
+ fprintf(stderr, "%s: out of memory\n",
+ argv[0]);
+ return 2;
+ }
+ }
+ }
+
+ for (i = 0; i < len; i++) {
+ active = security_get_boolean_active(names[i]);
+ if (active < 0) {
+ if (get_all && errno == EACCES)
+ continue;
+ fprintf(stderr, "Error getting active value for %s\n",
+ names[i]);
+ rc = -1;
+ goto out;
+ }
+ pending = security_get_boolean_pending(names[i]);
+ if (pending < 0) {
+ fprintf(stderr, "Error getting pending value for %s\n",
+ names[i]);
+ rc = -1;
+ goto out;
+ }
+ if (pending != active) {
+ printf("%s --> %s pending: %s\n", names[i],
+ (active ? "on" : "off"),
+ (pending ? "on" : "off"));
+ } else {
+ printf("%s --> %s\n", names[i],
+ (active ? "on" : "off"));
+ }
+ }
+
+ out:
+ for (i = 0; i < len; i++)
+ free(names[i]);
+ free(names);
+ return rc;
+}
diff --git a/libselinux/utils/getseuser.c b/libselinux/utils/getseuser.c
new file mode 100644
index 00000000..1e7ed765
--- /dev/null
+++ b/libselinux/utils/getseuser.c
@@ -0,0 +1,40 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <selinux/selinux.h>
+#include <selinux/get_context_list.h>
+
+int main(int argc, char **argv)
+{
+ char *seuser = NULL, *level = NULL;
+ security_context_t *contextlist;
+ int rc, n, i;
+
+ if (argc != 3) {
+ fprintf(stderr, "usage: %s linuxuser fromcon\n", argv[0]);
+ exit(1);
+ }
+
+ rc = getseuserbyname(argv[1], &seuser, &level);
+ if (rc) {
+ fprintf(stderr, "getseuserbyname failed: %s\n",
+ strerror(errno));
+ exit(2);
+ }
+ printf("seuser: %s, level %s\n", seuser, level);
+ n = get_ordered_context_list_with_level(seuser, level, argv[2],
+ &contextlist);
+ if (n <= 0) {
+ fprintf(stderr,
+ "get_ordered_context_list_with_level failed: %s\n",
+ strerror(errno));
+ exit(3);
+ }
+ free(seuser);
+ free(level);
+ for (i = 0; i < n; i++)
+ printf("Context %d\t%s\n", i, contextlist[i]);
+ freeconary(contextlist);
+ exit(0);
+}
diff --git a/libselinux/utils/matchpathcon.c b/libselinux/utils/matchpathcon.c
new file mode 100644
index 00000000..5276d24d
--- /dev/null
+++ b/libselinux/utils/matchpathcon.c
@@ -0,0 +1,143 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+#include <selinux/selinux.h>
+
+void usage(const char *progname)
+{
+ fprintf(stderr,
+ "usage: %s [-N] [-n] [-f file_contexts] [-p prefix] [-Vq] path...\n",
+ progname);
+ exit(1);
+}
+
+int printmatchpathcon(char *path, int header, int mode)
+{
+ char *buf;
+ int rc = matchpathcon(path, mode, &buf);
+ if (rc < 0) {
+ fprintf(stderr, "matchpathcon(%s) failed: %s\n", path,
+ strerror(errno));
+ return 1;
+ }
+ if (header)
+ printf("%s\t%s\n", path, buf);
+ else
+ printf("%s\n", buf);
+
+ freecon(buf);
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int i, init = 0;
+ int header = 1, opt;
+ int verify = 0;
+ int notrans = 0;
+ int error = 0;
+ int quiet = 0;
+
+ if (argc < 2)
+ usage(argv[0]);
+
+ while ((opt = getopt(argc, argv, "Nnf:p:Vq")) > 0) {
+ switch (opt) {
+ case 'n':
+ header = 0;
+ break;
+ case 'V':
+ verify = 1;
+ break;
+ case 'N':
+ notrans = 1;
+ set_matchpathcon_flags(MATCHPATHCON_NOTRANS);
+ break;
+ case 'f':
+ if (init) {
+ fprintf(stderr,
+ "%s: -f and -p are exclusive\n",
+ argv[0]);
+ exit(1);
+ }
+ init = 1;
+ if (matchpathcon_init(optarg)) {
+ fprintf(stderr,
+ "Error while processing %s: %s\n",
+ optarg,
+ errno ? strerror(errno) : "invalid");
+ exit(1);
+ }
+ break;
+ case 'p':
+ if (init) {
+ fprintf(stderr,
+ "%s: -f and -p are exclusive\n",
+ argv[0]);
+ exit(1);
+ }
+ init = 1;
+ if (matchpathcon_init_prefix(NULL, optarg)) {
+ fprintf(stderr,
+ "Error while processing %s: %s\n",
+ optarg,
+ errno ? strerror(errno) : "invalid");
+ exit(1);
+ }
+ break;
+ case 'q':
+ quiet = 1;
+ break;
+ default:
+ usage(argv[0]);
+ }
+ }
+ for (i = optind; i < argc; i++) {
+ int mode = 0;
+ struct stat buf;
+ if (lstat(argv[i], &buf) == 0)
+ mode = buf.st_mode;
+
+ if (verify) {
+ if (quiet) {
+ if (selinux_file_context_verify(argv[i], 0))
+ continue;
+ else
+ exit(1);
+ }
+ if (selinux_file_context_verify(argv[i], 0)) {
+ printf("%s verified.\n", argv[i]);
+ } else {
+ security_context_t con;
+ int rc;
+ error = 1;
+ if (notrans)
+ rc = lgetfilecon_raw(argv[i], &con);
+ else
+ rc = lgetfilecon(argv[i], &con);
+
+ if (rc >= 0) {
+ printf("%s has context %s, should be ",
+ argv[i], con);
+ printmatchpathcon(argv[i], 0, mode);
+ freecon(con);
+ } else {
+ printf
+ ("actual context unknown: %s, should be ",
+ strerror(errno));
+ printmatchpathcon(argv[i], 0, mode);
+ }
+ }
+ } else {
+ error |= printmatchpathcon(argv[i], header, mode);
+ }
+ }
+ matchpathcon_fini();
+ return error;
+}
diff --git a/libselinux/utils/policyvers.c b/libselinux/utils/policyvers.c
new file mode 100644
index 00000000..0309d7d1
--- /dev/null
+++ b/libselinux/utils/policyvers.c
@@ -0,0 +1,18 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <selinux/selinux.h>
+
+int main(int argc __attribute__ ((unused)), char **argv)
+{
+ int rc;
+
+ rc = security_policyvers();
+ if (rc < 0) {
+ fprintf(stderr, "%s: policyvers() failed\n", argv[0]);
+ exit(2);
+ }
+
+ printf("%d\n", rc);
+ exit(0);
+}
diff --git a/libselinux/utils/selinux_check_securetty_context.c b/libselinux/utils/selinux_check_securetty_context.c
new file mode 100644
index 00000000..95bfb7f2
--- /dev/null
+++ b/libselinux/utils/selinux_check_securetty_context.c
@@ -0,0 +1,35 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+#include <selinux/selinux.h>
+
+void usage(const char *progname)
+{
+ fprintf(stderr, "usage: %s tty_context...\n", progname);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+ if (argc < 2)
+ usage(argv[0]);
+
+ for (i = 1; i < argc; i++) {
+ switch (selinux_check_securetty_context(argv[i])) {
+ case 0:
+ printf("%s securetty.\n", argv[i]);
+ break;
+ default:
+ printf("%s not securetty.\n", argv[i]);
+ break;
+ }
+ }
+ return 0;
+}
diff --git a/libselinux/utils/selinuxenabled.c b/libselinux/utils/selinuxenabled.c
new file mode 100644
index 00000000..04ea7783
--- /dev/null
+++ b/libselinux/utils/selinuxenabled.c
@@ -0,0 +1,9 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <selinux/selinux.h>
+
+int main(void)
+{
+ return !is_selinux_enabled();
+}
diff --git a/libselinux/utils/setenforce.c b/libselinux/utils/setenforce.c
new file mode 100644
index 00000000..e45b804d
--- /dev/null
+++ b/libselinux/utils/setenforce.c
@@ -0,0 +1,42 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <strings.h>
+#include <selinux/selinux.h>
+
+void usage(const char *progname)
+{
+ fprintf(stderr, "usage: %s [ Enforcing | Permissive | 1 | 0 ]\n",
+ progname);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ int rc = 0;
+ if (argc != 2) {
+ usage(argv[0]);
+ }
+
+ if (is_selinux_enabled() <= 0) {
+ fprintf(stderr, "%s: SELinux is disabled\n", argv[0]);
+ return 1;
+ }
+ if (strlen(argv[1]) == 1 && (argv[1][0] == '0' || argv[1][0] == '1')) {
+ rc = security_setenforce(atoi(argv[1]));
+ } else {
+ if (strcasecmp(argv[1], "enforcing") == 0) {
+ rc = security_setenforce(1);
+ } else if (strcasecmp(argv[1], "permissive") == 0) {
+ rc = security_setenforce(0);
+ } else
+ usage(argv[0]);
+ }
+ if (rc < 0) {
+ fprintf(stderr, "%s: setenforce() failed\n", argv[0]);
+ return 2;
+ }
+ return 0;
+}
diff --git a/libselinux/utils/setfilecon.c b/libselinux/utils/setfilecon.c
new file mode 100644
index 00000000..d69af84a
--- /dev/null
+++ b/libselinux/utils/setfilecon.c
@@ -0,0 +1,24 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <selinux/selinux.h>
+
+int main(int argc, char **argv)
+{
+ int rc, i;
+
+ if (argc < 3) {
+ fprintf(stderr, "usage: %s context path...\n", argv[0]);
+ exit(1);
+ }
+
+ for (i = 2; i < argc; i++) {
+ rc = setfilecon(argv[i], argv[1]);
+ if (rc < 0) {
+ fprintf(stderr, "%s: setfilecon(%s,%s) failed\n",
+ argv[0], argv[i], argv[1]);
+ exit(2);
+ }
+ }
+ exit(0);
+}
diff --git a/libselinux/utils/togglesebool.c b/libselinux/utils/togglesebool.c
new file mode 100644
index 00000000..680ed8d0
--- /dev/null
+++ b/libselinux/utils/togglesebool.c
@@ -0,0 +1,97 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <libgen.h>
+#include <errno.h>
+#include <selinux/selinux.h>
+#include <syslog.h>
+#include <pwd.h>
+#include <string.h>
+
+/* Attempt to rollback the transaction. No need to check error
+ codes since this is rolling back something that blew up. */
+void rollback(int argc, char **argv)
+{
+ int i;
+
+ for (i = 1; i < argc; i++)
+ security_set_boolean(argv[i],
+ security_get_boolean_active(argv[i]));
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+
+ int rc, i, commit = 0;
+
+ if (is_selinux_enabled() <= 0) {
+ fprintf(stderr, "%s: SELinux is disabled\n", argv[0]);
+ return 1;
+ }
+
+ if (argc < 2) {
+ printf("Usage: %s boolname1 [boolname2 ...]\n",
+ basename(argv[0]));
+ return 1;
+ }
+
+ for (i = 1; i < argc; i++) {
+ printf("%s: ", argv[i]);
+ rc = security_get_boolean_active(argv[i]);
+ switch (rc) {
+ case 1:
+ if (security_set_boolean(argv[i], 0) >= 0) {
+ printf("inactive\n");
+ commit++;
+ } else {
+ printf("%s - rolling back all changes\n",
+ strerror(errno));
+ rollback(i, argv);
+ }
+ break;
+ case 0:
+ if (security_set_boolean(argv[i], 1) >= 0) {
+ printf("active\n");
+ commit++;
+ } else {
+ printf("%s - rolling back all changes\n",
+ strerror(errno));
+ rollback(i, argv);
+ }
+ break;
+ default:
+ if (errno == ENOENT)
+ printf
+ ("Boolean does not exist - rolling back all changes.\n");
+ else
+ printf("%s - rolling back all changes.\n",
+ strerror(errno));
+ rollback(i, argv);
+ break; /* Not reached. */
+ }
+ }
+
+ if (commit > 0) {
+ if (security_commit_booleans() < 0) {
+ printf("Commit failed. (%s) No change to booleans.\n",
+ strerror(errno));
+ } else {
+ /* syslog all the changes */
+ struct passwd *pwd = getpwuid(getuid());
+ for (i = 1; i < argc; i++) {
+ if (pwd && pwd->pw_name)
+ syslog(LOG_NOTICE,
+ "The %s policy boolean was toggled by %s",
+ argv[i], pwd->pw_name);
+ else
+ syslog(LOG_NOTICE,
+ "The %s policy boolean was toggled by uid:%d",
+ argv[i], getuid());
+
+ }
+ return 0;
+ }
+ }
+ return 1;
+}