/* * key_loc must be at least PROPERTY_VALUE_MAX bytes long * * real_blk_dev must be at least PROPERTY_VALUE_MAX bytes long */ int fs_mgr_get_crypt_info(char *fstab_file, char *key_loc, char *real_blk_dev, int size) { int i = 0; struct fstab_rec *fstab = 0; if (!(fstab = read_fstab(fstab_file))) { return -1; } /* Initialize return values to null strings */ if (key_loc) { *key_loc = '\0'; } if (real_blk_dev) { *real_blk_dev = '\0'; } /* Look for the encryptable partition to find the data */ for (i = 0; fstab[i].blk_dev; i++) { if (!(fstab[i].fs_mgr_flags & MF_CRYPT)) { continue; } /* We found a match */ if (key_loc) { strlcpy(key_loc, fstab[i].key_loc, size); } if (real_blk_dev) { strlcpy(real_blk_dev, fstab[i].blk_dev, size); } break; } free_fstab(fstab); return 0; }
static struct mntentchn * fstab_head(void) { if (!got_fstab) read_fstab(); return &fstab; }
int fs_mgr_mount_all(char *fstab_file) { int i = 0; int encrypted = 0; int ret = -1; int mret; struct fstab_rec *fstab = 0; if (!(fstab = read_fstab(fstab_file))) { return ret; } for (i = 0; fstab[i].blk_dev; i++) { if (fstab[i].fs_mgr_flags & MF_WAIT) { wait_for_file(fstab[i].blk_dev, WAIT_TIMEOUT); } if (fstab[i].fs_mgr_flags & MF_CHECK) { check_fs(fstab[i].blk_dev, fstab[i].type, fstab[i].mnt_point); } mret = mount(fstab[i].blk_dev, fstab[i].mnt_point, fstab[i].type, fstab[i].flags, fstab[i].fs_options); if (!mret) { /* Success! Go get the next one */ continue; } /* mount(2) returned an error, check if it's encrypted and deal with it */ if ((fstab[i].fs_mgr_flags & MF_CRYPT) && !partition_wiped(fstab[i].blk_dev)) { /* Need to mount a tmpfs at this mountpoint for now, and set * properties that vold will query later for decrypting */ if (mount("tmpfs", fstab[i].mnt_point, "tmpfs", MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS) < 0) { ERROR("Cannot mount tmpfs filesystem for encrypted fs at %s\n", fstab[i].mnt_point); goto out; } encrypted = 1; } else { ERROR("Cannot mount filesystem on %s at %s\n", fstab[i].blk_dev, fstab[i].mnt_point); goto out; } } if (encrypted) { ret = 1; } else { ret = 0; } out: free_fstab(fstab); return ret; }
int main(int argc, char** argv) { const char* input_path; const char* map_file; if (argc != 3 && argc != 1 && (argc == 2 && strcmp(argv[1], "--reboot") != 0)) { fprintf(stderr, "usage: %s [--reboot] [<transform_path> <map_file>]\n", argv[0]); return 2; } // When uncrypt is started with "--reboot", it wipes misc and reboots. // Otherwise it uncrypts the package and writes the block map. if (argc == 2) { if (read_fstab() == NULL) { return 1; } wipe_misc(); reboot_to_recovery(); } else { // The pipe has been created by the system server. int status_fd = open(status_file.c_str(), O_WRONLY | O_CREAT | O_SYNC, S_IRUSR | S_IWUSR); if (status_fd == -1) { ALOGE("failed to open pipe \"%s\": %s\n", status_file.c_str(), strerror(errno)); return 1; } if (argc == 3) { // when command-line args are given this binary is being used // for debugging. input_path = argv[1]; map_file = argv[2]; } else { std::string package; if (!find_uncrypt_package(package)) { android::base::WriteStringToFd("-1\n", status_fd); close(status_fd); return 1; } input_path = package.c_str(); map_file = cache_block_map.c_str(); } int status = uncrypt(input_path, map_file, status_fd); if (status != 0) { android::base::WriteStringToFd("-1\n", status_fd); close(status_fd); return 1; } android::base::WriteStringToFd("100\n", status_fd); close(status_fd); } return 0; }
static std::string get_misc_blk_device() { struct fstab* fstab = read_fstab(); if (fstab == nullptr) { return ""; } for (int i = 0; i < fstab->num_entries; ++i) { fstab_rec* v = &fstab->recs[i]; if (v->mount_point != nullptr && strcmp(v->mount_point, "/misc") == 0) { return v->blk_device; } } return ""; }
/* If tmp_mnt_point is non-null, mount the filesystem there. This is for the * tmp mount we do to check the user password */ int fs_mgr_do_mount(char *fstab_file, char *n_name, char *n_blk_dev, char *tmp_mnt_point) { int i = 0; int ret = -1; struct fstab_rec *fstab = 0; char *m; if (!(fstab = read_fstab(fstab_file))) { return ret; } for (i = 0; fstab[i].blk_dev; i++) { if (!fs_match(fstab[i].mnt_point, n_name)) { continue; } /* We found our match */ /* First check the filesystem if requested */ if (fstab[i].fs_mgr_flags & MF_WAIT) { wait_for_file(fstab[i].blk_dev, WAIT_TIMEOUT); } if (fstab[i].fs_mgr_flags & MF_CHECK) { check_fs(fstab[i].blk_dev, fstab[i].type, fstab[i].mnt_point); } /* Now mount it where requested */ if (tmp_mnt_point) { m = tmp_mnt_point; } else { m = fstab[i].mnt_point; } if (mount(n_blk_dev, m, fstab[i].type, fstab[i].flags, fstab[i].fs_options)) { ERROR("Cannot mount filesystem on %s at %s\n", n_blk_dev, m); goto out; } else { ret = 0; goto out; } } /* We didn't find a match, say so and return an error */ ERROR("Cannot find mount point %s in fstab\n", fstab[i].mnt_point); out: free_fstab(fstab); return ret; }
static int uncrypt(const char* input_path, const char* map_file, int status_fd) { ALOGI("update package is \"%s\"", input_path); // Turn the name of the file we're supposed to convert into an // absolute path, so we can find what filesystem it's on. char path[PATH_MAX+1]; if (realpath(input_path, path) == NULL) { ALOGE("failed to convert \"%s\" to absolute path: %s", input_path, strerror(errno)); return 1; } if (read_fstab() == NULL) { return 1; } bool encryptable; bool encrypted; const char* blk_dev = find_block_device(path, &encryptable, &encrypted); if (blk_dev == NULL) { ALOGE("failed to find block device for %s", path); return 1; } // If the filesystem it's on isn't encrypted, we only produce the // block map, we don't rewrite the file contents (it would be // pointless to do so). ALOGI("encryptable: %s", encryptable ? "yes" : "no"); ALOGI(" encrypted: %s", encrypted ? "yes" : "no"); // Recovery supports installing packages from 3 paths: /cache, // /data, and /sdcard. (On a particular device, other locations // may work, but those are three we actually expect.) // // On /data we want to convert the file to a block map so that we // can read the package without mounting the partition. On /cache // and /sdcard we leave the file alone. if (strncmp(path, "/data/", 6) == 0) { ALOGI("writing block map %s", map_file); if (produce_block_map(path, map_file, blk_dev, encrypted, status_fd) != 0) { return 1; } } return 0; }
int fs_mgr_unmount_all(char *fstab_file) { int i = 0; int ret = 0; struct fstab_rec *fstab = 0; if (!(fstab = read_fstab(fstab_file))) { return -1; } while (fstab[i].blk_dev) { if (umount(fstab[i].mnt_point)) { ERROR("Cannot unmount filesystem at %s\n", fstab[i].mnt_point); ret = -1; } i++; } free_fstab(fstab); return ret; }
int main(int argc, char** argv) { enum { UNCRYPT, SETUP_BCB, CLEAR_BCB, UNCRYPT_DEBUG } action; const char* input_path = nullptr; const char* map_file = CACHE_BLOCK_MAP.c_str(); if (argc == 2 && strcmp(argv[1], "--clear-bcb") == 0) { action = CLEAR_BCB; } else if (argc == 2 && strcmp(argv[1], "--setup-bcb") == 0) { action = SETUP_BCB; } else if (argc == 1) { action = UNCRYPT; } else if (argc == 3) { input_path = argv[1]; map_file = argv[2]; action = UNCRYPT_DEBUG; } else { usage(argv[0]); return 2; } if ((fstab = read_fstab()) == nullptr) { log_uncrypt_error_code(kUncryptFstabReadError); return 1; } if (action == UNCRYPT_DEBUG) { LOG(INFO) << "uncrypt called in debug mode, skip socket communication"; bool success = uncrypt_wrapper(input_path, map_file, -1); if (success) { LOG(INFO) << "uncrypt succeeded"; } else{ LOG(INFO) << "uncrypt failed"; } return success ? 0 : 1; } // c3. The socket is created by init when starting the service. uncrypt // will use the socket to communicate with its caller. android::base::unique_fd service_socket(android_get_control_socket(UNCRYPT_SOCKET.c_str())); if (service_socket == -1) { PLOG(ERROR) << "failed to open socket \"" << UNCRYPT_SOCKET << "\""; log_uncrypt_error_code(kUncryptSocketOpenError); return 1; } fcntl(service_socket, F_SETFD, FD_CLOEXEC); if (listen(service_socket, 1) == -1) { PLOG(ERROR) << "failed to listen on socket " << service_socket.get(); log_uncrypt_error_code(kUncryptSocketListenError); return 1; } android::base::unique_fd socket_fd(accept4(service_socket, nullptr, nullptr, SOCK_CLOEXEC)); if (socket_fd == -1) { PLOG(ERROR) << "failed to accept on socket " << service_socket.get(); log_uncrypt_error_code(kUncryptSocketAcceptError); return 1; } bool success = false; switch (action) { case UNCRYPT: success = uncrypt_wrapper(input_path, map_file, socket_fd); break; case SETUP_BCB: success = setup_bcb(socket_fd); break; case CLEAR_BCB: success = clear_bcb(socket_fd); break; default: // Should never happen. LOG(ERROR) << "Invalid uncrypt action code: " << action; return 1; } // c13. Read a 4-byte code from the client before uncrypt exits. This is to // ensure the client to receive the last status code before the socket gets // destroyed. int code; if (android::base::ReadFully(socket_fd, &code, 4)) { LOG(INFO) << " received " << code << ", exiting now"; } else { PLOG(ERROR) << "failed to read the code"; } return success ? 0 : 1; }
int main(int argc, char** argv) { const char* input_path; const char* map_file; int do_reboot = 1; if (argc != 1 && argc != 3) { fprintf(stderr, "usage: %s [<transform_path> <map_file>]\n", argv[0]); return 2; } if (argc == 3) { // when command-line args are given this binary is being used // for debugging; don't reboot to recovery at the end. input_path = argv[1]; map_file = argv[2]; do_reboot = 0; } else { input_path = parse_recovery_command_file(); if (input_path == NULL) { // if we're rebooting to recovery without a package (say, // to wipe data), then we don't need to do anything before // going to recovery. ALOGI("no recovery command file or no update package arg"); reboot_to_recovery(); return 1; } map_file = CACHE_BLOCK_MAP; } ALOGI("update package is %s", input_path); // Turn the name of the file we're supposed to convert into an // absolute path, so we can find what filesystem it's on. char path[PATH_MAX+1]; if (realpath(input_path, path) == NULL) { ALOGE("failed to convert %s to absolute path: %s", input_path, strerror(errno)); return 1; } int encryptable; int encrypted; if (read_fstab() == NULL) { return 1; } const char* blk_dev = find_block_device(path, &encryptable, &encrypted); if (blk_dev == NULL) { ALOGE("failed to find block device for %s", path); return 1; } // If the filesystem it's on isn't encrypted, we only produce the // block map, we don't rewrite the file contents (it would be // pointless to do so). ALOGI("encryptable: %s\n", encryptable ? "yes" : "no"); ALOGI(" encrypted: %s\n", encrypted ? "yes" : "no"); // Recovery supports installing packages from 3 paths: /cache, // /data, and /sdcard. (On a particular device, other locations // may work, but those are three we actually expect.) // // On /data we want to convert the file to a block map so that we // can read the package without mounting the partition. On /cache // and /sdcard we leave the file alone. if (strncmp(path, "/data/", 6) != 0) { // path does not start with "/data/"; leave it alone. unlink(RECOVERY_COMMAND_FILE_TMP); } else { ALOGI("writing block map %s", map_file); if (produce_block_map(path, map_file, blk_dev, encrypted) != 0) { return 1; } } wipe_misc(); rename(RECOVERY_COMMAND_FILE_TMP, RECOVERY_COMMAND_FILE); if (do_reboot) reboot_to_recovery(); return 0; }