Merge changes from topic "deny-create-user-dirs" am: 9fb8825578
am: 65f0713d14
am: cf8713daf4
Original change: https://android-review.googlesource.com/c/platform/system/vold/+/2095484 Change-Id: I9395c42e8d2ebc5acf48b56dc3b489b23fbb6646 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
commit
896625bc6d
3 changed files with 62 additions and 7 deletions
61
FsCrypt.cpp
61
FsCrypt.cpp
|
@ -94,9 +94,16 @@ const std::string prepare_subdirs_path = "/system/bin/vold_prepare_subdirs";
|
||||||
const std::string systemwide_volume_key_dir =
|
const std::string systemwide_volume_key_dir =
|
||||||
std::string() + DATA_MNT_POINT + "/misc/vold/volume_keys";
|
std::string() + DATA_MNT_POINT + "/misc/vold/volume_keys";
|
||||||
|
|
||||||
|
const std::string data_data_dir = std::string() + DATA_MNT_POINT + "/data";
|
||||||
|
const std::string data_user_0_dir = std::string() + DATA_MNT_POINT + "/user/0";
|
||||||
|
const std::string media_obb_dir = std::string() + DATA_MNT_POINT + "/media/obb";
|
||||||
|
|
||||||
// Some users are ephemeral, don't try to wipe their keys from disk
|
// Some users are ephemeral, don't try to wipe their keys from disk
|
||||||
std::set<userid_t> s_ephemeral_users;
|
std::set<userid_t> s_ephemeral_users;
|
||||||
|
|
||||||
|
// The system DE encryption policy
|
||||||
|
EncryptionPolicy s_device_policy;
|
||||||
|
|
||||||
// Map user ids to encryption policies
|
// Map user ids to encryption policies
|
||||||
std::map<userid_t, EncryptionPolicy> s_de_policies;
|
std::map<userid_t, EncryptionPolicy> s_de_policies;
|
||||||
std::map<userid_t, EncryptionPolicy> s_ce_policies;
|
std::map<userid_t, EncryptionPolicy> s_ce_policies;
|
||||||
|
@ -443,11 +450,12 @@ bool fscrypt_initialize_systemwide_keys() {
|
||||||
makeGen(options), &device_key))
|
makeGen(options), &device_key))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
EncryptionPolicy device_policy;
|
// This initializes s_device_policy, which is a global variable so that
|
||||||
if (!install_storage_key(DATA_MNT_POINT, options, device_key, &device_policy)) return false;
|
// fscrypt_init_user0() can access it later.
|
||||||
|
if (!install_storage_key(DATA_MNT_POINT, options, device_key, &s_device_policy)) return false;
|
||||||
|
|
||||||
std::string options_string;
|
std::string options_string;
|
||||||
if (!OptionsToString(device_policy.options, &options_string)) {
|
if (!OptionsToString(s_device_policy.options, &options_string)) {
|
||||||
LOG(ERROR) << "Unable to serialize options";
|
LOG(ERROR) << "Unable to serialize options";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -455,7 +463,7 @@ bool fscrypt_initialize_systemwide_keys() {
|
||||||
if (!android::vold::writeStringToFile(options_string, options_filename)) return false;
|
if (!android::vold::writeStringToFile(options_string, options_filename)) return false;
|
||||||
|
|
||||||
std::string ref_filename = std::string(DATA_MNT_POINT) + fscrypt_key_ref;
|
std::string ref_filename = std::string(DATA_MNT_POINT) + fscrypt_key_ref;
|
||||||
if (!android::vold::writeStringToFile(device_policy.key_raw_ref, ref_filename)) return false;
|
if (!android::vold::writeStringToFile(s_device_policy.key_raw_ref, ref_filename)) return false;
|
||||||
LOG(INFO) << "Wrote system DE key reference to:" << ref_filename;
|
LOG(INFO) << "Wrote system DE key reference to:" << ref_filename;
|
||||||
|
|
||||||
KeyBuffer per_boot_key;
|
KeyBuffer per_boot_key;
|
||||||
|
@ -470,24 +478,63 @@ bool fscrypt_initialize_systemwide_keys() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool prepare_special_dirs() {
|
||||||
|
// Create /data/user/0 and its bind-mount alias /data/data. This *should*
|
||||||
|
// happen in fscrypt_prepare_user_storage(). However, it actually must be
|
||||||
|
// done early, before the rest of user 0's CE storage is prepared. This is
|
||||||
|
// because zygote may need to set up app data isolation before then, which
|
||||||
|
// requires mounting a tmpfs over /data/data to ensure it remains hidden.
|
||||||
|
// This issue arises due to /data/data being in the top-level directory.
|
||||||
|
//
|
||||||
|
// /data/user/0 used to be a symlink to /data/data, so we must first delete
|
||||||
|
// the old symlink if present.
|
||||||
|
if (android::vold::IsSymlink(data_user_0_dir) && android::vold::Unlink(data_user_0_dir) != 0)
|
||||||
|
return false;
|
||||||
|
if (!prepare_dir(data_data_dir, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
|
||||||
|
if (!prepare_dir(data_user_0_dir, 0700, AID_SYSTEM, AID_SYSTEM)) return false;
|
||||||
|
if (android::vold::BindMount(data_data_dir, data_user_0_dir) != 0) return false;
|
||||||
|
|
||||||
|
// If /data/media/obb doesn't exist, create it and encrypt it with the
|
||||||
|
// device policy. Normally, device-policy-encrypted directories are created
|
||||||
|
// and encrypted by init; /data/media/obb is special because it is located
|
||||||
|
// in /data/media. Since /data/media also contains per-user encrypted
|
||||||
|
// directories, by design only vold can write to it. As a side effect of
|
||||||
|
// that, vold must create /data/media/obb.
|
||||||
|
//
|
||||||
|
// We must tolerate /data/media/obb being unencrypted if it already exists
|
||||||
|
// on-disk, since it used to be unencrypted (b/64566063).
|
||||||
|
bool encrypt_obb = !android::vold::pathExists(media_obb_dir) && fscrypt_is_native();
|
||||||
|
if (!prepare_dir(media_obb_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return false;
|
||||||
|
if (encrypt_obb && !EnsurePolicy(s_device_policy, media_obb_dir)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool fscrypt_init_user0_done;
|
bool fscrypt_init_user0_done;
|
||||||
|
|
||||||
bool fscrypt_init_user0() {
|
bool fscrypt_init_user0() {
|
||||||
LOG(DEBUG) << "fscrypt_init_user0";
|
LOG(DEBUG) << "fscrypt_init_user0";
|
||||||
|
|
||||||
|
if (!prepare_special_dirs()) return false;
|
||||||
|
|
||||||
if (fscrypt_is_native()) {
|
if (fscrypt_is_native()) {
|
||||||
if (!prepare_dir(user_key_dir, 0700, AID_ROOT, AID_ROOT)) return false;
|
if (!prepare_dir(user_key_dir, 0700, AID_ROOT, AID_ROOT)) return false;
|
||||||
if (!prepare_dir(user_key_dir + "/ce", 0700, AID_ROOT, AID_ROOT)) return false;
|
if (!prepare_dir(user_key_dir + "/ce", 0700, AID_ROOT, AID_ROOT)) return false;
|
||||||
if (!prepare_dir(user_key_dir + "/de", 0700, AID_ROOT, AID_ROOT)) return false;
|
if (!prepare_dir(user_key_dir + "/de", 0700, AID_ROOT, AID_ROOT)) return false;
|
||||||
if (!android::vold::pathExists(get_de_key_path(0))) {
|
if (!android::vold::pathExists(get_de_key_path(0))) {
|
||||||
if (!create_and_install_user_keys(0, false)) return false;
|
if (!create_and_install_user_keys(0, false)) return false;
|
||||||
|
// Since /data/user/0 was created already, and directory creation
|
||||||
|
// and encryption should always happen together, encrypt
|
||||||
|
// /data/user/0 right away without waiting for the request to
|
||||||
|
// prepare user 0's CE storage.
|
||||||
|
if (!EnsurePolicy(s_ce_policies[0], data_user_0_dir)) return false;
|
||||||
}
|
}
|
||||||
// TODO: switch to loading only DE_0 here once framework makes
|
// TODO: switch to loading only DE_0 here once framework makes
|
||||||
// explicit calls to install DE keys for secondary users
|
// explicit calls to install DE keys for secondary users
|
||||||
if (!load_all_de_keys()) return false;
|
if (!load_all_de_keys()) return false;
|
||||||
}
|
}
|
||||||
// We can only safely prepare DE storage here, since CE keys are probably
|
// We only prepare DE storage here, since user 0's CE key won't be installed
|
||||||
// entangled with user credentials. The framework will always prepare CE
|
// yet unless it was just created. The framework will prepare the user's CE
|
||||||
// storage once CE keys are installed.
|
// storage later, once their CE key is installed.
|
||||||
if (!fscrypt_prepare_user_storage("", 0, 0, android::os::IVold::STORAGE_FLAG_DE)) {
|
if (!fscrypt_prepare_user_storage("", 0, 0, android::os::IVold::STORAGE_FLAG_DE)) {
|
||||||
LOG(ERROR) << "Failed to prepare user 0 storage";
|
LOG(ERROR) << "Failed to prepare user 0 storage";
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1179,6 +1179,12 @@ dev_t GetDevice(const std::string& path) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true if |path| exists and is a symlink.
|
||||||
|
bool IsSymlink(const std::string& path) {
|
||||||
|
struct stat stbuf;
|
||||||
|
return lstat(path.c_str(), &stbuf) == 0 && S_ISLNK(stbuf.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true if |path1| names the same existing file or directory as |path2|.
|
// Returns true if |path1| names the same existing file or directory as |path2|.
|
||||||
bool IsSameFile(const std::string& path1, const std::string& path2) {
|
bool IsSameFile(const std::string& path1, const std::string& path2) {
|
||||||
struct stat stbuf1, stbuf2;
|
struct stat stbuf1, stbuf2;
|
||||||
|
|
2
Utils.h
2
Utils.h
|
@ -162,6 +162,8 @@ std::string BuildDataUserDePath(const std::string& volumeUuid, userid_t userid);
|
||||||
|
|
||||||
dev_t GetDevice(const std::string& path);
|
dev_t GetDevice(const std::string& path);
|
||||||
|
|
||||||
|
bool IsSymlink(const std::string& path);
|
||||||
|
|
||||||
bool IsSameFile(const std::string& path1, const std::string& path2);
|
bool IsSameFile(const std::string& path1, const std::string& path2);
|
||||||
|
|
||||||
status_t EnsureDirExists(const std::string& path, mode_t mode, uid_t uid, gid_t gid);
|
status_t EnsureDirExists(const std::string& path, mode_t mode, uid_t uid, gid_t gid);
|
||||||
|
|
Loading…
Reference in a new issue