diff options
Diffstat (limited to 'init/property_service.c')
-rwxr-xr-x[-rw-r--r--] | init/property_service.c | 105 |
1 files changed, 58 insertions, 47 deletions
diff --git a/init/property_service.c b/init/property_service.c index 5017375..61dd86f 100644..100755 --- a/init/property_service.c +++ b/init/property_service.c @@ -40,10 +40,8 @@ #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" @@ -81,6 +79,7 @@ struct { { "sys.", AID_SYSTEM, 0 }, { "service.", AID_SYSTEM, 0 }, { "wlan.", AID_SYSTEM, 0 }, + { "bluetooth.", AID_BLUETOOTH, 0 }, { "dhcp.", AID_SYSTEM, 0 }, { "dhcp.", AID_DHCP, 0 }, { "debug.", AID_SYSTEM, 0 }, @@ -91,6 +90,7 @@ struct { { "persist.sys.", AID_SYSTEM, 0 }, { "persist.service.", AID_SYSTEM, 0 }, { "persist.security.", AID_SYSTEM, 0 }, + { "persist.service.bdroid.", AID_BLUETOOTH, 0 }, { "selinux." , AID_SYSTEM, 0 }, { NULL, 0, 0 } }; @@ -123,7 +123,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, 0600); + fd = open("/dev/__properties__", O_RDWR | O_CREAT | O_NOFOLLOW, 0600); if (fd < 0) return -1; @@ -136,7 +136,7 @@ static int init_workspace(workspace *w, size_t size) close(fd); - fd = open("/dev/__properties__", O_RDONLY); + fd = open("/dev/__properties__", O_RDONLY | O_NOFOLLOW); if (fd < 0) return -1; @@ -199,7 +199,6 @@ 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; @@ -223,15 +222,10 @@ 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 @@ -245,9 +239,6 @@ static int check_control_mac_perms(const char *name, char *sctx) return 0; return check_mac_perms(ctl_name, sctx); - -#endif - return 1; } /* @@ -318,13 +309,12 @@ const char* property_get(const char *name) static void write_persistent_property(const char *name, const char *value) { - const char *tempPath = PERSISTENT_PROPERTY_DIR "/.temp"; + char tempPath[PATH_MAX]; char path[PATH_MAX]; - int fd, length; - - snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, name); + int fd; - fd = open(tempPath, O_WRONLY|O_CREAT|O_TRUNC, 0600); + snprintf(tempPath, sizeof(tempPath), "%s/.temp.XXXXXX", PERSISTENT_PROPERTY_DIR); + fd = mkstemp(tempPath); if (fd < 0) { ERROR("Unable to write persistent property to temp file %s errno: %d\n", tempPath, errno); return; @@ -332,6 +322,7 @@ 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); @@ -343,8 +334,8 @@ int property_set(const char *name, const char *value) prop_area *pa; prop_info *pi; - int namelen = strlen(name); - int valuelen = strlen(value); + size_t namelen = strlen(name); + size_t valuelen = strlen(value); if(namelen >= PROP_NAME_MAX) return -1; if(valuelen >= PROP_VALUE_MAX) return -1; @@ -394,11 +385,9 @@ 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; @@ -423,13 +412,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 recieve socket options\n"); + ERROR("Unable to receive 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 recieved: %d expected: %d errno: %d\n", + ERROR("sys_prop: mis-match msg size received: %d expected: %d errno: %d\n", r, sizeof(prop_msg), errno); close(s); return; @@ -440,9 +429,7 @@ 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 @@ -467,10 +454,7 @@ void handle_property_set_fd() // the property is written to memory. close(s); } -#ifdef HAVE_SELINUX freecon(source_ctx); -#endif - break; default: @@ -528,12 +512,14 @@ 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; @@ -542,20 +528,39 @@ static void load_persistent_properties() continue; #endif /* open the file and read the property value */ - 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); - } + 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); + 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 open persistent property file %s errno: %d\n", path, errno); + ERROR("Unable to read persistent property file %s errno: %d\n", + entry->d_name, errno); } + close(fd); } closedir(dir); } else { @@ -580,6 +585,16 @@ int properties_inited(void) return property_area_inited; } +static void load_override_properties() { +#ifdef ALLOW_LOCAL_PROP_OVERRIDE + const char *debuggable = property_get("ro.debuggable"); + if (debuggable && (strcmp(debuggable, "1") == 0)) { + load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE); + } +#endif /* ALLOW_LOCAL_PROP_OVERRIDE */ +} + + /* When booting an encrypted system, /data is not mounted when the * property service is started, so any properties stored there are * not loaded. Vold triggers init to load these properties once it @@ -587,9 +602,7 @@ int properties_inited(void) */ void load_persist_props(void) { -#ifdef ALLOW_LOCAL_PROP_OVERRIDE - load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE); -#endif /* ALLOW_LOCAL_PROP_OVERRIDE */ + load_override_properties(); /* Read persistent properties after all default values have been loaded. */ load_persistent_properties(); } @@ -600,9 +613,7 @@ void start_property_service(void) load_properties_from_file(PROP_PATH_SYSTEM_BUILD); load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT); -#ifdef ALLOW_LOCAL_PROP_OVERRIDE - load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE); -#endif /* ALLOW_LOCAL_PROP_OVERRIDE */ + load_override_properties(); /* Read persistent properties after all default values have been loaded. */ load_persistent_properties(); |