diff options
author | Eric Biggers <ebiggers@google.com> | 2019-09-05 22:51:17 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2019-09-05 22:51:17 +0000 |
commit | 59e1ab234c160684401b038fdb0111cfa92a73f9 (patch) | |
tree | 5b5aaa93be66ff578ae5c9278d2094b923a893ca | |
parent | 3342738e82b07afeccf0bc9962ff047093335a1f (diff) | |
parent | b90150822eb92fa2f8148d1951aa6c57869ab716 (diff) | |
download | extras-59e1ab234c160684401b038fdb0111cfa92a73f9.tar.gz |
Merge changes I51ee7070,I499a70a9
* changes:
libfscrypt: simplify fscrypt_policy_ensure()
libfscrypt: remove some hardcoded definitions
-rw-r--r-- | libfscrypt/fscrypt.cpp | 213 |
1 files changed, 57 insertions, 156 deletions
diff --git a/libfscrypt/fscrypt.cpp b/libfscrypt/fscrypt.cpp index adeb66aa..5182afc4 100644 --- a/libfscrypt/fscrypt.cpp +++ b/libfscrypt/fscrypt.cpp @@ -16,41 +16,29 @@ #include "fscrypt/fscrypt.h" -#include <array> - +#include <android-base/file.h> +#include <android-base/logging.h> +#include <android-base/unique_fd.h> #include <asm/ioctl.h> -#include <dirent.h> +#include <cutils/properties.h> #include <errno.h> #include <fcntl.h> #include <linux/fs.h> +#include <logwrap/logwrap.h> #include <string.h> #include <sys/stat.h> -#include <sys/syscall.h> #include <sys/types.h> #include <unistd.h> - -#include <android-base/file.h> -#include <android-base/logging.h> -#include <cutils/properties.h> -#include <logwrap/logwrap.h> #include <utils/misc.h> +#include <array> + #define FS_KEY_DESCRIPTOR_SIZE_HEX (2 * FS_KEY_DESCRIPTOR_SIZE + 1) /* modes not supported by upstream kernel, so not in <linux/fs.h> */ #define FS_ENCRYPTION_MODE_AES_256_HEH 126 #define FS_ENCRYPTION_MODE_PRIVATE 127 -/* new definition, not yet in Bionic's <linux/fs.h> */ -#ifndef FS_ENCRYPTION_MODE_ADIANTUM -#define FS_ENCRYPTION_MODE_ADIANTUM 9 -#endif - -/* new definition, not yet in Bionic's <linux/fs.h> */ -#ifndef FS_POLICY_FLAG_DIRECT_KEY -#define FS_POLICY_FLAG_DIRECT_KEY 0x4 -#endif - #define HEX_LOOKUP "0123456789abcdef" bool fscrypt_is_native() { @@ -88,36 +76,6 @@ static void policy_to_hex(const char* policy, char* hex) { hex[FS_KEY_DESCRIPTOR_SIZE_HEX - 1] = '\0'; } -static bool is_dir_empty(const char *dirname, bool *is_empty) -{ - int n = 0; - auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(dirname), closedir); - if (!dirp) { - PLOG(ERROR) << "Unable to read directory: " << dirname; - return false; - } - for (;;) { - errno = 0; - auto entry = readdir(dirp.get()); - if (!entry) { - if (errno) { - PLOG(ERROR) << "Unable to read directory: " << dirname; - return false; - } - break; - } - if (strcmp(entry->d_name, "lost+found") != 0) { // Skip lost+found - ++n; - if (n > 2) { - *is_empty = false; - return true; - } - } - } - *is_empty = true; - return true; -} - static uint8_t fscrypt_get_policy_flags(int filenames_encryption_mode) { if (filenames_encryption_mode == FS_ENCRYPTION_MODE_AES_256_CTS) { // Use legacy padding with our original filenames encryption mode. @@ -135,107 +93,9 @@ static uint8_t fscrypt_get_policy_flags(int filenames_encryption_mode) { return FS_POLICY_FLAGS_PAD_16; } -static bool fscrypt_policy_set(const char *directory, const char *policy, - size_t policy_length, - int contents_encryption_mode, - int filenames_encryption_mode) { - if (policy_length != FS_KEY_DESCRIPTOR_SIZE) { - LOG(ERROR) << "Policy wrong length: " << policy_length; - return false; - } - char policy_hex[FS_KEY_DESCRIPTOR_SIZE_HEX]; - policy_to_hex(policy, policy_hex); - - int fd = open(directory, O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); - if (fd == -1) { - PLOG(ERROR) << "Failed to open directory " << directory; - return false; - } - +static bool fscrypt_is_encrypted(int fd) { fscrypt_policy fp; - fp.version = 0; - fp.contents_encryption_mode = contents_encryption_mode; - fp.filenames_encryption_mode = filenames_encryption_mode; - fp.flags = fscrypt_get_policy_flags(filenames_encryption_mode); - memcpy(fp.master_key_descriptor, policy, FS_KEY_DESCRIPTOR_SIZE); - if (ioctl(fd, FS_IOC_SET_ENCRYPTION_POLICY, &fp)) { - PLOG(ERROR) << "Failed to set encryption policy for " << directory << " to " << policy_hex - << " modes " << contents_encryption_mode << "/" << filenames_encryption_mode; - close(fd); - return false; - } - close(fd); - - LOG(INFO) << "Policy for " << directory << " set to " << policy_hex - << " modes " << contents_encryption_mode << "/" << filenames_encryption_mode; - return true; -} - -static bool fscrypt_policy_get(const char *directory, char *policy, - size_t policy_length, - int contents_encryption_mode, - int filenames_encryption_mode) { - if (policy_length != FS_KEY_DESCRIPTOR_SIZE) { - LOG(ERROR) << "Policy wrong length: " << policy_length; - return false; - } - - int fd = open(directory, O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); - if (fd == -1) { - PLOG(ERROR) << "Failed to open directory " << directory; - return false; - } - - fscrypt_policy fp; - memset(&fp, 0, sizeof(fscrypt_policy)); - if (ioctl(fd, FS_IOC_GET_ENCRYPTION_POLICY, &fp) != 0) { - PLOG(ERROR) << "Failed to get encryption policy for " << directory; - close(fd); - log_ls(directory); - return false; - } - close(fd); - - if ((fp.version != 0) - || (fp.contents_encryption_mode != contents_encryption_mode) - || (fp.filenames_encryption_mode != filenames_encryption_mode) - || (fp.flags != - fscrypt_get_policy_flags(filenames_encryption_mode))) { - LOG(ERROR) << "Failed to find matching encryption policy for " << directory; - return false; - } - memcpy(policy, fp.master_key_descriptor, FS_KEY_DESCRIPTOR_SIZE); - - return true; -} - -static bool fscrypt_policy_check(const char *directory, const char *policy, - size_t policy_length, - int contents_encryption_mode, - int filenames_encryption_mode) { - if (policy_length != FS_KEY_DESCRIPTOR_SIZE) { - LOG(ERROR) << "Policy wrong length: " << policy_length; - return false; - } - char existing_policy[FS_KEY_DESCRIPTOR_SIZE]; - if (!fscrypt_policy_get(directory, existing_policy, FS_KEY_DESCRIPTOR_SIZE, - contents_encryption_mode, - filenames_encryption_mode)) return false; - char existing_policy_hex[FS_KEY_DESCRIPTOR_SIZE_HEX]; - - policy_to_hex(existing_policy, existing_policy_hex); - - if (memcmp(policy, existing_policy, FS_KEY_DESCRIPTOR_SIZE) != 0) { - char policy_hex[FS_KEY_DESCRIPTOR_SIZE_HEX]; - policy_to_hex(policy, policy_hex); - LOG(ERROR) << "Found policy " << existing_policy_hex << " at " << directory - << " which doesn't match expected value " << policy_hex; - log_ls(directory); - return false; - } - LOG(INFO) << "Found policy " << existing_policy_hex << " at " << directory - << " which matches expected value"; - return true; + return ioctl(fd, FS_IOC_GET_ENCRYPTION_POLICY, &fp) == 0; } int fscrypt_policy_ensure(const char *directory, const char *policy, @@ -270,14 +130,55 @@ int fscrypt_policy_ensure(const char *directory, const char *policy, return -1; } - bool is_empty; - if (!is_dir_empty(directory, &is_empty)) return -1; - if (is_empty) { - if (!fscrypt_policy_set(directory, policy, policy_length, - contents_mode, filenames_mode)) return -1; + if (policy_length != FS_KEY_DESCRIPTOR_SIZE) { + LOG(ERROR) << "Policy wrong length: " << policy_length; + return -1; + } + char policy_hex[FS_KEY_DESCRIPTOR_SIZE_HEX]; + policy_to_hex(policy, policy_hex); + + fscrypt_policy fp; + fp.version = 0; + fp.contents_encryption_mode = contents_mode; + fp.filenames_encryption_mode = filenames_mode; + fp.flags = fscrypt_get_policy_flags(filenames_mode); + memcpy(fp.master_key_descriptor, policy, FS_KEY_DESCRIPTOR_SIZE); + + android::base::unique_fd fd(open(directory, O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC)); + if (fd == -1) { + PLOG(ERROR) << "Failed to open directory " << directory; + return -1; + } + + bool already_encrypted = fscrypt_is_encrypted(fd); + + // FS_IOC_SET_ENCRYPTION_POLICY will set the policy if the directory is + // unencrypted; otherwise it will verify that the existing policy matches. + // Setting the policy will fail if the directory is already nonempty. + if (ioctl(fd, FS_IOC_SET_ENCRYPTION_POLICY, &fp) != 0) { + std::string reason; + switch (errno) { + case EEXIST: + reason = "The directory already has a different encryption policy."; + break; + default: + reason = strerror(errno); + break; + } + LOG(ERROR) << "Failed to set encryption policy of " << directory << " to " << policy_hex + << " modes " << contents_mode << "/" << filenames_mode << ": " << reason; + if (errno == ENOTEMPTY) { + log_ls(directory); + } + return -1; + } + + if (already_encrypted) { + LOG(INFO) << "Verified that " << directory << " has the encryption policy " << policy_hex + << " modes " << contents_mode << "/" << filenames_mode; } else { - if (!fscrypt_policy_check(directory, policy, policy_length, - contents_mode, filenames_mode)) return -1; + LOG(INFO) << "Encryption policy of " << directory << " set to " << policy_hex << " modes " + << contents_mode << "/" << filenames_mode; } return 0; } |