Merge "storageproxyd: Remove setuid, setgid, and capset"
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index f1071b0..43961da 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -439,34 +439,6 @@
return fstab_result;
}
-// Return the path to the fstab file. There may be multiple fstab files; the
-// one that is returned will be the first that exists of fstab.<fstab_suffix>,
-// fstab.<hardware>, and fstab.<hardware.platform>. The fstab is searched for
-// in /odm/etc/ and /vendor/etc/, as well as in the locations where it may be in
-// the first stage ramdisk during early boot. Previously, the first stage
-// ramdisk's copy of the fstab had to be located in the root directory, but now
-// the system/etc directory is supported too and is the preferred location.
-std::string GetFstabPath() {
- for (const char* prop : {"fstab_suffix", "hardware", "hardware.platform"}) {
- std::string suffix;
-
- if (!fs_mgr_get_boot_config(prop, &suffix)) continue;
-
- for (const char* prefix : {// late-boot/post-boot locations
- "/odm/etc/fstab.", "/vendor/etc/fstab.",
- // early boot locations
- "/system/etc/fstab.", "/first_stage_ramdisk/system/etc/fstab.",
- "/fstab.", "/first_stage_ramdisk/fstab."}) {
- std::string fstab_path = prefix + suffix;
- if (access(fstab_path.c_str(), F_OK) == 0) {
- return fstab_path;
- }
- }
- }
-
- return "";
-}
-
/* Extracts <device>s from the by-name symlinks specified in a fstab:
* /dev/block/<type>/<device>/by-name/<partition>
*
@@ -526,6 +498,34 @@
} // namespace
+// Return the path to the fstab file. There may be multiple fstab files; the
+// one that is returned will be the first that exists of fstab.<fstab_suffix>,
+// fstab.<hardware>, and fstab.<hardware.platform>. The fstab is searched for
+// in /odm/etc/ and /vendor/etc/, as well as in the locations where it may be in
+// the first stage ramdisk during early boot. Previously, the first stage
+// ramdisk's copy of the fstab had to be located in the root directory, but now
+// the system/etc directory is supported too and is the preferred location.
+std::string GetFstabPath() {
+ for (const char* prop : {"fstab_suffix", "hardware", "hardware.platform"}) {
+ std::string suffix;
+
+ if (!fs_mgr_get_boot_config(prop, &suffix)) continue;
+
+ for (const char* prefix : {// late-boot/post-boot locations
+ "/odm/etc/fstab.", "/vendor/etc/fstab.",
+ // early boot locations
+ "/system/etc/fstab.", "/first_stage_ramdisk/system/etc/fstab.",
+ "/fstab.", "/first_stage_ramdisk/fstab."}) {
+ std::string fstab_path = prefix + suffix;
+ if (access(fstab_path.c_str(), F_OK) == 0) {
+ return fstab_path;
+ }
+ }
+ }
+
+ return "";
+}
+
bool ParseFstabFromString(const std::string& fstab_str, bool proc_mounts, Fstab* fstab_out) {
const int expected_fields = proc_mounts ? 4 : 5;
@@ -804,7 +804,7 @@
std::string default_fstab_path;
// Use different fstab paths for normal boot and recovery boot, respectively
- if (access("/system/bin/recovery", F_OK) == 0) {
+ if ((access("/sbin/recovery", F_OK) == 0) || (access("/system/bin/recovery", F_OK) == 0)) {
default_fstab_path = "/etc/recovery.fstab";
} else { // normal boot
default_fstab_path = GetFstabPath();
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 82b5275..07eaf58 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -642,6 +642,10 @@
if (ret) {
PERROR << "__mount(target=" << mount_point
<< ",flag=" << (shared_flag ? "MS_SHARED" : "MS_PRIVATE") << ")=" << ret;
+ // If "/system" doesn't look like a mountpoint, retry with "/".
+ if (errno == EINVAL && mount_point == "/system") {
+ return fs_mgr_overlayfs_set_shared_mount("/", shared_flag);
+ }
return false;
}
return true;
@@ -1140,7 +1144,13 @@
return 0;
}
- return std::min(super_info.size, (uint64_t(s.f_frsize) * s.f_bfree) / 2);
+ auto ideal_size = std::min(super_info.size, (uint64_t(s.f_frsize) * s.f_bfree) / 2);
+
+ // Align up to the filesystem block size.
+ if (auto remainder = ideal_size % s.f_bsize; remainder > 0) {
+ ideal_size += s.f_bsize - remainder;
+ }
+ return ideal_size;
}
static bool CreateScratchOnData(std::string* scratch_device, bool* partition_exists, bool* change) {
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index 8f200a8..689d18b 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -95,6 +95,8 @@
// Exported for testability. Regular users should use ReadFstabFromFile().
bool ParseFstabFromString(const std::string& fstab_str, bool proc_mounts, Fstab* fstab_out);
+// Exported for testability. Regular users should use ReadDefaultFstab().
+std::string GetFstabPath();
bool ReadFstabFromFile(const std::string& path, Fstab* fstab);
bool ReadFstabFromDt(Fstab* fstab, bool verbose = true);
diff --git a/fs_mgr/tests/vts_fs_test.cpp b/fs_mgr/tests/vts_fs_test.cpp
index ae8e459..b8b34e2 100644
--- a/fs_mgr/tests/vts_fs_test.cpp
+++ b/fs_mgr/tests/vts_fs_test.cpp
@@ -23,6 +23,9 @@
#include <gtest/gtest.h>
#include <libdm/dm.h>
+using testing::Contains;
+using testing::Not;
+
static int GetVsrLevel() {
return android::base::GetIntProperty("ro.vendor.api_level", -1);
}
@@ -117,3 +120,30 @@
android::fs_mgr::Fstab fstab;
EXPECT_FALSE(android::fs_mgr::ReadFstabFromDt(&fstab, false));
}
+
+TEST(fs, NoLegacyVerifiedBoot) {
+ if (GetVsrLevel() < __ANDROID_API_T__) {
+ GTEST_SKIP();
+ }
+
+ const auto& default_fstab_path = android::fs_mgr::GetFstabPath();
+ EXPECT_FALSE(default_fstab_path.empty());
+
+ std::string fstab_str;
+ EXPECT_TRUE(android::base::ReadFileToString(default_fstab_path, &fstab_str,
+ /* follow_symlinks = */ true));
+
+ for (const auto& line : android::base::Split(fstab_str, "\n")) {
+ auto fields = android::base::Tokenize(line, " \t");
+ // Ignores empty lines and comments.
+ if (fields.empty() || android::base::StartsWith(fields.front(), '#')) {
+ continue;
+ }
+ // Each line in a fstab should have at least five entries.
+ // <src> <mnt_point> <type> <mnt_flags and options> <fs_mgr_flags>
+ ASSERT_GE(fields.size(), 5);
+ EXPECT_THAT(android::base::Split(fields[4], ","), Not(Contains("verify")))
+ << "AVB 1.0 isn't supported now, but the 'verify' flag is found:\n"
+ << " " << line;
+ }
+}
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 4bbbc20..07ce458 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -507,16 +507,16 @@
SaveRamdiskPathToSnapuserd();
}
- if (MountPartition(system_partition, false /* erase_same_mounts */)) {
- if (dsu_not_on_userdata_ && fs_mgr_verity_is_check_at_most_once(*system_partition)) {
- LOG(ERROR) << "check_most_at_once forbidden on external media";
- return false;
- }
- SwitchRoot("/system");
- } else {
+ if (!MountPartition(system_partition, false /* erase_same_mounts */)) {
PLOG(ERROR) << "Failed to mount /system";
return false;
}
+ if (dsu_not_on_userdata_ && fs_mgr_verity_is_check_at_most_once(*system_partition)) {
+ LOG(ERROR) << "check_at_most_once forbidden on external media";
+ return false;
+ }
+
+ SwitchRoot("/system");
return true;
}
diff --git a/init/init.cpp b/init/init.cpp
index 0658942..535033d 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -54,6 +54,7 @@
#include <libavb/libavb.h>
#include <libgsi/libgsi.h>
#include <libsnapshot/snapshot.h>
+#include <logwrap/logwrap.h>
#include <processgroup/processgroup.h>
#include <processgroup/setup.h>
#include <selinux/android.h>
@@ -442,17 +443,43 @@
return {};
}
-static void DoUnloadApex(const std::string& apex_name) {
+static Result<void> DoUnloadApex(const std::string& apex_name) {
std::string prop_name = "init.apex." + apex_name;
// TODO(b/232114573) remove services and actions read from the apex
// TODO(b/232799709) kill services from the apex
SetProperty(prop_name, "unloaded");
+ return {};
}
-static void DoLoadApex(const std::string& apex_name) {
+static Result<void> UpdateApexLinkerConfig(const std::string& apex_name) {
+ // Do not invoke linkerconfig when there's no bin/ in the apex.
+ const std::string bin_path = "/apex/" + apex_name + "/bin";
+ if (access(bin_path.c_str(), R_OK) != 0) {
+ return {};
+ }
+ const char* linkerconfig_binary = "/apex/com.android.runtime/bin/linkerconfig";
+ const char* linkerconfig_target = "/linkerconfig";
+ const char* arguments[] = {linkerconfig_binary, "--target", linkerconfig_target, "--apex",
+ apex_name.c_str(), "--strict"};
+
+ if (logwrap_fork_execvp(arraysize(arguments), arguments, nullptr, false, LOG_KLOG, false,
+ nullptr) != 0) {
+ return ErrnoError() << "failed to execute linkerconfig";
+ }
+ LOG(INFO) << "Generated linker configuration for " << apex_name;
+ return {};
+}
+
+static Result<void> DoLoadApex(const std::string& apex_name) {
std::string prop_name = "init.apex." + apex_name;
// TODO(b/232799709) read .rc files from the apex
+
+ if (auto result = UpdateApexLinkerConfig(apex_name); !result.ok()) {
+ return result.error();
+ }
+
SetProperty(prop_name, "loaded");
+ return {};
}
enum class ControlTarget {
@@ -478,17 +505,14 @@
return control_message_functions;
}
-static bool HandleApexControlMessage(std::string_view action, const std::string& name,
- std::string_view message) {
+static Result<void> HandleApexControlMessage(std::string_view action, const std::string& name,
+ std::string_view message) {
if (action == "load") {
- DoLoadApex(name);
- return true;
+ return DoLoadApex(name);
} else if (action == "unload") {
- DoUnloadApex(name);
- return true;
+ return DoUnloadApex(name);
} else {
- LOG(ERROR) << "Unknown control msg '" << message << "'";
- return false;
+ return Error() << "Unknown control msg '" << message << "'";
}
}
@@ -505,7 +529,15 @@
auto action = message;
if (ConsumePrefix(&action, "apex_")) {
- return HandleApexControlMessage(action, name, message);
+ if (auto result = HandleApexControlMessage(action, name, message); !result.ok()) {
+ LOG(ERROR) << "Control message: Could not ctl." << message << " for '" << name
+ << "' from pid: " << from_pid << " (" << process_cmdline
+ << "): " << result.error();
+ return false;
+ }
+ LOG(INFO) << "Control message: Processed ctl." << message << " for '" << name
+ << "' from pid: " << from_pid << " (" << process_cmdline << ")";
+ return true;
}
Service* service = nullptr;
diff --git a/init/security.cpp b/init/security.cpp
index 970696e..0e9f6c2 100644
--- a/init/security.cpp
+++ b/init/security.cpp
@@ -15,6 +15,7 @@
*/
#include "security.h"
+#include "util.h"
#include <errno.h>
#include <fcntl.h>
@@ -89,7 +90,7 @@
// Set /proc/sys/vm/mmap_rnd_bits and potentially
// /proc/sys/vm/mmap_rnd_compat_bits to the maximum supported values.
-// Returns -1 if unable to set these to an acceptable value.
+// Returns an error if unable to set these to an acceptable value.
//
// To support this sysctl, the following upstream commits are needed:
//
@@ -105,13 +106,20 @@
// uml does not support mmap_rnd_bits
return {};
#elif defined(__aarch64__)
- // arm64 supports 18 - 33 bits depending on pagesize and VA_SIZE
- if (SetMmapRndBitsMin(33, 24, false) && SetMmapRndBitsMin(16, 16, true)) {
+ // arm64 architecture supports 18 - 33 rnd bits depending on pagesize and
+ // VA_SIZE. However the kernel might have been compiled with a narrower
+ // range using CONFIG_ARCH_MMAP_RND_BITS_MIN/MAX. To use the maximum
+ // supported number of bits, we start from the theoretical maximum of 33
+ // bits and try smaller values until we reach 24 bits which is the
+ // Android-specific minimum. Don't go lower even if the configured maximum
+ // is smaller than 24.
+ if (SetMmapRndBitsMin(33, 24, false) && (!Has32BitAbi() || SetMmapRndBitsMin(16, 16, true))) {
return {};
}
#elif defined(__x86_64__)
- // x86_64 supports 28 - 32 bits
- if (SetMmapRndBitsMin(32, 32, false) && SetMmapRndBitsMin(16, 16, true)) {
+ // x86_64 supports 28 - 32 rnd bits, but Android wants to ensure that the
+ // theoretical maximum of 32 bits is always supported and used.
+ if (SetMmapRndBitsMin(32, 32, false) && (!Has32BitAbi() || SetMmapRndBitsMin(16, 16, true))) {
return {};
}
#elif defined(__arm__) || defined(__i386__)
diff --git a/init/service.cpp b/init/service.cpp
index 01dd685..8c4ee93 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -315,7 +315,9 @@
#else
static bool is_apex_updatable = false;
#endif
- const bool is_process_updatable = !use_bootstrap_ns_ && is_apex_updatable;
+ const bool use_default_mount_ns =
+ mount_namespace_.has_value() && *mount_namespace_ == NS_DEFAULT;
+ const bool is_process_updatable = use_default_mount_ns && is_apex_updatable;
// If we crash > 4 times in 'fatal_crash_window_' minutes or before boot_completed,
// reboot into bootloader or set crashing property
@@ -474,10 +476,9 @@
}
// Enters namespaces, sets environment variables, writes PID files and runs the service executable.
-void Service::RunService(const std::optional<MountNamespace>& override_mount_namespace,
- const std::vector<Descriptor>& descriptors,
+void Service::RunService(const std::vector<Descriptor>& descriptors,
std::unique_ptr<std::array<int, 2>, decltype(&ClosePipe)> pipefd) {
- if (auto result = EnterNamespaces(namespaces_, name_, override_mount_namespace); !result.ok()) {
+ if (auto result = EnterNamespaces(namespaces_, name_, mount_namespace_); !result.ok()) {
LOG(FATAL) << "Service '" << name_ << "' failed to set up namespaces: " << result.error();
}
@@ -581,26 +582,9 @@
scon = *result;
}
- // APEXd is always started in the "current" namespace because it is the process to set up
- // the current namespace.
- const bool is_apexd = args_[0] == "/system/bin/apexd";
-
- if (!IsDefaultMountNamespaceReady() && !is_apexd) {
- // If this service is started before APEXes and corresponding linker configuration
- // get available, mark it as pre-apexd one. Note that this marking is
- // permanent. So for example, if the service is re-launched (e.g., due
- // to crash), it is still recognized as pre-apexd... for consistency.
- use_bootstrap_ns_ = true;
- }
-
- // For pre-apexd services, override mount namespace as "bootstrap" one before starting.
- // Note: "ueventd" is supposed to be run in "default" mount namespace even if it's pre-apexd
- // to support loading firmwares from APEXes.
- std::optional<MountNamespace> override_mount_namespace;
- if (name_ == "ueventd") {
- override_mount_namespace = NS_DEFAULT;
- } else if (use_bootstrap_ns_) {
- override_mount_namespace = NS_BOOTSTRAP;
+ if (!mount_namespace_.has_value()) {
+ // remember from which mount namespace the service should start
+ SetMountNamespace();
}
post_data_ = ServiceList::GetInstance().IsPostData();
@@ -633,7 +617,7 @@
if (pid == 0) {
umask(077);
- RunService(override_mount_namespace, descriptors, std::move(pipefd));
+ RunService(descriptors, std::move(pipefd));
_exit(127);
}
@@ -684,6 +668,33 @@
return {};
}
+// Set mount namespace for the service.
+// The reason why remember the mount namespace:
+// If this service is started before APEXes and corresponding linker configuration
+// get available, mark it as pre-apexd one. Note that this marking is
+// permanent. So for example, if the service is re-launched (e.g., due
+// to crash), it is still recognized as pre-apexd... for consistency.
+void Service::SetMountNamespace() {
+ // APEXd is always started in the "current" namespace because it is the process to set up
+ // the current namespace. So, leave mount_namespace_ as empty.
+ if (args_[0] == "/system/bin/apexd") {
+ return;
+ }
+ // Services in the following list start in the "default" mount namespace.
+ // Note that they should use bootstrap bionic if they start before APEXes are ready.
+ static const std::set<std::string> kUseDefaultMountNamespace = {
+ "ueventd", // load firmwares from APEXes
+ "hwservicemanager", // load VINTF fragments from APEXes
+ "servicemanager", // load VINTF fragments from APEXes
+ };
+ if (kUseDefaultMountNamespace.find(name_) != kUseDefaultMountNamespace.end()) {
+ mount_namespace_ = NS_DEFAULT;
+ return;
+ }
+ // Use the "default" mount namespace only if it's ready
+ mount_namespace_ = IsDefaultMountNamespaceReady() ? NS_DEFAULT : NS_BOOTSTRAP;
+}
+
void Service::SetStartedInFirstStage(pid_t pid) {
LOG(INFO) << "adding first-stage service '" << name_ << "'...";
diff --git a/init/service.h b/init/service.h
index d233cbf..4adbaa2 100644
--- a/init/service.h
+++ b/init/service.h
@@ -32,6 +32,7 @@
#include "action.h"
#include "capabilities.h"
#include "keyword_map.h"
+#include "mount_namespace.h"
#include "parser.h"
#include "service_utils.h"
#include "subcontext.h"
@@ -151,10 +152,9 @@
Result<void> CheckConsole();
void ConfigureMemcg();
void RunService(
- const std::optional<MountNamespace>& override_mount_namespace,
const std::vector<Descriptor>& descriptors,
std::unique_ptr<std::array<int, 2>, void (*)(const std::array<int, 2>* pipe)> pipefd);
-
+ void SetMountNamespace();
static unsigned long next_start_order_;
static bool is_exec_service_running_;
static std::chrono::time_point<std::chrono::steady_clock> exec_service_started_;
@@ -219,7 +219,7 @@
std::vector<std::function<void(const siginfo_t& siginfo)>> reap_callbacks_;
- bool use_bootstrap_ns_ = false;
+ std::optional<MountNamespace> mount_namespace_;
bool post_data_ = false;
diff --git a/init/util.cpp b/init/util.cpp
index 1801d17..523cce4 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -733,5 +733,10 @@
return is_microdroid;
}
+bool Has32BitAbi() {
+ static bool has = !android::base::GetProperty("ro.product.cpu.abilist32", "").empty();
+ return has;
+}
+
} // namespace init
} // namespace android
diff --git a/init/util.h b/init/util.h
index 47d4ff5..099b9ee 100644
--- a/init/util.h
+++ b/init/util.h
@@ -106,5 +106,6 @@
void SetDefaultMountNamespaceReady();
bool IsMicrodroid();
+bool Has32BitAbi();
} // namespace init
} // namespace android
diff --git a/libsync/libsync.map.txt b/libsync/libsync.map.txt
index aac6b57..32df91e 100644
--- a/libsync/libsync.map.txt
+++ b/libsync/libsync.map.txt
@@ -19,7 +19,7 @@
sync_merge; # introduced=26
sync_file_info; # introduced=26
sync_file_info_free; # introduced=26
- sync_wait; # llndk apex
+ sync_wait; # llndk systemapi
sync_fence_info; # llndk
sync_pt_info; # llndk
sync_fence_info_free; # llndk
diff --git a/libvndksupport/libvndksupport.map.txt b/libvndksupport/libvndksupport.map.txt
index a44ed18..1d94b9d 100644
--- a/libvndksupport/libvndksupport.map.txt
+++ b/libvndksupport/libvndksupport.map.txt
@@ -1,8 +1,8 @@
LIBVNDKSUPPORT {
global:
- android_is_in_vendor_process; # llndk apex
- android_load_sphal_library; # llndk apex
- android_unload_sphal_library; # llndk apex
+ android_is_in_vendor_process; # llndk systemapi
+ android_load_sphal_library; # llndk systemapi
+ android_unload_sphal_library; # llndk systemapi
local:
*;
};
diff --git a/rootdir/init.rc b/rootdir/init.rc
index a819c7a..660f18c 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -832,6 +832,7 @@
mkdir /data/misc/odsign 0710 root system
# directory used for odsign metrics
mkdir /data/misc/odsign/metrics 0770 root system
+
# Directory for VirtualizationService temporary image files.
# Delete any stale files owned by the old virtualizationservice uid (b/230056726).
chmod 0770 /data/misc/virtualizationservice
@@ -1040,7 +1041,8 @@
exec_start update_verifier_nonencrypted
start statsd
start netd
- trigger zygote-run
+ start zygote
+ start zygote_secondary
on zygote-start && property:ro.crypto.state=unsupported
wait_for_prop odsign.verification.done 1
@@ -1048,7 +1050,8 @@
exec_start update_verifier_nonencrypted
start statsd
start netd
- trigger zygote-run
+ start zygote
+ start zygote_secondary
on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
wait_for_prop odsign.verification.done 1
@@ -1056,15 +1059,6 @@
exec_start update_verifier_nonencrypted
start statsd
start netd
- trigger zygote-run
-
-on zygote-run && property:ro.zygote=zygote32
- start zygote
-
-on zygote-run && property:ro.zygote=zygote64
- start zygote
-
-on zygote-run && property:ro.zygote=zygote64_32
start zygote
start zygote_secondary
diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc
index dfe1645..efb30d6 100644
--- a/rootdir/init.zygote64_32.rc
+++ b/rootdir/init.zygote64_32.rc
@@ -25,4 +25,3 @@
socket usap_pool_secondary stream 660 root system
onrestart restart zygote
task_profiles ProcessCapacityHigh MaxPerformance
- disabled