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 */
gettime(void)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
wait_for_file(const char * filename,int timeout)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
check_fs(char * blk_device,char * fs_type,char * target)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
remove_trailing_slashes(char * n)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 */
fs_set_blk_ro(const char * blockdev)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 */
__mount(const char * source,const char * target,const struct fstab_rec * rec)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
fs_match(char * in1,char * in2)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
device_is_debuggable()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
device_is_secure()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
device_is_force_encrypted()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 */
mount_with_alternatives(struct fstab * fstab,int start_idx,int * end_idx,int * attempted_idx)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 */
fs_mgr_mount_all(struct fstab * fstab)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 */
fs_mgr_do_mount(struct fstab * fstab,char * n_name,char * n_blk_device,char * tmp_mount_point)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 */
fs_mgr_do_tmpfs_mount(char * n_name)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
fs_mgr_unmount_all(struct fstab * fstab)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 */
fs_mgr_swapon_all(struct fstab * fstab)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 */
fs_mgr_get_crypt_info(struct fstab * fstab,char * key_loc,char * real_blk_device,int size)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