diff options
Diffstat (limited to 'init')
-rw-r--r-- | init/Android.mk | 12 | ||||
-rw-r--r-- | init/builtins.c | 48 | ||||
-rw-r--r-- | init/devices.c | 21 | ||||
-rwxr-xr-x | init/init.c | 27 | ||||
-rw-r--r-- | init/init.h | 4 | ||||
-rw-r--r-- | init/init_parser.c | 2 | ||||
-rw-r--r-- | init/keywords.h | 2 | ||||
-rwxr-xr-x | init/property_service.c | 85 | ||||
-rw-r--r-- | init/readme.txt | 26 | ||||
-rwxr-xr-x | init/util.c | 15 |
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; } |