Example #1
0
/*
 * 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;
}
Example #2
0
static struct mntentchn *
fstab_head(void)
{
	if (!got_fstab)
		read_fstab();
	return &fstab;
}
Example #3
0
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 "";
}
Example #6
0
/* 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;
}
Example #8
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;
}
Example #9
0
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;
}
Example #10
0
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;
}