commands.c revision d24b8183b93e781080b2c16c487e60d51c12da31
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 19int install(const char *pkgname, uid_t uid, gid_t gid) 20{ 21 char pkgdir[PKG_PATH_MAX]; 22 char libdir[PKG_PATH_MAX]; 23 24 if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) { 25 LOGE("invalid uid/gid: %d %d\n", uid, gid); 26 return -1; 27 28 } 29 if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) 30 return -1; 31 if (create_pkg_path(libdir, PKG_LIB_PREFIX, pkgname, PKG_LIB_POSTFIX)) 32 return -1; 33 34 if (mkdir(pkgdir, 0755) < 0) { 35 LOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); 36 return -errno; 37 } 38 if (chown(pkgdir, uid, gid) < 0) { 39 LOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); 40 unlink(pkgdir); 41 return -errno; 42 } 43 if (mkdir(libdir, 0755) < 0) { 44 LOGE("cannot create dir '%s': %s\n", libdir, strerror(errno)); 45 unlink(pkgdir); 46 return -errno; 47 } 48 if (chown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) { 49 LOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno)); 50 unlink(libdir); 51 unlink(pkgdir); 52 return -errno; 53 } 54 return 0; 55} 56 57int uninstall(const char *pkgname) 58{ 59 char pkgdir[PKG_PATH_MAX]; 60 61 if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) 62 return -1; 63 64 /* delete contents AND directory, no exceptions */ 65 return delete_dir_contents(pkgdir, 1, 0); 66} 67 68int delete_user_data(const char *pkgname) 69{ 70 char pkgdir[PKG_PATH_MAX]; 71 72 if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) 73 return -1; 74 75 /* delete contents, excluding "lib", but not the directory itself */ 76 return delete_dir_contents(pkgdir, 0, "lib"); 77} 78 79int delete_cache(const char *pkgname) 80{ 81 char cachedir[PKG_PATH_MAX]; 82 83 if (create_pkg_path(cachedir, CACHE_DIR_PREFIX, pkgname, CACHE_DIR_POSTFIX)) 84 return -1; 85 86 /* delete contents, not the directory, no exceptions */ 87 return delete_dir_contents(cachedir, 0, 0); 88} 89 90 91static int disk_free(void) 92{ 93 struct statfs sfs; 94 if (statfs(PKG_DIR_PREFIX, &sfs) == 0) { 95 return sfs.f_bavail * sfs.f_bsize; 96 } else { 97 return -1; 98 } 99} 100 101 102/* Try to ensure free_size bytes of storage are available. 103 * Returns 0 on success. 104 * This is rather simple-minded because doing a full LRU would 105 * be potentially memory-intensive, and without atime it would 106 * also require that apps constantly modify file metadata even 107 * when just reading from the cache, which is pretty awful. 108 */ 109int free_cache(int free_size) 110{ 111 const char *name; 112 int dfd, subfd; 113 DIR *d; 114 struct dirent *de; 115 int avail; 116 117 avail = disk_free(); 118 if (avail < 0) return -1; 119 120 LOGI("free_cache(%d) avail %d\n", free_size, avail); 121 if (avail >= free_size) return 0; 122 123 d = opendir(PKG_DIR_PREFIX); 124 if (d == NULL) { 125 LOGE("cannot open %s\n", PKG_DIR_PREFIX); 126 return -1; 127 } 128 dfd = dirfd(d); 129 130 while ((de = readdir(d))) { 131 if (de->d_type != DT_DIR) continue; 132 name = de->d_name; 133 134 /* always skip "." and ".." */ 135 if (name[0] == '.') { 136 if (name[1] == 0) continue; 137 if ((name[1] == '.') && (name[2] == 0)) continue; 138 } 139 140 subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); 141 if (subfd < 0) continue; 142 143 delete_dir_contents_fd(subfd, "cache"); 144 close(subfd); 145 146 avail = disk_free(); 147 if (avail >= free_size) { 148 closedir(d); 149 return 0; 150 } 151 } 152 closedir(d); 153 return -1; 154} 155 156 157/* used by move_dex, rm_dex, etc to ensure that the provided paths 158 * don't point anywhere other than at the APK_DIR_PREFIX 159 */ 160static int is_valid_apk_path(const char *path) 161{ 162 int len = strlen(APK_DIR_PREFIX); 163 if (strncmp(path, APK_DIR_PREFIX, len)) { 164 len = strlen(PROTECTED_DIR_PREFIX); 165 if (strncmp(path, PROTECTED_DIR_PREFIX, len)) { 166 LOGE("invalid apk path '%s' (bad prefix)\n", path); 167 return 0; 168 } 169 } 170 if (strchr(path + len, '/')) { 171 LOGE("invalid apk path '%s' (subdir?)\n", path); 172 return 0; 173 } 174 if (path[len] == '.') { 175 LOGE("invalid apk path '%s' (trickery)\n", path); 176 return 0; 177 } 178 return 1; 179} 180 181int move_dex(const char *src, const char *dst) 182{ 183 char src_dex[PKG_PATH_MAX]; 184 char dst_dex[PKG_PATH_MAX]; 185 186 if (!is_valid_apk_path(src)) return -1; 187 if (!is_valid_apk_path(dst)) return -1; 188 189 if (create_cache_path(src_dex, src)) return -1; 190 if (create_cache_path(dst_dex, dst)) return -1; 191 192 LOGI("move %s -> %s\n", src_dex, dst_dex); 193 if (rename(src_dex, dst_dex) < 0) { 194 return -1; 195 } else { 196 return 0; 197 } 198} 199 200int rm_dex(const char *path) 201{ 202 char dex_path[PKG_PATH_MAX]; 203 204 if (!is_valid_apk_path(path)) return -1; 205 if (create_cache_path(dex_path, path)) return -1; 206 207 LOGI("unlink %s\n", dex_path); 208 if (unlink(dex_path) < 0) { 209 return -1; 210 } else { 211 return 0; 212 } 213} 214 215int protect(char *pkgname, gid_t gid) 216{ 217 struct stat s; 218 char pkgpath[PKG_PATH_MAX]; 219 220 if (gid < AID_SYSTEM) return -1; 221 222 if (create_pkg_path(pkgpath, PROTECTED_DIR_PREFIX, pkgname, ".apk")) 223 return -1; 224 225 if (stat(pkgpath, &s) < 0) return -1; 226 227 if (chown(pkgpath, s.st_uid, gid) < 0) { 228 LOGE("failed to chgrp '%s': %s\n", pkgpath, strerror(errno)); 229 return -1; 230 } 231 232 if (chmod(pkgpath, S_IRUSR|S_IWUSR|S_IRGRP) < 0) { 233 LOGE("failed to chmod '%s': %s\n", pkgpath, strerror(errno)); 234 return -1; 235 } 236 237 return 0; 238} 239 240static int stat_size(struct stat *s) 241{ 242 int blksize = s->st_blksize; 243 int size = s->st_size; 244 245 if (blksize) { 246 /* round up to filesystem block size */ 247 size = (size + blksize - 1) & (~(blksize - 1)); 248 } 249 250 return size; 251} 252 253static int calculate_dir_size(int dfd) 254{ 255 int size = 0; 256 struct stat s; 257 DIR *d; 258 struct dirent *de; 259 260 d = fdopendir(dfd); 261 if (d == NULL) { 262 close(dfd); 263 return 0; 264 } 265 266 while ((de = readdir(d))) { 267 const char *name = de->d_name; 268 if (de->d_type == DT_DIR) { 269 int subfd; 270 /* always skip "." and ".." */ 271 if (name[0] == '.') { 272 if (name[1] == 0) continue; 273 if ((name[1] == '.') && (name[2] == 0)) continue; 274 } 275 subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); 276 if (subfd >= 0) { 277 size += calculate_dir_size(subfd); 278 } 279 } else { 280 if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { 281 size += stat_size(&s); 282 } 283 } 284 } 285 closedir(d); 286 return size; 287} 288 289int get_size(const char *pkgname, const char *apkpath, 290 const char *fwdlock_apkpath, 291 int *_codesize, int *_datasize, int *_cachesize) 292{ 293 DIR *d; 294 int dfd; 295 struct dirent *de; 296 struct stat s; 297 char path[PKG_PATH_MAX]; 298 299 int codesize = 0; 300 int datasize = 0; 301 int cachesize = 0; 302 303 /* count the source apk as code -- but only if it's not 304 * on the /system partition 305 */ 306 if (strncmp(apkpath, "/system", 7) != 0) { 307 if (stat(apkpath, &s) == 0) { 308 codesize += stat_size(&s); 309 } 310 } 311 /* count the forward locked apk as code if it is given 312 */ 313 if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') { 314 if (stat(fwdlock_apkpath, &s) == 0) { 315 codesize += stat_size(&s); 316 } 317 } 318 319 320 /* count the cached dexfile as code */ 321 if (!create_cache_path(path, apkpath)) { 322 if (stat(path, &s) == 0) { 323 codesize += stat_size(&s); 324 } 325 } 326 327 if (create_pkg_path(path, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) { 328 goto done; 329 } 330 331 d = opendir(path); 332 if (d == NULL) { 333 goto done; 334 } 335 dfd = dirfd(d); 336 337 /* most stuff in the pkgdir is data, except for the "cache" 338 * directory and below, which is cache, and the "lib" directory 339 * and below, which is code... 340 */ 341 while ((de = readdir(d))) { 342 const char *name = de->d_name; 343 344 if (de->d_type == DT_DIR) { 345 int subfd; 346 /* always skip "." and ".." */ 347 if (name[0] == '.') { 348 if (name[1] == 0) continue; 349 if ((name[1] == '.') && (name[2] == 0)) continue; 350 } 351 subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); 352 if (subfd >= 0) { 353 int size = calculate_dir_size(subfd); 354 if (!strcmp(name,"lib")) { 355 codesize += size; 356 } else if(!strcmp(name,"cache")) { 357 cachesize += size; 358 } else { 359 datasize += size; 360 } 361 } 362 } else { 363 if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { 364 datasize += stat_size(&s); 365 } 366 } 367 } 368 closedir(d); 369done: 370 *_codesize = codesize; 371 *_datasize = datasize; 372 *_cachesize = cachesize; 373 return 0; 374} 375 376 377/* a simpler version of dexOptGenerateCacheFileName() */ 378int create_cache_path(char path[PKG_PATH_MAX], const char *src) 379{ 380 char *tmp; 381 int srclen; 382 int dstlen; 383 384 srclen = strlen(src); 385 386 /* demand that we are an absolute path */ 387 if ((src == 0) || (src[0] != '/') || strstr(src,"..")) { 388 return -1; 389 } 390 391 if (srclen > PKG_PATH_MAX) { // XXX: PKG_NAME_MAX? 392 return -1; 393 } 394 395 dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) + 396 strlen(DALVIK_CACHE_POSTFIX) + 1; 397 398 if (dstlen > PKG_PATH_MAX) { 399 return -1; 400 } 401 402 sprintf(path,"%s%s%s", 403 DALVIK_CACHE_PREFIX, 404 src + 1, /* skip the leading / */ 405 DALVIK_CACHE_POSTFIX); 406 407 for(tmp = path + strlen(DALVIK_CACHE_PREFIX); *tmp; tmp++) { 408 if (*tmp == '/') { 409 *tmp = '@'; 410 } 411 } 412 413 return 0; 414} 415 416static void run_dexopt(int zip_fd, int odex_fd, const char* input_file_name, 417 const char* dexopt_flags) 418{ 419 static const char* DEX_OPT_BIN = "/system/bin/dexopt"; 420 static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig 421 char zip_num[MAX_INT_LEN]; 422 char odex_num[MAX_INT_LEN]; 423 424 sprintf(zip_num, "%d", zip_fd); 425 sprintf(odex_num, "%d", odex_fd); 426 427 execl(DEX_OPT_BIN, DEX_OPT_BIN, "--zip", zip_num, odex_num, input_file_name, 428 dexopt_flags, (char*) NULL); 429 LOGE("execl(%s) failed: %s\n", DEX_OPT_BIN, strerror(errno)); 430} 431 432static int wait_dexopt(pid_t pid, const char* apk_path) 433{ 434 int status; 435 pid_t got_pid; 436 437 /* 438 * Wait for the optimization process to finish. 439 */ 440 while (1) { 441 got_pid = waitpid(pid, &status, 0); 442 if (got_pid == -1 && errno == EINTR) { 443 printf("waitpid interrupted, retrying\n"); 444 } else { 445 break; 446 } 447 } 448 if (got_pid != pid) { 449 LOGW("waitpid failed: wanted %d, got %d: %s\n", 450 (int) pid, (int) got_pid, strerror(errno)); 451 return 1; 452 } 453 454 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 455 LOGD("DexInv: --- END '%s' (success) ---\n", apk_path); 456 return 0; 457 } else { 458 LOGW("DexInv: --- END '%s' --- status=0x%04x, process failed\n", 459 apk_path, status); 460 return status; /* always nonzero */ 461 } 462} 463 464int dexopt(const char *apk_path, uid_t uid, int is_public) 465{ 466 struct utimbuf ut; 467 struct stat apk_stat, dex_stat; 468 char dex_path[PKG_PATH_MAX]; 469 char dexopt_flags[PROPERTY_VALUE_MAX]; 470 char *end; 471 int res, zip_fd=-1, odex_fd=-1; 472 473 /* Before anything else: is there a .odex file? If so, we have 474 * pre-optimized the apk and there is nothing to do here. 475 */ 476 if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) { 477 return -1; 478 } 479 480 /* platform-specific flags affecting optimization and verification */ 481 property_get("dalvik.vm.dexopt-flags", dexopt_flags, ""); 482 483 strcpy(dex_path, apk_path); 484 end = strrchr(dex_path, '.'); 485 if (end != NULL) { 486 strcpy(end, ".odex"); 487 if (stat(dex_path, &dex_stat) == 0) { 488 return 0; 489 } 490 } 491 492 if (create_cache_path(dex_path, apk_path)) { 493 return -1; 494 } 495 496 memset(&apk_stat, 0, sizeof(apk_stat)); 497 stat(apk_path, &apk_stat); 498 499 zip_fd = open(apk_path, O_RDONLY, 0); 500 if (zip_fd < 0) { 501 LOGE("dexopt cannot open '%s' for input\n", apk_path); 502 return -1; 503 } 504 505 unlink(dex_path); 506 odex_fd = open(dex_path, O_RDWR | O_CREAT | O_EXCL, 0644); 507 if (odex_fd < 0) { 508 LOGE("dexopt cannot open '%s' for output\n", dex_path); 509 goto fail; 510 } 511 if (fchown(odex_fd, AID_SYSTEM, uid) < 0) { 512 LOGE("dexopt cannot chown '%s'\n", dex_path); 513 goto fail; 514 } 515 if (fchmod(odex_fd, 516 S_IRUSR|S_IWUSR|S_IRGRP | 517 (is_public ? S_IROTH : 0)) < 0) { 518 LOGE("dexopt cannot chmod '%s'\n", dex_path); 519 goto fail; 520 } 521 522 LOGD("DexInv: --- BEGIN '%s' ---\n", apk_path); 523 524 pid_t pid; 525 pid = fork(); 526 if (pid == 0) { 527 /* child -- drop privileges before continuing */ 528 if (setgid(uid) != 0) { 529 LOGE("setgid(%d) failed during dexopt\n", uid); 530 exit(64); 531 } 532 if (setuid(uid) != 0) { 533 LOGE("setuid(%d) during dexopt\n", uid); 534 exit(65); 535 } 536 if (flock(odex_fd, LOCK_EX | LOCK_NB) != 0) { 537 LOGE("flock(%s) failed: %s\n", dex_path, strerror(errno)); 538 exit(66); 539 } 540 541 run_dexopt(zip_fd, odex_fd, apk_path, dexopt_flags); 542 exit(67); /* only get here on exec failure */ 543 } else { 544 res = wait_dexopt(pid, apk_path); 545 if (res != 0) { 546 LOGE("dexopt failed on '%s' res = %d\n", dex_path, res); 547 goto fail; 548 } 549 } 550 551 ut.actime = apk_stat.st_atime; 552 ut.modtime = apk_stat.st_mtime; 553 utime(dex_path, &ut); 554 555 close(odex_fd); 556 close(zip_fd); 557 return 0; 558 559fail: 560 if (odex_fd >= 0) { 561 close(odex_fd); 562 unlink(dex_path); 563 } 564 if (zip_fd >= 0) { 565 close(zip_fd); 566 } 567 return -1; 568} 569