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 int create_pkg_path_in_dir(char path[PKG_PATH_MAX], 20 const dir_rec_t* dir, 21 const char* pkgname, 22 const char* postfix) 23 { 24 const size_t postfix_len = strlen(postfix); 25 26 const size_t pkgname_len = strlen(pkgname); 27 if (pkgname_len > PKG_NAME_MAX) { 28 return -1; 29 } 30 31 if (is_valid_package_name(pkgname) < 0) { 32 return -1; 33 } 34 35 if ((pkgname_len + dir->len + postfix_len) >= PKG_PATH_MAX) { 36 return -1; 37 } 38 39 char *dst = path; 40 size_t dst_size = PKG_PATH_MAX; 41 42 if (append_and_increment(&dst, dir->path, &dst_size) < 0 43 || append_and_increment(&dst, pkgname, &dst_size) < 0 44 || append_and_increment(&dst, postfix, &dst_size) < 0) { 45 LOGE("Error building APK path"); 46 return -1; 47 } 48 49 return 0; 50 } 51 52 /** 53 * Create the package path name for a given package name with a postfix for 54 * a certain persona. Returns 0 on success, and -1 on failure. 55 */ 56 int create_pkg_path(char path[PKG_PATH_MAX], 57 const char *pkgname, 58 const char *postfix, 59 uid_t persona) 60 { 61 size_t uid_len; 62 char* persona_prefix; 63 if (persona == 0) { 64 persona_prefix = PRIMARY_USER_PREFIX; 65 uid_len = 0; 66 } else { 67 persona_prefix = SECONDARY_USER_PREFIX; 68 uid_len = snprintf(NULL, 0, "%d", persona); 69 } 70 71 const size_t prefix_len = android_data_dir.len + strlen(persona_prefix) + uid_len + 1 /*slash*/; 72 char prefix[prefix_len + 1]; 73 74 char *dst = prefix; 75 size_t dst_size = sizeof(prefix); 76 77 if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0 78 || append_and_increment(&dst, persona_prefix, &dst_size) < 0) { 79 LOGE("Error building prefix for APK path"); 80 return -1; 81 } 82 83 if (persona != 0) { 84 int ret = snprintf(dst, dst_size, "%d/", persona); 85 if (ret < 0 || (size_t) ret != uid_len + 1) { 86 LOGW("Error appending UID to APK path"); 87 return -1; 88 } 89 } 90 91 dir_rec_t dir; 92 dir.path = prefix; 93 dir.len = prefix_len; 94 95 return create_pkg_path_in_dir(path, &dir, pkgname, postfix); 96 } 97 98 /** 99 * Create the path name for user data for a certain persona. 100 * Returns 0 on success, and -1 on failure. 101 */ 102 int create_persona_path(char path[PKG_PATH_MAX], 103 uid_t persona) 104 { 105 size_t uid_len; 106 char* persona_prefix; 107 if (persona == 0) { 108 persona_prefix = PRIMARY_USER_PREFIX; 109 uid_len = 0; 110 } else { 111 persona_prefix = SECONDARY_USER_PREFIX; 112 uid_len = snprintf(NULL, 0, "%d", persona); 113 } 114 115 char *dst = path; 116 size_t dst_size = PKG_PATH_MAX; 117 118 if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0 119 || append_and_increment(&dst, persona_prefix, &dst_size) < 0) { 120 LOGE("Error building prefix for user path"); 121 return -1; 122 } 123 124 if (persona != 0) { 125 if (dst_size < uid_len + 1) { 126 LOGE("Error building user path"); 127 return -1; 128 } 129 int ret = snprintf(dst, dst_size, "%d", persona); 130 if (ret < 0 || (size_t) ret != uid_len) { 131 LOGE("Error appending persona id to path"); 132 return -1; 133 } 134 } 135 return 0; 136 } 137 138 /** 139 * Checks whether the package name is valid. Returns -1 on error and 140 * 0 on success. 141 */ 142 int is_valid_package_name(const char* pkgname) { 143 const char *x = pkgname; 144 int alpha = -1; 145 146 while (*x) { 147 if (isalnum(*x) || (*x == '_')) { 148 /* alphanumeric or underscore are fine */ 149 } else if (*x == '.') { 150 if ((x == pkgname) || (x[1] == '.') || (x[1] == 0)) { 151 /* periods must not be first, last, or doubled */ 152 LOGE("invalid package name '%s'\n", pkgname); 153 return -1; 154 } 155 } else if (*x == '-') { 156 /* Suffix -X is fine to let versioning of packages. 157 But whatever follows should be alphanumeric.*/ 158 alpha = 1; 159 } else { 160 /* anything not A-Z, a-z, 0-9, _, or . is invalid */ 161 LOGE("invalid package name '%s'\n", pkgname); 162 return -1; 163 } 164 165 x++; 166 } 167 168 if (alpha == 1) { 169 // Skip current character 170 x++; 171 while (*x) { 172 if (!isalnum(*x)) { 173 LOGE("invalid package name '%s' should include only numbers after -\n", pkgname); 174 return -1; 175 } 176 x++; 177 } 178 } 179 180 return 0; 181 } 182 183 static int _delete_dir_contents(DIR *d, const char *ignore) 184 { 185 int result = 0; 186 struct dirent *de; 187 int dfd; 188 189 dfd = dirfd(d); 190 191 if (dfd < 0) return -1; 192 193 while ((de = readdir(d))) { 194 const char *name = de->d_name; 195 196 /* skip the ignore name if provided */ 197 if (ignore && !strcmp(name, ignore)) continue; 198 199 if (de->d_type == DT_DIR) { 200 int r, subfd; 201 DIR *subdir; 202 203 /* always skip "." and ".." */ 204 if (name[0] == '.') { 205 if (name[1] == 0) continue; 206 if ((name[1] == '.') && (name[2] == 0)) continue; 207 } 208 209 subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); 210 if (subfd < 0) { 211 LOGE("Couldn't openat %s: %s\n", name, strerror(errno)); 212 result = -1; 213 continue; 214 } 215 subdir = fdopendir(subfd); 216 if (subdir == NULL) { 217 LOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno)); 218 close(subfd); 219 result = -1; 220 continue; 221 } 222 if (_delete_dir_contents(subdir, 0)) { 223 result = -1; 224 } 225 closedir(subdir); 226 if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) { 227 LOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno)); 228 result = -1; 229 } 230 } else { 231 if (unlinkat(dfd, name, 0) < 0) { 232 LOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno)); 233 result = -1; 234 } 235 } 236 } 237 238 return result; 239 } 240 241 int delete_dir_contents(const char *pathname, 242 int also_delete_dir, 243 const char *ignore) 244 { 245 int res = 0; 246 DIR *d; 247 248 d = opendir(pathname); 249 if (d == NULL) { 250 LOGE("Couldn't opendir %s: %s\n", pathname, strerror(errno)); 251 return -errno; 252 } 253 res = _delete_dir_contents(d, ignore); 254 closedir(d); 255 if (also_delete_dir) { 256 if (rmdir(pathname)) { 257 LOGE("Couldn't rmdir %s: %s\n", pathname, strerror(errno)); 258 res = -1; 259 } 260 } 261 return res; 262 } 263 264 int delete_dir_contents_fd(int dfd, const char *name) 265 { 266 int fd, res; 267 DIR *d; 268 269 fd = openat(dfd, name, O_RDONLY | O_DIRECTORY); 270 if (fd < 0) { 271 LOGE("Couldn't openat %s: %s\n", name, strerror(errno)); 272 return -1; 273 } 274 d = fdopendir(fd); 275 if (d == NULL) { 276 LOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno)); 277 close(fd); 278 return -1; 279 } 280 res = _delete_dir_contents(d, 0); 281 closedir(d); 282 return res; 283 } 284 285 /** 286 * Checks whether a path points to a system app (.apk file). Returns 0 287 * if it is a system app or -1 if it is not. 288 */ 289 int validate_system_app_path(const char* path) { 290 size_t i; 291 292 for (i = 0; i < android_system_dirs.count; i++) { 293 const size_t dir_len = android_system_dirs.dirs[i].len; 294 if (!strncmp(path, android_system_dirs.dirs[i].path, dir_len)) { 295 if (path[dir_len] == '.' || strchr(path + dir_len, '/') != NULL) { 296 LOGE("invalid system apk path '%s' (trickery)\n", path); 297 return -1; 298 } 299 return 0; 300 } 301 } 302 303 return -1; 304 } 305 306 /** 307 * Get the contents of a environment variable that contains a path. Caller 308 * owns the string that is inserted into the directory record. Returns 309 * 0 on success and -1 on error. 310 */ 311 int get_path_from_env(dir_rec_t* rec, const char* var) { 312 const char* path = getenv(var); 313 int ret = get_path_from_string(rec, path); 314 if (ret < 0) { 315 LOGW("Problem finding value for environment variable %s\n", var); 316 } 317 return ret; 318 } 319 320 /** 321 * Puts the string into the record as a directory. Appends '/' to the end 322 * of all paths. Caller owns the string that is inserted into the directory 323 * record. A null value will result in an error. 324 * 325 * Returns 0 on success and -1 on error. 326 */ 327 int get_path_from_string(dir_rec_t* rec, const char* path) { 328 if (path == NULL) { 329 return -1; 330 } else { 331 const size_t path_len = strlen(path); 332 if (path_len <= 0) { 333 return -1; 334 } 335 336 // Make sure path is absolute. 337 if (path[0] != '/') { 338 return -1; 339 } 340 341 if (path[path_len - 1] == '/') { 342 // Path ends with a forward slash. Make our own copy. 343 344 rec->path = strdup(path); 345 if (rec->path == NULL) { 346 return -1; 347 } 348 349 rec->len = path_len; 350 } else { 351 // Path does not end with a slash. Generate a new string. 352 char *dst; 353 354 // Add space for slash and terminating null. 355 size_t dst_size = path_len + 2; 356 357 rec->path = malloc(dst_size); 358 if (rec->path == NULL) { 359 return -1; 360 } 361 362 dst = rec->path; 363 364 if (append_and_increment(&dst, path, &dst_size) < 0 365 || append_and_increment(&dst, "/", &dst_size)) { 366 LOGE("Error canonicalizing path"); 367 return -1; 368 } 369 370 rec->len = dst - rec->path; 371 } 372 } 373 return 0; 374 } 375 376 int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix) { 377 dst->len = src->len + strlen(suffix); 378 const size_t dstSize = dst->len + 1; 379 dst->path = (char*) malloc(dstSize); 380 381 if (dst->path == NULL 382 || snprintf(dst->path, dstSize, "%s%s", src->path, suffix) 383 != (ssize_t) dst->len) { 384 LOGE("Could not allocate memory to hold appended path; aborting\n"); 385 return -1; 386 } 387 388 return 0; 389 } 390 391 /** 392 * Check whether path points to a valid path for an APK file. An ASEC 393 * directory is allowed to have one level of subdirectory names. Returns -1 394 * when an invalid path is encountered and 0 when a valid path is encountered. 395 */ 396 int validate_apk_path(const char *path) 397 { 398 int allowsubdir = 0; 399 char *subdir = NULL; 400 size_t dir_len; 401 size_t path_len; 402 403 if (!strncmp(path, android_app_dir.path, android_app_dir.len)) { 404 dir_len = android_app_dir.len; 405 } else if (!strncmp(path, android_app_private_dir.path, android_app_private_dir.len)) { 406 dir_len = android_app_private_dir.len; 407 } else if (!strncmp(path, android_asec_dir.path, android_asec_dir.len)) { 408 dir_len = android_asec_dir.len; 409 allowsubdir = 1; 410 } else { 411 LOGE("invalid apk path '%s' (bad prefix)\n", path); 412 return -1; 413 } 414 415 path_len = strlen(path); 416 417 /* 418 * Only allow the path to have a subdirectory if it's been marked as being allowed. 419 */ 420 if ((subdir = strchr(path + dir_len, '/')) != NULL) { 421 ++subdir; 422 if (!allowsubdir 423 || (path_len > (size_t) (subdir - path) && (strchr(subdir, '/') != NULL))) { 424 LOGE("invalid apk path '%s' (subdir?)\n", path); 425 return -1; 426 } 427 } 428 429 /* 430 * Directories can't have a period directly after the directory markers 431 * to prevent ".." 432 */ 433 if (path[dir_len] == '.' 434 || (subdir != NULL && ((*subdir == '.') || (strchr(subdir, '/') != NULL)))) { 435 LOGE("invalid apk path '%s' (trickery)\n", path); 436 return -1; 437 } 438 439 return 0; 440 } 441 442 int append_and_increment(char** dst, const char* src, size_t* dst_size) { 443 ssize_t ret = strlcpy(*dst, src, *dst_size); 444 if (ret < 0 || (size_t) ret >= *dst_size) { 445 return -1; 446 } 447 *dst += ret; 448 *dst_size -= ret; 449 return 0; 450 } 451 452 char *build_string2(char *s1, char *s2) { 453 if (s1 == NULL || s2 == NULL) return NULL; 454 455 int len_s1 = strlen(s1); 456 int len_s2 = strlen(s2); 457 int len = len_s1 + len_s2 + 1; 458 char *result = malloc(len); 459 if (result == NULL) return NULL; 460 461 strcpy(result, s1); 462 strcpy(result + len_s1, s2); 463 464 return result; 465 } 466 467 char *build_string3(char *s1, char *s2, char *s3) { 468 if (s1 == NULL || s2 == NULL || s3 == NULL) return NULL; 469 470 int len_s1 = strlen(s1); 471 int len_s2 = strlen(s2); 472 int len_s3 = strlen(s3); 473 int len = len_s1 + len_s2 + len_s3 + 1; 474 char *result = malloc(len); 475 if (result == NULL) return NULL; 476 477 strcpy(result, s1); 478 strcpy(result + len_s1, s2); 479 strcpy(result + len_s1 + len_s2, s3); 480 481 return result; 482 } 483