Merge "Fix a print format warning"
diff --git a/init/devices.c b/init/devices.c
index c367de8..597f958 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -33,6 +33,7 @@
#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
#include <selinux/label.h>
+#include <selinux/android.h>
#endif
#include <private/android_filesystem_config.h>
@@ -871,12 +872,10 @@
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);
+ sehandle = NULL;
+ if (is_selinux_enabled() > 0) {
+ sehandle = selinux_android_file_context_handle();
+ }
#endif
/* is 64K enough? udev uses 16MB! */
device_fd = uevent_open_socket(64*1024, true);
diff --git a/init/init.c b/init/init.c
index cc98afc..b2e39bd 100755
--- a/init/init.c
+++ b/init/init.c
@@ -33,9 +33,9 @@
#include <sys/un.h>
#ifdef HAVE_SELINUX
-#include <sys/mman.h>
#include <selinux/selinux.h>
#include <selinux/label.h>
+#include <selinux/android.h>
#endif
#include <libgen.h>
@@ -61,6 +61,7 @@
#ifdef HAVE_SELINUX
struct selabel_handle *sehandle;
+struct selabel_handle *sehandle_prop;
#endif
static int property_triggers_enabled = 0;
@@ -77,7 +78,6 @@
#ifdef HAVE_SELINUX
static int selinux_enabled = 1;
-static int selinux_enforcing = 0;
#endif
static struct action *cur_action = NULL;
@@ -604,9 +604,7 @@
if (name_len == 0) return;
#ifdef HAVE_SELINUX
- if (!strcmp(name,"enforcing")) {
- selinux_enforcing = atoi(value);
- } else if (!strcmp(name,"selinux")) {
+ if (!strcmp(name,"selinux")) {
selinux_enabled = atoi(value);
}
#endif
@@ -758,94 +756,64 @@
#endif
#ifdef HAVE_SELINUX
-void selinux_load_policy(void)
+static const struct selinux_opt seopts_prop[] = {
+ { SELABEL_OPT_PATH, "/data/system/property_contexts" },
+ { SELABEL_OPT_PATH, "/property_contexts" },
+ { 0, NULL }
+};
+
+struct selabel_handle* selinux_android_prop_context_handle(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;
+ int i = 0;
+ struct selabel_handle* sehandle = NULL;
+ while ((sehandle == NULL) && seopts_prop[i].value) {
+ sehandle = selabel_open(SELABEL_CTX_ANDROID_PROP, &seopts_prop[i], 1);
+ i++;
}
- 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",
+ ERROR("SELinux: Could not load property_contexts: %s\n",
strerror(errno));
- return;
+ return NULL;
}
- INFO("SELinux: Loaded file contexts from %s\n", seopts[0].value);
- return;
+ INFO("SELinux: Loaded property contexts from %s\n", seopts_prop[i - 1].value);
+ return sehandle;
}
+
+void selinux_init_all_handles(void)
+{
+ sehandle = selinux_android_file_context_handle();
+ sehandle_prop = selinux_android_prop_context_handle();
+}
+
+int selinux_reload_policy(void)
+{
+ if (!selinux_enabled) {
+ return -1;
+ }
+
+ INFO("SELinux: Attempting to reload policy files\n");
+
+ if (selinux_android_reload_policy() == -1) {
+ return -1;
+ }
+
+ if (sehandle)
+ selabel_close(sehandle);
+
+ if (sehandle_prop)
+ selabel_close(sehandle_prop);
+
+ selinux_init_all_handles();
+ return 0;
+}
+
+int audit_callback(void *data, security_class_t cls, char *buf, size_t len)
+{
+ snprintf(buf, len, "property=%s", !data ? "NULL" : (char *)data);
+ return 0;
+}
+
#endif
int main(int argc, char **argv)
@@ -899,9 +867,25 @@
process_kernel_cmdline();
#ifdef HAVE_SELINUX
+ union selinux_callback cb;
+ cb.func_log = klog_write;
+ selinux_set_callback(SELINUX_CB_LOG, cb);
+
+ cb.func_audit = audit_callback;
+ selinux_set_callback(SELINUX_CB_AUDIT, cb);
+
INFO("loading selinux policy\n");
- selinux_load_policy();
- /* These directories were necessarily created before policy load
+ if (selinux_enabled) {
+ if (selinux_android_load_policy() < 0) {
+ selinux_enabled = 0;
+ INFO("SELinux: Disabled due to failed policy load\n");
+ } else {
+ selinux_init_all_handles();
+ }
+ } else {
+ INFO("SELinux: Disabled by command line option\n");
+ }
+ /* These directories were necessarily created before initial policy load
* and therefore need their security context restored to the proper value.
* This must happen before /dev is populated by ueventd.
*/
diff --git a/init/init.h b/init/init.h
index 58bbbfe..b7e06c9 100644
--- a/init/init.h
+++ b/init/init.h
@@ -138,6 +138,8 @@
#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/property_service.c b/init/property_service.c
index 79914cd..5017375 100644
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -40,6 +40,11 @@
#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"
#include "util.h"
@@ -86,6 +91,7 @@
{ "persist.sys.", AID_SYSTEM, 0 },
{ "persist.service.", AID_SYSTEM, 0 },
{ "persist.security.", AID_SYSTEM, 0 },
+ { "selinux." , AID_SYSTEM, 0 },
{ NULL, 0, 0 }
};
@@ -191,23 +197,77 @@
__futex_wake(&pi->serial, INT32_MAX);
}
+static int check_mac_perms(const char *name, char *sctx)
+{
+#ifdef HAVE_SELINUX
+ if (is_selinux_enabled() <= 0)
+ return 1;
+
+ char *tctx = NULL;
+ const char *class = "property_service";
+ const char *perm = "set";
+ int result = 0;
+
+ if (!sctx)
+ goto err;
+
+ if (!sehandle_prop)
+ goto err;
+
+ if (selabel_lookup(sehandle_prop, &tctx, name, 1) != 0)
+ goto err;
+
+ if (selinux_check_access(sctx, tctx, class, perm, name) == 0)
+ result = 1;
+
+ 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
+ * property service backend labeling while avoiding
+ * mislabels based on true property prefixes.
+ */
+ char ctl_name[PROP_VALUE_MAX+4];
+ int ret = snprintf(ctl_name, sizeof(ctl_name), "ctl.%s", name);
+
+ if (ret < 0 || (size_t) ret >= sizeof(ctl_name))
+ return 0;
+
+ return check_mac_perms(ctl_name, sctx);
+
+#endif
+ return 1;
+}
+
/*
* Checks permissions for starting/stoping system services.
* AID_SYSTEM and AID_ROOT are always allowed.
*
* Returns 1 if uid allowed, 0 otherwise.
*/
-static int check_control_perms(const char *name, unsigned int uid, unsigned int gid) {
+static int check_control_perms(const char *name, unsigned int uid, unsigned int gid, char *sctx) {
+
int i;
if (uid == AID_SYSTEM || uid == AID_ROOT)
- return 1;
+ return check_control_mac_perms(name, sctx);
/* Search the ACL */
for (i = 0; control_perms[i].service; i++) {
if (strcmp(control_perms[i].service, name) == 0) {
if ((uid && control_perms[i].uid == uid) ||
(gid && control_perms[i].gid == gid)) {
- return 1;
+ return check_control_mac_perms(name, sctx);
}
}
}
@@ -218,22 +278,22 @@
* Checks permissions for setting system properties.
* Returns 1 if uid allowed, 0 otherwise.
*/
-static int check_perms(const char *name, unsigned int uid, unsigned int gid)
+static int check_perms(const char *name, unsigned int uid, unsigned int gid, char *sctx)
{
int i;
- if (uid == 0)
- return 1;
-
if(!strncmp(name, "ro.", 3))
name +=3;
+ if (uid == 0)
+ return check_mac_perms(name, sctx);
+
for (i = 0; property_perms[i].prefix; i++) {
- int tmp;
if (strncmp(property_perms[i].prefix, name,
strlen(property_perms[i].prefix)) == 0) {
if ((uid && property_perms[i].uid == uid) ||
(gid && property_perms[i].gid == gid)) {
- return 1;
+
+ return check_mac_perms(name, sctx);
}
}
}
@@ -334,6 +394,11 @@
* 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;
@@ -349,6 +414,7 @@
struct sockaddr_un addr;
socklen_t addr_size = sizeof(addr);
socklen_t cr_size = sizeof(cr);
+ char * source_ctx = NULL;
if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) {
return;
@@ -374,18 +440,22 @@
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
// ctl.* properties.
close(s);
- if (check_control_perms(msg.value, cr.uid, cr.gid)) {
+ if (check_control_perms(msg.value, cr.uid, cr.gid, source_ctx)) {
handle_control_message((char*) msg.name + 4, (char*) msg.value);
} else {
ERROR("sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n",
msg.name + 4, msg.value, cr.uid, cr.gid, cr.pid);
}
} else {
- if (check_perms(msg.name, cr.uid, cr.gid)) {
+ if (check_perms(msg.name, cr.uid, cr.gid, source_ctx)) {
property_set((char*) msg.name, (char*) msg.value);
} else {
ERROR("sys_prop: permission denied uid:%d name:%s\n",
@@ -397,6 +467,10 @@
// the property is written to memory.
close(s);
}
+#ifdef HAVE_SELINUX
+ freecon(source_ctx);
+#endif
+
break;
default:
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 054c2ca..6a0c332 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -355,6 +355,10 @@
critical
seclabel u:r:ueventd:s0
+on property:selinux.reload_policy=1
+ restart ueventd
+ restart installd
+
service console /system/bin/sh
class core
console
diff --git a/toolbox/restorecon.c b/toolbox/restorecon.c
index 5ef0ef1..f9f604f 100644
--- a/toolbox/restorecon.c
+++ b/toolbox/restorecon.c
@@ -7,8 +7,7 @@
#include <fts.h>
#include <selinux/selinux.h>
#include <selinux/label.h>
-
-#define FCPATH "/file_contexts"
+#include <selinux/android.h>
static struct selabel_handle *sehandle;
static const char *progname;
@@ -17,7 +16,7 @@
static void usage(void)
{
- fprintf(stderr, "usage: %s [-f file_contexts] [-nrRv] pathname...\n", progname);
+ fprintf(stderr, "usage: %s [-nrRv] pathname...\n", progname);
exit(1);
}
@@ -54,21 +53,16 @@
int restorecon_main(int argc, char **argv)
{
- struct selinux_opt seopts[] = {
- { SELABEL_OPT_PATH, FCPATH }
- };
int ch, recurse = 0, ftsflags = FTS_PHYSICAL;
+ int i = 0;
progname = argv[0];
do {
- ch = getopt(argc, argv, "f:nrRv");
+ ch = getopt(argc, argv, "nrRv");
if (ch == EOF)
break;
switch (ch) {
- case 'f':
- seopts[0].value = optarg;
- break;
case 'n':
nochange = 1;
break;
@@ -89,9 +83,10 @@
if (!argc)
usage();
- sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);
+ sehandle = selinux_android_file_context_handle();
+
if (!sehandle) {
- fprintf(stderr, "Could not load file contexts from %s: %s\n", seopts[0].value,
+ fprintf(stderr, "Could not load file_contexts: %s\n",
strerror(errno));
return -1;
}