diff options
author | Steven Laver <lavers@google.com> | 2019-09-29 10:18:49 -0700 |
---|---|---|
committer | Daniel Norman <danielnorman@google.com> | 2019-10-07 12:46:57 -0700 |
commit | 627f1999ed413ae6301a98910bf5623d10dea9dd (patch) | |
tree | cdb3aaa5a87f296c110581486737a3eff722c6e9 /init/builtins.cpp | |
parent | a0f694e020b1fd4aee741872962dc3a49a8886fb (diff) | |
parent | 1b546aa6858fc662711d09702894aee3eca9413b (diff) |
Merge RP1A.190923.001
Change-Id: I7f2a2533917f63711b8d372608e239cb6ced3aa6
Diffstat (limited to 'init/builtins.cpp')
-rw-r--r-- | init/builtins.cpp | 204 |
1 files changed, 124 insertions, 80 deletions
diff --git a/init/builtins.cpp b/init/builtins.cpp index 058c5ba00..aef2afc9e 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -55,7 +55,6 @@ #include <cutils/android_reboot.h> #include <fs_mgr.h> #include <fscrypt/fscrypt.h> -#include <fscrypt/fscrypt_init_extensions.h> #include <libgsi/libgsi.h> #include <selinux/android.h> #include <selinux/label.h> @@ -64,6 +63,7 @@ #include "action_manager.h" #include "bootchart.h" +#include "fscrypt_init_extensions.h" #include "init.h" #include "mount_namespace.h" #include "parser.h" @@ -80,6 +80,8 @@ using namespace std::literals::string_literals; using android::base::Basename; +using android::base::StartsWith; +using android::base::StringPrintf; using android::base::unique_fd; using android::fs_mgr::Fstab; using android::fs_mgr::ReadFstabFromFile; @@ -356,51 +358,64 @@ static Result<void> do_interface_stop(const BuiltinArguments& args) { // mkdir <path> [mode] [owner] [group] static Result<void> do_mkdir(const BuiltinArguments& args) { mode_t mode = 0755; - if (args.size() >= 3) { - mode = std::strtoul(args[2].c_str(), 0, 8); - } - - if (!make_dir(args[1], mode)) { - /* chmod in case the directory already exists */ - if (errno == EEXIST) { - if (fchmodat(AT_FDCWD, args[1].c_str(), mode, AT_SYMLINK_NOFOLLOW) == -1) { - return ErrnoError() << "fchmodat() failed"; - } - } else { - return ErrnoErrorIgnoreEnoent() << "mkdir() failed"; - } - } - - if (args.size() >= 4) { - auto uid = DecodeUid(args[3]); - if (!uid) { - return Error() << "Unable to decode UID for '" << args[3] << "': " << uid.error(); - } - Result<gid_t> gid = -1; + Result<uid_t> uid = -1; + Result<gid_t> gid = -1; - if (args.size() == 5) { + 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(); + } + std::string target = args[1]; + struct stat mstat; + if (lstat(target.c_str(), &mstat) != 0) { + if (errno != ENOENT) { + return ErrnoError() << "lstat() failed on " << target; } - - if (lchown(args[1].c_str(), *uid, *gid) == -1) { - return ErrnoError() << "lchown failed"; + if (!make_dir(target, mode)) { + return ErrnoErrorIgnoreEnoent() << "mkdir() failed on " << target; } - - /* chown may have cleared S_ISUID and S_ISGID, chmod again */ - if (mode & (S_ISUID | S_ISGID)) { - if (fchmodat(AT_FDCWD, args[1].c_str(), mode, AT_SYMLINK_NOFOLLOW) == -1) { - return ErrnoError() << "fchmodat failed"; - } + if (lstat(target.c_str(), &mstat) != 0) { + return ErrnoError() << "lstat() failed on new " << target; + } + } + if (!S_ISDIR(mstat.st_mode)) { + return Error() << "Not a directory on " << 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; + } + // 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 (fscrypt_is_native()) { - if (fscrypt_set_directory_policy(args[1].c_str())) { + if (fscrypt_set_directory_policy(target)) { return reboot_into_recovery( - {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + args[1]}); + {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + target}); } } return {}; @@ -647,12 +662,7 @@ static Result<void> do_mount_all(const BuiltinArguments& args) { if (!ReadFstabFromFile(fstab_file, &fstab)) { return Error() << "Could not read fstab"; } - - auto mount_fstab_return_code = - CallFunctionAndHandleProperties(fs_mgr_mount_all, &fstab, mount_mode); - if (!mount_fstab_return_code) { - return Error() << "Could not call fs_mgr_mount_all(): " << mount_fstab_return_code.error(); - } + auto mount_fstab_return_code = fs_mgr_mount_all(&fstab, mount_mode); property_set(prop_name, std::to_string(t.duration().count())); if (import_rc && SelinuxGetVendorAndroidVersion() <= __ANDROID_API_Q__) { @@ -663,7 +673,7 @@ static Result<void> do_mount_all(const BuiltinArguments& args) { if (queue_event) { /* queue_fs_event will queue event based on mount_fstab return code * and return processed return code*/ - auto queue_fs_result = queue_fs_event(*mount_fstab_return_code); + auto queue_fs_result = queue_fs_event(mount_fstab_return_code); if (!queue_fs_result) { return Error() << "queue_fs_event() failed: " << queue_fs_result.error(); } @@ -679,13 +689,8 @@ static Result<void> do_umount_all(const BuiltinArguments& args) { return Error() << "Could not read fstab"; } - auto result = CallFunctionAndHandleProperties(fs_mgr_umount_all, &fstab); - if (!result) { - return Error() << "Could not call fs_mgr_mount_all() " << result.error(); - } - - if (*result != 0) { - return Error() << "fs_mgr_mount_all() failed: " << *result; + if (auto result = fs_mgr_umount_all(&fstab); result != 0) { + return Error() << "umount_fstab() failed " << result; } return {}; } @@ -696,19 +701,23 @@ static Result<void> do_swapon_all(const BuiltinArguments& args) { return Error() << "Could not read fstab '" << args[1] << "'"; } - auto result = CallFunctionAndHandleProperties(fs_mgr_swapon_all, fstab); - if (!result) { - return Error() << "Could not call fs_mgr_swapon_all() " << result.error(); - } - - if (*result == 0) { - return Error() << "fs_mgr_swapon_all() failed."; + if (!fs_mgr_swapon_all(fstab)) { + return Error() << "fs_mgr_swapon_all() failed"; } return {}; } static Result<void> do_setprop(const BuiltinArguments& args) { + if (StartsWith(args[1], "ctl.")) { + return Error() + << "Cannot set ctl. properties from init; call the Service functions directly"; + } + if (args[1] == kRestoreconProperty) { + return Error() << "Cannot set '" << kRestoreconProperty + << "' from init; use the restorecon builtin directly"; + } + property_set(args[1], args[2]); return {}; } @@ -1023,8 +1032,36 @@ static Result<void> do_loglevel(const BuiltinArguments& args) { return {}; } +static int check_rlim_action() { + struct rlimit rl; + std::string value = android::base::GetProperty("persist.debug.trace", ""); + if(value == "1") { + rl.rlim_cur = RLIM_INFINITY; + rl.rlim_max = RLIM_INFINITY; + if (setrlimit(RLIMIT_CORE, &rl) < 0) { + PLOG(ERROR) << "could not enable core file generation"; + } + } + return 0; +} + static Result<void> do_load_persist_props(const BuiltinArguments& args) { - load_persist_props(); + // Devices with FDE have load_persist_props called twice; the first time when the temporary + // /data partition is mounted and then again once /data is truly mounted. We do not want to + // read persistent properties from the temporary /data partition or mark persistent properties + // as having been loaded during the first call, so we return in that case. + std::string crypto_state = android::base::GetProperty("ro.crypto.state", ""); + std::string crypto_type = android::base::GetProperty("ro.crypto.type", ""); + if (crypto_state == "encrypted" && crypto_type == "block") { + static size_t num_calls = 0; + if (++num_calls == 1) return {}; + } + + SendLoadPersistentPropertiesMessage(); + + start_waiting_for_property("ro.persistent_properties.ready", "true"); + /*check for coredump*/ + check_rlim_action(); return {}; } @@ -1071,34 +1108,45 @@ static bool is_file_crypto() { return android::base::GetProperty("ro.crypto.type", "") == "file"; } -static Result<void> ExecWithRebootOnFailure(const std::string& reboot_reason, - const BuiltinArguments& args) { - auto service = Service::MakeTemporaryOneshotService(args.args); +static Result<void> ExecWithFunctionOnFailure(const std::vector<std::string>& args, + std::function<void(const std::string&)> function) { + auto service = Service::MakeTemporaryOneshotService(args); if (!service) { - return Error() << "Could not create exec service: " << service.error(); + function("MakeTemporaryOneshotService failed: " + service.error().message()); } - (*service)->AddReapCallback([reboot_reason](const siginfo_t& siginfo) { + (*service)->AddReapCallback([function](const siginfo_t& siginfo) { if (siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) { - // TODO (b/122850122): support this in gsi - if (fscrypt_is_native() && !android::gsi::IsGsiRunning()) { - LOG(ERROR) << "Rebooting into recovery, reason: " << reboot_reason; - if (auto result = reboot_into_recovery( - {"--prompt_and_wipe_data", "--reason="s + reboot_reason}); - !result) { - LOG(FATAL) << "Could not reboot into recovery: " << result.error(); - } - } else { - LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason; - } + function(StringPrintf("Exec service failed, status %d", siginfo.si_status)); } }); if (auto result = (*service)->ExecStart(); !result) { - return Error() << "Could not start exec service: " << result.error(); + function("ExecStart failed: " + result.error().message()); } ServiceList::GetInstance().AddService(std::move(*service)); return {}; } +static Result<void> ExecVdcRebootOnFailure(const std::string& vdc_arg) { + auto reboot_reason = vdc_arg + "_failed"; + + auto reboot = [reboot_reason](const std::string& message) { + // TODO (b/122850122): support this in gsi + if (fscrypt_is_native() && !android::gsi::IsGsiRunning()) { + LOG(ERROR) << message << ": Rebooting into recovery, reason: " << reboot_reason; + if (auto result = reboot_into_recovery( + {"--prompt_and_wipe_data", "--reason="s + reboot_reason}); + !result) { + LOG(FATAL) << "Could not reboot into recovery: " << result.error(); + } + } else { + LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason; + } + }; + + std::vector<std::string> args = {"exec", "/system/bin/vdc", "--wait", "cryptfs", vdc_arg}; + return ExecWithFunctionOnFailure(args, reboot); +} + static Result<void> do_installkey(const BuiltinArguments& args) { if (!is_file_crypto()) return {}; @@ -1106,15 +1154,11 @@ static Result<void> do_installkey(const BuiltinArguments& args) { if (!make_dir(unencrypted_dir, 0700) && errno != EEXIST) { return ErrnoError() << "Failed to create " << unencrypted_dir; } - return ExecWithRebootOnFailure( - "enablefilecrypto_failed", - {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "enablefilecrypto"}, args.context}); + return ExecVdcRebootOnFailure("enablefilecrypto"); } static Result<void> do_init_user0(const BuiltinArguments& args) { - return ExecWithRebootOnFailure( - "init_user0_failed", - {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"}, args.context}); + return ExecVdcRebootOnFailure("init_user0"); } static Result<void> do_mark_post_data(const BuiltinArguments& args) { |