Merge "Extend init and ueventd for SE Android."
This commit is contained in:
commit
935530736d
8 changed files with 390 additions and 13 deletions
|
|
@ -30,6 +30,12 @@ LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
|
||||||
|
|
||||||
LOCAL_STATIC_LIBRARIES := libcutils libc
|
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)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
# Make a symlink from /sbin/ueventd to /init
|
# Make a symlink from /sbin/ueventd to /init
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,11 @@
|
||||||
#include <cutils/partition_utils.h>
|
#include <cutils/partition_utils.h>
|
||||||
#include <sys/system_properties.h>
|
#include <sys/system_properties.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
#include <selinux/selinux.h>
|
||||||
|
#include <selinux/label.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "keywords.h"
|
#include "keywords.h"
|
||||||
#include "property_service.h"
|
#include "property_service.h"
|
||||||
|
|
@ -436,6 +441,28 @@ exit_success:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
int do_setkey(int nargs, char **args)
|
||||||
{
|
{
|
||||||
struct kbentry kbe;
|
struct kbentry kbe;
|
||||||
|
|
@ -649,6 +676,64 @@ int do_chmod(int nargs, char **args) {
|
||||||
return 0;
|
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) {
|
int do_loglevel(int nargs, char **args) {
|
||||||
if (nargs == 2) {
|
if (nargs == 2) {
|
||||||
klog_set_level(atoi(args[1]));
|
klog_set_level(atoi(args[1]));
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,12 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
#include <selinux/selinux.h>
|
||||||
|
#include <selinux/label.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <private/android_filesystem_config.h>
|
#include <private/android_filesystem_config.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
|
|
@ -45,6 +51,10 @@
|
||||||
#define FIRMWARE_DIR1 "/etc/firmware"
|
#define FIRMWARE_DIR1 "/etc/firmware"
|
||||||
#define FIRMWARE_DIR2 "/vendor/firmware"
|
#define FIRMWARE_DIR2 "/vendor/firmware"
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
static struct selabel_handle *sehandle;
|
||||||
|
#endif
|
||||||
|
|
||||||
static int device_fd = -1;
|
static int device_fd = -1;
|
||||||
|
|
||||||
struct uevent {
|
struct uevent {
|
||||||
|
|
@ -180,8 +190,17 @@ static void make_device(const char *path,
|
||||||
unsigned gid;
|
unsigned gid;
|
||||||
mode_t mode;
|
mode_t mode;
|
||||||
dev_t dev;
|
dev_t dev;
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
char *secontext = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
mode = get_device_perm(path, &uid, &gid) | (block ? S_IFBLK : S_IFCHR);
|
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);
|
dev = makedev(major, minor);
|
||||||
/* Temporarily change egid to avoid race condition setting the gid of the
|
/* Temporarily change egid to avoid race condition setting the gid of the
|
||||||
* device node. Unforunately changing the euid would prevent creation of
|
* device node. Unforunately changing the euid would prevent creation of
|
||||||
|
|
@ -192,8 +211,40 @@ static void make_device(const char *path,
|
||||||
mknod(path, mode, dev);
|
mknod(path, mode, dev);
|
||||||
chown(path, uid, -1);
|
chown(path, uid, -1);
|
||||||
setegid(AID_ROOT);
|
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)
|
static void add_platform_device(const char *name)
|
||||||
{
|
{
|
||||||
int name_len = strlen(name);
|
int name_len = strlen(name);
|
||||||
|
|
@ -506,7 +557,7 @@ static void handle_block_device_event(struct uevent *uevent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
snprintf(devpath, sizeof(devpath), "%s%s", base, name);
|
snprintf(devpath, sizeof(devpath), "%s%s", base, name);
|
||||||
mkdir(base, 0755);
|
make_dir(base, 0755);
|
||||||
|
|
||||||
if (!strncmp(uevent->path, "/devices/platform/", 18))
|
if (!strncmp(uevent->path, "/devices/platform/", 18))
|
||||||
links = parse_platform_block_device(uevent);
|
links = parse_platform_block_device(uevent);
|
||||||
|
|
@ -535,10 +586,10 @@ static void handle_generic_device_event(struct uevent *uevent)
|
||||||
int bus_id = uevent->minor / 128 + 1;
|
int bus_id = uevent->minor / 128 + 1;
|
||||||
int device_id = uevent->minor % 128 + 1;
|
int device_id = uevent->minor % 128 + 1;
|
||||||
/* build directories */
|
/* build directories */
|
||||||
mkdir("/dev/bus", 0755);
|
make_dir("/dev/bus", 0755);
|
||||||
mkdir("/dev/bus/usb", 0755);
|
make_dir("/dev/bus/usb", 0755);
|
||||||
snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d", bus_id);
|
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);
|
snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d/%03d", bus_id, device_id);
|
||||||
} else {
|
} else {
|
||||||
/* ignore other USB events */
|
/* ignore other USB events */
|
||||||
|
|
@ -546,29 +597,29 @@ static void handle_generic_device_event(struct uevent *uevent)
|
||||||
}
|
}
|
||||||
} else if (!strncmp(uevent->subsystem, "graphics", 8)) {
|
} else if (!strncmp(uevent->subsystem, "graphics", 8)) {
|
||||||
base = "/dev/graphics/";
|
base = "/dev/graphics/";
|
||||||
mkdir(base, 0755);
|
make_dir(base, 0755);
|
||||||
} else if (!strncmp(uevent->subsystem, "oncrpc", 6)) {
|
} else if (!strncmp(uevent->subsystem, "oncrpc", 6)) {
|
||||||
base = "/dev/oncrpc/";
|
base = "/dev/oncrpc/";
|
||||||
mkdir(base, 0755);
|
make_dir(base, 0755);
|
||||||
} else if (!strncmp(uevent->subsystem, "adsp", 4)) {
|
} else if (!strncmp(uevent->subsystem, "adsp", 4)) {
|
||||||
base = "/dev/adsp/";
|
base = "/dev/adsp/";
|
||||||
mkdir(base, 0755);
|
make_dir(base, 0755);
|
||||||
} else if (!strncmp(uevent->subsystem, "msm_camera", 10)) {
|
} else if (!strncmp(uevent->subsystem, "msm_camera", 10)) {
|
||||||
base = "/dev/msm_camera/";
|
base = "/dev/msm_camera/";
|
||||||
mkdir(base, 0755);
|
make_dir(base, 0755);
|
||||||
} else if(!strncmp(uevent->subsystem, "input", 5)) {
|
} else if(!strncmp(uevent->subsystem, "input", 5)) {
|
||||||
base = "/dev/input/";
|
base = "/dev/input/";
|
||||||
mkdir(base, 0755);
|
make_dir(base, 0755);
|
||||||
} else if(!strncmp(uevent->subsystem, "mtd", 3)) {
|
} else if(!strncmp(uevent->subsystem, "mtd", 3)) {
|
||||||
base = "/dev/mtd/";
|
base = "/dev/mtd/";
|
||||||
mkdir(base, 0755);
|
make_dir(base, 0755);
|
||||||
} else if(!strncmp(uevent->subsystem, "sound", 5)) {
|
} else if(!strncmp(uevent->subsystem, "sound", 5)) {
|
||||||
base = "/dev/snd/";
|
base = "/dev/snd/";
|
||||||
mkdir(base, 0755);
|
make_dir(base, 0755);
|
||||||
} else if(!strncmp(uevent->subsystem, "misc", 4) &&
|
} else if(!strncmp(uevent->subsystem, "misc", 4) &&
|
||||||
!strncmp(name, "log_", 4)) {
|
!strncmp(name, "log_", 4)) {
|
||||||
base = "/dev/log/";
|
base = "/dev/log/";
|
||||||
mkdir(base, 0755);
|
make_dir(base, 0755);
|
||||||
name += 4;
|
name += 4;
|
||||||
} else
|
} else
|
||||||
base = "/dev/";
|
base = "/dev/";
|
||||||
|
|
@ -819,7 +870,14 @@ void device_init(void)
|
||||||
suseconds_t t0, t1;
|
suseconds_t t0, t1;
|
||||||
struct stat info;
|
struct stat info;
|
||||||
int fd;
|
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! */
|
/* is 64K enough? udev uses 16MB! */
|
||||||
device_fd = uevent_open_socket(64*1024, true);
|
device_fd = uevent_open_socket(64*1024, true);
|
||||||
if(device_fd < 0)
|
if(device_fd < 0)
|
||||||
|
|
|
||||||
176
init/init.c
176
init/init.c
|
|
@ -31,6 +31,13 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <selinux/selinux.h>
|
||||||
|
#include <selinux/label.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
|
||||||
#include <cutils/list.h>
|
#include <cutils/list.h>
|
||||||
|
|
@ -52,6 +59,10 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "ueventd.h"
|
#include "ueventd.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
struct selabel_handle *sehandle;
|
||||||
|
#endif
|
||||||
|
|
||||||
static int property_triggers_enabled = 0;
|
static int property_triggers_enabled = 0;
|
||||||
|
|
||||||
#if BOOTCHART
|
#if BOOTCHART
|
||||||
|
|
@ -64,6 +75,11 @@ static char hardware[32];
|
||||||
static unsigned revision = 0;
|
static unsigned revision = 0;
|
||||||
static char qemu[32];
|
static char qemu[32];
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
static int selinux_enabled = 1;
|
||||||
|
static int selinux_enforcing = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct action *cur_action = NULL;
|
static struct action *cur_action = NULL;
|
||||||
static struct command *cur_command = NULL;
|
static struct command *cur_command = NULL;
|
||||||
static struct listnode *command_queue = NULL;
|
static struct listnode *command_queue = NULL;
|
||||||
|
|
@ -145,7 +161,10 @@ void service_start(struct service *svc, const char *dynamic_args)
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int needs_console;
|
int needs_console;
|
||||||
int n;
|
int n;
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
char *scon = NULL;
|
||||||
|
int rc;
|
||||||
|
#endif
|
||||||
/* starting a service removes it from the disabled or reset
|
/* starting a service removes it from the disabled or reset
|
||||||
* state and immediately takes it out of the restarting
|
* state and immediately takes it out of the restarting
|
||||||
* state if it was in there
|
* state if it was in there
|
||||||
|
|
@ -182,6 +201,34 @@ void service_start(struct service *svc, const char *dynamic_args)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
if (is_selinux_enabled() > 0) {
|
||||||
|
char *mycon = NULL, *fcon = NULL;
|
||||||
|
|
||||||
|
INFO("computing context for service '%s'\n", svc->args[0]);
|
||||||
|
rc = getcon(&mycon);
|
||||||
|
if (rc < 0) {
|
||||||
|
ERROR("could not get context while starting '%s'\n", svc->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = getfilecon(svc->args[0], &fcon);
|
||||||
|
if (rc < 0) {
|
||||||
|
ERROR("could not get context while starting '%s'\n", svc->name);
|
||||||
|
freecon(mycon);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = security_compute_create(mycon, fcon, string_to_security_class("process"), &scon);
|
||||||
|
freecon(mycon);
|
||||||
|
freecon(fcon);
|
||||||
|
if (rc < 0) {
|
||||||
|
ERROR("could not get context while starting '%s'\n", svc->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
NOTICE("starting '%s'\n", svc->name);
|
NOTICE("starting '%s'\n", svc->name);
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
|
|
@ -201,6 +248,10 @@ void service_start(struct service *svc, const char *dynamic_args)
|
||||||
for (ei = svc->envvars; ei; ei = ei->next)
|
for (ei = svc->envvars; ei; ei = ei->next)
|
||||||
add_environment(ei->name, ei->value);
|
add_environment(ei->name, ei->value);
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
setsockcreatecon(scon);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (si = svc->sockets; si; si = si->next) {
|
for (si = svc->sockets; si; si = si->next) {
|
||||||
int socket_type = (
|
int socket_type = (
|
||||||
!strcmp(si->type, "stream") ? SOCK_STREAM :
|
!strcmp(si->type, "stream") ? SOCK_STREAM :
|
||||||
|
|
@ -212,6 +263,12 @@ void service_start(struct service *svc, const char *dynamic_args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
freecon(scon);
|
||||||
|
scon = NULL;
|
||||||
|
setsockcreatecon(NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (svc->ioprio_class != IoSchedClass_NONE) {
|
if (svc->ioprio_class != IoSchedClass_NONE) {
|
||||||
if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) {
|
if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) {
|
||||||
ERROR("Failed to set pid %d ioprio = %d,%d: %s\n",
|
ERROR("Failed to set pid %d ioprio = %d,%d: %s\n",
|
||||||
|
|
@ -257,6 +314,15 @@ void service_start(struct service *svc, const char *dynamic_args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
if (svc->seclabel) {
|
||||||
|
if (is_selinux_enabled() > 0 && setexeccon(svc->seclabel) < 0) {
|
||||||
|
ERROR("cannot setexeccon('%s'): %s\n", svc->seclabel, strerror(errno));
|
||||||
|
_exit(127);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!dynamic_args) {
|
if (!dynamic_args) {
|
||||||
if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {
|
if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {
|
||||||
ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
|
ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
|
||||||
|
|
@ -282,6 +348,10 @@ void service_start(struct service *svc, const char *dynamic_args)
|
||||||
_exit(127);
|
_exit(127);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
freecon(scon);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
ERROR("failed to start '%s'\n", svc->name);
|
ERROR("failed to start '%s'\n", svc->name);
|
||||||
svc->pid = 0;
|
svc->pid = 0;
|
||||||
|
|
@ -531,6 +601,14 @@ static void import_kernel_nv(char *name, int for_emulator)
|
||||||
*value++ = 0;
|
*value++ = 0;
|
||||||
if (name_len == 0) return;
|
if (name_len == 0) return;
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
if (!strcmp(name,"enforcing")) {
|
||||||
|
selinux_enforcing = atoi(value);
|
||||||
|
} else if (!strcmp(name,"selinux")) {
|
||||||
|
selinux_enabled = atoi(value);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (for_emulator) {
|
if (for_emulator) {
|
||||||
/* in the emulator, export any kernel option with the
|
/* in the emulator, export any kernel option with the
|
||||||
* ro.kernel. prefix */
|
* ro.kernel. prefix */
|
||||||
|
|
@ -678,6 +756,97 @@ static int bootchart_init_action(int nargs, char **args)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
void selinux_load_policy(void)
|
||||||
|
{
|
||||||
|
const char path_prefix[] = "/sepolicy";
|
||||||
|
struct selinux_opt seopts[] = {
|
||||||
|
{ SELABEL_OPT_PATH, "/file_contexts" }
|
||||||
|
};
|
||||||
|
char path[PATH_MAX];
|
||||||
|
int fd, rc, vers;
|
||||||
|
struct stat sb;
|
||||||
|
void *map;
|
||||||
|
|
||||||
|
sehandle = NULL;
|
||||||
|
if (!selinux_enabled) {
|
||||||
|
INFO("SELinux: Disabled by command line option\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir(SELINUXMNT, 0755);
|
||||||
|
if (mount("selinuxfs", SELINUXMNT, "selinuxfs", 0, NULL)) {
|
||||||
|
if (errno == ENODEV) {
|
||||||
|
/* SELinux not enabled in kernel */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ERROR("SELinux: Could not mount selinuxfs: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
set_selinuxmnt(SELINUXMNT);
|
||||||
|
|
||||||
|
vers = security_policyvers();
|
||||||
|
if (vers <= 0) {
|
||||||
|
ERROR("SELinux: Unable to read policy version\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
INFO("SELinux: Maximum supported policy version: %d\n", vers);
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "%s.%d",
|
||||||
|
path_prefix, vers);
|
||||||
|
fd = open(path, O_RDONLY);
|
||||||
|
while (fd < 0 && errno == ENOENT && --vers) {
|
||||||
|
snprintf(path, sizeof(path), "%s.%d",
|
||||||
|
path_prefix, vers);
|
||||||
|
fd = open(path, O_RDONLY);
|
||||||
|
}
|
||||||
|
if (fd < 0) {
|
||||||
|
ERROR("SELinux: Could not open %s: %s\n",
|
||||||
|
path, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fstat(fd, &sb) < 0) {
|
||||||
|
ERROR("SELinux: Could not stat %s: %s\n",
|
||||||
|
path, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
|
if (map == MAP_FAILED) {
|
||||||
|
ERROR("SELinux: Could not map %s: %s\n",
|
||||||
|
path, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = security_load_policy(map, sb.st_size);
|
||||||
|
if (rc < 0) {
|
||||||
|
ERROR("SELinux: Could not load policy: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = security_setenforce(selinux_enforcing);
|
||||||
|
if (rc < 0) {
|
||||||
|
ERROR("SELinux: Could not set enforcing mode to %s: %s\n",
|
||||||
|
selinux_enforcing ? "enforcing" : "permissive", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
munmap(map, sb.st_size);
|
||||||
|
close(fd);
|
||||||
|
INFO("SELinux: Loaded policy from %s\n", path);
|
||||||
|
|
||||||
|
sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);
|
||||||
|
if (!sehandle) {
|
||||||
|
ERROR("SELinux: Could not load file_contexts: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
INFO("SELinux: Loaded file contexts from %s\n", seopts[0].value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int fd_count = 0;
|
int fd_count = 0;
|
||||||
|
|
@ -728,6 +897,11 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
process_kernel_cmdline();
|
process_kernel_cmdline();
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
INFO("loading selinux policy\n");
|
||||||
|
selinux_load_policy();
|
||||||
|
#endif
|
||||||
|
|
||||||
is_charger = !strcmp(bootmode, "charger");
|
is_charger = !strcmp(bootmode, "charger");
|
||||||
|
|
||||||
INFO("property init\n");
|
INFO("property init\n");
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,10 @@ struct service {
|
||||||
gid_t supp_gids[NR_SVC_SUPP_GIDS];
|
gid_t supp_gids[NR_SVC_SUPP_GIDS];
|
||||||
size_t nr_supp_gids;
|
size_t nr_supp_gids;
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
char *seclabel;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct socketinfo *sockets;
|
struct socketinfo *sockets;
|
||||||
struct svcenvinfo *envvars;
|
struct svcenvinfo *envvars;
|
||||||
|
|
||||||
|
|
@ -132,4 +136,8 @@ void property_changed(const char *name, const char *value);
|
||||||
|
|
||||||
int load_565rle_image( char *file_name );
|
int load_565rle_image( char *file_name );
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
extern struct selabel_handle *sehandle;
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _INIT_INIT_H */
|
#endif /* _INIT_INIT_H */
|
||||||
|
|
|
||||||
|
|
@ -131,15 +131,20 @@ int lookup_keyword(const char *s)
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
if (!strcmp(s, "estart")) return K_restart;
|
if (!strcmp(s, "estart")) return K_restart;
|
||||||
|
if (!strcmp(s, "estorecon")) return K_restorecon;
|
||||||
if (!strcmp(s, "mdir")) return K_rmdir;
|
if (!strcmp(s, "mdir")) return K_rmdir;
|
||||||
if (!strcmp(s, "m")) return K_rm;
|
if (!strcmp(s, "m")) return K_rm;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
|
if (!strcmp(s, "eclabel")) return K_seclabel;
|
||||||
if (!strcmp(s, "ervice")) return K_service;
|
if (!strcmp(s, "ervice")) return K_service;
|
||||||
|
if (!strcmp(s, "etcon")) return K_setcon;
|
||||||
|
if (!strcmp(s, "etenforce")) return K_setenforce;
|
||||||
if (!strcmp(s, "etenv")) return K_setenv;
|
if (!strcmp(s, "etenv")) return K_setenv;
|
||||||
if (!strcmp(s, "etkey")) return K_setkey;
|
if (!strcmp(s, "etkey")) return K_setkey;
|
||||||
if (!strcmp(s, "etprop")) return K_setprop;
|
if (!strcmp(s, "etprop")) return K_setprop;
|
||||||
if (!strcmp(s, "etrlimit")) return K_setrlimit;
|
if (!strcmp(s, "etrlimit")) return K_setrlimit;
|
||||||
|
if (!strcmp(s, "etsebool")) return K_setsebool;
|
||||||
if (!strcmp(s, "ocket")) return K_socket;
|
if (!strcmp(s, "ocket")) return K_socket;
|
||||||
if (!strcmp(s, "tart")) return K_start;
|
if (!strcmp(s, "tart")) return K_start;
|
||||||
if (!strcmp(s, "top")) return K_stop;
|
if (!strcmp(s, "top")) return K_stop;
|
||||||
|
|
@ -792,6 +797,16 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args
|
||||||
svc->uid = decode_uid(args[1]);
|
svc->uid = decode_uid(args[1]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case K_seclabel:
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
if (nargs != 2) {
|
||||||
|
parse_error(state, "seclabel option requires a label string\n");
|
||||||
|
} else {
|
||||||
|
svc->seclabel = args[1];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
parse_error(state, "invalid option '%s'\n", args[0]);
|
parse_error(state, "invalid option '%s'\n", args[0]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,15 @@ int do_insmod(int nargs, char **args);
|
||||||
int do_mkdir(int nargs, char **args);
|
int do_mkdir(int nargs, char **args);
|
||||||
int do_mount(int nargs, char **args);
|
int do_mount(int nargs, char **args);
|
||||||
int do_restart(int nargs, char **args);
|
int do_restart(int nargs, char **args);
|
||||||
|
int do_restorecon(int nargs, char **args);
|
||||||
int do_rm(int nargs, char **args);
|
int do_rm(int nargs, char **args);
|
||||||
int do_rmdir(int nargs, char **args);
|
int do_rmdir(int nargs, char **args);
|
||||||
|
int do_setcon(int nargs, char **args);
|
||||||
|
int do_setenforce(int nargs, char **args);
|
||||||
int do_setkey(int nargs, char **args);
|
int do_setkey(int nargs, char **args);
|
||||||
int do_setprop(int nargs, char **args);
|
int do_setprop(int nargs, char **args);
|
||||||
int do_setrlimit(int nargs, char **args);
|
int do_setrlimit(int nargs, char **args);
|
||||||
|
int do_setsebool(int nargs, char **args);
|
||||||
int do_start(int nargs, char **args);
|
int do_start(int nargs, char **args);
|
||||||
int do_stop(int nargs, char **args);
|
int do_stop(int nargs, char **args);
|
||||||
int do_trigger(int nargs, char **args);
|
int do_trigger(int nargs, char **args);
|
||||||
|
|
@ -61,13 +65,18 @@ enum {
|
||||||
KEYWORD(oneshot, OPTION, 0, 0)
|
KEYWORD(oneshot, OPTION, 0, 0)
|
||||||
KEYWORD(onrestart, OPTION, 0, 0)
|
KEYWORD(onrestart, OPTION, 0, 0)
|
||||||
KEYWORD(restart, COMMAND, 1, do_restart)
|
KEYWORD(restart, COMMAND, 1, do_restart)
|
||||||
|
KEYWORD(restorecon, COMMAND, 1, do_restorecon)
|
||||||
KEYWORD(rm, COMMAND, 1, do_rm)
|
KEYWORD(rm, COMMAND, 1, do_rm)
|
||||||
KEYWORD(rmdir, COMMAND, 1, do_rmdir)
|
KEYWORD(rmdir, COMMAND, 1, do_rmdir)
|
||||||
|
KEYWORD(seclabel, OPTION, 0, 0)
|
||||||
KEYWORD(service, SECTION, 0, 0)
|
KEYWORD(service, SECTION, 0, 0)
|
||||||
|
KEYWORD(setcon, COMMAND, 1, do_setcon)
|
||||||
|
KEYWORD(setenforce, COMMAND, 1, do_setenforce)
|
||||||
KEYWORD(setenv, OPTION, 2, 0)
|
KEYWORD(setenv, OPTION, 2, 0)
|
||||||
KEYWORD(setkey, COMMAND, 0, do_setkey)
|
KEYWORD(setkey, COMMAND, 0, do_setkey)
|
||||||
KEYWORD(setprop, COMMAND, 2, do_setprop)
|
KEYWORD(setprop, COMMAND, 2, do_setprop)
|
||||||
KEYWORD(setrlimit, COMMAND, 3, do_setrlimit)
|
KEYWORD(setrlimit, COMMAND, 3, do_setrlimit)
|
||||||
|
KEYWORD(setsebool, COMMAND, 1, do_setsebool)
|
||||||
KEYWORD(socket, OPTION, 0, 0)
|
KEYWORD(socket, OPTION, 0, 0)
|
||||||
KEYWORD(start, COMMAND, 1, do_start)
|
KEYWORD(start, COMMAND, 1, do_start)
|
||||||
KEYWORD(stop, COMMAND, 1, do_stop)
|
KEYWORD(stop, COMMAND, 1, do_stop)
|
||||||
|
|
|
||||||
22
init/util.c
22
init/util.c
|
|
@ -23,6 +23,10 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
#include <selinux/label.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
@ -33,6 +37,7 @@
|
||||||
|
|
||||||
#include <private/android_filesystem_config.h>
|
#include <private/android_filesystem_config.h>
|
||||||
|
|
||||||
|
#include "init.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
|
@ -84,6 +89,9 @@ int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
struct sockaddr_un addr;
|
struct sockaddr_un addr;
|
||||||
int fd, ret;
|
int fd, ret;
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
char *secon;
|
||||||
|
#endif
|
||||||
|
|
||||||
fd = socket(PF_UNIX, type, 0);
|
fd = socket(PF_UNIX, type, 0);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
|
@ -102,12 +110,26 @@ int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid)
|
||||||
goto out_close;
|
goto out_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
secon = NULL;
|
||||||
|
if (sehandle) {
|
||||||
|
ret = selabel_lookup(sehandle, &secon, addr.sun_path, S_IFSOCK);
|
||||||
|
if (ret == 0)
|
||||||
|
setfscreatecon(secon);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr));
|
ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ERROR("Failed to bind socket '%s': %s\n", name, strerror(errno));
|
ERROR("Failed to bind socket '%s': %s\n", name, strerror(errno));
|
||||||
goto out_unlink;
|
goto out_unlink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SELINUX
|
||||||
|
setfscreatecon(NULL);
|
||||||
|
freecon(secon);
|
||||||
|
#endif
|
||||||
|
|
||||||
chown(addr.sun_path, uid, gid);
|
chown(addr.sun_path, uid, gid);
|
||||||
chmod(addr.sun_path, perm);
|
chmod(addr.sun_path, perm);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue