Merge "Extend toolbox with SE Android support."

This commit is contained in:
Jean-Baptiste Queru 2012-02-24 11:10:55 -08:00 committed by android code review
commit 1ea9fce46f
12 changed files with 616 additions and 8 deletions

View File

@ -57,6 +57,21 @@ TOOLS := \
touch \
lsof
ifeq ($(HAVE_SELINUX),true)
TOOLS += \
getenforce \
setenforce \
chcon \
restorecon \
runcon \
getsebool \
setsebool \
load_policy
endif
ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
TOOLS += r
endif
@ -68,6 +83,14 @@ LOCAL_SRC_FILES:= \
LOCAL_SHARED_LIBRARIES := libcutils libc libusbhost
ifeq ($(HAVE_SELINUX),true)
LOCAL_CFLAGS += -DHAVE_SELINUX
LOCAL_SHARED_LIBRARIES += libselinux
LOCAL_C_INCLUDES += external/libselinux/include
endif
LOCAL_MODULE:= toolbox
# Including this will define $(intermediates).

25
toolbox/chcon.c Normal file
View File

@ -0,0 +1,25 @@
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <selinux/selinux.h>
int chcon_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: Could not label %s with %s: %s\n",
argv[0], argv[i], argv[1], strerror(errno));
exit(2);
}
}
exit(0);
}

30
toolbox/getenforce.c Normal file
View File

@ -0,0 +1,30 @@
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <selinux/selinux.h>
int getenforce_main(int argc, char **argv)
{
int rc;
rc = is_selinux_enabled();
if (rc <= 0) {
printf("Disabled\n");
return 0;
}
rc = security_getenforce();
if (rc < 0) {
fprintf(stderr, "Could not get enforcing status: %s\n",
strerror(errno));
return 2;
}
if (rc)
printf("Enforcing\n");
else
printf("Permissive\n");
return 0;
}

104
toolbox/getsebool.c Normal file
View File

@ -0,0 +1,104 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>
#include <errno.h>
#include <string.h>
#include <selinux/selinux.h>
static void usage(const char *progname)
{
fprintf(stderr, "usage: %s -a or %s boolean...\n", progname, progname);
exit(1);
}
int getsebool_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;
}

View File

@ -5,6 +5,10 @@
#include <pwd.h>
#include <grp.h>
#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
#endif
static void print_uid(uid_t uid)
{
struct passwd *pw = getpwuid(uid);
@ -30,6 +34,9 @@ int id_main(int argc, char **argv)
{
gid_t list[64];
int n, max;
#ifdef HAVE_SELINUX
char *secctx;
#endif
max = getgroups(64, list);
if (max < 0) max = 0;
@ -46,6 +53,12 @@ int id_main(int argc, char **argv)
print_gid(list[n]);
}
}
#ifdef HAVE_SELINUX
if (getcon(&secctx) == 0) {
printf(" context=%s", secctx);
free(secctx);
}
#endif
printf("\n");
return 0;
}

49
toolbox/load_policy.c Normal file
View File

@ -0,0 +1,49 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <errno.h>
#include <selinux/selinux.h>
int load_policy_main(int argc, char **argv)
{
int fd, rc, vers;
struct stat sb;
void *map;
const char *path;
if (argc != 2) {
fprintf(stderr, "usage: %s policy-file\n", argv[0]);
exit(1);
}
path = argv[1];
fd = open(path, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Could not open %s: %s\n", path, strerror(errno));
exit(2);
}
if (fstat(fd, &sb) < 0) {
fprintf(stderr, "Could not stat %s: %s\n", path, strerror(errno));
exit(3);
}
map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (map == MAP_FAILED) {
fprintf(stderr, "Could not mmap %s: %s\n", path, strerror(errno));
exit(4);
}
rc = security_load_policy(map, sb.st_size);
if (rc < 0) {
fprintf(stderr, "Could not load %s: %s\n", path, strerror(errno));
exit(5);
}
munmap(map, sb.st_size);
close(fd);
exit(0);
}

View File

@ -5,6 +5,10 @@
#include <dirent.h>
#include <errno.h>
#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
#endif
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
@ -25,6 +29,7 @@
#define LIST_SIZE (1 << 4)
#define LIST_LONG_NUMERIC (1 << 5)
#define LIST_CLASSIFY (1 << 6)
#define LIST_MACLABEL (1 << 7)
// fwd
static int listpath(const char *name, int flags);
@ -234,9 +239,75 @@ static int listfile_long(const char *path, int flags)
return 0;
}
static int listfile_maclabel(const char *path, int flags)
{
struct stat s;
char mode[16];
char user[16];
char group[16];
char *maclabel = NULL;
const char *name;
/* name is anything after the final '/', or the whole path if none*/
name = strrchr(path, '/');
if(name == 0) {
name = path;
} else {
name++;
}
if(lstat(path, &s) < 0) {
return -1;
}
#ifdef HAVE_SELINUX
lgetfilecon(path, &maclabel);
#else
maclabel = strdup("-");
#endif
if (!maclabel) {
return -1;
}
mode2str(s.st_mode, mode);
user2str(s.st_uid, user);
group2str(s.st_gid, group);
switch(s.st_mode & S_IFMT) {
case S_IFLNK: {
char linkto[256];
int len;
len = readlink(path, linkto, sizeof(linkto));
if(len < 0) return -1;
if(len > sizeof(linkto)-1) {
linkto[sizeof(linkto)-4] = '.';
linkto[sizeof(linkto)-3] = '.';
linkto[sizeof(linkto)-2] = '.';
linkto[sizeof(linkto)-1] = 0;
} else {
linkto[len] = 0;
}
printf("%s %-8s %-8s %s %s -> %s\n",
mode, user, group, maclabel, name, linkto);
break;
}
default:
printf("%s %-8s %-8s %s %s\n",
mode, user, group, maclabel, name);
}
free(maclabel);
return 0;
}
static int listfile(const char *dirname, const char *filename, int flags)
{
if ((flags & (LIST_LONG | LIST_SIZE | LIST_CLASSIFY)) == 0) {
if ((flags & LIST_LONG | LIST_SIZE | LIST_CLASSIFY | LIST_MACLABEL) == 0) {
printf("%s\n", filename);
return 0;
}
@ -251,7 +322,9 @@ static int listfile(const char *dirname, const char *filename, int flags)
pathname = filename;
}
if ((flags & LIST_LONG) != 0) {
if ((flags & LIST_MACLABEL) != 0) {
return listfile_maclabel(pathname, flags);
} else if ((flags & LIST_LONG) != 0) {
return listfile_long(pathname, flags);
} else /*((flags & LIST_SIZE) != 0)*/ {
return listfile_size(pathname, filename, flags);
@ -386,6 +459,7 @@ int ls_main(int argc, char **argv)
case 's': flags |= LIST_SIZE; break;
case 'R': flags |= LIST_RECURSIVE; break;
case 'd': flags |= LIST_DIRECTORIES; break;
case 'Z': flags |= LIST_MACLABEL; break;
case 'a': flags |= LIST_ALL; break;
case 'F': flags |= LIST_CLASSIFY; break;
default:

View File

@ -13,7 +13,6 @@
#include <cutils/sched_policy.h>
static char *nexttoksep(char **strp, char *sep)
{
char *p = strsep(strp,sep);
@ -28,6 +27,7 @@ static char *nexttok(char **strp)
#define SHOW_TIME 2
#define SHOW_POLICY 4
#define SHOW_CPU 8
#define SHOW_MACLABEL 16
static int display_flags = 0;
@ -35,6 +35,7 @@ static int ps_line(int pid, int tid, char *namefilter)
{
char statline[1024];
char cmdline[1024];
char macline[1024];
char user[32];
struct stat stats;
int fd, r;
@ -51,9 +52,11 @@ static int ps_line(int pid, int tid, char *namefilter)
if(tid) {
sprintf(statline, "/proc/%d/task/%d/stat", pid, tid);
cmdline[0] = 0;
snprintf(macline, sizeof(macline), "/proc/%d/task/%d/attr/current", pid, tid);
} else {
sprintf(statline, "/proc/%d/stat", pid);
sprintf(cmdline, "/proc/%d/cmdline", pid);
sprintf(cmdline, "/proc/%d/cmdline", pid);
snprintf(macline, sizeof(macline), "/proc/%d/attr/current", pid);
fd = open(cmdline, O_RDONLY);
if(fd == 0) {
r = 0;
@ -142,6 +145,19 @@ static int ps_line(int pid, int tid, char *namefilter)
}
if(!namefilter || !strncmp(name, namefilter, strlen(namefilter))) {
if (display_flags & SHOW_MACLABEL) {
fd = open(macline, O_RDONLY);
strcpy(macline, "-");
if (fd >= 0) {
r = read(fd, macline, sizeof(macline)-1);
close(fd);
if (r > 0)
macline[r] = 0;
}
printf("%-30s %-9s %-5d %-5d %s\n", macline, user, pid, ppid, cmdline[0] ? cmdline : name);
return 0;
}
printf("%-9s %-5d %-5d %-6d %-5d", user, pid, ppid, vss / 1024, rss * 4);
if (display_flags & SHOW_CPU)
printf(" %-2d", psr);
@ -206,6 +222,8 @@ int ps_main(int argc, char **argv)
threads = 1;
} else if(!strcmp(argv[1],"-x")) {
display_flags |= SHOW_TIME;
} else if(!strcmp(argv[1], "-Z")) {
display_flags |= SHOW_MACLABEL;
} else if(!strcmp(argv[1],"-P")) {
display_flags |= SHOW_POLICY;
} else if(!strcmp(argv[1],"-p")) {
@ -221,10 +239,14 @@ int ps_main(int argc, char **argv)
argv++;
}
printf("USER PID PPID VSIZE RSS %s%s %s WCHAN PC NAME\n",
(display_flags&SHOW_CPU)?"CPU ":"",
(display_flags&SHOW_PRIO)?"PRIO NICE RTPRI SCHED ":"",
(display_flags&SHOW_POLICY)?"PCY " : "");
if (display_flags & SHOW_MACLABEL) {
printf("LABEL USER PID PPID NAME\n");
} else {
printf("USER PID PPID VSIZE RSS %s%s %s WCHAN PC NAME\n",
(display_flags&SHOW_CPU)?"CPU ":"",
(display_flags&SHOW_PRIO)?"PRIO NICE RTPRI SCHED ":"",
(display_flags&SHOW_POLICY)?"PCY " : "");
}
while((de = readdir(d)) != 0){
if(isdigit(de->d_name[0])){
int pid = atoi(de->d_name);

141
toolbox/restorecon.c Normal file
View File

@ -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;
}

28
toolbox/runcon.c Normal file
View File

@ -0,0 +1,28 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <selinux/selinux.h>
int runcon_main(int argc, char **argv)
{
int rc;
if (argc < 3) {
fprintf(stderr, "usage: %s context program args...\n", argv[0]);
exit(1);
}
rc = setexeccon(argv[1]);
if (rc < 0) {
fprintf(stderr, "Could not set context to %s: %s\n", argv[1], strerror(errno));
exit(2);
}
argv += 2;
argc -= 2;
execvp(argv[0], argv);
fprintf(stderr, "Could not exec %s: %s\n", argv[0], strerror(errno));
exit(3);
}

44
toolbox/setenforce.c Normal file
View File

@ -0,0 +1,44 @@
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <selinux/selinux.h>
void usage(const char *progname)
{
fprintf(stderr, "usage: %s [ Enforcing | Permissive | 1 | 0 ]\n",
progname);
exit(1);
}
int setenforce_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: Could not set enforcing status: %s\n",
argv[0], strerror(errno));
return 2;
}
return 0;
}

55
toolbox/setsebool.c Normal file
View File

@ -0,0 +1,55 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <selinux/selinux.h>
#include <errno.h>
static int do_setsebool(int nargs, char **args) {
SELboolean *b = alloca(nargs * sizeof(SELboolean));
char *v;
int i;
if (is_selinux_enabled() <= 0)
return 0;
for (i = 1; i < nargs; i++) {
char *name = args[i];
v = strchr(name, '=');
if (!v) {
fprintf(stderr, "setsebool: argument %s had no =\n", name);
return -1;
}
*v++ = 0;
b[i-1].name = name;
if (!strcmp(v, "1") || !strcasecmp(v, "true") || !strcasecmp(v, "on"))
b[i-1].value = 1;
else if (!strcmp(v, "0") || !strcasecmp(v, "false") || !strcasecmp(v, "off"))
b[i-1].value = 0;
else {
fprintf(stderr, "setsebool: invalid value %s\n", v);
return -1;
}
}
if (security_set_boolean_list(nargs - 1, b, 0) < 0)
{
fprintf(stderr, "setsebool: unable to set booleans: %s", strerror(errno));
return -1;
}
return 0;
}
int setsebool_main(int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr, "Usage: %s name=value...\n", argv[0]);
exit(1);
}
return do_setsebool(argc, argv);
}