fs_mgr.c revision 28483d7ec497e06850be1d8f87d7fa522c8ab9d4
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/partition_utils.h> 35#include <cutils/properties.h> 36#include <logwrap/logwrap.h> 37 38#include "mincrypt/rsa.h" 39#include "mincrypt/sha.h" 40#include "mincrypt/sha256.h" 41 42#include "fs_mgr_priv.h" 43#include "fs_mgr_priv_verity.h" 44 45#define KEY_LOC_PROP "ro.crypto.keyfile.userdata" 46#define KEY_IN_FOOTER "footer" 47 48#define E2FSCK_BIN "/system/bin/e2fsck" 49#define MKSWAP_BIN "/system/bin/mkswap" 50 51#define FSCK_LOG_FILE "/dev/fscklogs/log" 52 53#define ZRAM_CONF_DEV "/sys/block/zram0/disksize" 54 55#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) 56 57/* 58 * gettime() - returns the time in seconds of the system's monotonic clock or 59 * zero on error. 60 */ 61static time_t gettime(void) 62{ 63 struct timespec ts; 64 int ret; 65 66 ret = clock_gettime(CLOCK_MONOTONIC, &ts); 67 if (ret < 0) { 68 ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno)); 69 return 0; 70 } 71 72 return ts.tv_sec; 73} 74 75static int wait_for_file(const char *filename, int timeout) 76{ 77 struct stat info; 78 time_t timeout_time = gettime() + timeout; 79 int ret = -1; 80 81 while (gettime() < timeout_time && ((ret = stat(filename, &info)) < 0)) 82 usleep(10000); 83 84 return ret; 85} 86 87static void check_fs(char *blk_device, char *fs_type, char *target) 88{ 89 int status; 90 int ret; 91 long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID; 92 char *tmpmnt_opts = "nomblk_io_submit,errors=remount-ro"; 93 char *e2fsck_argv[] = { 94 E2FSCK_BIN, 95 "-y", 96 blk_device 97 }; 98 99 /* Check for the types of filesystems we know how to check */ 100 if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) { 101 /* 102 * First try to mount and unmount the filesystem. We do this because 103 * the kernel is more efficient than e2fsck in running the journal and 104 * processing orphaned inodes, and on at least one device with a 105 * performance issue in the emmc firmware, it can take e2fsck 2.5 minutes 106 * to do what the kernel does in about a second. 107 * 108 * After mounting and unmounting the filesystem, run e2fsck, and if an 109 * error is recorded in the filesystem superblock, e2fsck will do a full 110 * check. Otherwise, it does nothing. If the kernel cannot mount the 111 * filesytsem due to an error, e2fsck is still run to do a full check 112 * fix the filesystem. 113 */ 114 ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts); 115 if (!ret) { 116 umount(target); 117 } 118 119 /* 120 * Some system images do not have e2fsck for licensing reasons 121 * (e.g. recent SDK system images). Detect these and skip the check. 122 */ 123 if (access(E2FSCK_BIN, X_OK)) { 124 INFO("Not running %s on %s (executable not in system image)\n", 125 E2FSCK_BIN, blk_device); 126 } else { 127 INFO("Running %s on %s\n", E2FSCK_BIN, blk_device); 128 129 ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv), e2fsck_argv, 130 &status, true, LOG_KLOG | LOG_FILE, 131 true, FSCK_LOG_FILE); 132 133 if (ret < 0) { 134 /* No need to check for error in fork, we can't really handle it now */ 135 ERROR("Failed trying to run %s\n", E2FSCK_BIN); 136 } 137 } 138 } 139 140 return; 141} 142 143static void remove_trailing_slashes(char *n) 144{ 145 int len; 146 147 len = strlen(n) - 1; 148 while ((*(n + len) == '/') && len) { 149 *(n + len) = '\0'; 150 len--; 151 } 152} 153 154/* 155 * Mark the given block device as read-only, using the BLKROSET ioctl. 156 * Return 0 on success, and -1 on error. 157 */ 158static void fs_set_blk_ro(const char *blockdev) 159{ 160 int fd; 161 int ON = 1; 162 163 fd = open(blockdev, O_RDONLY); 164 if (fd < 0) { 165 // should never happen 166 return; 167 } 168 169 ioctl(fd, BLKROSET, &ON); 170 close(fd); 171} 172 173/* 174 * __mount(): wrapper around the mount() system call which also 175 * sets the underlying block device to read-only if the mount is read-only. 176 * See "man 2 mount" for return values. 177 */ 178static int __mount(const char *source, const char *target, 179 const char *filesystemtype, unsigned long mountflags, 180 const void *data) 181{ 182 int ret = mount(source, target, filesystemtype, mountflags, data); 183 184 if ((ret == 0) && (mountflags & MS_RDONLY) != 0) { 185 fs_set_blk_ro(source); 186 } 187 188 return ret; 189} 190 191static int fs_match(char *in1, char *in2) 192{ 193 char *n1; 194 char *n2; 195 int ret; 196 197 n1 = strdup(in1); 198 n2 = strdup(in2); 199 200 remove_trailing_slashes(n1); 201 remove_trailing_slashes(n2); 202 203 ret = !strcmp(n1, n2); 204 205 free(n1); 206 free(n2); 207 208 return ret; 209} 210 211int fs_mgr_mount_all(struct fstab *fstab) 212{ 213 int i = 0; 214 int encrypted = 0; 215 int ret = -1; 216 int mret; 217 int mount_errno; 218 219 if (!fstab) { 220 return ret; 221 } 222 223 for (i = 0; i < fstab->num_entries; i++) { 224 /* Don't mount entries that are managed by vold */ 225 if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) { 226 continue; 227 } 228 229 /* Skip swap and raw partition entries such as boot, recovery, etc */ 230 if (!strcmp(fstab->recs[i].fs_type, "swap") || 231 !strcmp(fstab->recs[i].fs_type, "emmc") || 232 !strcmp(fstab->recs[i].fs_type, "mtd")) { 233 continue; 234 } 235 236 if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { 237 wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); 238 } 239 240 if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { 241 check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type, 242 fstab->recs[i].mount_point); 243 } 244 245 if (fstab->recs[i].fs_mgr_flags & MF_VERIFY) { 246 if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) { 247 ERROR("Could not set up verified partition, skipping!"); 248 continue; 249 } 250 } 251 252 mret = __mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, 253 fstab->recs[i].fs_type, fstab->recs[i].flags, 254 fstab->recs[i].fs_options); 255 256 if (!mret) { 257 /* Success! Go get the next one */ 258 continue; 259 } 260 261 /* back up errno as partition_wipe clobbers the value */ 262 mount_errno = errno; 263 264 /* mount(2) returned an error, check if it's encrypted and deal with it */ 265 if ((fstab->recs[i].fs_mgr_flags & MF_CRYPT) && 266 !partition_wiped(fstab->recs[i].blk_device)) { 267 /* Need to mount a tmpfs at this mountpoint for now, and set 268 * properties that vold will query later for decrypting 269 */ 270 if (mount("tmpfs", fstab->recs[i].mount_point, "tmpfs", 271 MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS) < 0) { 272 ERROR("Cannot mount tmpfs filesystem for encrypted fs at %s error: %s\n", 273 fstab->recs[i].mount_point, strerror(errno)); 274 goto out; 275 } 276 encrypted = 1; 277 } else { 278 ERROR("Failed to mount an un-encryptable or wiped partition on" 279 "%s at %s options: %s error: %s\n", 280 fstab->recs[i].blk_device, fstab->recs[i].mount_point, 281 fstab->recs[i].fs_options, strerror(mount_errno)); 282 goto out; 283 } 284 } 285 286 if (encrypted) { 287 ret = 1; 288 } else { 289 ret = 0; 290 } 291 292out: 293 return ret; 294} 295 296/* If tmp_mount_point is non-null, mount the filesystem there. This is for the 297 * tmp mount we do to check the user password 298 */ 299int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device, 300 char *tmp_mount_point) 301{ 302 int i = 0; 303 int ret = -1; 304 char *m; 305 306 if (!fstab) { 307 return ret; 308 } 309 310 for (i = 0; i < fstab->num_entries; i++) { 311 if (!fs_match(fstab->recs[i].mount_point, n_name)) { 312 continue; 313 } 314 315 /* We found our match */ 316 /* If this swap or a raw partition, report an error */ 317 if (!strcmp(fstab->recs[i].fs_type, "swap") || 318 !strcmp(fstab->recs[i].fs_type, "emmc") || 319 !strcmp(fstab->recs[i].fs_type, "mtd")) { 320 ERROR("Cannot mount filesystem of type %s on %s\n", 321 fstab->recs[i].fs_type, n_blk_device); 322 goto out; 323 } 324 325 /* First check the filesystem if requested */ 326 if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { 327 wait_for_file(n_blk_device, WAIT_TIMEOUT); 328 } 329 330 if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { 331 check_fs(n_blk_device, fstab->recs[i].fs_type, 332 fstab->recs[i].mount_point); 333 } 334 335 if (fstab->recs[i].fs_mgr_flags & MF_VERIFY) { 336 if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) { 337 ERROR("Could not set up verified partition, skipping!"); 338 continue; 339 } 340 } 341 342 /* Now mount it where requested */ 343 if (tmp_mount_point) { 344 m = tmp_mount_point; 345 } else { 346 m = fstab->recs[i].mount_point; 347 } 348 if (__mount(n_blk_device, m, fstab->recs[i].fs_type, 349 fstab->recs[i].flags, fstab->recs[i].fs_options)) { 350 ERROR("Cannot mount filesystem on %s at %s options: %s error: %s\n", 351 n_blk_device, m, fstab->recs[i].fs_options, strerror(errno)); 352 goto out; 353 } else { 354 ret = 0; 355 goto out; 356 } 357 } 358 359 /* We didn't find a match, say so and return an error */ 360 ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point); 361 362out: 363 return ret; 364} 365 366/* 367 * mount a tmpfs filesystem at the given point. 368 * return 0 on success, non-zero on failure. 369 */ 370int fs_mgr_do_tmpfs_mount(char *n_name) 371{ 372 int ret; 373 374 ret = mount("tmpfs", n_name, "tmpfs", 375 MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS); 376 if (ret < 0) { 377 ERROR("Cannot mount tmpfs filesystem at %s\n", n_name); 378 return -1; 379 } 380 381 /* Success */ 382 return 0; 383} 384 385int fs_mgr_unmount_all(struct fstab *fstab) 386{ 387 int i = 0; 388 int ret = 0; 389 390 if (!fstab) { 391 return -1; 392 } 393 394 while (fstab->recs[i].blk_device) { 395 if (umount(fstab->recs[i].mount_point)) { 396 ERROR("Cannot unmount filesystem at %s\n", fstab->recs[i].mount_point); 397 ret = -1; 398 } 399 i++; 400 } 401 402 return ret; 403} 404 405/* This must be called after mount_all, because the mkswap command needs to be 406 * available. 407 */ 408int fs_mgr_swapon_all(struct fstab *fstab) 409{ 410 int i = 0; 411 int flags = 0; 412 int err = 0; 413 int ret = 0; 414 int status; 415 char *mkswap_argv[2] = { 416 MKSWAP_BIN, 417 NULL 418 }; 419 420 if (!fstab) { 421 return -1; 422 } 423 424 for (i = 0; i < fstab->num_entries; i++) { 425 /* Skip non-swap entries */ 426 if (strcmp(fstab->recs[i].fs_type, "swap")) { 427 continue; 428 } 429 430 if (fstab->recs[i].zram_size > 0) { 431 /* A zram_size was specified, so we need to configure the 432 * device. There is no point in having multiple zram devices 433 * on a system (all the memory comes from the same pool) so 434 * we can assume the device number is 0. 435 */ 436 FILE *zram_fp; 437 438 zram_fp = fopen(ZRAM_CONF_DEV, "r+"); 439 if (zram_fp == NULL) { 440 ERROR("Unable to open zram conf device " ZRAM_CONF_DEV); 441 ret = -1; 442 continue; 443 } 444 fprintf(zram_fp, "%d\n", fstab->recs[i].zram_size); 445 fclose(zram_fp); 446 } 447 448 if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { 449 wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); 450 } 451 452 /* Initialize the swap area */ 453 mkswap_argv[1] = fstab->recs[i].blk_device; 454 err = android_fork_execvp_ext(ARRAY_SIZE(mkswap_argv), mkswap_argv, 455 &status, true, LOG_KLOG, false, NULL); 456 if (err) { 457 ERROR("mkswap failed for %s\n", fstab->recs[i].blk_device); 458 ret = -1; 459 continue; 460 } 461 462 /* If -1, then no priority was specified in fstab, so don't set 463 * SWAP_FLAG_PREFER or encode the priority */ 464 if (fstab->recs[i].swap_prio >= 0) { 465 flags = (fstab->recs[i].swap_prio << SWAP_FLAG_PRIO_SHIFT) & 466 SWAP_FLAG_PRIO_MASK; 467 flags |= SWAP_FLAG_PREFER; 468 } else { 469 flags = 0; 470 } 471 err = swapon(fstab->recs[i].blk_device, flags); 472 if (err) { 473 ERROR("swapon failed for %s\n", fstab->recs[i].blk_device); 474 ret = -1; 475 } 476 } 477 478 return ret; 479} 480 481/* 482 * key_loc must be at least PROPERTY_VALUE_MAX bytes long 483 * 484 * real_blk_device must be at least PROPERTY_VALUE_MAX bytes long 485 */ 486int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_device, int size) 487{ 488 int i = 0; 489 490 if (!fstab) { 491 return -1; 492 } 493 /* Initialize return values to null strings */ 494 if (key_loc) { 495 *key_loc = '\0'; 496 } 497 if (real_blk_device) { 498 *real_blk_device = '\0'; 499 } 500 501 /* Look for the encryptable partition to find the data */ 502 for (i = 0; i < fstab->num_entries; i++) { 503 /* Don't deal with vold managed enryptable partitions here */ 504 if (fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) { 505 continue; 506 } 507 if (!(fstab->recs[i].fs_mgr_flags & MF_CRYPT)) { 508 continue; 509 } 510 511 /* We found a match */ 512 if (key_loc) { 513 strlcpy(key_loc, fstab->recs[i].key_loc, size); 514 } 515 if (real_blk_device) { 516 strlcpy(real_blk_device, fstab->recs[i].blk_device, size); 517 } 518 break; 519 } 520 521 return 0; 522} 523