| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 1 | /* | 
 | 2 | ** Copyright 2008, The Android Open Source Project | 
 | 3 | ** | 
| Jeff Sharkey | 1980380 | 2015-04-07 12:44:51 -0700 | [diff] [blame] | 4 | ** Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 | ** you may not use this file except in compliance with the License. | 
 | 6 | ** You may obtain a copy of the License at | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 7 | ** | 
| Jeff Sharkey | 1980380 | 2015-04-07 12:44:51 -0700 | [diff] [blame] | 8 | **     http://www.apache.org/licenses/LICENSE-2.0 | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 9 | ** | 
| Jeff Sharkey | 1980380 | 2015-04-07 12:44:51 -0700 | [diff] [blame] | 10 | ** Unless required by applicable law or agreed to in writing, software | 
 | 11 | ** distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 | ** See the License for the specific language governing permissions and | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 14 | ** limitations under the License. | 
 | 15 | */ | 
 | 16 |  | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 17 | #include <fcntl.h> | 
| Stephen Smalley | bd558d6 | 2013-04-16 12:16:50 -0400 | [diff] [blame] | 18 | #include <selinux/android.h> | 
 | 19 | #include <selinux/avc.h> | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 20 | #include <sys/capability.h> | 
| Jeff Sharkey | c7d1b22 | 2016-01-11 13:07:09 -0700 | [diff] [blame] | 21 | #include <sys/fsuid.h> | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 22 | #include <sys/prctl.h> | 
 | 23 | #include <sys/socket.h> | 
 | 24 | #include <sys/stat.h> | 
 | 25 |  | 
 | 26 | #include <android-base/logging.h> | 
 | 27 | #include <cutils/fs.h> | 
 | 28 | #include <cutils/log.h>               // TODO: Move everything to base::logging. | 
 | 29 | #include <cutils/properties.h> | 
 | 30 | #include <cutils/sockets.h> | 
 | 31 | #include <private/android_filesystem_config.h> | 
 | 32 |  | 
 | 33 | #include <commands.h> | 
 | 34 | #include <globals.h> | 
 | 35 | #include <installd_constants.h> | 
 | 36 | #include <installd_deps.h>  // Need to fill in requirements of commands. | 
 | 37 | #include <utils.h> | 
 | 38 |  | 
 | 39 | #ifndef LOG_TAG | 
 | 40 | #define LOG_TAG "installd" | 
 | 41 | #endif | 
 | 42 | #define SOCKET_PATH "installd" | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 43 |  | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 44 | #define BUFFER_MAX    1024  /* input buffer for commands */ | 
| Fyodor Kupolov | 88ce4ff | 2015-03-03 12:25:29 -0800 | [diff] [blame] | 45 | #define TOKEN_MAX     16    /* max number of arguments in buffer */ | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 46 | #define REPLY_MAX     256   /* largest reply allowed */ | 
 | 47 |  | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 48 | namespace android { | 
 | 49 | namespace installd { | 
 | 50 |  | 
 | 51 | // Check that installd-deps sizes match cutils sizes. | 
 | 52 | static_assert(kPropertyKeyMax == PROPERTY_KEY_MAX, "Size mismatch."); | 
 | 53 | static_assert(kPropertyValueMax == PROPERTY_VALUE_MAX, "Size mismatch."); | 
 | 54 |  | 
 | 55 | //////////////////////// | 
 | 56 | // Plug-in functions. // | 
 | 57 | //////////////////////// | 
 | 58 |  | 
 | 59 | int get_property(const char *key, char *value, const char *default_value) { | 
 | 60 |     return property_get(key, value, default_value); | 
 | 61 | } | 
 | 62 |  | 
 | 63 | // Compute the output path of | 
 | 64 | bool calculate_oat_file_path(char path[PKG_PATH_MAX], | 
 | 65 |                              const char *oat_dir, | 
 | 66 |                              const char *apk_path, | 
 | 67 |                              const char *instruction_set) { | 
| Dan Austin | 6323502 | 2016-03-28 15:09:02 -0700 | [diff] [blame] | 68 |     const char *file_name_start; | 
 | 69 |     const char *file_name_end; | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 70 |  | 
 | 71 |     file_name_start = strrchr(apk_path, '/'); | 
 | 72 |     if (file_name_start == NULL) { | 
 | 73 |         ALOGE("apk_path '%s' has no '/'s in it\n", apk_path); | 
 | 74 |         return false; | 
 | 75 |     } | 
 | 76 |     file_name_end = strrchr(apk_path, '.'); | 
 | 77 |     if (file_name_end < file_name_start) { | 
 | 78 |         ALOGE("apk_path '%s' has no extension\n", apk_path); | 
 | 79 |         return false; | 
 | 80 |     } | 
 | 81 |  | 
 | 82 |     // Calculate file_name | 
 | 83 |     int file_name_len = file_name_end - file_name_start - 1; | 
 | 84 |     char file_name[file_name_len + 1]; | 
 | 85 |     memcpy(file_name, file_name_start + 1, file_name_len); | 
 | 86 |     file_name[file_name_len] = '\0'; | 
 | 87 |  | 
 | 88 |     // <apk_parent_dir>/oat/<isa>/<file_name>.odex | 
 | 89 |     snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name); | 
 | 90 |     return true; | 
 | 91 | } | 
 | 92 |  | 
 | 93 | /* | 
 | 94 |  * Computes the odex file for the given apk_path and instruction_set. | 
 | 95 |  * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex | 
 | 96 |  * | 
 | 97 |  * Returns false if it failed to determine the odex file path. | 
 | 98 |  */ | 
 | 99 | bool calculate_odex_file_path(char path[PKG_PATH_MAX], | 
 | 100 |                               const char *apk_path, | 
 | 101 |                               const char *instruction_set) { | 
 | 102 |     if (strlen(apk_path) + strlen("oat/") + strlen(instruction_set) | 
 | 103 |             + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) { | 
 | 104 |         ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path); | 
 | 105 |         return false; | 
 | 106 |     } | 
 | 107 |  | 
 | 108 |     strcpy(path, apk_path); | 
 | 109 |     char *end = strrchr(path, '/'); | 
 | 110 |     if (end == NULL) { | 
 | 111 |         ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path); | 
 | 112 |         return false; | 
 | 113 |     } | 
 | 114 |     const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/'); | 
 | 115 |  | 
 | 116 |     strcpy(end + 1, "oat/");       // path = /system/framework/oat/\0 | 
 | 117 |     strcat(path, instruction_set); // path = /system/framework/oat/<isa>\0 | 
 | 118 |     strcat(path, apk_end);         // path = /system/framework/oat/<isa>/whatever.jar\0 | 
 | 119 |     end = strrchr(path, '.'); | 
 | 120 |     if (end == NULL) { | 
 | 121 |         ALOGE("apk_path '%s' has no extension.\n", apk_path); | 
 | 122 |         return false; | 
 | 123 |     } | 
 | 124 |     strcpy(end + 1, "odex"); | 
 | 125 |     return true; | 
 | 126 | } | 
 | 127 |  | 
 | 128 | bool create_cache_path(char path[PKG_PATH_MAX], | 
 | 129 |                        const char *src, | 
 | 130 |                        const char *instruction_set) { | 
| Greg Kaiser | 00087b7 | 2016-03-14 13:29:10 -0700 | [diff] [blame] | 131 |     /* demand that we are an absolute path */ | 
 | 132 |     if ((src == nullptr) || (src[0] != '/') || strstr(src,"..")) { | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 133 |         return false; | 
 | 134 |     } | 
 | 135 |  | 
| Greg Kaiser | 00087b7 | 2016-03-14 13:29:10 -0700 | [diff] [blame] | 136 |     size_t srclen = strlen(src); | 
 | 137 |  | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 138 |     if (srclen > PKG_PATH_MAX) {        // XXX: PKG_NAME_MAX? | 
 | 139 |         return false; | 
 | 140 |     } | 
 | 141 |  | 
 | 142 |     size_t dstlen = | 
 | 143 |         android_data_dir.len + | 
 | 144 |         strlen(DALVIK_CACHE) + | 
 | 145 |         1 + | 
 | 146 |         strlen(instruction_set) + | 
 | 147 |         srclen + | 
 | 148 |         strlen(DALVIK_CACHE_POSTFIX) + 2; | 
 | 149 |  | 
 | 150 |     if (dstlen > PKG_PATH_MAX) { | 
 | 151 |         return false; | 
 | 152 |     } | 
 | 153 |  | 
 | 154 |     sprintf(path,"%s%s/%s/%s%s", | 
 | 155 |             android_data_dir.path, | 
 | 156 |             DALVIK_CACHE, | 
 | 157 |             instruction_set, | 
 | 158 |             src + 1, /* skip the leading / */ | 
 | 159 |             DALVIK_CACHE_POSTFIX); | 
 | 160 |  | 
 | 161 |     char* tmp = | 
 | 162 |             path + | 
 | 163 |             android_data_dir.len + | 
 | 164 |             strlen(DALVIK_CACHE) + | 
 | 165 |             1 + | 
 | 166 |             strlen(instruction_set) + 1; | 
 | 167 |  | 
 | 168 |     for(; *tmp; tmp++) { | 
 | 169 |         if (*tmp == '/') { | 
 | 170 |             *tmp = '@'; | 
 | 171 |         } | 
 | 172 |     } | 
 | 173 |  | 
 | 174 |     return true; | 
 | 175 | } | 
 | 176 |  | 
 | 177 |  | 
| Jeff Sharkey | 6fe28a0 | 2015-04-09 13:10:03 -0700 | [diff] [blame] | 178 | static char* parse_null(char* arg) { | 
 | 179 |     if (strcmp(arg, "!") == 0) { | 
 | 180 |         return nullptr; | 
 | 181 |     } else { | 
 | 182 |         return arg; | 
 | 183 |     } | 
 | 184 | } | 
 | 185 |  | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 186 | static int do_ping(char **arg ATTRIBUTE_UNUSED, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 187 | { | 
 | 188 |     return 0; | 
 | 189 | } | 
 | 190 |  | 
| Jeff Sharkey | c7d1b22 | 2016-01-11 13:07:09 -0700 | [diff] [blame] | 191 | static int do_create_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { | 
 | 192 |     /* const char *uuid, const char *pkgname, userid_t userid, int flags, | 
| Janis Danisevskis | eecb2d2 | 2016-01-12 14:45:55 +0000 | [diff] [blame] | 193 |             appid_t appid, const char* seinfo, int target_sdk_version */ | 
 | 194 |     return create_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), | 
 | 195 |                            atoi(arg[4]), arg[5], atoi(arg[6])); | 
| Jeff Sharkey | c7d1b22 | 2016-01-11 13:07:09 -0700 | [diff] [blame] | 196 | } | 
 | 197 |  | 
 | 198 | static int do_restorecon_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { | 
 | 199 |     /* const char* uuid, const char* pkgName, userid_t userid, int flags, | 
 | 200 |             appid_t appid, const char* seinfo */ | 
 | 201 |     return restorecon_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atoi(arg[4]), arg[5]); | 
 | 202 | } | 
 | 203 |  | 
| Jeff Sharkey | cc6281c | 2016-02-06 19:46:09 -0700 | [diff] [blame] | 204 | static int do_migrate_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { | 
 | 205 |     /* const char *uuid, const char *pkgname, userid_t userid, int flags */ | 
 | 206 |     return migrate_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3])); | 
 | 207 | } | 
 | 208 |  | 
| Jeff Sharkey | c7d1b22 | 2016-01-11 13:07:09 -0700 | [diff] [blame] | 209 | static int do_clear_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { | 
| Jeff Sharkey | 2f720f7 | 2016-04-10 20:51:40 -0600 | [diff] [blame] | 210 |     /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */ | 
 | 211 |     return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4])); | 
| Jeff Sharkey | c7d1b22 | 2016-01-11 13:07:09 -0700 | [diff] [blame] | 212 | } | 
 | 213 |  | 
 | 214 | static int do_destroy_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { | 
| Jeff Sharkey | 2f720f7 | 2016-04-10 20:51:40 -0600 | [diff] [blame] | 215 |     /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */ | 
 | 216 |     return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4])); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 217 | } | 
 | 218 |  | 
| Andreas Gampe | 01ad598 | 2016-03-09 16:27:29 -0800 | [diff] [blame] | 219 | // We use otapreopt_chroot to get into the chroot. | 
 | 220 | static constexpr const char* kOtaPreopt = "/system/bin/otapreopt_chroot"; | 
| Andreas Gampe | 73dae11 | 2015-11-19 14:12:14 -0800 | [diff] [blame] | 221 |  | 
| Andreas Gampe | aef445d | 2016-06-02 17:56:45 -0700 | [diff] [blame] | 222 | static int do_ota_dexopt(const char* args[DEXOPT_PARAM_COUNT], | 
 | 223 |                          char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { | 
| Andreas Gampe | 01ad598 | 2016-03-09 16:27:29 -0800 | [diff] [blame] | 224 |     // Time to fork and run otapreopt. | 
 | 225 |  | 
 | 226 |     // Check that the tool exists. | 
 | 227 |     struct stat s; | 
 | 228 |     if (stat(kOtaPreopt, &s) != 0) { | 
 | 229 |         LOG(ERROR) << "Otapreopt chroot tool not found."; | 
 | 230 |         return -1; | 
| Andreas Gampe | 73dae11 | 2015-11-19 14:12:14 -0800 | [diff] [blame] | 231 |     } | 
| Andreas Gampe | 01ad598 | 2016-03-09 16:27:29 -0800 | [diff] [blame] | 232 |  | 
 | 233 |     pid_t pid = fork(); | 
 | 234 |     if (pid == 0) { | 
| Andreas Gampe | aef445d | 2016-06-02 17:56:45 -0700 | [diff] [blame] | 235 |         const char* argv[1 + DEXOPT_PARAM_COUNT + 1]; | 
| Andreas Gampe | 01ad598 | 2016-03-09 16:27:29 -0800 | [diff] [blame] | 236 |         argv[0] = kOtaPreopt; | 
| Andreas Gampe | aef445d | 2016-06-02 17:56:45 -0700 | [diff] [blame] | 237 |  | 
 | 238 |         for (size_t i = 0; i < DEXOPT_PARAM_COUNT; ++i) { | 
 | 239 |             argv[i + 1] = args[i]; | 
| Andreas Gampe | 01ad598 | 2016-03-09 16:27:29 -0800 | [diff] [blame] | 240 |         } | 
| Andreas Gampe | aef445d | 2016-06-02 17:56:45 -0700 | [diff] [blame] | 241 |  | 
 | 242 |         argv[DEXOPT_PARAM_COUNT + 1] = nullptr; | 
| Andreas Gampe | 01ad598 | 2016-03-09 16:27:29 -0800 | [diff] [blame] | 243 |  | 
 | 244 |         execv(argv[0], (char * const *)argv); | 
 | 245 |         PLOG(ERROR) << "execv(OTAPREOPT_CHROOT) failed"; | 
 | 246 |         exit(99); | 
 | 247 |     } else { | 
 | 248 |         int res = wait_child(pid); | 
 | 249 |         if (res == 0) { | 
 | 250 |             ALOGV("DexInv: --- END OTAPREOPT (success) ---\n"); | 
 | 251 |         } else { | 
 | 252 |             ALOGE("DexInv: --- END OTAPREOPT --- status=0x%04x, process failed\n", res); | 
 | 253 |         } | 
 | 254 |         return res; | 
 | 255 |     } | 
| Andreas Gampe | 73dae11 | 2015-11-19 14:12:14 -0800 | [diff] [blame] | 256 | } | 
 | 257 |  | 
| Andreas Gampe | aef445d | 2016-06-02 17:56:45 -0700 | [diff] [blame] | 258 | static int do_regular_dexopt(const char* args[DEXOPT_PARAM_COUNT], | 
 | 259 |                              char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { | 
 | 260 |     return dexopt(args); | 
 | 261 | } | 
 | 262 |  | 
 | 263 | using DexoptFn = int (*)(const char* args[DEXOPT_PARAM_COUNT], | 
 | 264 |                          char reply[REPLY_MAX]); | 
 | 265 |  | 
| Andreas Gampe | 73dae11 | 2015-11-19 14:12:14 -0800 | [diff] [blame] | 266 | static int do_dexopt(char **arg, char reply[REPLY_MAX]) | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 267 | { | 
| Andreas Gampe | aef445d | 2016-06-02 17:56:45 -0700 | [diff] [blame] | 268 |     const char* args[DEXOPT_PARAM_COUNT]; | 
 | 269 |     for (size_t i = 0; i < DEXOPT_PARAM_COUNT; ++i) { | 
 | 270 |         CHECK(arg[i] != nullptr); | 
 | 271 |         args[i] = arg[i]; | 
| Andreas Gampe | 73dae11 | 2015-11-19 14:12:14 -0800 | [diff] [blame] | 272 |     } | 
| Andreas Gampe | aef445d | 2016-06-02 17:56:45 -0700 | [diff] [blame] | 273 |  | 
 | 274 |     int dexopt_flags = atoi(arg[6]); | 
 | 275 |     DexoptFn dexopt_fn; | 
 | 276 |     if ((dexopt_flags & DEXOPT_OTA) != 0) { | 
 | 277 |         dexopt_fn = do_ota_dexopt; | 
 | 278 |     } else { | 
 | 279 |         dexopt_fn = do_regular_dexopt; | 
 | 280 |     } | 
 | 281 |     return dexopt_fn(args, reply); | 
| Andreas Gampe | 4d0f825 | 2016-03-20 11:30:28 -0700 | [diff] [blame] | 282 | } | 
 | 283 |  | 
 | 284 | static int do_merge_profiles(char **arg, char reply[REPLY_MAX]) | 
 | 285 | { | 
 | 286 |     uid_t uid = static_cast<uid_t>(atoi(arg[0])); | 
 | 287 |     const char* pkgname = arg[1]; | 
 | 288 |     if (merge_profiles(uid, pkgname)) { | 
 | 289 |         strncpy(reply, "true", REPLY_MAX); | 
 | 290 |     } else { | 
 | 291 |         strncpy(reply, "false", REPLY_MAX); | 
 | 292 |     } | 
 | 293 |     return 0; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 294 | } | 
 | 295 |  | 
| David Sehr | 6727c2d | 2016-05-17 16:06:22 -0700 | [diff] [blame] | 296 | static int do_dump_profiles(char **arg, char reply[REPLY_MAX]) | 
 | 297 | { | 
 | 298 |     uid_t uid = static_cast<uid_t>(atoi(arg[0])); | 
 | 299 |     const char* pkgname = arg[1]; | 
 | 300 |     const char* dex_files = arg[2]; | 
 | 301 |     if (dump_profile(uid, pkgname, dex_files)) { | 
 | 302 |         strncpy(reply, "true", REPLY_MAX); | 
 | 303 |     } else { | 
 | 304 |         strncpy(reply, "false", REPLY_MAX); | 
 | 305 |     } | 
 | 306 |     return 0; | 
 | 307 | } | 
 | 308 |  | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 309 | static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) | 
| Narayan Kamath | 091ea77 | 2014-11-10 15:03:46 +0000 | [diff] [blame] | 310 | { | 
 | 311 |     return mark_boot_complete(arg[0] /* instruction set */); | 
 | 312 | } | 
 | 313 |  | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 314 | static int do_rm_dex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 315 | { | 
| Narayan Kamath | 1b40032 | 2014-04-11 13:17:00 +0100 | [diff] [blame] | 316 |     return rm_dex(arg[0], arg[1]); /* pkgname, instruction_set */ | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 317 | } | 
 | 318 |  | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 319 | static int do_free_cache(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) /* TODO int:free_size */ | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 320 | { | 
| Jeff Sharkey | 6fe28a0 | 2015-04-09 13:10:03 -0700 | [diff] [blame] | 321 |     return free_cache(parse_null(arg[0]), (int64_t)atoll(arg[1])); /* uuid, free_size */ | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 322 | } | 
 | 323 |  | 
| Jeff Sharkey | c7d1b22 | 2016-01-11 13:07:09 -0700 | [diff] [blame] | 324 | static int do_get_app_size(char **arg, char reply[REPLY_MAX]) { | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 325 |     int64_t codesize = 0; | 
 | 326 |     int64_t datasize = 0; | 
 | 327 |     int64_t cachesize = 0; | 
 | 328 |     int64_t asecsize = 0; | 
 | 329 |     int res = 0; | 
 | 330 |  | 
| Jeff Sharkey | 2f720f7 | 2016-04-10 20:51:40 -0600 | [diff] [blame] | 331 |     /* const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode, | 
 | 332 |             const char* code_path */ | 
 | 333 |     res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]), | 
 | 334 |             arg[5], &codesize, &datasize, &cachesize, &asecsize); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 335 |  | 
 | 336 |     /* | 
 | 337 |      * Each int64_t can take up 22 characters printed out. Make sure it | 
 | 338 |      * doesn't go over REPLY_MAX in the future. | 
 | 339 |      */ | 
 | 340 |     snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64, | 
 | 341 |             codesize, datasize, cachesize, asecsize); | 
 | 342 |     return res; | 
 | 343 | } | 
 | 344 |  | 
| Jeff Sharkey | 2f720f7 | 2016-04-10 20:51:40 -0600 | [diff] [blame] | 345 | static int do_get_app_data_inode(char **arg, char reply[REPLY_MAX]) { | 
 | 346 |     ino_t inode = 0; | 
 | 347 |     int res = 0; | 
 | 348 |  | 
 | 349 |     /* const char *uuid, const char *pkgname, int userid, int flags */ | 
 | 350 |     res = get_app_data_inode(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), &inode); | 
 | 351 |  | 
| Jeff Sharkey | 7240a15 | 2016-04-11 00:30:24 -0600 | [diff] [blame] | 352 |     snprintf(reply, REPLY_MAX, "%" PRId64, (int64_t) inode); | 
| Jeff Sharkey | 2f720f7 | 2016-04-10 20:51:40 -0600 | [diff] [blame] | 353 |     return res; | 
 | 354 | } | 
 | 355 |  | 
| Jeff Sharkey | c7d1b22 | 2016-01-11 13:07:09 -0700 | [diff] [blame] | 356 | static int do_move_complete_app(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { | 
 | 357 |     /* const char* from_uuid, const char *to_uuid, const char *package_name, | 
| Janis Danisevskis | eecb2d2 | 2016-01-12 14:45:55 +0000 | [diff] [blame] | 358 |             const char *data_app_name, appid_t appid, const char* seinfo, | 
 | 359 |             int target_sdk_version */ | 
 | 360 |     return move_complete_app(parse_null(arg[0]), parse_null(arg[1]), arg[2], arg[3], | 
 | 361 |                              atoi(arg[4]), arg[5], atoi(arg[6])); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 362 | } | 
 | 363 |  | 
| Jeff Sharkey | 379a12b | 2016-04-14 20:45:06 -0600 | [diff] [blame] | 364 | static int do_create_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) | 
| Robin Lee | 095c763 | 2014-04-25 15:05:19 +0100 | [diff] [blame] | 365 | { | 
| Jeff Sharkey | 379a12b | 2016-04-14 20:45:06 -0600 | [diff] [blame] | 366 |     /* const char *uuid, userid_t userid, int user_serial, int flags */ | 
 | 367 |     return create_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]), atoi(arg[3])); | 
| Robin Lee | 095c763 | 2014-04-25 15:05:19 +0100 | [diff] [blame] | 368 | } | 
 | 369 |  | 
| Jeff Sharkey | 379a12b | 2016-04-14 20:45:06 -0600 | [diff] [blame] | 370 | static int do_destroy_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 371 | { | 
| Jeff Sharkey | 379a12b | 2016-04-14 20:45:06 -0600 | [diff] [blame] | 372 |     /* const char *uuid, userid_t userid, int flags */ | 
 | 373 |     return destroy_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2])); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 374 | } | 
 | 375 |  | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 376 | static int do_linklib(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 377 | { | 
| Jeff Sharkey | 6fe28a0 | 2015-04-09 13:10:03 -0700 | [diff] [blame] | 378 |     return linklib(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3])); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 379 | } | 
 | 380 |  | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 381 | static int do_idmap(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) | 
| MÃ¥rten Kongstad | 63568b1 | 2014-01-31 14:42:59 +0100 | [diff] [blame] | 382 | { | 
 | 383 |     return idmap(arg[0], arg[1], atoi(arg[2])); | 
 | 384 | } | 
 | 385 |  | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 386 | static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) | 
| Fyodor Kupolov | 88ce4ff | 2015-03-03 12:25:29 -0800 | [diff] [blame] | 387 | { | 
 | 388 |     /* oat_dir, instruction_set */ | 
 | 389 |     return create_oat_dir(arg[0], arg[1]); | 
 | 390 | } | 
 | 391 |  | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 392 | static int do_rm_package_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) | 
| Fyodor Kupolov | 88ce4ff | 2015-03-03 12:25:29 -0800 | [diff] [blame] | 393 | { | 
 | 394 |     /* oat_dir */ | 
 | 395 |     return rm_package_dir(arg[0]); | 
| Alex Light | 43c5d30 | 2014-07-21 12:23:48 -0700 | [diff] [blame] | 396 | } | 
 | 397 |  | 
| Calin Juravle | edae669 | 2016-03-23 13:55:31 +0000 | [diff] [blame] | 398 | static int do_clear_app_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) | 
| David Brazdil | d828d68 | 2016-03-08 12:50:20 +0000 | [diff] [blame] | 399 | { | 
 | 400 |     /* package_name */ | 
| Calin Juravle | edae669 | 2016-03-23 13:55:31 +0000 | [diff] [blame] | 401 |     return clear_app_profiles(arg[0]); | 
 | 402 | } | 
 | 403 |  | 
 | 404 | static int do_destroy_app_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) | 
 | 405 | { | 
 | 406 |     /* package_name */ | 
 | 407 |     return destroy_app_profiles(arg[0]); | 
| David Brazdil | d828d68 | 2016-03-08 12:50:20 +0000 | [diff] [blame] | 408 | } | 
 | 409 |  | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 410 | static int do_link_file(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) | 
| Narayan Kamath | d845c96 | 2015-06-04 13:20:27 +0100 | [diff] [blame] | 411 | { | 
 | 412 |     /* relative_path, from_base, to_base */ | 
 | 413 |     return link_file(arg[0], arg[1], arg[2]); | 
 | 414 | } | 
 | 415 |  | 
| Andreas Gampe | e65b4fa | 2016-03-01 11:46:45 -0800 | [diff] [blame] | 416 | static int do_move_ab(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { | 
 | 417 |     // apk_path, instruction_set, oat_dir | 
 | 418 |     return move_ab(arg[0], arg[1], arg[2]); | 
 | 419 | } | 
 | 420 |  | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 421 | struct cmdinfo { | 
 | 422 |     const char *name; | 
 | 423 |     unsigned numargs; | 
 | 424 |     int (*func)(char **arg, char reply[REPLY_MAX]); | 
 | 425 | }; | 
 | 426 |  | 
 | 427 | struct cmdinfo cmds[] = { | 
 | 428 |     { "ping",                 0, do_ping }, | 
| Jeff Sharkey | c7d1b22 | 2016-01-11 13:07:09 -0700 | [diff] [blame] | 429 |  | 
| Janis Danisevskis | eecb2d2 | 2016-01-12 14:45:55 +0000 | [diff] [blame] | 430 |     { "create_app_data",      7, do_create_app_data }, | 
| Jeff Sharkey | c7d1b22 | 2016-01-11 13:07:09 -0700 | [diff] [blame] | 431 |     { "restorecon_app_data",  6, do_restorecon_app_data }, | 
| Jeff Sharkey | cc6281c | 2016-02-06 19:46:09 -0700 | [diff] [blame] | 432 |     { "migrate_app_data",     4, do_migrate_app_data }, | 
| Jeff Sharkey | 2f720f7 | 2016-04-10 20:51:40 -0600 | [diff] [blame] | 433 |     { "clear_app_data",       5, do_clear_app_data }, | 
 | 434 |     { "destroy_app_data",     5, do_destroy_app_data }, | 
| Janis Danisevskis | eecb2d2 | 2016-01-12 14:45:55 +0000 | [diff] [blame] | 435 |     { "move_complete_app",    7, do_move_complete_app }, | 
| Jeff Sharkey | 2f720f7 | 2016-04-10 20:51:40 -0600 | [diff] [blame] | 436 |     { "get_app_size",         6, do_get_app_size }, | 
 | 437 |     { "get_app_data_inode",   4, do_get_app_data_inode }, | 
| Jeff Sharkey | c7d1b22 | 2016-01-11 13:07:09 -0700 | [diff] [blame] | 438 |  | 
| Jeff Sharkey | 379a12b | 2016-04-14 20:45:06 -0600 | [diff] [blame] | 439 |     { "create_user_data",     4, do_create_user_data }, | 
 | 440 |     { "destroy_user_data",    3, do_destroy_user_data }, | 
 | 441 |  | 
| Jeff Hao | b63d91f | 2016-03-16 15:59:25 -0700 | [diff] [blame] | 442 |     { "dexopt",              10, do_dexopt }, | 
| Narayan Kamath | 091ea77 | 2014-11-10 15:03:46 +0000 | [diff] [blame] | 443 |     { "markbootcomplete",     1, do_mark_boot_complete }, | 
| Narayan Kamath | 1b40032 | 2014-04-11 13:17:00 +0100 | [diff] [blame] | 444 |     { "rmdex",                2, do_rm_dex }, | 
| Jeff Sharkey | 6fe28a0 | 2015-04-09 13:10:03 -0700 | [diff] [blame] | 445 |     { "freecache",            2, do_free_cache }, | 
| Jeff Sharkey | 6fe28a0 | 2015-04-09 13:10:03 -0700 | [diff] [blame] | 446 |     { "linklib",              4, do_linklib }, | 
| MÃ¥rten Kongstad | 63568b1 | 2014-01-31 14:42:59 +0100 | [diff] [blame] | 447 |     { "idmap",                3, do_idmap }, | 
| Fyodor Kupolov | 88ce4ff | 2015-03-03 12:25:29 -0800 | [diff] [blame] | 448 |     { "createoatdir",         2, do_create_oat_dir }, | 
| Narayan Kamath | d845c96 | 2015-06-04 13:20:27 +0100 | [diff] [blame] | 449 |     { "rmpackagedir",         1, do_rm_package_dir }, | 
| Calin Juravle | edae669 | 2016-03-23 13:55:31 +0000 | [diff] [blame] | 450 |     { "clear_app_profiles",   1, do_clear_app_profiles }, | 
 | 451 |     { "destroy_app_profiles", 1, do_destroy_app_profiles }, | 
| Jeff Sharkey | c7d1b22 | 2016-01-11 13:07:09 -0700 | [diff] [blame] | 452 |     { "linkfile",             3, do_link_file }, | 
| Andreas Gampe | e65b4fa | 2016-03-01 11:46:45 -0800 | [diff] [blame] | 453 |     { "move_ab",              3, do_move_ab }, | 
| Andreas Gampe | 4d0f825 | 2016-03-20 11:30:28 -0700 | [diff] [blame] | 454 |     { "merge_profiles",       2, do_merge_profiles }, | 
| David Sehr | 6727c2d | 2016-05-17 16:06:22 -0700 | [diff] [blame] | 455 |     { "dump_profiles",        3, do_dump_profiles }, | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 456 | }; | 
 | 457 |  | 
 | 458 | static int readx(int s, void *_buf, int count) | 
 | 459 | { | 
| Jeff Sharkey | 1980380 | 2015-04-07 12:44:51 -0700 | [diff] [blame] | 460 |     char *buf = (char *) _buf; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 461 |     int n = 0, r; | 
 | 462 |     if (count < 0) return -1; | 
 | 463 |     while (n < count) { | 
 | 464 |         r = read(s, buf + n, count - n); | 
 | 465 |         if (r < 0) { | 
 | 466 |             if (errno == EINTR) continue; | 
 | 467 |             ALOGE("read error: %s\n", strerror(errno)); | 
 | 468 |             return -1; | 
 | 469 |         } | 
 | 470 |         if (r == 0) { | 
 | 471 |             ALOGE("eof\n"); | 
 | 472 |             return -1; /* EOF */ | 
 | 473 |         } | 
 | 474 |         n += r; | 
 | 475 |     } | 
 | 476 |     return 0; | 
 | 477 | } | 
 | 478 |  | 
 | 479 | static int writex(int s, const void *_buf, int count) | 
 | 480 | { | 
| Jeff Sharkey | 1980380 | 2015-04-07 12:44:51 -0700 | [diff] [blame] | 481 |     const char *buf = (const char *) _buf; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 482 |     int n = 0, r; | 
 | 483 |     if (count < 0) return -1; | 
 | 484 |     while (n < count) { | 
 | 485 |         r = write(s, buf + n, count - n); | 
 | 486 |         if (r < 0) { | 
 | 487 |             if (errno == EINTR) continue; | 
 | 488 |             ALOGE("write error: %s\n", strerror(errno)); | 
 | 489 |             return -1; | 
 | 490 |         } | 
 | 491 |         n += r; | 
 | 492 |     } | 
 | 493 |     return 0; | 
 | 494 | } | 
 | 495 |  | 
 | 496 |  | 
 | 497 | /* Tokenize the command buffer, locate a matching command, | 
 | 498 |  * ensure that the required number of arguments are provided, | 
 | 499 |  * call the function(), return the result. | 
 | 500 |  */ | 
 | 501 | static int execute(int s, char cmd[BUFFER_MAX]) | 
 | 502 | { | 
 | 503 |     char reply[REPLY_MAX]; | 
 | 504 |     char *arg[TOKEN_MAX+1]; | 
 | 505 |     unsigned i; | 
 | 506 |     unsigned n = 0; | 
 | 507 |     unsigned short count; | 
 | 508 |     int ret = -1; | 
 | 509 |  | 
| Brian Carlstrom | 1705fc4 | 2013-03-21 18:20:22 -0700 | [diff] [blame] | 510 |     // ALOGI("execute('%s')\n", cmd); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 511 |  | 
 | 512 |         /* default reply is "" */ | 
 | 513 |     reply[0] = 0; | 
 | 514 |  | 
 | 515 |         /* n is number of args (not counting arg[0]) */ | 
 | 516 |     arg[0] = cmd; | 
 | 517 |     while (*cmd) { | 
 | 518 |         if (isspace(*cmd)) { | 
 | 519 |             *cmd++ = 0; | 
 | 520 |             n++; | 
 | 521 |             arg[n] = cmd; | 
 | 522 |             if (n == TOKEN_MAX) { | 
 | 523 |                 ALOGE("too many arguments\n"); | 
 | 524 |                 goto done; | 
 | 525 |             } | 
 | 526 |         } | 
| Serguei Katkov | 62bb385 | 2014-10-29 19:38:01 +0600 | [diff] [blame] | 527 |         if (*cmd) { | 
 | 528 |           cmd++; | 
 | 529 |         } | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 530 |     } | 
 | 531 |  | 
 | 532 |     for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) { | 
 | 533 |         if (!strcmp(cmds[i].name,arg[0])) { | 
 | 534 |             if (n != cmds[i].numargs) { | 
 | 535 |                 ALOGE("%s requires %d arguments (%d given)\n", | 
 | 536 |                      cmds[i].name, cmds[i].numargs, n); | 
 | 537 |             } else { | 
 | 538 |                 ret = cmds[i].func(arg + 1, reply); | 
 | 539 |             } | 
 | 540 |             goto done; | 
 | 541 |         } | 
 | 542 |     } | 
 | 543 |     ALOGE("unsupported command '%s'\n", arg[0]); | 
 | 544 |  | 
 | 545 | done: | 
 | 546 |     if (reply[0]) { | 
 | 547 |         n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply); | 
 | 548 |     } else { | 
 | 549 |         n = snprintf(cmd, BUFFER_MAX, "%d", ret); | 
 | 550 |     } | 
 | 551 |     if (n > BUFFER_MAX) n = BUFFER_MAX; | 
 | 552 |     count = n; | 
 | 553 |  | 
| Brian Carlstrom | 1705fc4 | 2013-03-21 18:20:22 -0700 | [diff] [blame] | 554 |     // ALOGI("reply: '%s'\n", cmd); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 555 |     if (writex(s, &count, sizeof(count))) return -1; | 
 | 556 |     if (writex(s, cmd, count)) return -1; | 
 | 557 |     return 0; | 
 | 558 | } | 
 | 559 |  | 
| Andreas Gampe | 0354bd0 | 2016-06-27 14:25:30 -0700 | [diff] [blame] | 560 | static bool initialize_globals() { | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 561 |     const char* data_path = getenv("ANDROID_DATA"); | 
 | 562 |     if (data_path == nullptr) { | 
 | 563 |         ALOGE("Could not find ANDROID_DATA"); | 
 | 564 |         return false; | 
 | 565 |     } | 
 | 566 |     const char* root_path = getenv("ANDROID_ROOT"); | 
 | 567 |     if (root_path == nullptr) { | 
 | 568 |         ALOGE("Could not find ANDROID_ROOT"); | 
 | 569 |         return false; | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 570 |     } | 
 | 571 |  | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 572 |     return init_globals_from_data_and_root(data_path, root_path); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 573 | } | 
 | 574 |  | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 575 | static int initialize_directories() { | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 576 |     int res = -1; | 
 | 577 |  | 
 | 578 |     // Read current filesystem layout version to handle upgrade paths | 
 | 579 |     char version_path[PATH_MAX]; | 
 | 580 |     snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path); | 
 | 581 |  | 
 | 582 |     int oldVersion; | 
 | 583 |     if (fs_read_atomic_int(version_path, &oldVersion) == -1) { | 
 | 584 |         oldVersion = 0; | 
 | 585 |     } | 
 | 586 |     int version = oldVersion; | 
 | 587 |  | 
| Jeff Sharkey | e02657d | 2016-01-13 09:37:46 -0700 | [diff] [blame] | 588 |     if (version < 2) { | 
 | 589 |         SLOGD("Assuming that device has multi-user storage layout; upgrade no longer supported"); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 590 |         version = 2; | 
 | 591 |     } | 
 | 592 |  | 
| Robin Lee | 07053fc | 2014-04-29 19:42:01 +0100 | [diff] [blame] | 593 |     if (ensure_config_user_dirs(0) == -1) { | 
 | 594 |         ALOGE("Failed to setup misc for user 0"); | 
 | 595 |         goto fail; | 
 | 596 |     } | 
 | 597 |  | 
| Robin Lee | 095c763 | 2014-04-25 15:05:19 +0100 | [diff] [blame] | 598 |     if (version == 2) { | 
 | 599 |         ALOGD("Upgrading to /data/misc/user directories"); | 
 | 600 |  | 
| Robin Lee | 60fd3fe | 2014-10-07 16:55:02 +0100 | [diff] [blame] | 601 |         char misc_dir[PATH_MAX]; | 
 | 602 |         snprintf(misc_dir, PATH_MAX, "%smisc", android_data_dir.path); | 
 | 603 |  | 
 | 604 |         char keychain_added_dir[PATH_MAX]; | 
 | 605 |         snprintf(keychain_added_dir, PATH_MAX, "%s/keychain/cacerts-added", misc_dir); | 
 | 606 |  | 
 | 607 |         char keychain_removed_dir[PATH_MAX]; | 
 | 608 |         snprintf(keychain_removed_dir, PATH_MAX, "%s/keychain/cacerts-removed", misc_dir); | 
 | 609 |  | 
| Robin Lee | 095c763 | 2014-04-25 15:05:19 +0100 | [diff] [blame] | 610 |         DIR *dir; | 
 | 611 |         struct dirent *dirent; | 
| Jeff Sharkey | e02657d | 2016-01-13 09:37:46 -0700 | [diff] [blame] | 612 |         dir = opendir("/data/user"); | 
| Robin Lee | 095c763 | 2014-04-25 15:05:19 +0100 | [diff] [blame] | 613 |         if (dir != NULL) { | 
 | 614 |             while ((dirent = readdir(dir))) { | 
| Robin Lee | 60fd3fe | 2014-10-07 16:55:02 +0100 | [diff] [blame] | 615 |                 const char *name = dirent->d_name; | 
| Robin Lee | 095c763 | 2014-04-25 15:05:19 +0100 | [diff] [blame] | 616 |  | 
| Robin Lee | 60fd3fe | 2014-10-07 16:55:02 +0100 | [diff] [blame] | 617 |                 // skip "." and ".." | 
 | 618 |                 if (name[0] == '.') { | 
 | 619 |                     if (name[1] == 0) continue; | 
 | 620 |                     if ((name[1] == '.') && (name[2] == 0)) continue; | 
 | 621 |                 } | 
 | 622 |  | 
 | 623 |                 uint32_t user_id = atoi(name); | 
 | 624 |  | 
 | 625 |                 // /data/misc/user/<user_id> | 
 | 626 |                 if (ensure_config_user_dirs(user_id) == -1) { | 
 | 627 |                     goto fail; | 
 | 628 |                 } | 
 | 629 |  | 
 | 630 |                 char misc_added_dir[PATH_MAX]; | 
 | 631 |                 snprintf(misc_added_dir, PATH_MAX, "%s/user/%s/cacerts-added", misc_dir, name); | 
 | 632 |  | 
 | 633 |                 char misc_removed_dir[PATH_MAX]; | 
 | 634 |                 snprintf(misc_removed_dir, PATH_MAX, "%s/user/%s/cacerts-removed", misc_dir, name); | 
 | 635 |  | 
 | 636 |                 uid_t uid = multiuser_get_uid(user_id, AID_SYSTEM); | 
 | 637 |                 gid_t gid = uid; | 
 | 638 |                 if (access(keychain_added_dir, F_OK) == 0) { | 
 | 639 |                     if (copy_dir_files(keychain_added_dir, misc_added_dir, uid, gid) != 0) { | 
 | 640 |                         ALOGE("Some files failed to copy"); | 
| Robin Lee | 095c763 | 2014-04-25 15:05:19 +0100 | [diff] [blame] | 641 |                     } | 
| Robin Lee | 60fd3fe | 2014-10-07 16:55:02 +0100 | [diff] [blame] | 642 |                 } | 
 | 643 |                 if (access(keychain_removed_dir, F_OK) == 0) { | 
 | 644 |                     if (copy_dir_files(keychain_removed_dir, misc_removed_dir, uid, gid) != 0) { | 
 | 645 |                         ALOGE("Some files failed to copy"); | 
| Robin Lee | 095c763 | 2014-04-25 15:05:19 +0100 | [diff] [blame] | 646 |                     } | 
 | 647 |                 } | 
 | 648 |             } | 
 | 649 |             closedir(dir); | 
| Robin Lee | 095c763 | 2014-04-25 15:05:19 +0100 | [diff] [blame] | 650 |  | 
| Robin Lee | 60fd3fe | 2014-10-07 16:55:02 +0100 | [diff] [blame] | 651 |             if (access(keychain_added_dir, F_OK) == 0) { | 
 | 652 |                 delete_dir_contents(keychain_added_dir, 1, 0); | 
| Robin Lee | 07053fc | 2014-04-29 19:42:01 +0100 | [diff] [blame] | 653 |             } | 
| Robin Lee | 60fd3fe | 2014-10-07 16:55:02 +0100 | [diff] [blame] | 654 |             if (access(keychain_removed_dir, F_OK) == 0) { | 
 | 655 |                 delete_dir_contents(keychain_removed_dir, 1, 0); | 
| Robin Lee | 07053fc | 2014-04-29 19:42:01 +0100 | [diff] [blame] | 656 |             } | 
 | 657 |         } | 
 | 658 |  | 
 | 659 |         version = 3; | 
| Robin Lee | 095c763 | 2014-04-25 15:05:19 +0100 | [diff] [blame] | 660 |     } | 
 | 661 |  | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 662 |     // Persist layout version if changed | 
 | 663 |     if (version != oldVersion) { | 
 | 664 |         if (fs_write_atomic_int(version_path, version) == -1) { | 
 | 665 |             ALOGE("Failed to save version to %s: %s", version_path, strerror(errno)); | 
 | 666 |             goto fail; | 
 | 667 |         } | 
 | 668 |     } | 
 | 669 |  | 
 | 670 |     // Success! | 
 | 671 |     res = 0; | 
 | 672 |  | 
 | 673 | fail: | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 674 |     return res; | 
 | 675 | } | 
 | 676 |  | 
| Stephen Smalley | 7abb52b | 2014-03-26 09:30:37 -0400 | [diff] [blame] | 677 | static int log_callback(int type, const char *fmt, ...) { | 
 | 678 |     va_list ap; | 
 | 679 |     int priority; | 
 | 680 |  | 
 | 681 |     switch (type) { | 
 | 682 |     case SELINUX_WARNING: | 
 | 683 |         priority = ANDROID_LOG_WARN; | 
 | 684 |         break; | 
 | 685 |     case SELINUX_INFO: | 
 | 686 |         priority = ANDROID_LOG_INFO; | 
 | 687 |         break; | 
 | 688 |     default: | 
 | 689 |         priority = ANDROID_LOG_ERROR; | 
 | 690 |         break; | 
 | 691 |     } | 
 | 692 |     va_start(ap, fmt); | 
 | 693 |     LOG_PRI_VA(priority, "SELinux", fmt, ap); | 
 | 694 |     va_end(ap); | 
 | 695 |     return 0; | 
 | 696 | } | 
 | 697 |  | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 698 | static int installd_main(const int argc ATTRIBUTE_UNUSED, char *argv[]) { | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 699 |     char buf[BUFFER_MAX]; | 
 | 700 |     struct sockaddr addr; | 
 | 701 |     socklen_t alen; | 
| Chih-Hung Hsieh | 99d9fb1 | 2014-09-11 14:44:46 -0700 | [diff] [blame] | 702 |     int lsocket, s; | 
| Stephen Smalley | bd558d6 | 2013-04-16 12:16:50 -0400 | [diff] [blame] | 703 |     int selinux_enabled = (is_selinux_enabled() > 0); | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 704 |  | 
| Jeff Sharkey | e363724 | 2015-04-08 20:56:42 -0700 | [diff] [blame] | 705 |     setenv("ANDROID_LOG_TAGS", "*:v", 1); | 
 | 706 |     android::base::InitLogging(argv); | 
 | 707 |  | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 708 |     ALOGI("installd firing up\n"); | 
 | 709 |  | 
| Stephen Smalley | 7abb52b | 2014-03-26 09:30:37 -0400 | [diff] [blame] | 710 |     union selinux_callback cb; | 
 | 711 |     cb.func_log = log_callback; | 
 | 712 |     selinux_set_callback(SELINUX_CB_LOG, cb); | 
 | 713 |  | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 714 |     if (!initialize_globals()) { | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 715 |         ALOGE("Could not initialize globals; exiting.\n"); | 
 | 716 |         exit(1); | 
 | 717 |     } | 
 | 718 |  | 
 | 719 |     if (initialize_directories() < 0) { | 
 | 720 |         ALOGE("Could not create directories; exiting.\n"); | 
 | 721 |         exit(1); | 
 | 722 |     } | 
 | 723 |  | 
| Stephen Smalley | bd558d6 | 2013-04-16 12:16:50 -0400 | [diff] [blame] | 724 |     if (selinux_enabled && selinux_status_open(true) < 0) { | 
 | 725 |         ALOGE("Could not open selinux status; exiting.\n"); | 
 | 726 |         exit(1); | 
 | 727 |     } | 
 | 728 |  | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 729 |     lsocket = android_get_control_socket(SOCKET_PATH); | 
 | 730 |     if (lsocket < 0) { | 
 | 731 |         ALOGE("Failed to get socket from environment: %s\n", strerror(errno)); | 
 | 732 |         exit(1); | 
 | 733 |     } | 
 | 734 |     if (listen(lsocket, 5)) { | 
 | 735 |         ALOGE("Listen on socket failed: %s\n", strerror(errno)); | 
 | 736 |         exit(1); | 
 | 737 |     } | 
 | 738 |     fcntl(lsocket, F_SETFD, FD_CLOEXEC); | 
 | 739 |  | 
 | 740 |     for (;;) { | 
 | 741 |         alen = sizeof(addr); | 
 | 742 |         s = accept(lsocket, &addr, &alen); | 
 | 743 |         if (s < 0) { | 
 | 744 |             ALOGE("Accept failed: %s\n", strerror(errno)); | 
 | 745 |             continue; | 
 | 746 |         } | 
 | 747 |         fcntl(s, F_SETFD, FD_CLOEXEC); | 
 | 748 |  | 
 | 749 |         ALOGI("new connection\n"); | 
 | 750 |         for (;;) { | 
 | 751 |             unsigned short count; | 
 | 752 |             if (readx(s, &count, sizeof(count))) { | 
 | 753 |                 ALOGE("failed to read size\n"); | 
 | 754 |                 break; | 
 | 755 |             } | 
 | 756 |             if ((count < 1) || (count >= BUFFER_MAX)) { | 
 | 757 |                 ALOGE("invalid size %d\n", count); | 
 | 758 |                 break; | 
 | 759 |             } | 
 | 760 |             if (readx(s, buf, count)) { | 
 | 761 |                 ALOGE("failed to read command\n"); | 
 | 762 |                 break; | 
 | 763 |             } | 
 | 764 |             buf[count] = 0; | 
| Stephen Smalley | bd558d6 | 2013-04-16 12:16:50 -0400 | [diff] [blame] | 765 |             if (selinux_enabled && selinux_status_updated() > 0) { | 
 | 766 |                 selinux_android_seapp_context_reload(); | 
 | 767 |             } | 
| Mike Lockwood | 94afecf | 2012-10-24 10:45:23 -0700 | [diff] [blame] | 768 |             if (execute(s, buf)) break; | 
 | 769 |         } | 
 | 770 |         ALOGI("closing connection\n"); | 
 | 771 |         close(s); | 
 | 772 |     } | 
 | 773 |  | 
 | 774 |     return 0; | 
 | 775 | } | 
| Andreas Gampe | 02d0de5 | 2015-11-11 20:43:16 -0800 | [diff] [blame] | 776 |  | 
 | 777 | }  // namespace installd | 
 | 778 | }  // namespace android | 
 | 779 |  | 
 | 780 | int main(const int argc, char *argv[]) { | 
 | 781 |     return android::installd::installd_main(argc, argv); | 
 | 782 | } |