summaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
Diffstat (limited to 'init')
-rw-r--r--init/Android.mk12
-rw-r--r--init/builtins.c48
-rw-r--r--init/devices.c21
-rwxr-xr-xinit/init.c27
-rw-r--r--init/init.h4
-rw-r--r--init/init_parser.c2
-rw-r--r--init/keywords.h2
-rwxr-xr-xinit/property_service.c85
-rw-r--r--init/readme.txt26
-rwxr-xr-xinit/util.c15
10 files changed, 139 insertions, 103 deletions
diff --git a/init/Android.mk b/init/Android.mk
index 00d2144..a1c1e7a 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -33,11 +33,13 @@ LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
-LOCAL_STATIC_LIBRARIES := \
- libfs_mgr \
- libcutils \
- libc \
- libselinux
+LOCAL_STATIC_LIBRARIES := libfs_mgr libcutils libc
+
+ifeq ($(HAVE_SELINUX),true)
+LOCAL_STATIC_LIBRARIES += libselinux
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_CFLAGS += -DHAVE_SELINUX
+endif
include $(BUILD_EXECUTABLE)
diff --git a/init/builtins.c b/init/builtins.c
index dc7900e..aaf85d9 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -35,8 +35,10 @@
#include <sys/system_properties.h>
#include <fs_mgr.h>
+#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
#include <selinux/label.h>
+#endif
#include "init.h"
#include "keywords.h"
@@ -513,20 +515,24 @@ int do_mount_all(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;
}
@@ -754,30 +760,36 @@ int do_restorecon(int nargs, char **args) {
}
int do_setsebool(int nargs, char **args) {
- const char *name = args[1];
- const char *value = args[2];
- SELboolean b;
- int ret;
+#ifdef HAVE_SELINUX
+ SELboolean *b = alloca(nargs * sizeof(SELboolean));
+ char *v;
+ int i;
if (is_selinux_enabled() <= 0)
return 0;
- b.name = name;
- if (!strcmp(value, "1") || !strcasecmp(value, "true") || !strcasecmp(value, "on"))
- b.value = 1;
- else if (!strcmp(value, "0") || !strcasecmp(value, "false") || !strcasecmp(value, "off"))
- b.value = 0;
- else {
- ERROR("setsebool: invalid value %s\n", value);
- return -EINVAL;
- }
-
- if (security_set_boolean_list(1, &b, 0) < 0) {
- ret = -errno;
- ERROR("setsebool: could not set %s to %s\n", name, value);
- return ret;
+ 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;
}
diff --git a/init/devices.c b/init/devices.c
index b07a1a6..c30303f 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -30,9 +30,11 @@
#include <sys/un.h>
#include <linux/netlink.h>
+#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
#include <selinux/label.h>
#include <selinux/android.h>
+#endif
#include <private/android_filesystem_config.h>
#include <sys/time.h>
@@ -51,7 +53,9 @@
#define FIRMWARE_DIR2 "/vendor/firmware"
#define FIRMWARE_DIR3 "/firmware/image"
+#ifdef HAVE_SELINUX
extern struct selabel_handle *sehandle;
+#endif
static int device_fd = -1;
@@ -189,15 +193,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
@@ -208,11 +214,12 @@ 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 void add_platform_device(const char *name)
@@ -875,14 +882,14 @@ void device_init(void)
suseconds_t t0, t1;
struct stat info;
int fd;
-
+#ifdef HAVE_SELINUX
sehandle = NULL;
if (is_selinux_enabled() > 0) {
sehandle = selinux_android_file_context_handle();
}
-
- /* is 256K enough? udev uses 16MB! */
- device_fd = uevent_open_socket(256*1024, true);
+#endif
+ /* is 64K enough? udev uses 16MB! */
+ device_fd = uevent_open_socket(64*1024, true);
if(device_fd < 0)
return;
diff --git a/init/init.c b/init/init.c
index 48d8559..fa2b4e8 100755
--- a/init/init.c
+++ b/init/init.c
@@ -33,9 +33,11 @@
#include <sys/un.h>
#include <sys/personality.h>
+#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
#include <selinux/label.h>
#include <selinux/android.h>
+#endif
#include <libgen.h>
@@ -59,8 +61,10 @@
#include "ueventd.h"
#include "watchdogd.h"
+#ifdef HAVE_SELINUX
struct selabel_handle *sehandle;
struct selabel_handle *sehandle_prop;
+#endif
static int property_triggers_enabled = 0;
@@ -74,7 +78,9 @@ static char hardware[32];
static unsigned revision = 0;
static char qemu[32];
+#ifdef HAVE_SELINUX
static int selinux_enabled = 1;
+#endif
static struct action *cur_action = NULL;
static struct command *cur_command = NULL;
@@ -158,9 +164,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
@@ -197,6 +204,7 @@ void service_start(struct service *svc, const char *dynamic_args)
return;
}
+#ifdef HAVE_SELINUX
if (is_selinux_enabled() > 0) {
if (svc->seclabel) {
scon = strdup(svc->seclabel);
@@ -230,6 +238,7 @@ void service_start(struct service *svc, const char *dynamic_args)
}
}
}
+#endif
NOTICE("starting '%s'\n", svc->name);
@@ -266,7 +275,9 @@ 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 = (
@@ -279,9 +290,11 @@ 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)) {
@@ -327,12 +340,15 @@ void service_start(struct service *svc, const char *dynamic_args)
_exit(127);
}
}
+
+#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) {
@@ -359,7 +375,9 @@ 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);
@@ -610,9 +628,11 @@ static void import_kernel_nv(char *name, int for_emulator)
*value++ = 0;
if (name_len == 0) return;
+#ifdef HAVE_SELINUX
if (!strcmp(name,"selinux")) {
selinux_enabled = atoi(value);
}
+#endif
if (for_emulator) {
/* in the emulator, export any kernel option with the
@@ -760,6 +780,7 @@ static int bootchart_init_action(int nargs, char **args)
}
#endif
+#ifdef HAVE_SELINUX
static const struct selinux_opt seopts_prop[] = {
{ SELABEL_OPT_PATH, "/data/system/property_contexts" },
{ SELABEL_OPT_PATH, "/property_contexts" },
@@ -818,6 +839,8 @@ int audit_callback(void *data, security_class_t cls, char *buf, size_t len)
return 0;
}
+#endif
+
int main(int argc, char **argv)
{
int fd_count = 0;
@@ -871,6 +894,7 @@ int main(int argc, char **argv)
process_kernel_cmdline();
+#ifdef HAVE_SELINUX
union selinux_callback cb;
cb.func_log = klog_write;
selinux_set_callback(SELINUX_CB_LOG, cb);
@@ -895,6 +919,7 @@ int main(int argc, char **argv)
*/
restorecon("/dev");
restorecon("/dev/socket");
+#endif
is_charger = !strcmp(bootmode, "charger");
diff --git a/init/init.h b/init/init.h
index 955e1f0..b7e06c9 100644
--- a/init/init.h
+++ b/init/init.h
@@ -95,7 +95,9 @@ 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;
@@ -134,8 +136,10 @@ void property_changed(const char *name, const char *value);
int load_565rle_image( char *file_name );
+#ifdef HAVE_SELINUX
extern struct selabel_handle *sehandle;
extern struct selabel_handle *sehandle_prop;
extern int selinux_reload_policy(void);
+#endif
#endif /* _INIT_INIT_H */
diff --git a/init/init_parser.c b/init/init_parser.c
index beb9188..5393e52 100644
--- a/init/init_parser.c
+++ b/init/init_parser.c
@@ -799,11 +799,13 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args
}
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:
diff --git a/init/keywords.h b/init/keywords.h
index f188db5..97d4950 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -78,7 +78,7 @@ enum {
KEYWORD(setkey, COMMAND, 0, do_setkey)
KEYWORD(setprop, COMMAND, 2, do_setprop)
KEYWORD(setrlimit, COMMAND, 3, do_setrlimit)
- KEYWORD(setsebool, COMMAND, 2, do_setsebool)
+ KEYWORD(setsebool, COMMAND, 1, do_setsebool)
KEYWORD(socket, OPTION, 0, 0)
KEYWORD(start, COMMAND, 1, do_start)
KEYWORD(stop, COMMAND, 1, do_stop)
diff --git a/init/property_service.c b/init/property_service.c
index 61dd86f..f58e07d 100755
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -40,8 +40,10 @@
#include <sys/atomics.h>
#include <private/android_filesystem_config.h>
+#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
#include <selinux/label.h>
+#endif
#include "property_service.h"
#include "init.h"
@@ -123,7 +125,7 @@ static int init_workspace(workspace *w, size_t size)
/* dev is a tmpfs that we can use to carve a shared workspace
* out of, so let's do that...
*/
- fd = open("/dev/__properties__", O_RDWR | O_CREAT | O_NOFOLLOW, 0600);
+ fd = open("/dev/__properties__", O_RDWR | O_CREAT, 0600);
if (fd < 0)
return -1;
@@ -136,7 +138,7 @@ static int init_workspace(workspace *w, size_t size)
close(fd);
- fd = open("/dev/__properties__", O_RDONLY | O_NOFOLLOW);
+ fd = open("/dev/__properties__", O_RDONLY);
if (fd < 0)
return -1;
@@ -199,6 +201,7 @@ static void update_prop_info(prop_info *pi, const char *value, unsigned len)
static int check_mac_perms(const char *name, char *sctx)
{
+#ifdef HAVE_SELINUX
if (is_selinux_enabled() <= 0)
return 1;
@@ -222,10 +225,15 @@ static int check_mac_perms(const char *name, char *sctx)
freecon(tctx);
err:
return result;
+
+#endif
+ return 1;
}
static int check_control_mac_perms(const char *name, char *sctx)
{
+#ifdef HAVE_SELINUX
+
/*
* Create a name prefix out of ctl.<service name>
* The new prefix allows the use of the existing
@@ -239,6 +247,9 @@ static int check_control_mac_perms(const char *name, char *sctx)
return 0;
return check_mac_perms(ctl_name, sctx);
+
+#endif
+ return 1;
}
/*
@@ -309,12 +320,13 @@ const char* property_get(const char *name)
static void write_persistent_property(const char *name, const char *value)
{
- char tempPath[PATH_MAX];
+ const char *tempPath = PERSISTENT_PROPERTY_DIR "/.temp";
char path[PATH_MAX];
- int fd;
+ int fd, length;
+
+ snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, name);
- snprintf(tempPath, sizeof(tempPath), "%s/.temp.XXXXXX", PERSISTENT_PROPERTY_DIR);
- fd = mkstemp(tempPath);
+ fd = open(tempPath, O_WRONLY|O_CREAT|O_TRUNC, 0600);
if (fd < 0) {
ERROR("Unable to write persistent property to temp file %s errno: %d\n", tempPath, errno);
return;
@@ -322,7 +334,6 @@ static void write_persistent_property(const char *name, const char *value)
write(fd, value, strlen(value));
close(fd);
- snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, name);
if (rename(tempPath, path)) {
unlink(tempPath);
ERROR("Unable to rename persistent property file %s to %s\n", tempPath, path);
@@ -334,8 +345,8 @@ int property_set(const char *name, const char *value)
prop_area *pa;
prop_info *pi;
- size_t namelen = strlen(name);
- size_t valuelen = strlen(value);
+ int namelen = strlen(name);
+ int valuelen = strlen(value);
if(namelen >= PROP_NAME_MAX) return -1;
if(valuelen >= PROP_VALUE_MAX) return -1;
@@ -385,9 +396,11 @@ int property_set(const char *name, const char *value)
* to prevent them from being overwritten by default values.
*/
write_persistent_property(name, value);
+#ifdef HAVE_SELINUX
} else if (strcmp("selinux.reload_policy", name) == 0 &&
strcmp("1", value) == 0) {
selinux_reload_policy();
+#endif
}
property_changed(name, value);
return 0;
@@ -412,13 +425,13 @@ void handle_property_set_fd()
/* Check socket options here */
if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
close(s);
- ERROR("Unable to receive socket options\n");
+ ERROR("Unable to recieve socket options\n");
return;
}
r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), 0));
if(r != sizeof(prop_msg)) {
- ERROR("sys_prop: mis-match msg size received: %d expected: %d errno: %d\n",
+ ERROR("sys_prop: mis-match msg size recieved: %d expected: %d errno: %d\n",
r, sizeof(prop_msg), errno);
close(s);
return;
@@ -429,7 +442,9 @@ void handle_property_set_fd()
msg.name[PROP_NAME_MAX-1] = 0;
msg.value[PROP_VALUE_MAX-1] = 0;
+#ifdef HAVE_SELINUX
getpeercon(s, &source_ctx);
+#endif
if(memcmp(msg.name,"ctl.",4) == 0) {
// Keep the old close-socket-early behavior when handling
@@ -454,7 +469,10 @@ void handle_property_set_fd()
// the property is written to memory.
close(s);
}
+#ifdef HAVE_SELINUX
freecon(source_ctx);
+#endif
+
break;
default:
@@ -512,14 +530,12 @@ static void load_properties_from_file(const char *fn)
static void load_persistent_properties()
{
DIR* dir = opendir(PERSISTENT_PROPERTY_DIR);
- int dir_fd;
struct dirent* entry;
+ char path[PATH_MAX];
char value[PROP_VALUE_MAX];
int fd, length;
- struct stat sb;
if (dir) {
- dir_fd = dirfd(dir);
while ((entry = readdir(dir)) != NULL) {
if (strncmp("persist.", entry->d_name, strlen("persist.")))
continue;
@@ -528,39 +544,20 @@ static void load_persistent_properties()
continue;
#endif
/* open the file and read the property value */
- fd = openat(dir_fd, entry->d_name, O_RDONLY | O_NOFOLLOW);
- if (fd < 0) {
- ERROR("Unable to open persistent property file \"%s\" errno: %d\n",
- entry->d_name, errno);
- continue;
- }
- if (fstat(fd, &sb) < 0) {
- ERROR("fstat on property file \"%s\" failed errno: %d\n", entry->d_name, errno);
- close(fd);
- continue;
- }
-
- // File must not be accessible to others, be owned by root/root, and
- // not be a hard link to any other file.
- if (((sb.st_mode & (S_IRWXG | S_IRWXO)) != 0)
- || (sb.st_uid != 0)
- || (sb.st_gid != 0)
- || (sb.st_nlink != 1)) {
- ERROR("skipping insecure property file %s (uid=%lu gid=%lu nlink=%d mode=%o)\n",
- entry->d_name, sb.st_uid, sb.st_gid, sb.st_nlink, sb.st_mode);
+ snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, entry->d_name);
+ fd = open(path, O_RDONLY);
+ if (fd >= 0) {
+ length = read(fd, value, sizeof(value) - 1);
+ if (length >= 0) {
+ value[length] = 0;
+ property_set(entry->d_name, value);
+ } else {
+ ERROR("Unable to read persistent property file %s errno: %d\n", path, errno);
+ }
close(fd);
- continue;
- }
-
- length = read(fd, value, sizeof(value) - 1);
- if (length >= 0) {
- value[length] = 0;
- property_set(entry->d_name, value);
} else {
- ERROR("Unable to read persistent property file %s errno: %d\n",
- entry->d_name, errno);
+ ERROR("Unable to open persistent property file %s errno: %d\n", path, errno);
}
- close(fd);
}
closedir(dir);
} else {
diff --git a/init/readme.txt b/init/readme.txt
index 7a5997d..fe0d15d 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -88,13 +88,6 @@ group <groupname> [ <groupname> ]*
supplemental groups of the process (via setgroups()).
Currently defaults to root. (??? probably should default to nobody)
-seclabel <securitycontext>
- Change to securitycontext before exec'ing this service.
- Primarily for use by services run from the rootfs, e.g. ueventd, adbd.
- Services on the system partition can instead use policy-defined transitions
- based on their file security context.
- If not specified and no transition is defined in policy, defaults to the init context.
-
oneshot
Do not restart the service when it exits.
@@ -189,21 +182,6 @@ mount <type> <device> <dir> [ <mountoption> ]*
device by name.
<mountoption>s include "ro", "rw", "remount", "noatime", ...
-restorecon <path>
- Restore the file named by <path> to the security context specified
- in the file_contexts configuration.
- Not required for directories created by the init.rc as these are
- automatically labeled correctly by init.
-
-setcon <securitycontext>
- Set the current process security context to the specified string.
- This is typically only used from early-init to set the init context
- before any other process is started.
-
-setenforce 0|1
- Set the SELinux system-wide enforcing status.
- 0 is permissive (i.e. log but do not deny), 1 is enforcing.
-
setkey
TBD
@@ -213,10 +191,6 @@ setprop <name> <value>
setrlimit <resource> <cur> <max>
Set the rlimit for a resource.
-setsebool <name> <value>
- Set SELinux boolean <name> to <value>.
- <value> may be 1|true|on or 0|false|off
-
start <service>
Start a service running if it is not already running.
diff --git a/init/util.c b/init/util.c
index 918bc05..743748b 100755
--- a/init/util.c
+++ b/init/util.c
@@ -23,7 +23,9 @@
#include <errno.h>
#include <time.h>
+#ifdef HAVE_SELINUX
#include <selinux/label.h>
+#endif
#include <sys/stat.h>
#include <sys/types.h>
@@ -87,7 +89,9 @@ int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid)
{
struct sockaddr_un addr;
int fd, ret;
+#ifdef HAVE_SELINUX
char *secon;
+#endif
fd = socket(PF_UNIX, type, 0);
if (fd < 0) {
@@ -106,12 +110,14 @@ int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid)
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));
if (ret) {
@@ -119,8 +125,10 @@ int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid)
goto out_unlink;
}
+#ifdef HAVE_SELINUX
setfscreatecon(NULL);
freecon(secon);
+#endif
chown(addr.sun_path, uid, gid);
chmod(addr.sun_path, perm);
@@ -460,27 +468,31 @@ 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) {
int save_errno = errno;
freecon(secontext);
setfscreatecon(NULL);
errno = save_errno;
}
-
+#endif
return rc;
}
int restorecon(const char *pathname)
{
+#ifdef HAVE_SELINUX
char *secontext = NULL;
struct stat sb;
int i;
@@ -497,5 +509,6 @@ int restorecon(const char *pathname)
return -errno;
}
freecon(secontext);
+#endif
return 0;
}