Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ee79b455 authored by Jean-Baptiste Queru's avatar Jean-Baptiste Queru Committed by Android Git Automerger
Browse files

am 93553073: Merge "Extend init and ueventd for SE Android."

* commit '93553073':
  Extend init and ueventd for SE Android.
parents aee9fc1e 93553073
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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
+85 −0
Original line number Diff line number Diff line
@@ -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"
@@ -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)
{
    struct kbentry kbe;
@@ -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]));
+70 −12
Original line number Diff line number Diff line
@@ -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>
@@ -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 {
@@ -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
@@ -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);
@@ -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);
@@ -535,10 +586,10 @@ 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 */
@@ -546,29 +597,29 @@ static void handle_generic_device_event(struct uevent *uevent)
         }
     } 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/";
@@ -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)
+175 −1
Original line number Diff line number Diff line
@@ -31,6 +31,13 @@
#include <sys/types.h>
#include <sys/socket.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 <cutils/list.h>
@@ -52,6 +59,10 @@
#include "util.h"
#include "ueventd.h"

#ifdef HAVE_SELINUX
struct selabel_handle *sehandle;
#endif

static int property_triggers_enabled = 0;

#if BOOTCHART
@@ -64,6 +75,11 @@ static char hardware[32];
static unsigned revision = 0;
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 command *cur_command = NULL;
static struct listnode *command_queue = NULL;
@@ -145,7 +161,10 @@ void service_start(struct service *svc, const char *dynamic_args)
    pid_t pid;
    int needs_console;
    int n;

#ifdef HAVE_SELINUX
    char *scon = NULL;
    int rc;
#endif
        /* starting a service removes it from the disabled or reset
         * state and immediately takes it out of the restarting
         * state if it was in there
@@ -182,6 +201,34 @@ void service_start(struct service *svc, const char *dynamic_args)
        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);

    pid = fork();
@@ -201,6 +248,10 @@ void service_start(struct service *svc, const char *dynamic_args)
        for (ei = svc->envvars; ei; ei = ei->next)
            add_environment(ei->name, ei->value);

#ifdef HAVE_SELINUX
        setsockcreatecon(scon);
#endif

        for (si = svc->sockets; si; si = si->next) {
            int socket_type = (
                    !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 (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) {
                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 (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {
                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);
    }

#ifdef HAVE_SELINUX
    freecon(scon);
#endif

    if (pid < 0) {
        ERROR("failed to start '%s'\n", svc->name);
        svc->pid = 0;
@@ -531,6 +601,14 @@ static void import_kernel_nv(char *name, int for_emulator)
    *value++ = 0;
    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) {
        /* in the emulator, export any kernel option with the
         * ro.kernel. prefix */
@@ -678,6 +756,97 @@ static int bootchart_init_action(int nargs, char **args)
}
#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 fd_count = 0;
@@ -728,6 +897,11 @@ int main(int argc, char **argv)

    process_kernel_cmdline();

#ifdef HAVE_SELINUX
    INFO("loading selinux policy\n");
    selinux_load_policy();
#endif

    is_charger = !strcmp(bootmode, "charger");

    INFO("property init\n");
+8 −0
Original line number Diff line number Diff line
@@ -95,6 +95,10 @@ struct service {
    gid_t supp_gids[NR_SVC_SUPP_GIDS];
    size_t nr_supp_gids;

#ifdef HAVE_SELINUX
    char *seclabel;
#endif

    struct socketinfo *sockets;
    struct svcenvinfo *envvars;

@@ -132,4 +136,8 @@ void property_changed(const char *name, const char *value);

int load_565rle_image( char *file_name );

#ifdef HAVE_SELINUX
extern struct selabel_handle *sehandle;
#endif

#endif	/* _INIT_INIT_H */
Loading