summaryrefslogtreecommitdiff
path: root/init/builtins.cpp
diff options
context:
space:
mode:
authorPaul Crowley <paulcrowley@google.com>2019-10-28 07:55:03 -0700
committerPaul Crowley <paulcrowley@google.com>2019-11-05 16:26:43 -0800
commit68258e8444e0daa967b007edf659e8bb7b38c59f (patch)
treecfc0af3158e4e08000efd12b79b879fa98236a0c /init/builtins.cpp
parent46452100977f66956175793a9557b0263bb58e0b (diff)
Make encryption action an argument to mkdir
FscryptSetDirectoryPolicy no longer tries to infer the action from the filename. Well mostly; it still assumes top-level directories in /data should be encrypted unless the mkdir arguments say otherwise, but it warns. Bug: 26641735 Test: boot, check log messages Change-Id: Id6d2cea7fb856f17323897d85cf6190c981b443c
Diffstat (limited to 'init/builtins.cpp')
-rw-r--r--init/builtins.cpp83
1 files changed, 34 insertions, 49 deletions
diff --git a/init/builtins.cpp b/init/builtins.cpp
index b2c64613a..67c05b2a1 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -364,67 +364,52 @@ static Result<void> do_interface_stop(const BuiltinArguments& args) {
return {};
}
-// mkdir <path> [mode] [owner] [group]
+// mkdir <path> [mode] [owner] [group] [<option> ...]
static Result<void> do_mkdir(const BuiltinArguments& args) {
- mode_t mode = 0755;
- Result<uid_t> uid = -1;
- Result<gid_t> gid = -1;
-
- switch (args.size()) {
- case 5:
- gid = DecodeUid(args[4]);
- if (!gid) {
- return Error() << "Unable to decode GID for '" << args[4] << "': " << gid.error();
- }
- FALLTHROUGH_INTENDED;
- case 4:
- uid = DecodeUid(args[3]);
- if (!uid) {
- return Error() << "Unable to decode UID for '" << args[3] << "': " << uid.error();
- }
- FALLTHROUGH_INTENDED;
- case 3:
- mode = std::strtoul(args[2].c_str(), 0, 8);
- FALLTHROUGH_INTENDED;
- case 2:
- break;
- default:
- return Error() << "Unexpected argument count: " << args.size();
+ auto options = ParseMkdir(args.args);
+ if (!options) return options.error();
+ std::string ref_basename;
+ if (options->ref_option == "ref") {
+ ref_basename = fscrypt_key_ref;
+ } else if (options->ref_option == "per_boot_ref") {
+ ref_basename = fscrypt_key_per_boot_ref;
+ } else {
+ return Error() << "Unknown key option: '" << options->ref_option << "'";
}
- std::string target = args[1];
+
struct stat mstat;
- if (lstat(target.c_str(), &mstat) != 0) {
+ if (lstat(options->target.c_str(), &mstat) != 0) {
if (errno != ENOENT) {
- return ErrnoError() << "lstat() failed on " << target;
+ return ErrnoError() << "lstat() failed on " << options->target;
}
- if (!make_dir(target, mode)) {
- return ErrnoErrorIgnoreEnoent() << "mkdir() failed on " << target;
+ if (!make_dir(options->target, options->mode)) {
+ return ErrnoErrorIgnoreEnoent() << "mkdir() failed on " << options->target;
}
- if (lstat(target.c_str(), &mstat) != 0) {
- return ErrnoError() << "lstat() failed on new " << target;
+ if (lstat(options->target.c_str(), &mstat) != 0) {
+ return ErrnoError() << "lstat() failed on new " << options->target;
}
}
if (!S_ISDIR(mstat.st_mode)) {
- return Error() << "Not a directory on " << target;
+ return Error() << "Not a directory on " << options->target;
}
- bool needs_chmod = (mstat.st_mode & ~S_IFMT) != mode;
- if ((*uid != static_cast<uid_t>(-1) && *uid != mstat.st_uid) ||
- (*gid != static_cast<gid_t>(-1) && *gid != mstat.st_gid)) {
- if (lchown(target.c_str(), *uid, *gid) == -1) {
- return ErrnoError() << "lchown failed on " << target;
+ bool needs_chmod = (mstat.st_mode & ~S_IFMT) != options->mode;
+ if ((options->uid != static_cast<uid_t>(-1) && options->uid != mstat.st_uid) ||
+ (options->gid != static_cast<gid_t>(-1) && options->gid != mstat.st_gid)) {
+ if (lchown(options->target.c_str(), options->uid, options->gid) == -1) {
+ return ErrnoError() << "lchown failed on " << options->target;
}
// chown may have cleared S_ISUID and S_ISGID, chmod again
needs_chmod = true;
}
if (needs_chmod) {
- if (fchmodat(AT_FDCWD, target.c_str(), mode, AT_SYMLINK_NOFOLLOW) == -1) {
- return ErrnoError() << "fchmodat() failed on " << target;
+ if (fchmodat(AT_FDCWD, options->target.c_str(), options->mode, AT_SYMLINK_NOFOLLOW) == -1) {
+ return ErrnoError() << "fchmodat() failed on " << options->target;
}
}
if (fscrypt_is_native()) {
- if (fscrypt_set_directory_policy(target)) {
+ if (!FscryptSetDirectoryPolicy(ref_basename, options->fscrypt_action, options->target)) {
return reboot_into_recovery(
- {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + target});
+ {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + options->target});
}
}
return {};
@@ -589,8 +574,8 @@ static Result<void> queue_fs_event(int code) {
return reboot_into_recovery(options);
/* If reboot worked, there is no return. */
} else if (code == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) {
- if (fscrypt_install_keyring()) {
- return Error() << "fscrypt_install_keyring() failed";
+ if (!FscryptInstallKeyring()) {
+ return Error() << "FscryptInstallKeyring() failed";
}
property_set("ro.crypto.state", "encrypted");
property_set("ro.crypto.type", "file");
@@ -600,8 +585,8 @@ static Result<void> queue_fs_event(int code) {
ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
return {};
} else if (code == FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED) {
- if (fscrypt_install_keyring()) {
- return Error() << "fscrypt_install_keyring() failed";
+ if (!FscryptInstallKeyring()) {
+ return Error() << "FscryptInstallKeyring() failed";
}
property_set("ro.crypto.state", "encrypted");
property_set("ro.crypto.type", "file");
@@ -611,8 +596,8 @@ static Result<void> queue_fs_event(int code) {
ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
return {};
} else if (code == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
- if (fscrypt_install_keyring()) {
- return Error() << "fscrypt_install_keyring() failed";
+ if (!FscryptInstallKeyring()) {
+ return Error() << "FscryptInstallKeyring() failed";
}
property_set("ro.crypto.state", "encrypted");
property_set("ro.crypto.type", "file");
@@ -1257,7 +1242,7 @@ const BuiltinFunctionMap& GetBuiltinFunctionMap() {
{"load_system_props", {0, 0, {false, do_load_system_props}}},
{"loglevel", {1, 1, {false, do_loglevel}}},
{"mark_post_data", {0, 0, {false, do_mark_post_data}}},
- {"mkdir", {1, 4, {true, do_mkdir}}},
+ {"mkdir", {1, 6, {true, do_mkdir}}},
// TODO: Do mount operations in vendor_init.
// mount_all is currently too complex to run in vendor_init as it queues action triggers,
// imports rc scripts, etc. It should be simplified and run in vendor_init context.