Extend toolbox with SE Android support.
Add -Z option to ls and ps for displaying security contexts.
Modify id to display security context.
Add new SELinux commands: chcon, getenforce, getsebool, load_policy, restorecon, runcon, setenforce, setsebool.
Change-Id: Ia20941be4a6cd706fe392fed6e38a37d880ec5f1
diff --git a/toolbox/restorecon.c b/toolbox/restorecon.c
new file mode 100644
index 0000000..5ef0ef1
--- /dev/null
+++ b/toolbox/restorecon.c
@@ -0,0 +1,141 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fts.h>
+#include <selinux/selinux.h>
+#include <selinux/label.h>
+
+#define FCPATH "/file_contexts"
+
+static struct selabel_handle *sehandle;
+static const char *progname;
+static int nochange;
+static int verbose;
+
+static void usage(void)
+{
+ fprintf(stderr, "usage: %s [-f file_contexts] [-nrRv] pathname...\n", progname);
+ exit(1);
+}
+
+static int restore(const char *pathname, const struct stat *sb)
+{
+ char *oldcontext, *newcontext;
+
+ if (lgetfilecon(pathname, &oldcontext) < 0) {
+ fprintf(stderr, "Could not get context of %s: %s\n",
+ pathname, strerror(errno));
+ return -1;
+ }
+ if (selabel_lookup(sehandle, &newcontext, pathname, sb->st_mode) < 0) {
+ fprintf(stderr, "Could not lookup context for %s: %s\n", pathname,
+ strerror(errno));
+ return -1;
+ }
+ if (strcmp(newcontext, "<<none>>") &&
+ strcmp(oldcontext, newcontext)) {
+ if (verbose)
+ printf("Relabeling %s from %s to %s.\n", pathname, oldcontext, newcontext);
+ if (!nochange) {
+ if (lsetfilecon(pathname, newcontext) < 0) {
+ fprintf(stderr, "Could not label %s with %s: %s\n",
+ pathname, newcontext, strerror(errno));
+ return -1;
+ }
+ }
+ }
+ freecon(oldcontext);
+ freecon(newcontext);
+ return 0;
+}
+
+int restorecon_main(int argc, char **argv)
+{
+ struct selinux_opt seopts[] = {
+ { SELABEL_OPT_PATH, FCPATH }
+ };
+ int ch, recurse = 0, ftsflags = FTS_PHYSICAL;
+
+ progname = argv[0];
+
+ do {
+ ch = getopt(argc, argv, "f:nrRv");
+ if (ch == EOF)
+ break;
+ switch (ch) {
+ case 'f':
+ seopts[0].value = optarg;
+ break;
+ case 'n':
+ nochange = 1;
+ break;
+ case 'r':
+ case 'R':
+ recurse = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ usage();
+ }
+ } while (1);
+
+ argc -= optind;
+ argv += optind;
+ if (!argc)
+ usage();
+
+ sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);
+ if (!sehandle) {
+ fprintf(stderr, "Could not load file contexts from %s: %s\n", seopts[0].value,
+ strerror(errno));
+ return -1;
+ }
+
+ if (recurse) {
+ FTS *fts;
+ FTSENT *ftsent;
+ fts = fts_open(argv, ftsflags, NULL);
+ if (!fts) {
+ fprintf(stderr, "Could not traverse filesystems (first was %s): %s\n",
+ argv[0], strerror(errno));
+ return -1;
+ }
+ while ((ftsent = fts_read(fts))) {
+ switch (ftsent->fts_info) {
+ case FTS_DP:
+ break;
+ case FTS_DNR:
+ case FTS_ERR:
+ case FTS_NS:
+ fprintf(stderr, "Could not access %s: %s\n", ftsent->fts_path,
+ strerror(errno));
+ fts_set(fts, ftsent, FTS_SKIP);
+ break;
+ default:
+ if (restore(ftsent->fts_path, ftsent->fts_statp) < 0)
+ fts_set(fts, ftsent, FTS_SKIP);
+ break;
+ }
+ }
+ } else {
+ int i, rc;
+ struct stat sb;
+
+ for (i = 0; i < argc; i++) {
+ rc = lstat(argv[i], &sb);
+ if (rc < 0) {
+ fprintf(stderr, "Could not stat %s: %s\n", argv[i],
+ strerror(errno));
+ continue;
+ }
+ restore(argv[i], &sb);
+ }
+ }
+
+ return 0;
+}