diff options
Diffstat (limited to 'init/property_service.c')
-rw-r--r-- | init/property_service.c | 201 |
1 files changed, 70 insertions, 131 deletions
diff --git a/init/property_service.c b/init/property_service.c index ac63377..d112699 100644 --- a/init/property_service.c +++ b/init/property_service.c @@ -38,7 +38,6 @@ #include <sys/types.h> #include <netinet/in.h> #include <sys/mman.h> -#include <sys/atomics.h> #include <private/android_filesystem_config.h> #include <selinux/selinux.h> @@ -56,63 +55,6 @@ static int property_area_inited = 0; static int property_set_fd = -1; -/* White list of permissions for setting property services. */ -struct { - const char *prefix; - unsigned int uid; - unsigned int gid; -} property_perms[] = { - { "net.rmnet0.", AID_RADIO, 0 }, - { "net.gprs.", AID_RADIO, 0 }, - { "net.ppp", AID_RADIO, 0 }, - { "net.qmi", AID_RADIO, 0 }, - { "net.lte", AID_RADIO, 0 }, - { "net.cdma", AID_RADIO, 0 }, - { "ril.", AID_RADIO, 0 }, - { "gsm.", AID_RADIO, 0 }, - { "persist.radio", AID_RADIO, 0 }, - { "net.dns", AID_RADIO, 0 }, - { "sys.usb.config", AID_RADIO, 0 }, - { "net.", AID_SYSTEM, 0 }, - { "dev.", AID_SYSTEM, 0 }, - { "runtime.", AID_SYSTEM, 0 }, - { "hw.", AID_SYSTEM, 0 }, - { "sys.", AID_SYSTEM, 0 }, - { "sys.powerctl", AID_SHELL, 0 }, - { "service.", AID_SYSTEM, 0 }, - { "wlan.", AID_SYSTEM, 0 }, - { "gps.", AID_GPS, 0 }, - { "bluetooth.", AID_BLUETOOTH, 0 }, - { "dhcp.", AID_SYSTEM, 0 }, - { "dhcp.", AID_DHCP, 0 }, - { "debug.", AID_SYSTEM, 0 }, - { "debug.", AID_SHELL, 0 }, - { "log.", AID_SHELL, 0 }, - { "service.adb.root", AID_SHELL, 0 }, - { "service.adb.tcp.port", AID_SHELL, 0 }, - { "persist.sys.", AID_SYSTEM, 0 }, - { "persist.service.", AID_SYSTEM, 0 }, - { "persist.security.", AID_SYSTEM, 0 }, - { "persist.gps.", AID_GPS, 0 }, - { "persist.service.bdroid.", AID_BLUETOOTH, 0 }, - { "selinux." , AID_SYSTEM, 0 }, - { NULL, 0, 0 } -}; - -/* - * White list of UID that are allowed to start/stop services. - * Currently there are no user apps that require. - */ -struct { - const char *service; - unsigned int uid; - unsigned int gid; -} control_perms[] = { - { "dumpstate",AID_SHELL, AID_LOG }, - { "ril-daemon",AID_RADIO, AID_RADIO }, - {NULL, 0, 0 } -}; - typedef struct { size_t size; int fd; @@ -194,34 +136,10 @@ static int check_control_mac_perms(const char *name, char *sctx) } /* - * 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, char *sctx) { - - int i; - if (uid == AID_SYSTEM || uid == AID_ROOT) - 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 check_control_mac_perms(name, sctx); - } - } - } - return 0; -} - -/* * 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, char *sctx) +static int check_perms(const char *name, char *sctx) { int i; unsigned int app_id; @@ -229,26 +147,7 @@ static int check_perms(const char *name, unsigned int uid, unsigned int gid, cha if(!strncmp(name, "ro.", 3)) name +=3; - if (uid == 0) - return check_mac_perms(name, sctx); - - app_id = multiuser_get_app_id(uid); - if (app_id == AID_BLUETOOTH) { - uid = app_id; - } - - for (i = 0; property_perms[i].prefix; i++) { - 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 check_mac_perms(name, sctx); - } - } - } - - return 0; + return check_mac_perms(name, sctx); } int __property_get(const char *name, char *value) @@ -269,6 +168,7 @@ static void write_persistent_property(const char *name, const char *value) return; } write(fd, value, strlen(value)); + fsync(fd); close(fd); snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, name); @@ -405,14 +305,14 @@ void handle_property_set_fd() // Keep the old close-socket-early behavior when handling // ctl.* properties. close(s); - if (check_control_perms(msg.value, cr.uid, cr.gid, source_ctx)) { + if (check_control_mac_perms(msg.value, 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, source_ctx)) { + if (check_perms(msg.name, source_ctx)) { property_set((char*) msg.name, (char*) msg.value); } else { ERROR("sys_prop: permission denied uid:%d name:%s\n", @@ -439,40 +339,73 @@ void get_property_workspace(int *fd, int *sz) *sz = pa_workspace.size; } -static void load_properties(char *data, char *prefix) +static void load_properties_from_file(const char *, const char *); + +/* + * Filter is used to decide which properties to load: NULL loads all keys, + * "ro.foo.*" is a prefix match, and "ro.foo.bar" is an exact match. + */ +static void load_properties(char *data, const char *filter) { - char *key, *value, *eol, *sol, *tmp; - size_t plen; + char *key, *value, *eol, *sol, *tmp, *fn; + size_t flen = 0; + + if (filter) { + flen = strlen(filter); + } - if (prefix) - plen = strlen(prefix); sol = data; - while((eol = strchr(sol, '\n'))) { + while ((eol = strchr(sol, '\n'))) { key = sol; *eol++ = 0; sol = eol; - value = strchr(key, '='); - if(value == 0) continue; - *value++ = 0; + while (isspace(*key)) key++; + if (*key == '#') continue; - while(isspace(*key)) key++; - if(*key == '#') continue; - tmp = value - 2; - while((tmp > key) && isspace(*tmp)) *tmp-- = 0; + tmp = eol - 2; + while ((tmp > key) && isspace(*tmp)) *tmp-- = 0; - if (prefix && strncmp(key, prefix, plen)) - continue; + if (!strncmp(key, "import ", 7) && flen == 0) { + fn = key + 7; + while (isspace(*fn)) fn++; - while(isspace(*value)) value++; - tmp = eol - 2; - while((tmp > value) && isspace(*tmp)) *tmp-- = 0; + key = strchr(fn, ' '); + if (key) { + *key++ = 0; + while (isspace(*key)) key++; + } + + load_properties_from_file(fn, key); + + } else { + value = strchr(key, '='); + if (!value) continue; + *value++ = 0; + + tmp = value - 2; + while ((tmp > key) && isspace(*tmp)) *tmp-- = 0; + + while (isspace(*value)) value++; + + if (flen > 0) { + if (filter[flen - 1] == '*') { + if (strncmp(key, filter, flen - 1)) continue; + } else { + if (strcmp(key, filter)) continue; + } + } - property_set(key, value); + property_set(key, value); + } } } -static void load_properties_from_file(const char *fn, char *prefix) +/* + * Filter is used to decide which properties to load: NULL loads all keys, + * "ro.foo.*" is a prefix match, and "ro.foo.bar" is an exact match. + */ +static void load_properties_from_file(const char *fn, const char *filter) { char *data; unsigned sz; @@ -480,7 +413,7 @@ static void load_properties_from_file(const char *fn, char *prefix) data = read_file(fn, &sz); if(data != 0) { - load_properties(data, prefix); + load_properties(data, filter); free(data); } } @@ -523,7 +456,8 @@ static void load_persistent_properties() || (sb.st_gid != 0) || (sb.st_nlink != 1)) { ERROR("skipping insecure property file %s (uid=%u gid=%u nlink=%d mode=%o)\n", - entry->d_name, sb.st_uid, sb.st_gid, sb.st_nlink, sb.st_mode); + entry->d_name, (unsigned int)sb.st_uid, (unsigned int)sb.st_gid, + sb.st_nlink, sb.st_mode); close(fd); continue; } @@ -586,16 +520,21 @@ void load_persist_props(void) load_persistent_properties(); } -void start_property_service(void) +void load_all_props(void) { - int fd; - load_properties_from_file(PROP_PATH_SYSTEM_BUILD, NULL); load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT, NULL); - load_properties_from_file(PROP_PATH_FACTORY, "ro."); + load_properties_from_file(PROP_PATH_FACTORY, "ro.*"); + load_override_properties(); + /* Read persistent properties after all default values have been loaded. */ load_persistent_properties(); +} + +void start_property_service(void) +{ + int fd; fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM, 0666, 0, 0, NULL); if(fd < 0) return; |