summaryrefslogtreecommitdiff
path: root/init/builtins.cpp
diff options
context:
space:
mode:
authorSteven Laver <lavers@google.com>2019-09-29 10:18:49 -0700
committerDaniel Norman <danielnorman@google.com>2019-10-07 12:46:57 -0700
commit627f1999ed413ae6301a98910bf5623d10dea9dd (patch)
treecdb3aaa5a87f296c110581486737a3eff722c6e9 /init/builtins.cpp
parenta0f694e020b1fd4aee741872962dc3a49a8886fb (diff)
parent1b546aa6858fc662711d09702894aee3eca9413b (diff)
Merge RP1A.190923.001
Change-Id: I7f2a2533917f63711b8d372608e239cb6ced3aa6
Diffstat (limited to 'init/builtins.cpp')
-rw-r--r--init/builtins.cpp204
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) {