Loading init/init.c +43 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ #ifdef HAVE_SELINUX struct selabel_handle *sehandle; struct selabel_handle *sehandle_prop; #endif static int property_triggers_enabled = 0; Loading Loading @@ -755,9 +756,34 @@ 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" }, { 0, NULL } }; struct selabel_handle* selinux_android_prop_context_handle(void) { 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++; } if (!sehandle) { ERROR("SELinux: Could not load property_contexts: %s\n", strerror(errno)); return NULL; } 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) Loading @@ -775,9 +801,19 @@ int selinux_reload_policy(void) 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) Loading Loading @@ -831,6 +867,13 @@ 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); cb.func_audit = audit_callback; selinux_set_callback(SELINUX_CB_AUDIT, cb); INFO("loading selinux policy\n"); if (selinux_enabled) { if (selinux_android_load_policy() < 0) { Loading init/init.h +1 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,7 @@ 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 Loading init/property_service.c +79 −11 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -192,23 +197,77 @@ static void update_prop_info(prop_info *pi, const char *value, unsigned len) __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); } } } Loading @@ -219,22 +278,22 @@ static int check_control_perms(const char *name, unsigned int uid, unsigned int * 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); } } } Loading Loading @@ -355,6 +414,7 @@ void handle_property_set_fd() 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; Loading @@ -380,18 +440,22 @@ 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 // 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", Loading @@ -403,6 +467,10 @@ void handle_property_set_fd() // the property is written to memory. close(s); } #ifdef HAVE_SELINUX freecon(source_ctx); #endif break; default: Loading Loading
init/init.c +43 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,7 @@ #ifdef HAVE_SELINUX struct selabel_handle *sehandle; struct selabel_handle *sehandle_prop; #endif static int property_triggers_enabled = 0; Loading Loading @@ -755,9 +756,34 @@ 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" }, { 0, NULL } }; struct selabel_handle* selinux_android_prop_context_handle(void) { 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++; } if (!sehandle) { ERROR("SELinux: Could not load property_contexts: %s\n", strerror(errno)); return NULL; } 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) Loading @@ -775,9 +801,19 @@ int selinux_reload_policy(void) 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) Loading Loading @@ -831,6 +867,13 @@ 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); cb.func_audit = audit_callback; selinux_set_callback(SELINUX_CB_AUDIT, cb); INFO("loading selinux policy\n"); if (selinux_enabled) { if (selinux_android_load_policy() < 0) { Loading
init/init.h +1 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,7 @@ 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 Loading
init/property_service.c +79 −11 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -192,23 +197,77 @@ static void update_prop_info(prop_info *pi, const char *value, unsigned len) __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); } } } Loading @@ -219,22 +278,22 @@ static int check_control_perms(const char *name, unsigned int uid, unsigned int * 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); } } } Loading Loading @@ -355,6 +414,7 @@ void handle_property_set_fd() 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; Loading @@ -380,18 +440,22 @@ 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 // 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", Loading @@ -403,6 +467,10 @@ void handle_property_set_fd() // the property is written to memory. close(s); } #ifdef HAVE_SELINUX freecon(source_ctx); #endif break; default: Loading