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