Merge "libutils: T* is a trivial type" into main
diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp
index 74f9a8c..4cde986 100644
--- a/debuggerd/libdebuggerd/tombstone_proto.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto.cpp
@@ -203,7 +203,7 @@
}
static void dump_probable_cause(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
- const ProcessInfo& process_info, const ThreadInfo& main_thread) {
+ const ProcessInfo& process_info, const ThreadInfo& target_thread) {
#if defined(USE_SCUDO)
ScudoCrashData scudo_crash_data(unwinder->GetProcessMemory().get(), process_info);
if (scudo_crash_data.CrashIsMine()) {
@@ -213,13 +213,13 @@
#endif
GwpAsanCrashData gwp_asan_crash_data(unwinder->GetProcessMemory().get(), process_info,
- main_thread);
+ target_thread);
if (gwp_asan_crash_data.CrashIsMine()) {
gwp_asan_crash_data.AddCauseProtos(tombstone, unwinder);
return;
}
- const siginfo *si = main_thread.siginfo;
+ const siginfo *si = target_thread.siginfo;
auto fault_addr = reinterpret_cast<uint64_t>(si->si_addr);
unwindstack::Maps* maps = unwinder->GetMaps();
@@ -238,14 +238,14 @@
} else if (fault_addr == 0xffff0f60) {
cause = "call to kuser_cmpxchg64";
} else {
- cause = get_stack_overflow_cause(fault_addr, main_thread.registers->sp(), maps);
+ cause = get_stack_overflow_cause(fault_addr, target_thread.registers->sp(), maps);
}
} else if (si->si_signo == SIGSEGV && si->si_code == SEGV_ACCERR) {
auto map_info = maps->Find(fault_addr);
if (map_info != nullptr && map_info->flags() == PROT_EXEC) {
cause = "execute-only (no-read) memory access error; likely due to data in .text.";
} else {
- cause = get_stack_overflow_cause(fault_addr, main_thread.registers->sp(), maps);
+ cause = get_stack_overflow_cause(fault_addr, target_thread.registers->sp(), maps);
}
} else if (si->si_signo == SIGSYS && si->si_code == SYS_SECCOMP) {
cause = StringPrintf("seccomp prevented call to disallowed %s system call %d", ABI_STRING,
@@ -685,7 +685,7 @@
}
void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
- const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
+ const std::map<pid_t, ThreadInfo>& threads, pid_t target_tid,
const ProcessInfo& process_info, const OpenFilesList* open_files) {
Tombstone result;
@@ -694,19 +694,19 @@
result.set_revision(android::base::GetProperty("ro.revision", "unknown"));
result.set_timestamp(get_timestamp());
- const ThreadInfo& main_thread = threads.at(target_thread);
- result.set_pid(main_thread.pid);
- result.set_tid(main_thread.tid);
- result.set_uid(main_thread.uid);
- result.set_selinux_label(main_thread.selinux_label);
+ const ThreadInfo& target_thread = threads.at(target_tid);
+ result.set_pid(target_thread.pid);
+ result.set_tid(target_thread.tid);
+ result.set_uid(target_thread.uid);
+ result.set_selinux_label(target_thread.selinux_label);
// The main thread must have a valid siginfo.
- CHECK(main_thread.siginfo != nullptr);
+ CHECK(target_thread.siginfo != nullptr);
struct sysinfo si;
sysinfo(&si);
android::procinfo::ProcessInfo proc_info;
std::string error;
- if (android::procinfo::GetProcessInfo(main_thread.pid, &proc_info, &error)) {
+ if (android::procinfo::GetProcessInfo(target_thread.pid, &proc_info, &error)) {
uint64_t starttime = proc_info.starttime / sysconf(_SC_CLK_TCK);
result.set_process_uptime(si.uptime - starttime);
} else {
@@ -715,24 +715,24 @@
}
auto cmd_line = result.mutable_command_line();
- for (const auto& arg : main_thread.command_line) {
+ for (const auto& arg : target_thread.command_line) {
*cmd_line->Add() = arg;
}
- if (!main_thread.siginfo) {
+ if (!target_thread.siginfo) {
async_safe_fatal("siginfo missing");
}
Signal sig;
- sig.set_number(main_thread.signo);
- sig.set_name(get_signame(main_thread.siginfo));
- sig.set_code(main_thread.siginfo->si_code);
- sig.set_code_name(get_sigcode(main_thread.siginfo));
+ sig.set_number(target_thread.signo);
+ sig.set_name(get_signame(target_thread.siginfo));
+ sig.set_code(target_thread.siginfo->si_code);
+ sig.set_code_name(get_sigcode(target_thread.siginfo));
- if (signal_has_sender(main_thread.siginfo, main_thread.pid)) {
+ if (signal_has_sender(target_thread.siginfo, target_thread.pid)) {
sig.set_has_sender(true);
- sig.set_sender_uid(main_thread.siginfo->si_uid);
- sig.set_sender_pid(main_thread.siginfo->si_pid);
+ sig.set_sender_uid(target_thread.siginfo->si_uid);
+ sig.set_sender_pid(target_thread.siginfo->si_pid);
}
if (process_info.has_fault_address) {
@@ -746,28 +746,28 @@
dump_abort_message(&result, unwinder->GetProcessMemory(), process_info);
dump_crash_details(&result, unwinder->GetProcessMemory(), process_info);
- // Dump the main thread, but save the memory around the registers.
- dump_thread(&result, unwinder, main_thread, /* memory_dump */ true);
+ // Dump the target thread, but save the memory around the registers.
+ dump_thread(&result, unwinder, target_thread, /* memory_dump */ true);
for (const auto& [tid, thread_info] : threads) {
- if (tid != target_thread) {
+ if (tid != target_tid) {
dump_thread(&result, unwinder, thread_info);
}
}
- dump_probable_cause(&result, unwinder, process_info, main_thread);
+ dump_probable_cause(&result, unwinder, process_info, target_thread);
dump_mappings(&result, unwinder->GetMaps(), unwinder->GetProcessMemory());
// Only dump logs on debuggable devices.
if (android::base::GetBoolProperty("ro.debuggable", false)) {
// Get the thread that corresponds to the main pid of the process.
- const ThreadInfo& thread = threads.at(main_thread.pid);
+ const ThreadInfo& thread = threads.at(target_thread.pid);
// Do not attempt to dump logs of the logd process because the gathering
// of logs can hang until a timeout occurs.
if (thread.thread_name != "logd") {
- dump_logcat(&result, main_thread.pid);
+ dump_logcat(&result, target_thread.pid);
}
}
diff --git a/fs_mgr/libfstab/fstab.cpp b/fs_mgr/libfstab/fstab.cpp
index 6fa22fe..6273ee2 100644
--- a/fs_mgr/libfstab/fstab.cpp
+++ b/fs_mgr/libfstab/fstab.cpp
@@ -849,6 +849,14 @@
[&path](const FstabEntry& entry) { return entry.mount_point == path; });
}
+FstabEntry* GetEntryForMountPoint(Fstab* fstab, const std::string_view path,
+ const std::string_view fstype) {
+ auto&& vec = GetEntriesByPred(fstab, [&path, fstype](const FstabEntry& entry) {
+ return entry.mount_point == path && entry.fs_type == fstype;
+ });
+ return vec.empty() ? nullptr : vec.front();
+}
+
std::vector<const FstabEntry*> GetEntriesForMountPoint(const Fstab* fstab,
const std::string& path) {
return GetEntriesByPred(fstab,
diff --git a/fs_mgr/libfstab/include/fstab/fstab.h b/fs_mgr/libfstab/include/fstab/fstab.h
index 5e4019c..dea7238 100644
--- a/fs_mgr/libfstab/include/fstab/fstab.h
+++ b/fs_mgr/libfstab/include/fstab/fstab.h
@@ -108,6 +108,9 @@
FstabEntry* GetEntryForMountPoint(Fstab* fstab, const std::string& path);
const FstabEntry* GetEntryForMountPoint(const Fstab* fstab, const std::string& path);
+FstabEntry* GetEntryForMountPoint(Fstab* fstab, const std::string_view path,
+ const std::string_view fstype);
+
// This method builds DSU fstab entries and transfer the fstab.
//
// fstab points to the unmodified fstab.
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
index 6a7153d..991e17c 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
@@ -31,15 +31,9 @@
static constexpr uint32_t kCowVersionMajor = 2;
static constexpr uint32_t kCowVersionMinor = 0;
-static constexpr uint32_t kCowVersionManifest = 2;
-
static constexpr uint32_t kMinCowVersion = 1;
static constexpr uint32_t kMaxCowVersion = 3;
-// Normally, this should be kMaxCowVersion. When a new version is under testing
-// it may be the previous value of kMaxCowVersion.
-static constexpr uint32_t kDefaultCowVersion = 2;
-
// This header appears as the first sequence of bytes in the COW. All fields
// in the layout are little-endian encoded. The on-disk layout is:
//
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader_test.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader_test.cpp
index 10cb06d..f00f236 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader_test.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader_test.cpp
@@ -184,7 +184,7 @@
unique_fd cow_fd(dup(cow_->fd));
ASSERT_GE(cow_fd, 0);
- auto writer = CreateCowWriter(kDefaultCowVersion, options, std::move(cow_fd));
+ auto writer = CreateCowWriter(2, options, std::move(cow_fd));
ASSERT_NO_FATAL_FAILURE(WriteCow(writer.get()));
ASSERT_NO_FATAL_FAILURE(TestReads(writer.get()));
}
diff --git a/fs_mgr/libsnapshot/snapshotctl.cpp b/fs_mgr/libsnapshot/snapshotctl.cpp
index 192e1d6..0158d4d 100644
--- a/fs_mgr/libsnapshot/snapshotctl.cpp
+++ b/fs_mgr/libsnapshot/snapshotctl.cpp
@@ -110,6 +110,7 @@
private:
std::optional<std::string> GetCowImagePath(std::string& name);
bool PrepareUpdate();
+ bool GetCowDevicePath(std::string partition_name, std::string* cow_path);
bool WriteSnapshotPatch(std::string cow_device, std::string patch);
std::string GetGroupName(const android::fs_mgr::LpMetadata& pt,
const std::string& partiton_name);
@@ -231,6 +232,23 @@
return true;
}
+bool MapSnapshots::GetCowDevicePath(std::string partition_name, std::string* cow_path) {
+ auto& dm = android::dm::DeviceMapper::Instance();
+ std::string cow_device = partition_name + "-cow";
+ if (dm.GetDmDevicePathByName(cow_device, cow_path)) {
+ return true;
+ }
+
+ LOG(INFO) << "Failed to find cow path: " << cow_device << " Checking the device for -img path";
+ // If the COW device exists only on /data
+ cow_device = partition_name + "-cow-img";
+ if (!dm.GetDmDevicePathByName(cow_device, cow_path)) {
+ LOG(ERROR) << "Failed to cow path: " << cow_device;
+ return false;
+ }
+ return true;
+}
+
bool MapSnapshots::ApplyUpdate() {
if (!PrepareUpdate()) {
LOG(ERROR) << "PrepareUpdate failed";
@@ -253,15 +271,13 @@
LOG(INFO) << "MapAllSnapshots success";
- auto& dm = android::dm::DeviceMapper::Instance();
auto target_slot = fs_mgr_get_other_slot_suffix();
for (auto& patchfile : patchfiles_) {
auto npos = patchfile.rfind(".patch");
auto partition_name = patchfile.substr(0, npos) + target_slot;
- auto cow_device = partition_name + "-cow";
std::string cow_path;
- if (!dm.GetDmDevicePathByName(cow_device, &cow_path)) {
- LOG(ERROR) << "Failed to cow path";
+ if (!GetCowDevicePath(partition_name, &cow_path)) {
+ LOG(ERROR) << "Failed to find cow path";
return false;
}
threads_.emplace_back(std::async(std::launch::async, &MapSnapshots::WriteSnapshotPatch,
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
index d05df82..56f7b59 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
@@ -135,7 +135,7 @@
unique_fd fd(cow_system_->fd);
cow_system_->fd = -1;
- return CreateCowWriter(kDefaultCowVersion, options, std::move(fd));
+ return CreateCowWriter(2, options, std::move(fd));
}
std::unique_ptr<ICowWriter> SnapuserdTestBase::CreateV3Cow() {
diff --git a/init/Android.bp b/init/Android.bp
index ff82f7f..c4e74d0 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -96,6 +96,7 @@
config_namespace: "ANDROID",
bool_variables: [
"PRODUCT_INSTALL_DEBUG_POLICY_TO_SYSTEM_EXT",
+ "release_write_appcompat_override_system_properties",
],
properties: [
"cflags",
@@ -159,6 +160,9 @@
"-DINSTALL_DEBUG_POLICY_TO_SYSTEM_EXT=1",
],
},
+ release_write_appcompat_override_system_properties: {
+ cflags: ["-DWRITE_APPCOMPAT_OVERRIDE_SYSTEM_PROPERTIES"],
+ }
},
static_libs: [
"libavb",
@@ -259,6 +263,7 @@
"avf_build_flags_cc",
"libinit_defaults",
],
+ recovery_available: false,
cflags: ["-DMICRODROID=1"],
}
@@ -276,6 +281,13 @@
defaults: ["init_defaults"],
srcs: ["main.cpp"],
symlinks: ["ueventd"],
+}
+
+cc_binary {
+ name: "init_second_stage",
+ defaults: ["init_second_stage_defaults"],
+ static_libs: ["libinit"],
+ visibility: ["//visibility:any_system_partition"],
target: {
platform: {
required: [
@@ -310,18 +322,12 @@
}
cc_binary {
- name: "init_second_stage",
- defaults: ["init_second_stage_defaults"],
- static_libs: ["libinit"],
- visibility: ["//visibility:any_system_partition"],
-}
-
-cc_binary {
name: "init_second_stage.microdroid",
defaults: [
"avf_build_flags_cc",
"init_second_stage_defaults",
],
+ recovery_available: false,
static_libs: ["libinit.microdroid"],
cflags: ["-DMICRODROID=1"],
installable: false,
diff --git a/init/README.ueventd.md b/init/README.ueventd.md
index 3c7107a..7d00195 100644
--- a/init/README.ueventd.md
+++ b/init/README.ueventd.md
@@ -59,9 +59,10 @@
`subsystem_name` is used to match uevent `SUBSYSTEM` value
-`devname` takes one of two options
+`devname` takes one of three options
1. `uevent_devname` specifies that the name of the node will be the uevent `DEVNAME`
- 2. `uevent_devpath` specified that the name of the node will be basename uevent `DEVPATH`
+ 2. `uevent_devpath` specifies that the name of the node will be basename uevent `DEVPATH`
+ 3. `sys_name` specifies that the name of the node will be the contents of `/sys/DEVPATH/name`
`dirname` is an optional parameter that specifies a directory within `/dev` where the node will be
created.
diff --git a/init/devices.h b/init/devices.h
index f9f4d79..44ce2a9 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -82,6 +82,7 @@
enum DevnameSource {
DEVNAME_UEVENT_DEVNAME,
DEVNAME_UEVENT_DEVPATH,
+ DEVNAME_SYS_NAME,
};
Subsystem() {}
@@ -92,10 +93,18 @@
// Returns the full path for a uevent of a device that is a member of this subsystem,
// according to the rules parsed from ueventd.rc
std::string ParseDevPath(const Uevent& uevent) const {
- std::string devname = devname_source_ == DEVNAME_UEVENT_DEVNAME
- ? uevent.device_name
- : android::base::Basename(uevent.path);
-
+ std::string devname;
+ if (devname_source_ == DEVNAME_UEVENT_DEVNAME) {
+ devname = uevent.device_name;
+ } else if (devname_source_ == DEVNAME_UEVENT_DEVPATH) {
+ devname = android::base::Basename(uevent.path);
+ } else if (devname_source_ == DEVNAME_SYS_NAME) {
+ if (android::base::ReadFileToString("/sys/" + uevent.path + "/name", &devname)) {
+ devname.pop_back(); // Remove terminating newline
+ } else {
+ devname = uevent.device_name;
+ }
+ }
return dir_name_ + "/" + devname;
}
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index ae216c6..5d3a273 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -556,11 +556,11 @@
return true;
}
// clang-format off
- const std::array<const char*, 7> args = {
+ const std::array<const char*, 8> args = {
"/system/bin/derive_microdroid_vendor_dice_node",
"--dice-driver", "/dev/open-dice0",
"--microdroid-vendor-disk-image", microdroid_vendor_block_dev->data(),
- "--output", "/microdroid_resources/dice_chain.raw",
+ "--output", "/microdroid_resources/dice_chain.raw", nullptr,
};
// clang-format-on
// ForkExecveAndWaitForCompletion calls waitpid to wait for the fork-ed process to finish.
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 58a0a7f..5a1b63b 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -1308,12 +1308,14 @@
}
selinux_android_restorecon(PROP_TREE_FILE, 0);
+#ifdef WRITE_APPCOMPAT_OVERRIDE_SYSTEM_PROPERTIES
mkdir(APPCOMPAT_OVERRIDE_PROP_FOLDERNAME, S_IRWXU | S_IXGRP | S_IXOTH);
if (!WriteStringToFile(serialized_contexts, APPCOMPAT_OVERRIDE_PROP_TREE_FILE, 0444, 0, 0,
false)) {
PLOG(ERROR) << "Unable to write appcompat override property infos to file";
}
selinux_android_restorecon(APPCOMPAT_OVERRIDE_PROP_TREE_FILE, 0);
+#endif
}
static void ExportKernelBootProps() {
diff --git a/init/ueventd_parser.cpp b/init/ueventd_parser.cpp
index d34672e..4395d88 100644
--- a/init/ueventd_parser.cpp
+++ b/init/ueventd_parser.cpp
@@ -218,6 +218,10 @@
subsystem_.devname_source_ = Subsystem::DEVNAME_UEVENT_DEVPATH;
return {};
}
+ if (args[1] == "sys_name") {
+ subsystem_.devname_source_ = Subsystem::DEVNAME_SYS_NAME;
+ return {};
+ }
return Error() << "invalid devname '" << args[1] << "'";
}
diff --git a/libmodprobe/libmodprobe.cpp b/libmodprobe/libmodprobe.cpp
index 5023c79..1a40da1 100644
--- a/libmodprobe/libmodprobe.cpp
+++ b/libmodprobe/libmodprobe.cpp
@@ -484,7 +484,11 @@
return false;
}
- if (module_options_[cnd_last].find("load_sequential=1") != std::string::npos) {
+ std::string str = "load_sequential=1";
+ auto it = module_options_[cnd_last].find(str);
+ if (it != std::string::npos) {
+ module_options_[cnd_last].erase(it, it + str.size());
+
if (!LoadWithAliases(cnd_last, true)) {
return false;
}
diff --git a/libpackagelistparser/include/packagelistparser/packagelistparser.h b/libpackagelistparser/include/packagelistparser/packagelistparser.h
index e89cb54..9bd212a 100644
--- a/libpackagelistparser/include/packagelistparser/packagelistparser.h
+++ b/libpackagelistparser/include/packagelistparser/packagelistparser.h
@@ -33,7 +33,10 @@
/** Package name like "com.android.blah". */
char* name;
- /** Package uid like 10014. */
+ /**
+ * Package uid like 10014.
+ * Note that apexes and SDK libraries may have a bogus 0xffffffff value.
+ */
uid_t uid;
/** Package's AndroidManifest.xml debuggable flag. */
diff --git a/libpackagelistparser/packagelistparser.cpp b/libpackagelistparser/packagelistparser.cpp
index 59c3a74..638cc43 100644
--- a/libpackagelistparser/packagelistparser.cpp
+++ b/libpackagelistparser/packagelistparser.cpp
@@ -63,14 +63,13 @@
}
static bool parse_line(const char* path, size_t line_number, const char* line, pkg_info* info) {
- unsigned long uid;
int debuggable;
char* gid_list;
int profileable_from_shell = 0;
-
int fields =
- sscanf(line, "%ms %lu %d %ms %ms %ms %d %ld", &info->name, &uid, &debuggable, &info->data_dir,
- &info->seinfo, &gid_list, &profileable_from_shell, &info->version_code);
+ sscanf(line, "%ms %u %d %ms %ms %ms %d %ld", &info->name, &info->uid,
+ &debuggable, &info->data_dir, &info->seinfo, &gid_list,
+ &profileable_from_shell, &info->version_code);
// Handle the more complicated gids field and free the temporary string.
bool gids_okay = parse_gids(path, line_number, gid_list, info);
@@ -84,14 +83,7 @@
return false;
}
- // Extra validation.
- if (uid > UID_MAX) {
- ALOGE("%s:%zu: uid %lu > UID_MAX", path, line_number, uid);
- return false;
- }
- info->uid = uid;
-
- // Integer to bool conversions.
+ // Convert integers to bools.
info->debuggable = debuggable;
info->profileable_from_shell = profileable_from_shell;
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 8df2805..387c104 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -520,8 +520,14 @@
static int KillProcessGroup(
uid_t uid, pid_t initialPid, int signal, bool once = false,
std::chrono::steady_clock::time_point until = std::chrono::steady_clock::now() + 2200ms) {
- CHECK_GE(uid, 0);
- CHECK_GT(initialPid, 0);
+ if (uid < 0) {
+ LOG(ERROR) << __func__ << ": invalid UID " << uid;
+ return -1;
+ }
+ if (initialPid <= 0) {
+ LOG(ERROR) << __func__ << ": invalid PID " << initialPid;
+ return -1;
+ }
// Always attempt to send a kill signal to at least the initialPid, at least once, regardless of
// whether its cgroup exists or not. This should only be necessary if a bug results in the
@@ -681,8 +687,14 @@
}
int createProcessGroup(uid_t uid, pid_t initialPid, bool memControl) {
- CHECK_GE(uid, 0);
- CHECK_GT(initialPid, 0);
+ if (uid < 0) {
+ LOG(ERROR) << __func__ << ": invalid UID " << uid;
+ return -1;
+ }
+ if (initialPid <= 0) {
+ LOG(ERROR) << __func__ << ": invalid PID " << initialPid;
+ return -1;
+ }
if (memControl && !UsePerAppMemcg()) {
LOG(ERROR) << "service memory controls are used without per-process memory cgroup support";
diff --git a/libsysutils/include/sysutils/SocketListener.h b/libsysutils/include/sysutils/SocketListener.h
index 67a691a..a7fd09e 100644
--- a/libsysutils/include/sysutils/SocketListener.h
+++ b/libsysutils/include/sysutils/SocketListener.h
@@ -19,6 +19,7 @@
#include <pthread.h>
#include <unordered_map>
+#include <vector>
#include <sysutils/SocketClient.h>
#include "SocketClientCommand.h"
diff --git a/libutils/Android.bp b/libutils/Android.bp
index ad5b752..1741187 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -109,7 +109,7 @@
},
},
fuzz_config: {
- cc: ["smoreland@google.com"],
+ cc: ["smoreland@google.com"],
},
}
@@ -273,6 +273,17 @@
"libbase",
"liblog",
],
+ fuzz_config: {
+ cc: [
+ "smoreland@google.com",
+ ],
+ componentid: 128577,
+ description: "The fuzzer targets the APIs of libutils",
+ vector: "local_no_privileges_required",
+ service_privilege: "privileged",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
+ },
}
cc_fuzz {
diff --git a/rootdir/Android.bp b/rootdir/Android.bp
index 6a3484e..06227c3 100644
--- a/rootdir/Android.bp
+++ b/rootdir/Android.bp
@@ -101,3 +101,15 @@
src: "init.usb.configfs.rc",
sub_dir: "init/hw",
}
+
+prebuilt_etc {
+ name: "etc_hosts",
+ src: "etc/hosts",
+ filename: "hosts",
+}
+
+prebuilt_etc {
+ name: "init-debug.rc",
+ src: "init-debug.rc",
+ sub_dir: "init",
+}
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 593bb1e..fb91b58 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -3,19 +3,6 @@
$(eval $(call declare-1p-copy-files,system/core/rootdir,))
#######################################
-# init-debug.rc
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := init-debug.rc
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/init
-
-include $(BUILD_PREBUILT)
-
-#######################################
# asan.options
ifneq ($(filter address,$(SANITIZE_TARGET)),)
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 1af46c1..f7f0cc3 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -425,16 +425,6 @@
chown system system /proc/pressure/memory
chmod 0664 /proc/pressure/memory
- # qtaguid will limit access to specific data based on group memberships.
- # net_bw_acct grants impersonation of socket owners.
- # net_bw_stats grants access to other apps' detailed tagged-socket stats.
- chown root net_bw_acct /proc/net/xt_qtaguid/ctrl
- chown root net_bw_stats /proc/net/xt_qtaguid/stats
-
- # Allow everybody to read the xt_qtaguid resource tracking misc dev.
- # This is needed by any process that uses socket tagging.
- chmod 0644 /dev/xt_qtaguid
-
mount bpf bpf /sys/fs/bpf nodev noexec nosuid
# pstore/ramoops previous console log
@@ -666,10 +656,6 @@
exec -- /system/bin/fsverity_init --load-verified-keys
# Only enable the bootreceiver tracing instance for kernels 5.10 and above.
-on late-fs && property:ro.kernel.version=4.9
- setprop bootreceiver.enable 0
-on late-fs && property:ro.kernel.version=4.14
- setprop bootreceiver.enable 0
on late-fs && property:ro.kernel.version=4.19
setprop bootreceiver.enable 0
on late-fs && property:ro.kernel.version=5.4
@@ -884,6 +870,9 @@
mkdir /data/app-lib 0771 system system encryption=Require
mkdir /data/app 0771 system system encryption=Require
+ # Create directory for app metadata files
+ mkdir /data/app-metadata 0700 system system encryption=Require
+
# create directory for updated font files.
mkdir /data/fonts/ 0771 root root encryption=Require
mkdir /data/fonts/files 0771 system system
@@ -972,6 +961,10 @@
mkdir /data/vendor_ce 0551 root root encryption=None
mkdir /data/vendor_de 0551 root root encryption=None
+ # Similar to the top-level CE and DE directories, /data/storage_area must
+ # itself be unencrypted, since it contains encrypted directories.
+ mkdir /data/storage_area 0551 root root encryption=None
+
# Set the casefold flag on /data/media. For upgrades, a restorecon can be
# needed first to relabel the directory from media_rw_data_file.
restorecon /data/media
@@ -985,8 +978,12 @@
mkdir /data_mirror/data_de 0700 root root
mkdir /data_mirror/misc_ce 0700 root root
mkdir /data_mirror/misc_de 0700 root root
+ mkdir /data_mirror/storage_area 0700 root root
# Create CE and DE data directory for default volume
+ # Not needed for storage_area directory, since this is
+ # not supported for non-default volumes and the path
+ # does not include the volume ID
mkdir /data_mirror/data_ce/null 0700 root root
mkdir /data_mirror/data_de/null 0700 root root
mkdir /data_mirror/misc_ce/null 0700 root root
@@ -1001,6 +998,9 @@
mount none /data/misc_ce /data_mirror/misc_ce/null bind rec
mount none /data/misc_de /data_mirror/misc_de/null bind rec
+ # Also bind mount for the storage area directory (minus the volume ID)
+ mount none /data/storage_area /data_mirror/storage_area bind rec
+
# Create mirror directory for jit profiles
mkdir /data_mirror/cur_profiles 0700 root root
mount none /data/misc/profiles/cur /data_mirror/cur_profiles bind rec
@@ -1341,6 +1341,8 @@
umount /data_mirror/data_ce/null/0
umount /data_mirror/data_ce/null
umount /data_mirror/data_de/null
+ umount /data_mirror/storage_area/0
+ umount /data_mirror/storage_area
umount /data_mirror/cur_profiles
umount /data_mirror/ref_profiles
umount /data_mirror
diff --git a/toolbox/modprobe.cpp b/toolbox/modprobe.cpp
index 45dd9b8..b0e76ea 100644
--- a/toolbox/modprobe.cpp
+++ b/toolbox/modprobe.cpp
@@ -15,6 +15,7 @@
*/
#include <ctype.h>
+#include <fcntl.h>
#include <getopt.h>
#include <stdlib.h>
@@ -27,6 +28,7 @@
#include <modprobe/modprobe.h>
#include <sys/utsname.h>
+#include <unistd.h>
namespace {
@@ -105,6 +107,11 @@
return 0;
}
+std::string GetPageSizeSuffix() {
+ static const size_t page_size = sysconf(_SC_PAGE_SIZE);
+ return android::base::StringPrintf("_%zuk", page_size / 1024);
+}
+
} // anonymous namespace
extern "C" int modprobe_main(int argc, char** argv) {
@@ -233,6 +240,19 @@
// Allow modules to be directly inside /lib/modules
mod_dirs.emplace_back(LIB_MODULES_PREFIX);
}
+ if (getpagesize() != 4096) {
+ struct utsname uts {};
+ if (uname(&uts)) {
+ PLOG(FATAL) << "Failed to get kernel version";
+ }
+ const auto module_dir = android::base::StringPrintf("/lib/modules/%s%s", uts.release,
+ GetPageSizeSuffix().c_str());
+ struct stat st {};
+ if (stat(module_dir.c_str(), &st) == 0 && S_ISDIR(st.st_mode)) {
+ mod_dirs.clear();
+ mod_dirs.emplace_back(module_dir);
+ }
+ }
LOG(DEBUG) << "mode is " << mode;
LOG(DEBUG) << "mod_dirs is: " << android::base::Join(mod_dirs, " ");
diff --git a/toolbox/setprop.cpp b/toolbox/setprop.cpp
index acf8c3e..91edf45 100644
--- a/toolbox/setprop.cpp
+++ b/toolbox/setprop.cpp
@@ -58,7 +58,7 @@
}
}
- if (value.size() >= PROP_VALUE_MAX && !StartsWith(value, "ro.")) {
+ if (value.size() >= PROP_VALUE_MAX && !StartsWith(name, "ro.")) {
std::cerr << "Value '" << value << "' is too long, " << value.size()
<< " bytes vs a max of " << PROP_VALUE_MAX << std::endl;
return EXIT_FAILURE;
diff --git a/trusty/keymaster/set_attestation_ids/set_attestation_ids.cpp b/trusty/keymaster/set_attestation_ids/set_attestation_ids.cpp
index 6b8f90f..dec64e1 100644
--- a/trusty/keymaster/set_attestation_ids/set_attestation_ids.cpp
+++ b/trusty/keymaster/set_attestation_ids/set_attestation_ids.cpp
@@ -247,6 +247,7 @@
return EXIT_FAILURE;
} else {
printf("done\n");
+ printf("\nNOTE: device reboot may be required before changes take effect.\n");
return EXIT_SUCCESS;
}
}
diff --git a/trusty/storage/proxy/proxy.c b/trusty/storage/proxy/proxy.c
index 67e935e..6cb72d5 100644
--- a/trusty/storage/proxy/proxy.c
+++ b/trusty/storage/proxy/proxy.c
@@ -41,9 +41,13 @@
static const char* trusty_devname;
static const char* rpmb_devname;
static const char* ss_srv_name = STORAGE_DISK_PROXY_PORT;
+static const char* max_file_size_from;
static enum dev_type dev_type = MMC_RPMB;
+/* List head for storage mapping, elements added at init, and never removed */
+static struct storage_mapping_node* storage_mapping_head;
+
static enum dev_type parse_dev_type(const char* dev_type_name) {
if (!strcmp(dev_type_name, "mmc")) {
return MMC_RPMB;
@@ -58,17 +62,61 @@
}
}
-static const char* _sopts = "hp:d:r:t:";
+static int parse_and_append_file_mapping(const char* file_mapping) {
+ if (file_mapping == NULL) {
+ ALOGE("Provided file mapping is null\n");
+ return -1;
+ }
+ char* file_mapping_dup = strdup(file_mapping);
+ if (file_mapping_dup == NULL) {
+ ALOGE("Couldn't duplicate string: %s\n", file_mapping);
+ return -1;
+ }
+ const char* file_name = strtok(file_mapping_dup, ":");
+ if (file_name == NULL) {
+ ALOGE("No file name found\n");
+ return -1;
+ }
+ const char* backing_storage = strtok(NULL, ":");
+ if (backing_storage == NULL) {
+ ALOGE("No backing storage found\n");
+ return -1;
+ }
+
+ struct storage_mapping_node* new_node = malloc(sizeof(struct storage_mapping_node));
+ if (new_node == NULL) {
+ ALOGE("Couldn't allocate additional storage_mapping_node\n");
+ return -1;
+ }
+ *new_node = (struct storage_mapping_node){.file_name = file_name,
+ .backing_storage = backing_storage,
+ .next = storage_mapping_head,
+ .fd = -1};
+ storage_mapping_head = new_node;
+ return 0;
+}
+
+static const char* _sopts = "hp:d:r:t:m:f:";
static const struct option _lopts[] = {{"help", no_argument, NULL, 'h'},
{"trusty_dev", required_argument, NULL, 'd'},
{"data_path", required_argument, NULL, 'p'},
{"rpmb_dev", required_argument, NULL, 'r'},
{"dev_type", required_argument, NULL, 't'},
+ {"max_file_size_from", required_argument, NULL, 'm'},
+ {"file_storage_mapping", required_argument, NULL, 'f'},
{0, 0, 0, 0}};
static void show_usage_and_exit(int code) {
- ALOGE("usage: storageproxyd -d <trusty_dev> -p <data_path> -r <rpmb_dev> -t <dev_type>\n");
+ ALOGE("usage: storageproxyd -d <trusty_dev> -p <data_path> -r <rpmb_dev> -t <dev_type> [-m "
+ "<file>] [-f <file>:<mapping>]\n");
ALOGE("Available dev types: mmc, virt\n");
+ ALOGE("-f = Maps secure storage files like `0` and `persist/0`\n"
+ "to block devices. Storageproxyd will handle creating the\n"
+ "appropriate symlinks in the root datapath.\n");
+ ALOGE("-m = Specifies the max size constraint for file backed storages.\n"
+ "The constraint is chosen by giving a file, this allows for passing a\n"
+ "block device for which a max file size can be queried. File based\n"
+ "storages will be constrained to that size as well.\n");
exit(code);
}
@@ -187,6 +235,7 @@
static void parse_args(int argc, char* argv[]) {
int opt;
int oidx = 0;
+ int rc = 0;
while ((opt = getopt_long(argc, argv, _sopts, _lopts, &oidx)) != -1) {
switch (opt) {
@@ -210,6 +259,18 @@
}
break;
+ case 'f':
+ rc = parse_and_append_file_mapping(optarg);
+ if (rc < 0) {
+ ALOGE("Failed to parse file mapping: %s\n", optarg);
+ show_usage_and_exit(EXIT_FAILURE);
+ }
+ break;
+
+ case 'm':
+ max_file_size_from = strdup(optarg);
+ break;
+
default:
ALOGE("unrecognized option (%c):\n", opt);
show_usage_and_exit(EXIT_FAILURE);
@@ -225,6 +286,12 @@
ALOGI("storage data root: %s\n", ss_data_root);
ALOGI("trusty dev: %s\n", trusty_devname);
ALOGI("rpmb dev: %s\n", rpmb_devname);
+ ALOGI("File Mappings: \n");
+ const struct storage_mapping_node* curr = storage_mapping_head;
+ for (; curr != NULL; curr = curr->next) {
+ ALOGI("\t%s -> %s\n", curr->file_name, curr->backing_storage);
+ }
+ ALOGI("max file size from: %s\n", max_file_size_from ? max_file_size_from : "(unset)");
}
int main(int argc, char* argv[]) {
@@ -252,7 +319,7 @@
ABinderProcess_startThreadPool();
/* initialize secure storage directory */
- rc = storage_init(ss_data_root);
+ rc = storage_init(ss_data_root, storage_mapping_head, max_file_size_from);
if (rc < 0) return EXIT_FAILURE;
/* open rpmb device */
diff --git a/trusty/storage/proxy/storage.c b/trusty/storage/proxy/storage.c
index 8c8edb7..6d0c616 100644
--- a/trusty/storage/proxy/storage.c
+++ b/trusty/storage/proxy/storage.c
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <assert.h>
#include <cutils/properties.h>
#include <errno.h>
#include <fcntl.h>
@@ -39,16 +40,20 @@
#define ALTERNATE_DATA_DIR "alternate/"
/* Maximum file size for filesystem backed storage (i.e. not block dev backed storage) */
-#define MAX_FILE_SIZE (0x10000000000)
+static uint64_t max_file_size = 0x10000000000;
enum sync_state {
SS_UNUSED = -1,
- SS_CLEAN = 0,
- SS_DIRTY = 1,
+ SS_CLEAN = 0,
+ SS_DIRTY = 1,
+ SS_CLEAN_NEED_SYMLINK = 2,
};
static const char *ssdir_name;
+/* List head for storage mapping, elements added at init, and never removed */
+static struct storage_mapping_node* storage_mapping_head;
+
/*
* Property set to 1 after we have opened a file under ssdir_name. The backing
* files for both TD and TDP are currently located under /data/vendor/ss and can
@@ -75,24 +80,103 @@
uint8_t data[MAX_READ_SIZE];
} read_rsp;
-static uint32_t insert_fd(int open_flags, int fd)
-{
+static uint32_t insert_fd(int open_flags, int fd, struct storage_mapping_node* node) {
uint32_t handle = fd;
if (handle < FD_TBL_SIZE) {
- fd_state[fd] = SS_CLEAN; /* fd clean */
- if (open_flags & O_TRUNC) {
- fd_state[fd] = SS_DIRTY; /* set fd dirty */
- }
+ fd_state[fd] = SS_CLEAN; /* fd clean */
+ if (open_flags & O_TRUNC) {
+ assert(node == NULL);
+ fd_state[fd] = SS_DIRTY; /* set fd dirty */
+ }
+
+ if (node != NULL) {
+ fd_state[fd] = SS_CLEAN_NEED_SYMLINK;
+ }
} else {
ALOGW("%s: untracked fd %u\n", __func__, fd);
if (open_flags & (O_TRUNC | O_CREAT)) {
fs_state = SS_DIRTY;
}
}
+
+ if (node != NULL) {
+ node->fd = fd;
+ }
+
return handle;
}
+static void clear_fd_symlink_status(uint32_t handle, struct storage_mapping_node* entry) {
+ /* Always clear FD, in case fd is not in FD_TBL */
+ entry->fd = -1;
+
+ if (handle >= FD_TBL_SIZE) {
+ ALOGE("%s: untracked fd=%u\n", __func__, handle);
+ return;
+ }
+
+ if (fd_state[handle] == SS_CLEAN_NEED_SYMLINK) {
+ fd_state[handle] = SS_CLEAN;
+ }
+}
+
+static struct storage_mapping_node* get_pending_symlink_mapping(uint32_t handle) {
+ /* Fast lookup failure, is it in FD TBL */
+ if (handle < FD_TBL_SIZE && fd_state[handle] != SS_CLEAN_NEED_SYMLINK) {
+ return NULL;
+ }
+
+ /* Go find our mapping */
+ struct storage_mapping_node* curr = storage_mapping_head;
+ for (; curr != NULL; curr = curr->next) {
+ if (curr->fd == handle) {
+ return curr;
+ }
+ }
+
+ /* Safety check: state inconsistent if we get here with handle inside table range */
+ assert(handle >= FD_TBL_SIZE);
+
+ return NULL;
+};
+
+static int possibly_symlink_and_clear_mapping(uint32_t handle) {
+ struct storage_mapping_node* entry = get_pending_symlink_mapping(handle);
+ if (entry == NULL) {
+ /* No mappings pending */
+ return 0;
+ }
+
+ /* Create full path */
+ char* path = NULL;
+ int rc = asprintf(&path, "%s/%s", ssdir_name, entry->file_name);
+ if (rc < 0) {
+ ALOGE("%s: asprintf failed\n", __func__);
+ return -1;
+ }
+
+ /* Try and setup the symlinking */
+ ALOGI("Creating symlink %s->%s\n", path, entry->backing_storage);
+ rc = symlink(entry->backing_storage, path);
+ if (rc < 0) {
+ ALOGE("%s: error symlinking %s->%s (%s)\n", __func__, path, entry->backing_storage,
+ strerror(errno));
+ free(path);
+ return rc;
+ }
+ free(path);
+
+ clear_fd_symlink_status(handle, entry);
+
+ return rc;
+}
+
+static bool is_pending_symlink(uint32_t handle) {
+ struct storage_mapping_node* entry = get_pending_symlink_mapping(handle);
+ return entry != NULL;
+}
+
static int lookup_fd(uint32_t handle, bool dirty)
{
if (dirty) {
@@ -107,6 +191,12 @@
static int remove_fd(uint32_t handle)
{
+ /* Cleanup fd in symlink mapping if it exists */
+ struct storage_mapping_node* entry = get_pending_symlink_mapping(handle);
+ if (entry != NULL) {
+ entry->fd = -1;
+ }
+
if (handle < FD_TBL_SIZE) {
fd_state[handle] = SS_UNUSED; /* set to uninstalled */
}
@@ -247,11 +337,73 @@
watch_progress(watcher, "done syncing parent");
}
+static struct storage_mapping_node* get_storage_mapping_entry(const char* source) {
+ struct storage_mapping_node* curr = storage_mapping_head;
+ for (; curr != NULL; curr = curr->next) {
+ if (!strcmp(source, curr->file_name)) {
+ ALOGI("Found backing file %s for %s\n", curr->backing_storage, source);
+ return curr;
+ }
+ }
+ return NULL;
+}
+
+static bool is_backing_storage_mapped(const char* source) {
+ const struct storage_mapping_node* curr = storage_mapping_head;
+ for (; curr != NULL; curr = curr->next) {
+ if (!strcmp(source, curr->backing_storage)) {
+ ALOGI("Backed storage mapping exists for %s\n", curr->backing_storage);
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Attempts to open a backed file, if mapped, without creating the symlink. Symlink will be created
+ * later on the first write. This allows us to continue reporting zero read sizes until the first
+ * write. */
+static int open_possibly_mapped_file(const char* short_path, const char* full_path, int open_flags,
+ struct storage_mapping_node** entry) {
+ /* See if mapping exists, report upstream if there is no mapping. */
+ struct storage_mapping_node* mapping_entry = get_storage_mapping_entry(short_path);
+ if (mapping_entry == NULL) {
+ return TEMP_FAILURE_RETRY(open(full_path, open_flags, S_IRUSR | S_IWUSR));
+ }
+
+ /* Check for existence of root path, we don't allow mappings during early boot */
+ struct stat buf = {0};
+ if (stat(ssdir_name, &buf) != 0) {
+ ALOGW("Root path not accessible yet, refuse to open mappings for now.\n");
+ return -1;
+ }
+
+ /* We don't support exclusive opening of mapped files */
+ if (open_flags & O_EXCL) {
+ ALOGE("Requesting exclusive open on backed storage isn't supported: %s\n", full_path);
+ return -1;
+ }
+
+ /* Try and open mapping file */
+ open_flags &= ~(O_CREAT | O_EXCL);
+ ALOGI("%s Attempting to open mapped file: %s\n", __func__, mapping_entry->backing_storage);
+ int fd =
+ TEMP_FAILURE_RETRY(open(mapping_entry->backing_storage, open_flags, S_IRUSR | S_IWUSR));
+ if (fd < 0) {
+ ALOGE("%s Failed to open mapping file: %s\n", __func__, mapping_entry->backing_storage);
+ return -1;
+ }
+
+ /* Let caller know which entry we used for opening */
+ *entry = mapping_entry;
+ return fd;
+}
+
int storage_file_open(struct storage_msg* msg, const void* r, size_t req_len,
struct watcher* watcher) {
char* path = NULL;
const struct storage_file_open_req *req = r;
struct storage_file_open_resp resp = {0};
+ struct storage_mapping_node* mapping_entry = NULL;
if (req_len < sizeof(*req)) {
ALOGE("%s: invalid request length (%zd < %zd)\n",
@@ -321,14 +473,18 @@
if (req->flags & STORAGE_FILE_OPEN_CREATE_EXCLUSIVE) {
/* create exclusive */
open_flags |= O_CREAT | O_EXCL;
- rc = TEMP_FAILURE_RETRY(open(path, open_flags, S_IRUSR | S_IWUSR));
+
+ /* Look for and attempt opening a mapping, else just do normal open. */
+ rc = open_possibly_mapped_file(req->name, path, open_flags, &mapping_entry);
} else {
/* try open first */
rc = TEMP_FAILURE_RETRY(open(path, open_flags, S_IRUSR | S_IWUSR));
if (rc == -1 && errno == ENOENT) {
/* then try open with O_CREATE */
open_flags |= O_CREAT;
- rc = TEMP_FAILURE_RETRY(open(path, open_flags, S_IRUSR | S_IWUSR));
+
+ /* Look for and attempt opening a mapping, else just do normal open. */
+ rc = open_possibly_mapped_file(req->name, path, open_flags, &mapping_entry);
}
}
@@ -356,7 +512,7 @@
/* at this point rc contains storage file fd */
msg->result = STORAGE_NO_ERROR;
- resp.handle = insert_fd(open_flags, rc);
+ resp.handle = insert_fd(open_flags, rc, mapping_entry);
ALOGV("%s: \"%s\": fd = %u: handle = %d\n",
__func__, path, rc, resp.handle);
@@ -433,6 +589,14 @@
goto err_response;
}
+ /* Handle any delayed symlinking for this handle if any */
+ rc = possibly_symlink_and_clear_mapping(req->handle);
+ if (rc < 0) {
+ ALOGE("Failed to symlink storage\n");
+ msg->result = STORAGE_ERR_GENERIC;
+ goto err_response;
+ }
+
int fd = lookup_fd(req->handle, true);
watch_progress(watcher, "writing");
if (write_with_retry(fd, &req->data[0], req_len - sizeof(*req),
@@ -479,6 +643,14 @@
goto err_response;
}
+ /* If this handle has a delayed symlink we should report 0 size reads until first write occurs
+ */
+ if (is_pending_symlink(req->handle)) {
+ ALOGI("Pending symlink: Forcing read result 0.\n");
+ msg->result = STORAGE_NO_ERROR;
+ return ipc_respond(msg, &read_rsp, sizeof(read_rsp.hdr));
+ }
+
int fd = lookup_fd(req->handle, false);
watch_progress(watcher, "reading");
ssize_t read_res = read_with_retry(fd, read_rsp.hdr.data, req->size,
@@ -592,7 +764,7 @@
goto err_response;
}
} else {
- max_size = MAX_FILE_SIZE;
+ max_size = max_file_size;
}
resp.max_size = max_size;
@@ -603,17 +775,79 @@
return ipc_respond(msg, NULL, 0);
}
-int storage_init(const char *dirname)
-{
+int determine_max_file_size(const char* max_file_size_from) {
+ /* Use default if none passed in */
+ if (max_file_size_from == NULL) {
+ ALOGI("No max file source given, continuing to use default: 0x%" PRIx64 "\n",
+ max_file_size);
+ return 0;
+ }
+
+ /* Check that max_file_size_from is part of our mapping list. */
+ if (!is_backing_storage_mapped(max_file_size_from)) {
+ ALOGE("%s: file doesn't match mapped storages (filename=%s)\n", __func__,
+ max_file_size_from);
+ return -1;
+ }
+
+ ALOGI("Using %s to determine max file size.\n", max_file_size_from);
+
+ /* Error if max file size source not found, possible misconfig. */
+ struct stat buf = {0};
+ int rc = stat(max_file_size_from, &buf);
+ if (rc < 0) {
+ ALOGE("%s: error stat'ing file (filename=%s): %s\n", __func__, max_file_size_from,
+ strerror(errno));
+ return -1;
+ }
+
+ /* Currently only support block device as max file size source */
+ if ((buf.st_mode & S_IFMT) != S_IFBLK) {
+ ALOGE("Unsupported max file size source type: %d\n", buf.st_mode);
+ return -1;
+ }
+
+ ALOGI("%s is a block device, determining block device size\n", max_file_size_from);
+ uint64_t max_size = 0;
+ int fd = TEMP_FAILURE_RETRY(open(max_file_size_from, O_RDONLY | O_NONBLOCK));
+ if (fd < 0) {
+ ALOGE("%s: failed to open backing file %s for ioctl: %s\n", __func__, max_file_size_from,
+ strerror(errno));
+ return -1;
+ }
+ rc = ioctl(fd, BLKGETSIZE64, &max_size);
+ if (rc < 0) {
+ ALOGE("%s: error calling ioctl on file (fd=%d): %s\n", __func__, fd, strerror(errno));
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ max_file_size = max_size;
+
+ ALOGI("Using 0x%" PRIx64 " as max file size\n", max_file_size);
+ return 0;
+}
+
+int storage_init(const char* dirname, struct storage_mapping_node* mappings,
+ const char* max_file_size_from) {
/* If there is an active DSU image, use the alternate fs mode. */
alternate_mode = is_gsi_running();
fs_state = SS_CLEAN;
for (uint i = 0; i < FD_TBL_SIZE; i++) {
- fd_state[i] = SS_UNUSED; /* uninstalled */
+ fd_state[i] = SS_UNUSED; /* uninstalled */
}
ssdir_name = dirname;
+
+ storage_mapping_head = mappings;
+
+ /* Set the max file size based on incoming configuration */
+ int rc = determine_max_file_size(max_file_size_from);
+ if (rc < 0) {
+ return rc;
+ }
+
return 0;
}
@@ -623,17 +857,17 @@
watch_progress(watcher, "sync fd table");
/* sync fd table and reset it to clean state first */
for (uint fd = 0; fd < FD_TBL_SIZE; fd++) {
- if (fd_state[fd] == SS_DIRTY) {
- if (fs_state == SS_CLEAN) {
- /* need to sync individual fd */
- rc = fsync(fd);
- if (rc < 0) {
- ALOGE("fsync for fd=%d failed: %s\n", fd, strerror(errno));
- return rc;
- }
- }
- fd_state[fd] = SS_CLEAN; /* set to clean */
- }
+ if (fd_state[fd] == SS_DIRTY) {
+ if (fs_state == SS_CLEAN) {
+ /* need to sync individual fd */
+ rc = fsync(fd);
+ if (rc < 0) {
+ ALOGE("fsync for fd=%d failed: %s\n", fd, strerror(errno));
+ return rc;
+ }
+ }
+ fd_state[fd] = SS_CLEAN; /* set to clean */
+ }
}
/* check if we need to sync all filesystems */
diff --git a/trusty/storage/proxy/storage.h b/trusty/storage/proxy/storage.h
index f29fdf2..6dbfe37 100644
--- a/trusty/storage/proxy/storage.h
+++ b/trusty/storage/proxy/storage.h
@@ -21,6 +21,14 @@
/* Defined in watchdog.h */
struct watcher;
+/* Is used for managing alternate backing storage, generally will be a block device. */
+struct storage_mapping_node {
+ struct storage_mapping_node* next;
+ const char* file_name;
+ const char* backing_storage;
+ int fd;
+};
+
int storage_file_delete(struct storage_msg* msg, const void* req, size_t req_len,
struct watcher* watcher);
@@ -45,6 +53,7 @@
int storage_file_get_max_size(struct storage_msg* msg, const void* req, size_t req_len,
struct watcher* watcher);
-int storage_init(const char* dirname);
+int storage_init(const char* dirname, struct storage_mapping_node* head,
+ const char* max_file_size_from);
int storage_sync_checkpoint(struct watcher* watcher);