1 /* 2 ** Copyright 2008, The Android Open Source Project 3 ** 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 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 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 14 ** limitations under the License. 15 */ 16 17 #include "installd.h" 18 19 20 #define BUFFER_MAX 1024 /* input buffer for commands */ 21 #define TOKEN_MAX 8 /* max number of arguments in buffer */ 22 #define REPLY_MAX 256 /* largest reply allowed */ 23 24 static int do_ping(char **arg, char reply[REPLY_MAX]) 25 { 26 return 0; 27 } 28 29 static int do_install(char **arg, char reply[REPLY_MAX]) 30 { 31 return install(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */ 32 } 33 34 static int do_dexopt(char **arg, char reply[REPLY_MAX]) 35 { 36 /* apk_path, uid, is_public */ 37 return dexopt(arg[0], atoi(arg[1]), atoi(arg[2])); 38 } 39 40 static int do_move_dex(char **arg, char reply[REPLY_MAX]) 41 { 42 return move_dex(arg[0], arg[1]); /* src, dst */ 43 } 44 45 static int do_rm_dex(char **arg, char reply[REPLY_MAX]) 46 { 47 return rm_dex(arg[0]); /* pkgname */ 48 } 49 50 static int do_remove(char **arg, char reply[REPLY_MAX]) 51 { 52 return uninstall(arg[0], atoi(arg[1])); /* pkgname, userid */ 53 } 54 55 static int do_rename(char **arg, char reply[REPLY_MAX]) 56 { 57 return renamepkg(arg[0], arg[1]); /* oldpkgname, newpkgname */ 58 } 59 60 static int do_fixuid(char **arg, char reply[REPLY_MAX]) 61 { 62 return fix_uid(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */ 63 } 64 65 static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */ 66 { 67 return free_cache((int64_t)atoll(arg[0])); /* free_size */ 68 } 69 70 static int do_rm_cache(char **arg, char reply[REPLY_MAX]) 71 { 72 return delete_cache(arg[0]); /* pkgname */ 73 } 74 75 static int do_protect(char **arg, char reply[REPLY_MAX]) 76 { 77 return protect(arg[0], atoi(arg[1])); /* pkgname, gid */ 78 } 79 80 static int do_get_size(char **arg, char reply[REPLY_MAX]) 81 { 82 int64_t codesize = 0; 83 int64_t datasize = 0; 84 int64_t cachesize = 0; 85 int64_t asecsize = 0; 86 int res = 0; 87 88 /* pkgdir, apkpath */ 89 res = get_size(arg[0], arg[1], arg[2], arg[3], &codesize, &datasize, &cachesize, &asecsize); 90 91 /* 92 * Each int64_t can take up 22 characters printed out. Make sure it 93 * doesn't go over REPLY_MAX in the future. 94 */ 95 snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64, 96 codesize, datasize, cachesize, asecsize); 97 return res; 98 } 99 100 static int do_rm_user_data(char **arg, char reply[REPLY_MAX]) 101 { 102 return delete_user_data(arg[0], atoi(arg[1])); /* pkgname, userid */ 103 } 104 105 static int do_mk_user_data(char **arg, char reply[REPLY_MAX]) 106 { 107 return make_user_data(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, userid */ 108 } 109 110 static int do_rm_user(char **arg, char reply[REPLY_MAX]) 111 { 112 return delete_persona(atoi(arg[0])); /* userid */ 113 } 114 115 static int do_clone_user_data(char **arg, char reply[REPLY_MAX]) 116 { 117 return clone_persona_data(atoi(arg[0]), atoi(arg[1]), atoi(arg[2])); 118 } 119 120 static int do_movefiles(char **arg, char reply[REPLY_MAX]) 121 { 122 return movefiles(); 123 } 124 125 static int do_linklib(char **arg, char reply[REPLY_MAX]) 126 { 127 return linklib(arg[0], arg[1]); 128 } 129 130 static int do_unlinklib(char **arg, char reply[REPLY_MAX]) 131 { 132 return unlinklib(arg[0]); 133 } 134 135 struct cmdinfo { 136 const char *name; 137 unsigned numargs; 138 int (*func)(char **arg, char reply[REPLY_MAX]); 139 }; 140 141 struct cmdinfo cmds[] = { 142 { "ping", 0, do_ping }, 143 { "install", 3, do_install }, 144 { "dexopt", 3, do_dexopt }, 145 { "movedex", 2, do_move_dex }, 146 { "rmdex", 1, do_rm_dex }, 147 { "remove", 2, do_remove }, 148 { "rename", 2, do_rename }, 149 { "fixuid", 3, do_fixuid }, 150 { "freecache", 1, do_free_cache }, 151 { "rmcache", 1, do_rm_cache }, 152 { "protect", 2, do_protect }, 153 { "getsize", 4, do_get_size }, 154 { "rmuserdata", 2, do_rm_user_data }, 155 { "movefiles", 0, do_movefiles }, 156 { "linklib", 2, do_linklib }, 157 { "unlinklib", 1, do_unlinklib }, 158 { "mkuserdata", 3, do_mk_user_data }, 159 { "rmuser", 1, do_rm_user }, 160 { "cloneuserdata", 3, do_clone_user_data }, 161 }; 162 163 static int readx(int s, void *_buf, int count) 164 { 165 char *buf = _buf; 166 int n = 0, r; 167 if (count < 0) return -1; 168 while (n < count) { 169 r = read(s, buf + n, count - n); 170 if (r < 0) { 171 if (errno == EINTR) continue; 172 ALOGE("read error: %s\n", strerror(errno)); 173 return -1; 174 } 175 if (r == 0) { 176 ALOGE("eof\n"); 177 return -1; /* EOF */ 178 } 179 n += r; 180 } 181 return 0; 182 } 183 184 static int writex(int s, const void *_buf, int count) 185 { 186 const char *buf = _buf; 187 int n = 0, r; 188 if (count < 0) return -1; 189 while (n < count) { 190 r = write(s, buf + n, count - n); 191 if (r < 0) { 192 if (errno == EINTR) continue; 193 ALOGE("write error: %s\n", strerror(errno)); 194 return -1; 195 } 196 n += r; 197 } 198 return 0; 199 } 200 201 202 /* Tokenize the command buffer, locate a matching command, 203 * ensure that the required number of arguments are provided, 204 * call the function(), return the result. 205 */ 206 static int execute(int s, char cmd[BUFFER_MAX]) 207 { 208 char reply[REPLY_MAX]; 209 char *arg[TOKEN_MAX+1]; 210 unsigned i; 211 unsigned n = 0; 212 unsigned short count; 213 int ret = -1; 214 215 // ALOGI("execute('%s')\n", cmd); 216 217 /* default reply is "" */ 218 reply[0] = 0; 219 220 /* n is number of args (not counting arg[0]) */ 221 arg[0] = cmd; 222 while (*cmd) { 223 if (isspace(*cmd)) { 224 *cmd++ = 0; 225 n++; 226 arg[n] = cmd; 227 if (n == TOKEN_MAX) { 228 ALOGE("too many arguments\n"); 229 goto done; 230 } 231 } 232 cmd++; 233 } 234 235 for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) { 236 if (!strcmp(cmds[i].name,arg[0])) { 237 if (n != cmds[i].numargs) { 238 ALOGE("%s requires %d arguments (%d given)\n", 239 cmds[i].name, cmds[i].numargs, n); 240 } else { 241 ret = cmds[i].func(arg + 1, reply); 242 } 243 goto done; 244 } 245 } 246 ALOGE("unsupported command '%s'\n", arg[0]); 247 248 done: 249 if (reply[0]) { 250 n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply); 251 } else { 252 n = snprintf(cmd, BUFFER_MAX, "%d", ret); 253 } 254 if (n > BUFFER_MAX) n = BUFFER_MAX; 255 count = n; 256 257 // ALOGI("reply: '%s'\n", cmd); 258 if (writex(s, &count, sizeof(count))) return -1; 259 if (writex(s, cmd, count)) return -1; 260 return 0; 261 } 262 263 /** 264 * Initialize all the global variables that are used elsewhere. Returns 0 upon 265 * success and -1 on error. 266 */ 267 void free_globals() { 268 size_t i; 269 270 for (i = 0; i < android_system_dirs.count; i++) { 271 if (android_system_dirs.dirs[i].path != NULL) { 272 free(android_system_dirs.dirs[i].path); 273 } 274 } 275 276 free(android_system_dirs.dirs); 277 } 278 279 int initialize_globals() { 280 // Get the android data directory. 281 if (get_path_from_env(&android_data_dir, "ANDROID_DATA") < 0) { 282 return -1; 283 } 284 285 // Get the android app directory. 286 if (copy_and_append(&android_app_dir, &android_data_dir, APP_SUBDIR) < 0) { 287 return -1; 288 } 289 290 // Get the android protected app directory. 291 if (copy_and_append(&android_app_private_dir, &android_data_dir, PRIVATE_APP_SUBDIR) < 0) { 292 return -1; 293 } 294 295 // Get the sd-card ASEC mount point. 296 if (get_path_from_env(&android_asec_dir, "ASEC_MOUNTPOINT") < 0) { 297 return -1; 298 } 299 300 // Take note of the system and vendor directories. 301 android_system_dirs.count = 2; 302 303 android_system_dirs.dirs = calloc(android_system_dirs.count, sizeof(dir_rec_t)); 304 if (android_system_dirs.dirs == NULL) { 305 ALOGE("Couldn't allocate array for dirs; aborting\n"); 306 return -1; 307 } 308 309 // system 310 if (get_path_from_env(&android_system_dirs.dirs[0], "ANDROID_ROOT") < 0) { 311 free_globals(); 312 return -1; 313 } 314 315 // append "app/" to dirs[0] 316 char *system_app_path = build_string2(android_system_dirs.dirs[0].path, APP_SUBDIR); 317 android_system_dirs.dirs[0].path = system_app_path; 318 android_system_dirs.dirs[0].len = strlen(system_app_path); 319 320 // vendor 321 // TODO replace this with an environment variable (doesn't exist yet) 322 android_system_dirs.dirs[1].path = "/vendor/app/"; 323 android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path); 324 325 return 0; 326 } 327 328 int initialize_directories() { 329 // /data/user 330 char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX); 331 // /data/data 332 char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX); 333 // /data/user/0 334 char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, 335 "0"); 336 int ret = -1; 337 if (user_data_dir != NULL && primary_data_dir != NULL && legacy_data_dir != NULL) { 338 ret = 0; 339 // Make the /data/user directory if necessary 340 if (access(user_data_dir, R_OK) < 0) { 341 if (mkdir(user_data_dir, 0711) < 0) { 342 return -1; 343 } 344 if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) { 345 return -1; 346 } 347 if (chmod(user_data_dir, 0711) < 0) { 348 return -1; 349 } 350 } 351 // Make the /data/user/0 symlink to /data/data if necessary 352 if (access(primary_data_dir, R_OK) < 0) { 353 ret = symlink(legacy_data_dir, primary_data_dir); 354 } 355 free(user_data_dir); 356 free(legacy_data_dir); 357 free(primary_data_dir); 358 } 359 return ret; 360 } 361 362 int main(const int argc, const char *argv[]) { 363 char buf[BUFFER_MAX]; 364 struct sockaddr addr; 365 socklen_t alen; 366 int lsocket, s, count; 367 368 if (initialize_globals() < 0) { 369 ALOGE("Could not initialize globals; exiting.\n"); 370 exit(1); 371 } 372 373 if (initialize_directories() < 0) { 374 ALOGE("Could not create directories; exiting.\n"); 375 exit(1); 376 } 377 378 lsocket = android_get_control_socket(SOCKET_PATH); 379 if (lsocket < 0) { 380 ALOGE("Failed to get socket from environment: %s\n", strerror(errno)); 381 exit(1); 382 } 383 if (listen(lsocket, 5)) { 384 ALOGE("Listen on socket failed: %s\n", strerror(errno)); 385 exit(1); 386 } 387 fcntl(lsocket, F_SETFD, FD_CLOEXEC); 388 389 for (;;) { 390 alen = sizeof(addr); 391 s = accept(lsocket, &addr, &alen); 392 if (s < 0) { 393 ALOGE("Accept failed: %s\n", strerror(errno)); 394 continue; 395 } 396 fcntl(s, F_SETFD, FD_CLOEXEC); 397 398 ALOGI("new connection\n"); 399 for (;;) { 400 unsigned short count; 401 if (readx(s, &count, sizeof(count))) { 402 ALOGE("failed to read size\n"); 403 break; 404 } 405 if ((count < 1) || (count >= BUFFER_MAX)) { 406 ALOGE("invalid size %d\n", count); 407 break; 408 } 409 if (readx(s, buf, count)) { 410 ALOGE("failed to read command\n"); 411 break; 412 } 413 buf[count] = 0; 414 if (execute(s, buf)) break; 415 } 416 ALOGI("closing connection\n"); 417 close(s); 418 } 419 420 return 0; 421 } 422