1 /* 2 * Copyright (C) 2012 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 <stdio.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <unistd.h> 21 #include <fcntl.h> 22 #include <ctype.h> 23 #include <sys/mount.h> 24 #include <sys/stat.h> 25 #include <errno.h> 26 #include <sys/types.h> 27 #include <sys/wait.h> 28 #include <libgen.h> 29 #include <time.h> 30 #include <sys/swap.h> 31 32 #include <linux/loop.h> 33 #include <private/android_filesystem_config.h> 34 #include <cutils/android_reboot.h> 35 #include <cutils/partition_utils.h> 36 #include <cutils/properties.h> 37 #include <logwrap/logwrap.h> 38 39 #include "mincrypt/rsa.h" 40 #include "mincrypt/sha.h" 41 #include "mincrypt/sha256.h" 42 43 #include "ext4_utils.h" 44 #include "wipe.h" 45 46 #include "fs_mgr_priv.h" 47 #include "fs_mgr_priv_verity.h" 48 49 #define KEY_LOC_PROP "ro.crypto.keyfile.userdata" 50 #define KEY_IN_FOOTER "footer" 51 52 #define E2FSCK_BIN "/system/bin/e2fsck" 53 #define F2FS_FSCK_BIN "/system/bin/fsck.f2fs" 54 #define MKSWAP_BIN "/system/bin/mkswap" 55 56 #define FSCK_LOG_FILE "/dev/fscklogs/log" 57 58 #define ZRAM_CONF_DEV "/sys/block/zram0/disksize" 59 60 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) 61 62 /* 63 * gettime() - returns the time in seconds of the system's monotonic clock or 64 * zero on error. 65 */ 66 static time_t gettime(void) 67 { 68 struct timespec ts; 69 int ret; 70 71 ret = clock_gettime(CLOCK_MONOTONIC, &ts); 72 if (ret < 0) { 73 ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno)); 74 return 0; 75 } 76 77 return ts.tv_sec; 78 } 79 80 static int wait_for_file(const char *filename, int timeout) 81 { 82 struct stat info; 83 time_t timeout_time = gettime() + timeout; 84 int ret = -1; 85 86 while (gettime() < timeout_time && ((ret = stat(filename, &info)) < 0)) 87 usleep(10000); 88 89 return ret; 90 } 91 92 static void check_fs(char *blk_device, char *fs_type, char *target) 93 { 94 int status; 95 int ret; 96 long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID; 97 char *tmpmnt_opts = "nomblk_io_submit,errors=remount-ro"; 98 char *e2fsck_argv[] = { 99 E2FSCK_BIN, 100 "-y", 101 blk_device 102 }; 103 104 /* Check for the types of filesystems we know how to check */ 105 if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) { 106 /* 107 * First try to mount and unmount the filesystem. We do this because 108 * the kernel is more efficient than e2fsck in running the journal and 109 * processing orphaned inodes, and on at least one device with a 110 * performance issue in the emmc firmware, it can take e2fsck 2.5 minutes 111 * to do what the kernel does in about a second. 112 * 113 * After mounting and unmounting the filesystem, run e2fsck, and if an 114 * error is recorded in the filesystem superblock, e2fsck will do a full 115 * check. Otherwise, it does nothing. If the kernel cannot mount the 116 * filesytsem due to an error, e2fsck is still run to do a full check 117 * fix the filesystem. 118 */ 119 ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts); 120 INFO("%s(): mount(%s,%s,%s)=%d\n", __func__, blk_device, target, fs_type, ret); 121 if (!ret) { 122 umount(target); 123 } 124 125 /* 126 * Some system images do not have e2fsck for licensing reasons 127 * (e.g. recent SDK system images). Detect these and skip the check. 128 */ 129 if (access(E2FSCK_BIN, X_OK)) { 130 INFO("Not running %s on %s (executable not in system image)\n", 131 E2FSCK_BIN, blk_device); 132 } else { 133 INFO("Running %s on %s\n", E2FSCK_BIN, blk_device); 134 135 ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv, 136 &status, true, LOG_KLOG | LOG_FILE, 137 true, FSCK_LOG_FILE); 138 139 if (ret < 0) { 140 /* No need to check for error in fork, we can't really handle it now */ 141 ERROR("Failed trying to run %s\n", E2FSCK_BIN); 142 } 143 } 144 } else if (!strcmp(fs_type, "f2fs")) { 145 char *f2fs_fsck_argv[] = { 146 F2FS_FSCK_BIN, 147 "-f", 148 blk_device 149 }; 150 INFO("Running %s -f %s\n", F2FS_FSCK_BIN, blk_device); 151 152 ret = android_fork_execvp_ext(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv, 153 &status, true, LOG_KLOG | LOG_FILE, 154 true, FSCK_LOG_FILE); 155 if (ret < 0) { 156 /* No need to check for error in fork, we can't really handle it now */ 157 ERROR("Failed trying to run %s\n", F2FS_FSCK_BIN); 158 } 159 } 160 161 return; 162 } 163 164 static void remove_trailing_slashes(char *n) 165 { 166 int len; 167 168 len = strlen(n) - 1; 169 while ((*(n + len) == '/') && len) { 170 *(n + len) = '\0'; 171 len--; 172 } 173 } 174 175 /* 176 * Mark the given block device as read-only, using the BLKROSET ioctl. 177 * Return 0 on success, and -1 on error. 178 */ 179 static void fs_set_blk_ro(const char *blockdev) 180 { 181 int fd; 182 int ON = 1; 183 184 fd = open(blockdev, O_RDONLY); 185 if (fd < 0) { 186 // should never happen 187 return; 188 } 189 190 ioctl(fd, BLKROSET, &ON); 191 close(fd); 192 } 193 194 /* 195 * __mount(): wrapper around the mount() system call which also 196 * sets the underlying block device to read-only if the mount is read-only. 197 * See "man 2 mount" for return values. 198 */ 199 static int __mount(const char *source, const char *target, const struct fstab_rec *rec) 200 { 201 unsigned long mountflags = rec->flags; 202 int ret; 203 int save_errno; 204 205 /* We need this because sometimes we have legacy symlinks 206 * that are lingering around and need cleaning up. 207 */ 208 struct stat info; 209 if (!lstat(target, &info)) 210 if ((info.st_mode & S_IFMT) == S_IFLNK) 211 unlink(target); 212 mkdir(target, 0755); 213 ret = mount(source, target, rec->fs_type, mountflags, rec->fs_options); 214 save_errno = errno; 215 INFO("%s(source=%s,target=%s,type=%s)=%d\n", __func__, source, target, rec->fs_type, ret); 216 if ((ret == 0) && (mountflags & MS_RDONLY) != 0) { 217 fs_set_blk_ro(source); 218 } 219 errno = save_errno; 220 return ret; 221 } 222 223 static int fs_match(char *in1, char *in2) 224 { 225 char *n1; 226 char *n2; 227 int ret; 228 229 n1 = strdup(in1); 230 n2 = strdup(in2); 231 232 remove_trailing_slashes(n1); 233 remove_trailing_slashes(n2); 234 235 ret = !strcmp(n1, n2); 236 237 free(n1); 238 free(n2); 239 240 return ret; 241 } 242 243 static int device_is_debuggable() { 244 int ret = -1; 245 char value[PROP_VALUE_MAX]; 246 ret = __system_property_get("ro.debuggable", value); 247 if (ret < 0) 248 return ret; 249 return strcmp(value, "1") ? 0 : 1; 250 } 251 252 static int device_is_secure() { 253 int ret = -1; 254 char value[PROP_VALUE_MAX]; 255 ret = __system_property_get("ro.secure", value); 256 /* If error, we want to fail secure */ 257 if (ret < 0) 258 return 1; 259 return strcmp(value, "0") ? 1 : 0; 260 } 261 262 static int device_is_force_encrypted() { 263 int ret = -1; 264 char value[PROP_VALUE_MAX]; 265 ret = __system_property_get("ro.vold.forceencryption", value); 266 if (ret < 0) 267 return 0; 268 return strcmp(value, "1") ? 0 : 1; 269 } 270 271 /* 272 * Tries to mount any of the consecutive fstab entries that match 273 * the mountpoint of the one given by fstab->recs[start_idx]. 274 * 275 * end_idx: On return, will be the last rec that was looked at. 276 * attempted_idx: On return, will indicate which fstab rec 277 * succeeded. In case of failure, it will be the start_idx. 278 * Returns 279 * -1 on failure with errno set to match the 1st mount failure. 280 * 0 on success. 281 */ 282 static int mount_with_alternatives(struct fstab *fstab, int start_idx, int *end_idx, int *attempted_idx) 283 { 284 int i; 285 int mount_errno = 0; 286 int mounted = 0; 287 288 if (!end_idx || !attempted_idx || start_idx >= fstab->num_entries) { 289 errno = EINVAL; 290 if (end_idx) *end_idx = start_idx; 291 if (attempted_idx) *end_idx = start_idx; 292 return -1; 293 } 294 295 /* Hunt down an fstab entry for the same mount point that might succeed */ 296 for (i = start_idx; 297 /* We required that fstab entries for the same mountpoint be consecutive */ 298 i < fstab->num_entries && !strcmp(fstab->recs[start_idx].mount_point, fstab->recs[i].mount_point); 299 i++) { 300 /* 301 * Don't try to mount/encrypt the same mount point again. 302 * Deal with alternate entries for the same point which are required to be all following 303 * each other. 304 */ 305 if (mounted) { 306 ERROR("%s(): skipping fstab dup mountpoint=%s rec[%d].fs_type=%s already mounted as %s.\n", __func__, 307 fstab->recs[i].mount_point, i, fstab->recs[i].fs_type, fstab->recs[*attempted_idx].fs_type); 308 continue; 309 } 310 311 if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { 312 check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type, 313 fstab->recs[i].mount_point); 314 } 315 if (!__mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, &fstab->recs[i])) { 316 *attempted_idx = i; 317 mounted = 1; 318 if (i != start_idx) { 319 ERROR("%s(): Mounted %s on %s with fs_type=%s instead of %s\n", __func__, 320 fstab->recs[i].blk_device, fstab->recs[i].mount_point, fstab->recs[i].fs_type, 321 fstab->recs[start_idx].fs_type); 322 } 323 } else { 324 /* back up errno for crypto decisions */ 325 mount_errno = errno; 326 } 327 } 328 329 /* Adjust i for the case where it was still withing the recs[] */ 330 if (i < fstab->num_entries) --i; 331 332 *end_idx = i; 333 if (!mounted) { 334 *attempted_idx = start_idx; 335 errno = mount_errno; 336 return -1; 337 } 338 return 0; 339 } 340 341 /* When multiple fstab records share the same mount_point, it will 342 * try to mount each one in turn, and ignore any duplicates after a 343 * first successful mount. 344 * Returns -1 on error, and FS_MGR_MNTALL_* otherwise. 345 */ 346 int fs_mgr_mount_all(struct fstab *fstab) 347 { 348 int i = 0; 349 int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTED; 350 int error_count = 0; 351 int mret = -1; 352 int mount_errno = 0; 353 int attempted_idx = -1; 354 355 if (!fstab) { 356 return -1; 357 } 358 359 for (i = 0; i < fstab->num_entries; i++) { 360 /* Don't mount entries that are managed by vold */ 361 if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) { 362 continue; 363 } 364 365 /* Skip swap and raw partition entries such as boot, recovery, etc */ 366 if (!strcmp(fstab->recs[i].fs_type, "swap") || 367 !strcmp(fstab->recs[i].fs_type, "emmc") || 368 !strcmp(fstab->recs[i].fs_type, "mtd")) { 369 continue; 370 } 371 372 if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { 373 wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); 374 } 375 376 if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) { 377 int rc = fs_mgr_setup_verity(&fstab->recs[i]); 378 if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) { 379 INFO("Verity disabled"); 380 } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) { 381 ERROR("Could not set up verified partition, skipping!\n"); 382 continue; 383 } 384 } 385 int last_idx_inspected; 386 int top_idx = i; 387 388 mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx); 389 i = last_idx_inspected; 390 mount_errno = errno; 391 392 /* Deal with encryptability. */ 393 if (!mret) { 394 /* If this is encryptable, need to trigger encryption */ 395 if ( (fstab->recs[attempted_idx].fs_mgr_flags & MF_FORCECRYPT) 396 || (device_is_force_encrypted() 397 && fs_mgr_is_encryptable(&fstab->recs[attempted_idx]))) { 398 if (umount(fstab->recs[attempted_idx].mount_point) == 0) { 399 if (encryptable == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { 400 ERROR("Will try to encrypt %s %s\n", fstab->recs[attempted_idx].mount_point, 401 fstab->recs[attempted_idx].fs_type); 402 encryptable = FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION; 403 } else { 404 ERROR("Only one encryptable/encrypted partition supported\n"); 405 encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; 406 } 407 } else { 408 INFO("Could not umount %s - allow continue unencrypted\n", 409 fstab->recs[attempted_idx].mount_point); 410 continue; 411 } 412 } 413 /* Success! Go get the next one */ 414 continue; 415 } 416 417 /* mount(2) returned an error, handle the encryptable/formattable case */ 418 bool wiped = partition_wiped(fstab->recs[top_idx].blk_device); 419 if (mret && mount_errno != EBUSY && mount_errno != EACCES && 420 fs_mgr_is_formattable(&fstab->recs[top_idx]) && wiped) { 421 /* top_idx and attempted_idx point at the same partition, but sometimes 422 * at two different lines in the fstab. Use the top one for formatting 423 * as that is the preferred one. 424 */ 425 ERROR("%s(): %s is wiped and %s %s is formattable. Format it.\n", __func__, 426 fstab->recs[top_idx].blk_device, fstab->recs[top_idx].mount_point, 427 fstab->recs[top_idx].fs_type); 428 if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) && 429 strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) { 430 int fd = open(fstab->recs[top_idx].key_loc, O_WRONLY, 0644); 431 if (fd >= 0) { 432 INFO("%s(): also wipe %s\n", __func__, fstab->recs[top_idx].key_loc); 433 wipe_block_device(fd, get_file_size(fd)); 434 close(fd); 435 } else { 436 ERROR("%s(): %s wouldn't open (%s)\n", __func__, 437 fstab->recs[top_idx].key_loc, strerror(errno)); 438 } 439 } 440 if (fs_mgr_do_format(&fstab->recs[top_idx]) == 0) { 441 /* Let's replay the mount actions. */ 442 i = top_idx - 1; 443 continue; 444 } 445 } 446 if (mret && mount_errno != EBUSY && mount_errno != EACCES && 447 fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) { 448 if (wiped) { 449 ERROR("%s(): %s is wiped and %s %s is encryptable. Suggest recovery...\n", __func__, 450 fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, 451 fstab->recs[attempted_idx].fs_type); 452 encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY; 453 continue; 454 } else { 455 /* Need to mount a tmpfs at this mountpoint for now, and set 456 * properties that vold will query later for decrypting 457 */ 458 ERROR("%s(): possibly an encryptable blkdev %s for mount %s type %s )\n", __func__, 459 fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, 460 fstab->recs[attempted_idx].fs_type); 461 if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) { 462 ++error_count; 463 continue; 464 } 465 } 466 encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; 467 } else { 468 ERROR("Failed to mount an un-encryptable or wiped partition on" 469 "%s at %s options: %s error: %s\n", 470 fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, 471 fstab->recs[attempted_idx].fs_options, strerror(mount_errno)); 472 ++error_count; 473 continue; 474 } 475 } 476 477 if (error_count) { 478 return -1; 479 } else { 480 return encryptable; 481 } 482 } 483 484 /* If tmp_mount_point is non-null, mount the filesystem there. This is for the 485 * tmp mount we do to check the user password 486 * If multiple fstab entries are to be mounted on "n_name", it will try to mount each one 487 * in turn, and stop on 1st success, or no more match. 488 */ 489 int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device, 490 char *tmp_mount_point) 491 { 492 int i = 0; 493 int ret = FS_MGR_DOMNT_FAILED; 494 int mount_errors = 0; 495 int first_mount_errno = 0; 496 char *m; 497 498 if (!fstab) { 499 return ret; 500 } 501 502 for (i = 0; i < fstab->num_entries; i++) { 503 if (!fs_match(fstab->recs[i].mount_point, n_name)) { 504 continue; 505 } 506 507 /* We found our match */ 508 /* If this swap or a raw partition, report an error */ 509 if (!strcmp(fstab->recs[i].fs_type, "swap") || 510 !strcmp(fstab->recs[i].fs_type, "emmc") || 511 !strcmp(fstab->recs[i].fs_type, "mtd")) { 512 ERROR("Cannot mount filesystem of type %s on %s\n", 513 fstab->recs[i].fs_type, n_blk_device); 514 goto out; 515 } 516 517 /* First check the filesystem if requested */ 518 if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { 519 wait_for_file(n_blk_device, WAIT_TIMEOUT); 520 } 521 522 if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { 523 check_fs(n_blk_device, fstab->recs[i].fs_type, 524 fstab->recs[i].mount_point); 525 } 526 527 if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) { 528 int rc = fs_mgr_setup_verity(&fstab->recs[i]); 529 if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) { 530 INFO("Verity disabled"); 531 } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) { 532 ERROR("Could not set up verified partition, skipping!\n"); 533 continue; 534 } 535 } 536 537 /* Now mount it where requested */ 538 if (tmp_mount_point) { 539 m = tmp_mount_point; 540 } else { 541 m = fstab->recs[i].mount_point; 542 } 543 if (__mount(n_blk_device, m, &fstab->recs[i])) { 544 if (!first_mount_errno) first_mount_errno = errno; 545 mount_errors++; 546 continue; 547 } else { 548 ret = 0; 549 goto out; 550 } 551 } 552 if (mount_errors) { 553 ERROR("Cannot mount filesystem on %s at %s. error: %s\n", 554 n_blk_device, m, strerror(first_mount_errno)); 555 if (first_mount_errno == EBUSY) { 556 ret = FS_MGR_DOMNT_BUSY; 557 } else { 558 ret = FS_MGR_DOMNT_FAILED; 559 } 560 } else { 561 /* We didn't find a match, say so and return an error */ 562 ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point); 563 } 564 565 out: 566 return ret; 567 } 568 569 /* 570 * mount a tmpfs filesystem at the given point. 571 * return 0 on success, non-zero on failure. 572 */ 573 int fs_mgr_do_tmpfs_mount(char *n_name) 574 { 575 int ret; 576 577 ret = mount("tmpfs", n_name, "tmpfs", 578 MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS); 579 if (ret < 0) { 580 ERROR("Cannot mount tmpfs filesystem at %s\n", n_name); 581 return -1; 582 } 583 584 /* Success */ 585 return 0; 586 } 587 588 int fs_mgr_unmount_all(struct fstab *fstab) 589 { 590 int i = 0; 591 int ret = 0; 592 593 if (!fstab) { 594 return -1; 595 } 596 597 while (fstab->recs[i].blk_device) { 598 if (umount(fstab->recs[i].mount_point)) { 599 ERROR("Cannot unmount filesystem at %s\n", fstab->recs[i].mount_point); 600 ret = -1; 601 } 602 i++; 603 } 604 605 return ret; 606 } 607 608 /* This must be called after mount_all, because the mkswap command needs to be 609 * available. 610 */ 611 int fs_mgr_swapon_all(struct fstab *fstab) 612 { 613 int i = 0; 614 int flags = 0; 615 int err = 0; 616 int ret = 0; 617 int status; 618 char *mkswap_argv[2] = { 619 MKSWAP_BIN, 620 NULL 621 }; 622 623 if (!fstab) { 624 return -1; 625 } 626 627 for (i = 0; i < fstab->num_entries; i++) { 628 /* Skip non-swap entries */ 629 if (strcmp(fstab->recs[i].fs_type, "swap")) { 630 continue; 631 } 632 633 if (fstab->recs[i].zram_size > 0) { 634 /* A zram_size was specified, so we need to configure the 635 * device. There is no point in having multiple zram devices 636 * on a system (all the memory comes from the same pool) so 637 * we can assume the device number is 0. 638 */ 639 FILE *zram_fp; 640 641 zram_fp = fopen(ZRAM_CONF_DEV, "r+"); 642 if (zram_fp == NULL) { 643 ERROR("Unable to open zram conf device %s\n", ZRAM_CONF_DEV); 644 ret = -1; 645 continue; 646 } 647 fprintf(zram_fp, "%d\n", fstab->recs[i].zram_size); 648 fclose(zram_fp); 649 } 650 651 if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { 652 wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); 653 } 654 655 /* Initialize the swap area */ 656 mkswap_argv[1] = fstab->recs[i].blk_device; 657 err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv), mkswap_argv, 658 &status, true, LOG_KLOG, false, NULL); 659 if (err) { 660 ERROR("mkswap failed for %s\n", fstab->recs[i].blk_device); 661 ret = -1; 662 continue; 663 } 664 665 /* If -1, then no priority was specified in fstab, so don't set 666 * SWAP_FLAG_PREFER or encode the priority */ 667 if (fstab->recs[i].swap_prio >= 0) { 668 flags = (fstab->recs[i].swap_prio << SWAP_FLAG_PRIO_SHIFT) & 669 SWAP_FLAG_PRIO_MASK; 670 flags |= SWAP_FLAG_PREFER; 671 } else { 672 flags = 0; 673 } 674 err = swapon(fstab->recs[i].blk_device, flags); 675 if (err) { 676 ERROR("swapon failed for %s\n", fstab->recs[i].blk_device); 677 ret = -1; 678 } 679 } 680 681 return ret; 682 } 683 684 /* 685 * key_loc must be at least PROPERTY_VALUE_MAX bytes long 686 * 687 * real_blk_device must be at least PROPERTY_VALUE_MAX bytes long 688 */ 689 int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_device, int size) 690 { 691 int i = 0; 692 693 if (!fstab) { 694 return -1; 695 } 696 /* Initialize return values to null strings */ 697 if (key_loc) { 698 *key_loc = '\0'; 699 } 700 if (real_blk_device) { 701 *real_blk_device = '\0'; 702 } 703 704 /* Look for the encryptable partition to find the data */ 705 for (i = 0; i < fstab->num_entries; i++) { 706 /* Don't deal with vold managed enryptable partitions here */ 707 if (fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) { 708 continue; 709 } 710 if (!(fstab->recs[i].fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT))) { 711 continue; 712 } 713 714 /* We found a match */ 715 if (key_loc) { 716 strlcpy(key_loc, fstab->recs[i].key_loc, size); 717 } 718 if (real_blk_device) { 719 strlcpy(real_blk_device, fstab->recs[i].blk_device, size); 720 } 721 break; 722 } 723 724 return 0; 725 } 726