Skip to content

Commit

Permalink
Extend init and ueventd for SE Android.
Browse files Browse the repository at this point in the history
Add SE Android support for init and ueventd.

init:
- Load policy at boot.
- Set the security context for service daemons and their sockets.
- New built-in commands: setcon, setenforce, restorecon, setsebool.
- New option for services: seclabel.

ueventd:
- Set the security context for device directories and nodes.

Change-Id: I98ed752cde503c94d99dfa5b5a47e3c33db16aac
  • Loading branch information
stephensmalley committed Feb 1, 2012
1 parent 0458d37 commit e46f9d5
Show file tree
Hide file tree
Showing 8 changed files with 390 additions and 13 deletions.
6 changes: 6 additions & 0 deletions init/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)

LOCAL_STATIC_LIBRARIES := libcutils libc

ifeq ($(HAVE_SELINUX),true)
LOCAL_STATIC_LIBRARIES += libselinux
LOCAL_C_INCLUDES := external/libselinux/include
LOCAL_CFLAGS += -DHAVE_SELINUX
endif

include $(BUILD_EXECUTABLE)

# Make a symlink from /sbin/ueventd to /init
Expand Down
85 changes: 85 additions & 0 deletions init/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@
#include <cutils/partition_utils.h>
#include <sys/system_properties.h>

#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
#include <selinux/label.h>
#endif

#include "init.h"
#include "keywords.h"
#include "property_service.h"
Expand Down Expand Up @@ -436,6 +441,28 @@ int do_mount(int nargs, char **args)

}

int do_setcon(int nargs, char **args) {
#ifdef HAVE_SELINUX
if (is_selinux_enabled() <= 0)
return 0;
if (setcon(args[1]) < 0) {
return -errno;
}
#endif
return 0;
}

int do_setenforce(int nargs, char **args) {
#ifdef HAVE_SELINUX
if (is_selinux_enabled() <= 0)
return 0;
if (security_setenforce(atoi(args[1])) < 0) {
return -errno;
}
#endif
return 0;
}

int do_setkey(int nargs, char **args)
{
struct kbentry kbe;
Expand Down Expand Up @@ -649,6 +676,64 @@ int do_chmod(int nargs, char **args) {
return 0;
}

int do_restorecon(int nargs, char **args) {
#ifdef HAVE_SELINUX
char *secontext = NULL;
struct stat sb;
int i;

if (is_selinux_enabled() <= 0 || !sehandle)
return 0;

for (i = 1; i < nargs; i++) {
if (lstat(args[i], &sb) < 0)
return -errno;
if (selabel_lookup(sehandle, &secontext, args[i], sb.st_mode) < 0)
return -errno;
if (lsetfilecon(args[i], secontext) < 0) {
freecon(secontext);
return -errno;
}
freecon(secontext);
}
#endif
return 0;
}

int do_setsebool(int nargs, char **args) {
#ifdef HAVE_SELINUX
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) {
ERROR("setsebool: argument %s had no =\n", name);
return -EINVAL;
}
*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 {
ERROR("setsebool: invalid value %s\n", v);
return -EINVAL;
}
}

if (security_set_boolean_list(nargs - 1, b, 0) < 0)
return -errno;
#endif
return 0;
}

int do_loglevel(int nargs, char **args) {
if (nargs == 2) {
klog_set_level(atoi(args[1]));
Expand Down
82 changes: 70 additions & 12 deletions init/devices.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <linux/netlink.h>

#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
#include <selinux/label.h>
#endif

#include <private/android_filesystem_config.h>
#include <sys/time.h>
#include <asm/page.h>
Expand All @@ -45,6 +51,10 @@
#define FIRMWARE_DIR1 "/etc/firmware"
#define FIRMWARE_DIR2 "/vendor/firmware"

#ifdef HAVE_SELINUX
static struct selabel_handle *sehandle;
#endif

static int device_fd = -1;

struct uevent {
Expand Down Expand Up @@ -180,8 +190,17 @@ static void make_device(const char *path,
unsigned gid;
mode_t mode;
dev_t dev;
#ifdef HAVE_SELINUX
char *secontext = NULL;
#endif

mode = get_device_perm(path, &uid, &gid) | (block ? S_IFBLK : S_IFCHR);
#ifdef HAVE_SELINUX
if (sehandle) {
selabel_lookup(sehandle, &secontext, path, mode);
setfscreatecon(secontext);
}
#endif
dev = makedev(major, minor);
/* Temporarily change egid to avoid race condition setting the gid of the
* device node. Unforunately changing the euid would prevent creation of
Expand All @@ -192,8 +211,40 @@ static void make_device(const char *path,
mknod(path, mode, dev);
chown(path, uid, -1);
setegid(AID_ROOT);
#ifdef HAVE_SELINUX
if (secontext) {
freecon(secontext);
setfscreatecon(NULL);
}
#endif
}


static int make_dir(const char *path, mode_t mode)
{
int rc;

#ifdef HAVE_SELINUX
char *secontext = NULL;

if (sehandle) {
selabel_lookup(sehandle, &secontext, path, mode);
setfscreatecon(secontext);
}
#endif

rc = mkdir(path, mode);

#ifdef HAVE_SELINUX
if (secontext) {
freecon(secontext);
setfscreatecon(NULL);
}
#endif
return rc;
}


static void add_platform_device(const char *name)
{
int name_len = strlen(name);
Expand Down Expand Up @@ -506,7 +557,7 @@ static void handle_block_device_event(struct uevent *uevent)
return;

snprintf(devpath, sizeof(devpath), "%s%s", base, name);
mkdir(base, 0755);
make_dir(base, 0755);

if (!strncmp(uevent->path, "/devices/platform/", 18))
links = parse_platform_block_device(uevent);
Expand Down Expand Up @@ -535,40 +586,40 @@ static void handle_generic_device_event(struct uevent *uevent)
int bus_id = uevent->minor / 128 + 1;
int device_id = uevent->minor % 128 + 1;
/* build directories */
mkdir("/dev/bus", 0755);
mkdir("/dev/bus/usb", 0755);
make_dir("/dev/bus", 0755);
make_dir("/dev/bus/usb", 0755);
snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d", bus_id);
mkdir(devpath, 0755);
make_dir(devpath, 0755);
snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d/%03d", bus_id, device_id);
} else {
/* ignore other USB events */
return;
}
} else if (!strncmp(uevent->subsystem, "graphics", 8)) {
base = "/dev/graphics/";
mkdir(base, 0755);
make_dir(base, 0755);
} else if (!strncmp(uevent->subsystem, "oncrpc", 6)) {
base = "/dev/oncrpc/";
mkdir(base, 0755);
make_dir(base, 0755);
} else if (!strncmp(uevent->subsystem, "adsp", 4)) {
base = "/dev/adsp/";
mkdir(base, 0755);
make_dir(base, 0755);
} else if (!strncmp(uevent->subsystem, "msm_camera", 10)) {
base = "/dev/msm_camera/";
mkdir(base, 0755);
make_dir(base, 0755);
} else if(!strncmp(uevent->subsystem, "input", 5)) {
base = "/dev/input/";
mkdir(base, 0755);
make_dir(base, 0755);
} else if(!strncmp(uevent->subsystem, "mtd", 3)) {
base = "/dev/mtd/";
mkdir(base, 0755);
make_dir(base, 0755);
} else if(!strncmp(uevent->subsystem, "sound", 5)) {
base = "/dev/snd/";
mkdir(base, 0755);
make_dir(base, 0755);
} else if(!strncmp(uevent->subsystem, "misc", 4) &&
!strncmp(name, "log_", 4)) {
base = "/dev/log/";
mkdir(base, 0755);
make_dir(base, 0755);
name += 4;
} else
base = "/dev/";
Expand Down Expand Up @@ -819,7 +870,14 @@ void device_init(void)
suseconds_t t0, t1;
struct stat info;
int fd;
#ifdef HAVE_SELINUX
struct selinux_opt seopts[] = {
{ SELABEL_OPT_PATH, "/file_contexts" }
};

if (is_selinux_enabled() > 0)
sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);
#endif
/* is 64K enough? udev uses 16MB! */
device_fd = uevent_open_socket(64*1024, true);
if(device_fd < 0)
Expand Down
Loading

0 comments on commit e46f9d5

Please sign in to comment.