Merge "Rename data/pkg_staging to data/app-staging."
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 3286959..2b328ab 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -222,7 +222,9 @@
" all,adb,sockets,packets,rwx,usb,sync,sysdeps,transport,jdwp\n"
" $ADB_VENDOR_KEYS colon-separated list of keys (files or directories)\n"
" $ANDROID_SERIAL serial number to connect to (see -s)\n"
- " $ANDROID_LOG_TAGS tags to be used by logcat (see logcat --help)\n");
+ " $ANDROID_LOG_TAGS tags to be used by logcat (see logcat --help)\n"
+ " $ADB_LOCAL_TRANSPORT_MAX_PORT max emulator scan port (default 5585, 16 emus)\n"
+ );
// clang-format on
}
diff --git a/adb/daemon/remount_service.cpp b/adb/daemon/remount_service.cpp
index 7999ddc..ce494ee 100644
--- a/adb/daemon/remount_service.cpp
+++ b/adb/daemon/remount_service.cpp
@@ -27,68 +27,62 @@
#include "adb_io.h"
#include "adb_unique_fd.h"
-void remount_service(unique_fd fd, const std::string& cmd) {
- static constexpr char remount_cmd[] = "/system/bin/remount";
- static constexpr char remount_failed[] = "remount failed\n";
+static constexpr char kRemountCmd[] = "/system/bin/remount";
+static bool do_remount(int fd, const std::string& cmd) {
if (getuid() != 0) {
- WriteFdExactly(fd.get(), "Not running as root. Try \"adb root\" first.\n");
- WriteFdExactly(fd.get(), remount_failed);
- return;
+ WriteFdExactly(fd, "Not running as root. Try \"adb root\" first.\n");
+ return false;
}
- auto pid = vfork();
+ auto pid = fork();
if (pid < 0) {
- WriteFdFmt(fd.get(), "Failed to fork to %s: %s\n", remount_cmd, strerror(errno));
- WriteFdExactly(fd.get(), remount_failed);
- return;
+ WriteFdFmt(fd, "Failed to fork to %s: %s\n", kRemountCmd, strerror(errno));
+ return false;
}
if (pid == 0) {
// child side of the fork
- fcntl(fd.get(), F_SETFD, 0);
- dup2(fd.get(), STDIN_FILENO);
- dup2(fd.get(), STDOUT_FILENO);
- dup2(fd.get(), STDERR_FILENO);
+ dup2(fd, STDIN_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
- execl(remount_cmd, remount_cmd, cmd.empty() ? nullptr : cmd.c_str(), nullptr);
- _exit(-errno ?: 42);
+ execl(kRemountCmd, kRemountCmd, cmd.empty() ? nullptr : cmd.c_str(), nullptr);
+ _exit(errno);
}
int wstatus = 0;
auto ret = waitpid(pid, &wstatus, 0);
if (ret == -1) {
- WriteFdFmt(fd.get(), "Failed to wait for %s: %s\n", remount_cmd, strerror(errno));
- goto err;
- }
-
- if (ret != pid) {
- WriteFdFmt(fd.get(), "pid %d and waitpid return %d do not match for %s\n",
- static_cast<int>(pid), static_cast<int>(ret), remount_cmd);
- goto err;
+ WriteFdFmt(fd, "Failed to wait for %s: %s\n", kRemountCmd, strerror(errno));
+ return false;
+ } else if (ret != pid) {
+ WriteFdFmt(fd, "pid %d and waitpid return %d do not match for %s\n",
+ static_cast<int>(pid), static_cast<int>(ret), kRemountCmd);
+ return false;
}
if (WIFSIGNALED(wstatus)) {
- WriteFdFmt(fd.get(), "%s terminated with signal %s\n", remount_cmd,
+ WriteFdFmt(fd, "%s terminated with signal %s\n", kRemountCmd,
strsignal(WTERMSIG(wstatus)));
- goto err;
+ return false;
}
if (!WIFEXITED(wstatus)) {
- WriteFdFmt(fd.get(), "%s stopped with status 0x%x\n", remount_cmd, wstatus);
- goto err;
+ WriteFdFmt(fd, "%s stopped with status 0x%x\n", kRemountCmd, wstatus);
+ return false;
}
if (WEXITSTATUS(wstatus)) {
- WriteFdFmt(fd.get(), "%s exited with status %d\n", remount_cmd,
- static_cast<signed char>(WEXITSTATUS(wstatus)));
- goto err;
+ WriteFdFmt(fd, "%s exited with status %d\n", kRemountCmd, WEXITSTATUS(wstatus));
+ return false;
}
- WriteFdExactly(fd.get(), "remount succeeded\n");
- return;
+ return true;
+}
-err:
- WriteFdExactly(fd.get(), remount_failed);
+void remount_service(unique_fd fd, const std::string& cmd) {
+ const char* success = do_remount(fd.get(), cmd) ? "succeeded" : "failed";
+ WriteFdFmt(fd.get(), "remount %s\n", success);
}
diff --git a/adb/daemon/set_verity_enable_state_service.cpp b/adb/daemon/set_verity_enable_state_service.cpp
index 658261e..889229f 100644
--- a/adb/daemon/set_verity_enable_state_service.cpp
+++ b/adb/daemon/set_verity_enable_state_service.cpp
@@ -52,14 +52,13 @@
}
static bool make_block_device_writable(const std::string& dev) {
- int fd = unix_open(dev, O_RDONLY | O_CLOEXEC);
+ unique_fd fd(unix_open(dev, O_RDONLY | O_CLOEXEC));
if (fd == -1) {
return false;
}
int OFF = 0;
bool result = (ioctl(fd, BLKROSET, &OFF) != -1);
- unix_close(fd);
return result;
}
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index 598f2cd..a44ff43 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -654,9 +654,10 @@
}
void usb_init() {
- if (!android::base::GetBoolProperty("persist.adb.nonblocking_ffs", false)) {
- usb_init_legacy();
- } else {
+ bool use_nonblocking = android::base::GetBoolProperty("persist.adb.nonblocking_ffs", true);
+ if (use_nonblocking) {
std::thread(usb_ffs_open_thread).detach();
+ } else {
+ usb_init_legacy();
}
}
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 9a74fb3..b9f738d 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -53,12 +53,27 @@
// Android Wear has been using port 5601 in all of its documentation/tooling,
// but we search for emulators on ports [5554, 5555 + ADB_LOCAL_TRANSPORT_MAX].
-// Avoid stomping on their port by limiting the number of emulators that can be
-// connected.
-#define ADB_LOCAL_TRANSPORT_MAX 16
+// Avoid stomping on their port by restricting the active scanning range.
+// Once emulators self-(re-)register, they'll have to avoid 5601 in their own way.
+static int adb_local_transport_max_port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT + 16 * 2 - 1;
static std::mutex& local_transports_lock = *new std::mutex();
+static void adb_local_transport_max_port_env_override() {
+ const char* env_max_s = getenv("ADB_LOCAL_TRANSPORT_MAX_PORT");
+ if (env_max_s != nullptr) {
+ size_t env_max;
+ if (ParseUint(&env_max, env_max_s, nullptr) && env_max < 65536) {
+ // < DEFAULT_ADB_LOCAL_TRANSPORT_PORT harmlessly mimics ADB_EMU=0
+ adb_local_transport_max_port = env_max;
+ D("transport: ADB_LOCAL_TRANSPORT_MAX_PORT read as %d", adb_local_transport_max_port);
+ } else {
+ D("transport: ADB_LOCAL_TRANSPORT_MAX_PORT '%s' invalid or >= 65536, so ignored",
+ env_max_s);
+ }
+ }
+}
+
// We keep a map from emulator port to transport.
// TODO: weak_ptr?
static auto& local_transports GUARDED_BY(local_transports_lock) =
@@ -110,7 +125,6 @@
D("reconnect failed: %s", response.c_str());
return ReconnectResult::Retry;
}
-
// This invokes the part of register_socket_transport() that needs to be
// invoked if the atransport* has already been setup. This eventually
// calls atransport->SetConnection() with a newly created Connection*
@@ -168,12 +182,10 @@
#if ADB_HOST
static void PollAllLocalPortsForEmulator() {
- int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
- int count = ADB_LOCAL_TRANSPORT_MAX;
-
// Try to connect to any number of running emulator instances.
- for ( ; count > 0; count--, port += 2 ) {
- local_connect(port);
+ for (int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT; port <= adb_local_transport_max_port;
+ port += 2) {
+ local_connect(port); // Note, uses port and port-1, so '=max_port' is OK.
}
}
@@ -289,6 +301,7 @@
#if ADB_HOST
D("transport: local client init");
std::thread(client_socket_thread, port).detach();
+ adb_local_transport_max_port_env_override();
#elif !defined(__ANDROID__)
// Host adbd.
D("transport: local server init");
@@ -371,10 +384,6 @@
if (existing_transport != nullptr) {
D("local transport for port %d already registered (%p)?", adb_port, existing_transport);
fail = -1;
- } else if (local_transports.size() >= ADB_LOCAL_TRANSPORT_MAX) {
- // Too many emulators.
- D("cannot register more emulators. Maximum is %d", ADB_LOCAL_TRANSPORT_MAX);
- fail = -1;
} else {
local_transports[adb_port] = t;
}
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 8798ad3..c08afda 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -316,7 +316,7 @@
std::shared_ptr<unwindstack::Memory>& process_memory = unwinder->GetProcessMemory();
std::string line;
- for (unwindstack::MapInfo* map_info : *maps) {
+ for (auto const& map_info : *maps) {
line = " ";
if (print_fault_address_marker) {
if (addr < map_info->start) {
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 40da36d..e61f588 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -769,9 +769,10 @@
// in recovery, fastbootd, or gsi mode, not allowed!
if (fs_mgr_access("/system/bin/recovery")) return true;
- if (android::gsi::IsGsiRunning()) return true;
-
- return false;
+ auto save_errno = errno;
+ auto ret = android::gsi::IsGsiRunning();
+ errno = save_errno;
+ return ret;
}
} // namespace
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index 6312734..5c4008c 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -263,35 +263,43 @@
// Check verity and optionally setup overlayfs backing.
auto reboot_later = false;
+ auto uses_overlayfs = fs_mgr_overlayfs_valid() != OverlayfsValidResult::kNotSupported;
for (auto it = partitions.begin(); it != partitions.end();) {
auto& entry = *it;
auto& mount_point = entry.mount_point;
if (fs_mgr_is_verity_enabled(entry)) {
- LOG(WARNING) << "Verity enabled on " << mount_point;
- if (can_reboot &&
- (android::base::GetProperty("ro.boot.vbmeta.devices_state", "") != "locked")) {
+ retval = VERITY_PARTITION;
+ if (android::base::GetProperty("ro.boot.vbmeta.devices_state", "") != "locked") {
if (AvbOps* ops = avb_ops_user_new()) {
auto ret = avb_user_verity_set(
ops, android::base::GetProperty("ro.boot.slot_suffix", "").c_str(),
false);
avb_ops_user_free(ops);
if (ret) {
- if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
- retval = VERITY_PARTITION;
+ LOG(WARNING) << "Disable verity for " << mount_point;
+ reboot_later = can_reboot;
+ if (reboot_later) {
// w/o overlayfs available, also check for dedupe
- reboot_later = true;
- ++it;
- continue;
+ if (!uses_overlayfs) {
+ ++it;
+ continue;
+ }
+ reboot(false);
}
- reboot(false);
} else if (fs_mgr_set_blk_ro(entry.blk_device, false)) {
fec::io fh(entry.blk_device.c_str(), O_RDWR);
- if (fh && fh.set_verity_status(false)) reboot_later = true;
+ if (fh && fh.set_verity_status(false)) {
+ LOG(WARNING) << "Disable verity for " << mount_point;
+ reboot_later = can_reboot;
+ if (reboot_later && !uses_overlayfs) {
+ ++it;
+ continue;
+ }
+ }
}
}
}
LOG(ERROR) << "Skipping " << mount_point;
- retval = VERITY_PARTITION;
it = partitions.erase(it);
continue;
}
@@ -318,7 +326,8 @@
}
// Mount overlayfs.
- if (!fs_mgr_overlayfs_mount_all(&partitions)) {
+ errno = 0;
+ if (!fs_mgr_overlayfs_mount_all(&partitions) && errno) {
retval = BAD_OVERLAY;
PLOG(ERROR) << "Can not mount overlayfs for partitions";
}
@@ -346,11 +355,15 @@
break;
}
if ((mount_point == "/") && (rentry.mount_point == "/system")) {
- if (blk_device != "/dev/root") blk_device = rentry.blk_device;
+ blk_device = rentry.blk_device;
mount_point = "/system";
break;
}
}
+ if (blk_device == "/dev/root") {
+ auto from_fstab = GetEntryForMountPoint(&fstab, mount_point);
+ if (from_fstab) blk_device = from_fstab->blk_device;
+ }
fs_mgr_set_blk_ro(blk_device, false);
// Now remount!
diff --git a/fs_mgr/libfiemap_writer/fiemap_writer.cpp b/fs_mgr/libfiemap_writer/fiemap_writer.cpp
index 3d41876..99a1a2f 100644
--- a/fs_mgr/libfiemap_writer/fiemap_writer.cpp
+++ b/fs_mgr/libfiemap_writer/fiemap_writer.cpp
@@ -618,7 +618,6 @@
fmap->file_path_ = abs_path;
fmap->bdev_path_ = bdev_path;
- fmap->file_fd_ = std::move(file_fd);
fmap->file_size_ = file_size;
fmap->bdev_size_ = bdevsz;
fmap->fs_type_ = fs_type;
diff --git a/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp b/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp
index ab4efae..66eb9ae 100644
--- a/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp
+++ b/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp
@@ -38,6 +38,9 @@
#include "utility.h"
+namespace android {
+namespace fiemap_writer {
+
using namespace std;
using namespace std::string_literals;
using namespace android::fiemap_writer;
@@ -234,6 +237,105 @@
ASSERT_EQ(errno, ENOENT);
}
+static string ReadSplitFiles(const std::string& base_path, size_t num_files) {
+ std::string result;
+ for (int i = 0; i < num_files; i++) {
+ std::string path = base_path + android::base::StringPrintf(".%04d", i);
+ std::string data;
+ if (!android::base::ReadFileToString(path, &data)) {
+ return {};
+ }
+ result += data;
+ }
+ return result;
+}
+
+TEST_F(SplitFiemapTest, WriteWholeFile) {
+ static constexpr size_t kChunkSize = 32768;
+ static constexpr size_t kSize = kChunkSize * 3;
+ auto ptr = SplitFiemap::Create(testfile, kSize, kChunkSize);
+ ASSERT_NE(ptr, nullptr);
+
+ auto buffer = std::make_unique<int[]>(kSize / sizeof(int));
+ for (size_t i = 0; i < kSize / sizeof(int); i++) {
+ buffer[i] = i;
+ }
+ ASSERT_TRUE(ptr->Write(buffer.get(), kSize));
+
+ std::string expected(reinterpret_cast<char*>(buffer.get()), kSize);
+ auto actual = ReadSplitFiles(testfile, 3);
+ ASSERT_EQ(expected.size(), actual.size());
+ EXPECT_EQ(memcmp(expected.data(), actual.data(), actual.size()), 0);
+}
+
+TEST_F(SplitFiemapTest, WriteFileInChunks1) {
+ static constexpr size_t kChunkSize = 32768;
+ static constexpr size_t kSize = kChunkSize * 3;
+ auto ptr = SplitFiemap::Create(testfile, kSize, kChunkSize);
+ ASSERT_NE(ptr, nullptr);
+
+ auto buffer = std::make_unique<int[]>(kSize / sizeof(int));
+ for (size_t i = 0; i < kSize / sizeof(int); i++) {
+ buffer[i] = i;
+ }
+
+ // Write in chunks of 1000 (so some writes straddle the boundary of two
+ // files).
+ size_t bytes_written = 0;
+ while (bytes_written < kSize) {
+ size_t to_write = std::min(kSize - bytes_written, (size_t)1000);
+ char* data = reinterpret_cast<char*>(buffer.get()) + bytes_written;
+ ASSERT_TRUE(ptr->Write(data, to_write));
+ bytes_written += to_write;
+ }
+
+ std::string expected(reinterpret_cast<char*>(buffer.get()), kSize);
+ auto actual = ReadSplitFiles(testfile, 3);
+ ASSERT_EQ(expected.size(), actual.size());
+ EXPECT_EQ(memcmp(expected.data(), actual.data(), actual.size()), 0);
+}
+
+TEST_F(SplitFiemapTest, WriteFileInChunks2) {
+ static constexpr size_t kChunkSize = 32768;
+ static constexpr size_t kSize = kChunkSize * 3;
+ auto ptr = SplitFiemap::Create(testfile, kSize, kChunkSize);
+ ASSERT_NE(ptr, nullptr);
+
+ auto buffer = std::make_unique<int[]>(kSize / sizeof(int));
+ for (size_t i = 0; i < kSize / sizeof(int); i++) {
+ buffer[i] = i;
+ }
+
+ // Write in chunks of 32KiB so every write is exactly at the end of the
+ // current file.
+ size_t bytes_written = 0;
+ while (bytes_written < kSize) {
+ size_t to_write = std::min(kSize - bytes_written, kChunkSize);
+ char* data = reinterpret_cast<char*>(buffer.get()) + bytes_written;
+ ASSERT_TRUE(ptr->Write(data, to_write));
+ bytes_written += to_write;
+ }
+
+ std::string expected(reinterpret_cast<char*>(buffer.get()), kSize);
+ auto actual = ReadSplitFiles(testfile, 3);
+ ASSERT_EQ(expected.size(), actual.size());
+ EXPECT_EQ(memcmp(expected.data(), actual.data(), actual.size()), 0);
+}
+
+TEST_F(SplitFiemapTest, WritePastEnd) {
+ static constexpr size_t kChunkSize = 32768;
+ static constexpr size_t kSize = kChunkSize * 3;
+ auto ptr = SplitFiemap::Create(testfile, kSize, kChunkSize);
+ ASSERT_NE(ptr, nullptr);
+
+ auto buffer = std::make_unique<int[]>(kSize / sizeof(int));
+ for (size_t i = 0; i < kSize / sizeof(int); i++) {
+ buffer[i] = i;
+ }
+ ASSERT_TRUE(ptr->Write(buffer.get(), kSize));
+ ASSERT_FALSE(ptr->Write(buffer.get(), kSize));
+}
+
class VerifyBlockWritesExt4 : public ::testing::Test {
// 2GB Filesystem and 4k block size by default
static constexpr uint64_t block_size = 4096;
@@ -333,6 +435,11 @@
return true;
}
+} // namespace fiemap_writer
+} // namespace android
+
+using namespace android::fiemap_writer;
+
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
if (argc <= 1) {
diff --git a/fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h b/fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h
index 831bc75..9486122 100644
--- a/fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h
+++ b/fs_mgr/libfiemap_writer/include/libfiemap_writer/fiemap_writer.h
@@ -88,9 +88,6 @@
// Block device on which we have created the file.
std::string bdev_path_;
- // File descriptors for the file and block device
- ::android::base::unique_fd file_fd_;
-
// Size in bytes of the file this class is writing
uint64_t file_size_;
diff --git a/fs_mgr/libfiemap_writer/include/libfiemap_writer/split_fiemap_writer.h b/fs_mgr/libfiemap_writer/include/libfiemap_writer/split_fiemap_writer.h
index 765cc84..07f3c10 100644
--- a/fs_mgr/libfiemap_writer/include/libfiemap_writer/split_fiemap_writer.h
+++ b/fs_mgr/libfiemap_writer/include/libfiemap_writer/split_fiemap_writer.h
@@ -23,6 +23,8 @@
#include <string>
#include <vector>
+#include <android-base/unique_fd.h>
+
#include "fiemap_writer.h"
namespace android {
@@ -54,6 +56,16 @@
// this returns true and does not report an error.
static bool RemoveSplitFiles(const std::string& file_path, std::string* message = nullptr);
+ // Return whether all components of a split file still have pinned extents.
+ bool HasPinnedExtents() const;
+
+ // Helper method for writing data that spans files. Note there is no seek
+ // method (yet); this starts at 0 and increments the position by |bytes|.
+ bool Write(const void* data, uint64_t bytes);
+
+ // Flush all writes to all split files.
+ bool Flush();
+
const std::vector<struct fiemap_extent>& extents();
uint32_t block_size() const;
uint64_t size() const { return total_size_; }
@@ -73,6 +85,11 @@
std::vector<FiemapUniquePtr> files_;
std::vector<struct fiemap_extent> extents_;
uint64_t total_size_ = 0;
+
+ // Most recently open file and position for Write().
+ size_t cursor_index_ = 0;
+ uint64_t cursor_file_pos_ = 0;
+ android::base::unique_fd cursor_fd_;
};
} // namespace fiemap_writer
diff --git a/fs_mgr/libfiemap_writer/split_fiemap_writer.cpp b/fs_mgr/libfiemap_writer/split_fiemap_writer.cpp
index 1f80370..dbb67a8 100644
--- a/fs_mgr/libfiemap_writer/split_fiemap_writer.cpp
+++ b/fs_mgr/libfiemap_writer/split_fiemap_writer.cpp
@@ -176,6 +176,15 @@
return ok;
}
+bool SplitFiemap::HasPinnedExtents() const {
+ for (const auto& file : files_) {
+ if (!FiemapWriter::HasPinnedExtents(file->file_path())) {
+ return false;
+ }
+ }
+ return true;
+}
+
const std::vector<struct fiemap_extent>& SplitFiemap::extents() {
if (extents_.empty()) {
for (const auto& file : files_) {
@@ -186,6 +195,76 @@
return extents_;
}
+bool SplitFiemap::Write(const void* data, uint64_t bytes) {
+ // Open the current file.
+ FiemapWriter* file = files_[cursor_index_].get();
+
+ const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(data);
+ uint64_t bytes_remaining = bytes;
+ while (bytes_remaining) {
+ // How many bytes can we write into the current file?
+ uint64_t file_bytes_left = file->size() - cursor_file_pos_;
+ if (!file_bytes_left) {
+ if (cursor_index_ == files_.size() - 1) {
+ LOG(ERROR) << "write past end of file requested";
+ return false;
+ }
+
+ // No space left in the current file, but we have more files to
+ // use, so prep the next one.
+ cursor_fd_ = {};
+ cursor_file_pos_ = 0;
+ file = files_[++cursor_index_].get();
+ file_bytes_left = file->size();
+ }
+
+ // Open the current file if it's not open.
+ if (cursor_fd_ < 0) {
+ cursor_fd_.reset(open(file->file_path().c_str(), O_CLOEXEC | O_WRONLY));
+ if (cursor_fd_ < 0) {
+ PLOG(ERROR) << "open failed: " << file->file_path();
+ return false;
+ }
+ CHECK(cursor_file_pos_ == 0);
+ }
+
+ if (!FiemapWriter::HasPinnedExtents(file->file_path())) {
+ LOG(ERROR) << "file is no longer pinned: " << file->file_path();
+ return false;
+ }
+
+ uint64_t bytes_to_write = std::min(file_bytes_left, bytes_remaining);
+ if (!android::base::WriteFully(cursor_fd_, data_ptr, bytes_to_write)) {
+ PLOG(ERROR) << "write failed: " << file->file_path();
+ return false;
+ }
+ data_ptr += bytes_to_write;
+ bytes_remaining -= bytes_to_write;
+ cursor_file_pos_ += bytes_to_write;
+ }
+
+ // If we've reached the end of the current file, close it for sanity.
+ if (cursor_file_pos_ == file->size()) {
+ cursor_fd_ = {};
+ }
+ return true;
+}
+
+bool SplitFiemap::Flush() {
+ for (const auto& file : files_) {
+ unique_fd fd(open(file->file_path().c_str(), O_RDONLY | O_CLOEXEC));
+ if (fd < 0) {
+ PLOG(ERROR) << "open failed: " << file->file_path();
+ return false;
+ }
+ if (fsync(fd)) {
+ PLOG(ERROR) << "fsync failed: " << file->file_path();
+ return false;
+ }
+ }
+ return true;
+}
+
SplitFiemap::~SplitFiemap() {
if (!creating_) {
return;
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index a6baf1d..bd5a4fe 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -48,6 +48,7 @@
TMPDIR=${TMPDIR:-/tmp}
print_time=false
start_time=`date +%s`
+ACTIVE_SLOT=
##
## Helper Functions
@@ -77,6 +78,7 @@
wc -l | grep '^1$' >/dev/null
fi
}
+
[ "USAGE: inRecovery
Returns: true if device is in recovery mode" ]
@@ -221,15 +223,23 @@
Returns: waits until the device has returned for adb or optional timeout" ]
adb_wait() {
+ local ret
if [ -n "${1}" ]; then
echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}"
timeout --preserve-status --signal=KILL ${1} adb wait-for-device 2>/dev/null
- local ret=${?}
+ ret=${?}
echo -n " ${CR}"
- return ${ret}
else
adb wait-for-device
+ ret=${?}
fi
+ if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then
+ local active_slot=`get_active_slot`
+ if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
+ echo "${ORANGE}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2
+ fi
+ fi
+ return ${ret}
}
[ "USAGE: usb_status > stdout
@@ -254,33 +264,50 @@
Returns: waits until the device has returned for fastboot or optional timeout" ]
fastboot_wait() {
+ local ret
# fastboot has no wait-for-device, but it does an automatic
# wait and requires (even a nonsensical) command to do so.
if [ -n "${1}" ]; then
echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}"
timeout --preserve-status --signal=KILL ${1} fastboot wait-for-device >/dev/null 2>/dev/null
- local ret=${?}
+ ret=${?}
echo -n " ${CR}"
( exit ${ret} )
else
fastboot wait-for-device >/dev/null 2>/dev/null
fi ||
inFastboot
+ ret=${?}
+ if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then
+ local active_slot=`get_active_slot`
+ if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
+ echo "${ORANGE}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2
+ fi
+ fi
+ return ${ret}
}
[ "USAGE: recovery_wait [timeout]
Returns: waits until the device has returned for recovery or optional timeout" ]
recovery_wait() {
+ local ret
if [ -n "${1}" ]; then
echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}"
timeout --preserve-status --signal=KILL ${1} adb wait-for-recovery 2>/dev/null
- local ret=${?}
+ ret=${?}
echo -n " ${CR}"
- return ${ret}
else
adb wait-for-recovery
+ ret=${?}
fi
+ if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then
+ local active_slot=`get_active_slot`
+ if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
+ echo "${ORANGE}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2
+ fi
+ fi
+ return ${ret}
}
[ "any_wait [timeout]
@@ -326,7 +353,7 @@
[ root != "`adb_sh echo '${USER}' </dev/null`" ]
}
-[ "USAGE: fastboot_getvar var expected
+[ "USAGE: fastboot_getvar var expected >/dev/stderr
Returns: true if var output matches expected" ]
fastboot_getvar() {
@@ -350,6 +377,19 @@
echo ${O} >&2
}
+[ "USAGE: get_active_slot >/dev/stdout
+
+Returns: with a or b string reporting active slot" ]
+get_active_slot() {
+ if inAdb || inRecovery; then
+ get_property ro.boot.slot_suffix | tr -d _
+ elif inFastboot; then
+ fastboot_getvar current-slot 2>&1 | sed -n 's/current-slot: //p'
+ else
+ false
+ fi
+}
+
[ "USAGE: restore
Do nothing: should be redefined when necessary. Called after cleanup.
@@ -583,6 +623,9 @@
BUILD_DESCRIPTION=`get_property ro.build.description`
[ -z "${BUILD_DESCRIPTION}" ] ||
echo "${BLUE}[ INFO ]${NORMAL} ${BUILD_DESCRIPTION}" >&2
+ACTIVE_SLOT=`get_active_slot`
+[ -z "${ACTIVE_SLOT}" ] ||
+ echo "${BLUE}[ INFO ]${NORMAL} active slot is ${ACTIVE_SLOT}" >&2
# Report existing partition sizes
adb_sh ls -l /dev/block/by-name/ </dev/null 2>/dev/null |
@@ -1031,13 +1074,7 @@
check_eq "${A}" "${B}" system after flash vendor
adb_root ||
die "adb root"
- B="`adb_cat /vendor/hello`" &&
- if ${is_userspace_fastboot} || ! ${overlayfs_needed}; then
- die "re-read /vendor/hello after flash vendor"
- else
- echo "${ORANGE}[ WARNING ]${NORMAL} user fastboot missing required to invalidate, ignoring a failure" >&2
- echo "${ORANGE}[ WARNING ]${NORMAL} re-read /vendor/hello after flash vendor" >&2
- fi
+ B="`adb_cat /vendor/hello`"
if ${is_userspace_fastboot} || ! ${overlayfs_needed}; then
check_eq "cat: /vendor/hello: No such file or directory" "${B}" \
vendor content after flash vendor
diff --git a/init/Android.bp b/init/Android.bp
index 639d8d1..9aeb837 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -132,7 +132,7 @@
"ueventd_parser.cpp",
"util.cpp",
],
- whole_static_libs: ["libcap"],
+ whole_static_libs: ["libcap", "com.android.sysprop.apex"],
header_libs: ["bootimg_headers"],
proto: {
type: "lite",
diff --git a/init/Android.mk b/init/Android.mk
index 59d7f11..cc514ed 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -63,8 +63,9 @@
LOCAL_UNSTRIPPED_PATH := $(TARGET_RAMDISK_OUT_UNSTRIPPED)
# Set up the same mount points on the ramdisk that system-as-root contains.
-LOCAL_POST_INSTALL_CMD := \
- mkdir -p $(TARGET_RAMDISK_OUT)/dev \
+LOCAL_POST_INSTALL_CMD := mkdir -p \
+ $(TARGET_RAMDISK_OUT)/apex \
+ $(TARGET_RAMDISK_OUT)/dev \
$(TARGET_RAMDISK_OUT)/mnt \
$(TARGET_RAMDISK_OUT)/proc \
$(TARGET_RAMDISK_OUT)/sys \
@@ -93,6 +94,7 @@
libselinux \
libcap \
libgsi \
+ libcom.android.sysprop.apex \
LOCAL_SANITIZE := signed-integer-overflow
# First stage init is weird: it may start without stdout/stderr, and no /proc.
diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp
index 327446a..4161df2 100644
--- a/init/mount_namespace.cpp
+++ b/init/mount_namespace.cpp
@@ -21,6 +21,7 @@
#include <string>
#include <vector>
+#include <ApexProperties.sysprop.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
@@ -132,9 +133,9 @@
return true;
}
-static bool IsBionicUpdatable() {
- static bool result = android::base::GetBoolProperty("ro.apex.IsBionicUpdatable", false);
- return result;
+static bool IsApexUpdatable() {
+ static bool updatable = android::sysprop::ApexProperties::updatable().value_or(false);
+ return updatable;
}
static android::base::unique_fd bootstrap_ns_fd;
@@ -187,7 +188,7 @@
// bind-mounted. In the namespace for post-apexd processes, the bionic from
// the runtime APEX is bind-mounted.
bool success = true;
- if (IsBionicUpdatable() && !IsRecoveryMode()) {
+ if (IsApexUpdatable() && !IsRecoveryMode()) {
// Creating a new namespace by cloning, saving, and switching back to
// the original namespace.
if (unshare(CLONE_NEWNS) == -1) {
@@ -244,7 +245,7 @@
return true;
}
// Bind-mount bionic from the runtime APEX since it is now available. Note
- // that in case of IsBionicUpdatable() == false, these mounts are over the
+ // that in case of IsApexUpdatable() == false, these mounts are over the
// existing existing bind mounts for the bootstrap bionic, which effectively
// becomes hidden.
if (!BindMountBionic(kRuntimeLinkerPath, kRuntimeBionicLibsDir, kLinkerMountPoint,
@@ -264,7 +265,7 @@
return true;
}
if (bootstrap_ns_id != GetMountNamespaceId() && bootstrap_ns_fd.get() != -1 &&
- IsBionicUpdatable()) {
+ IsApexUpdatable()) {
if (setns(bootstrap_ns_fd.get(), CLONE_NEWNS) == -1) {
PLOG(ERROR) << "Failed to switch to bootstrap mount namespace.";
return false;
diff --git a/init/service.cpp b/init/service.cpp
index 2186a85..cba42c4 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -1059,7 +1059,7 @@
std::string oom_str = std::to_string(oom_score_adjust_);
std::string oom_file = StringPrintf("/proc/%d/oom_score_adj", pid);
if (!WriteStringToFile(oom_str, oom_file)) {
- PLOG(ERROR) << "couldn't write oom_score_adj: " << strerror(errno);
+ PLOG(ERROR) << "couldn't write oom_score_adj";
}
}
diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp
index 9d15af2..4518891 100644
--- a/libbacktrace/UnwindStackMap.cpp
+++ b/libbacktrace/UnwindStackMap.cpp
@@ -55,7 +55,7 @@
}
// Iterate through the maps and fill in the backtrace_map_t structure.
- for (auto* map_info : *stack_maps_) {
+ for (const auto& map_info : *stack_maps_) {
backtrace_map_t map;
map.start = map_info->start;
map.end = map_info->end;
diff --git a/libcutils/include/cutils/native_handle.h b/libcutils/include/cutils/native_handle.h
index f6cae36..4f07456 100644
--- a/libcutils/include/cutils/native_handle.h
+++ b/libcutils/include/cutils/native_handle.h
@@ -69,10 +69,11 @@
/*
* native_handle_create
- *
+ *
* creates a native_handle_t and initializes it. must be destroyed with
- * native_handle_delete().
- *
+ * native_handle_delete(). Note that numFds must be <= NATIVE_HANDLE_MAX_FDS,
+ * numInts must be <= NATIVE_HANDLE_MAX_INTS, and both must be >= 0.
+ *
*/
native_handle_t* native_handle_create(int numFds, int numInts);
diff --git a/libkeyutils/Android.bp b/libkeyutils/Android.bp
index e816926..dda491a 100644
--- a/libkeyutils/Android.bp
+++ b/libkeyutils/Android.bp
@@ -19,13 +19,14 @@
cc_binary {
name: "mini-keyctl",
- srcs: ["mini_keyctl.cpp"],
-
+ srcs: [
+ "mini_keyctl.cpp",
+ "mini_keyctl_utils.cpp"
+ ],
shared_libs: [
"libbase",
"libkeyutils",
"liblog",
],
-
- cflags: ["-Werror", "-Wall", "-Wextra"],
+ cflags: ["-Werror", "-Wall", "-Wextra", "-fexceptions"],
}
diff --git a/libkeyutils/mini_keyctl.cpp b/libkeyutils/mini_keyctl.cpp
index abc8f82..4fe4c3c 100644
--- a/libkeyutils/mini_keyctl.cpp
+++ b/libkeyutils/mini_keyctl.cpp
@@ -18,159 +18,57 @@
* A tool loads keys to keyring.
*/
-#include <dirent.h>
-#include <errno.h>
-#include <sys/types.h>
+#include "mini_keyctl_utils.h"
+
#include <unistd.h>
-#include <fstream>
-#include <iostream>
-#include <iterator>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/strings.h>
-#include <keyutils.h>
-
-static constexpr int kMaxCertSize = 4096;
-
-// Add all the certs from directory path to keyring with keyring_id. Returns the number of keys
-// added.
-int AddKeys(const std::string& path, const key_serial_t keyring_id, const std::string& keyring_desc,
- int start_index) {
- std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(path.c_str()), closedir);
- if (!dir) {
- PLOG(WARNING) << "Failed to open directory " << path;
- return 0;
- }
- int keys_added = 0;
- struct dirent* dp;
- while ((dp = readdir(dir.get())) != NULL) {
- if (dp->d_type != DT_REG) {
- continue;
- }
- std::string cert_path = path + "/" + dp->d_name;
- std::string cert_buf;
- if (!android::base::ReadFileToString(cert_path, &cert_buf, false /* follow_symlinks */)) {
- LOG(ERROR) << "Failed to read " << cert_path;
- continue;
- }
-
- if (cert_buf.size() > kMaxCertSize) {
- LOG(ERROR) << "Certficate size too large: " << cert_path;
- continue;
- }
-
- // Add key to keyring.
- int key_desc_index = keys_added + start_index;
- std::string key_desc = keyring_desc + "-key" + std::to_string(key_desc_index);
- key_serial_t key =
- add_key("asymmetric", key_desc.c_str(), &cert_buf[0], cert_buf.size(), keyring_id);
- if (key < 0) {
- PLOG(ERROR) << "Failed to add key to keyring: " << cert_path;
- continue;
- }
- keys_added++;
- }
- return keys_added;
-}
-
-std::vector<std::string> SplitBySpace(const std::string& s) {
- std::istringstream iss(s);
- return std::vector<std::string>{std::istream_iterator<std::string>{iss},
- std::istream_iterator<std::string>{}};
-}
-
-// Find the keyring id. Because request_key(2) syscall is not available or the key is
-// kernel keyring, the id is looked up from /proc/keys. The keyring description may contain other
-// information in the descritption section depending on the key type, only the first word in the
-// keyring description is used for searching.
-bool GetKeyringId(const std::string& keyring_desc, key_serial_t* keyring_id) {
- if (!keyring_id) {
- LOG(ERROR) << "keyring_id is null";
- return false;
- }
-
- // Only keys allowed by SELinux rules will be shown here.
- std::ifstream proc_keys_file("/proc/keys");
- if (!proc_keys_file.is_open()) {
- PLOG(ERROR) << "Failed to open /proc/keys";
- return false;
- }
-
- std::string line;
- while (getline(proc_keys_file, line)) {
- std::vector<std::string> tokens = SplitBySpace(line);
- if (tokens.size() < 9) {
- continue;
- }
- std::string key_id = tokens[0];
- std::string key_type = tokens[7];
- // The key description may contain space.
- std::string key_desc_prefix = tokens[8];
- // The prefix has a ":" at the end
- std::string key_desc_pattern = keyring_desc + ":";
- if (key_type != "keyring" || key_desc_prefix != key_desc_pattern) {
- continue;
- }
- *keyring_id = std::stoi(key_id, nullptr, 16);
- return true;
- }
- return false;
-}
-
static void Usage(int exit_code) {
- fprintf(stderr, "usage: mini-keyctl -c PATHS -s DESCRIPTION\n");
- fprintf(stderr, "\n");
- fprintf(stderr, "-c, --cert_dirs the certificate locations, separated by comma\n");
- fprintf(stderr, "-k, --keyring the keyring description\n");
+ fprintf(stderr, "usage: mini-keyctl <action> [args,]\n");
+ fprintf(stderr, " mini-keyctl add <type> <desc> <data> <keyring>\n");
+ fprintf(stderr, " mini-keyctl padd <type> <desc> <keyring>\n");
+ fprintf(stderr, " mini-keyctl dadd <type> <desc_prefix> <cert_dir> <keyring>\n");
+ fprintf(stderr, " mini-keyctl unlink <key> <keyring>\n");
+ fprintf(stderr, " mini-keyctl restrict_keyring <keyring>\n");
_exit(exit_code);
}
-int main(int argc, char** argv) {
- if (argc < 5) Usage(1);
+int main(int argc, const char** argv) {
+ if (argc < 2) Usage(1);
+ const std::string action = argv[1];
- std::string arg_cert_dirs;
- std::string arg_keyring_desc;
-
- for (int i = 1; i < argc; i++) {
- std::string option = argv[i];
- if (option == "-c" || option == "--cert_dirs") {
- if (i + 1 < argc) arg_cert_dirs = argv[++i];
- } else if (option == "-k" || option == "--keyring") {
- if (i + 1 < argc) arg_keyring_desc = argv[++i];
- }
- }
-
- if (arg_cert_dirs.empty() || arg_keyring_desc.empty()) {
- LOG(ERROR) << "Missing cert_dirs or keyring desc";
+ if (action == "add") {
+ if (argc != 6) Usage(1);
+ std::string type = argv[2];
+ std::string desc = argv[3];
+ std::string data = argv[4];
+ std::string keyring = argv[5];
+ return Add(type, desc, data, keyring);
+ } else if (action == "dadd") {
+ if (argc != 6) Usage(1);
+ std::string type = argv[2];
+ // The key description contains desc_prefix and an index.
+ std::string desc_prefix = argv[3];
+ std::string cert_dir = argv[4];
+ std::string keyring = argv[5];
+ return AddCertsFromDir(type, desc_prefix, cert_dir, keyring);
+ } else if (action == "padd") {
+ if (argc != 5) Usage(1);
+ std::string type = argv[2];
+ std::string desc = argv[3];
+ std::string keyring = argv[4];
+ return Padd(type, desc, keyring);
+ } else if (action == "restrict_keyring") {
+ if (argc != 3) Usage(1);
+ std::string keyring = argv[2];
+ return RestrictKeyring(keyring);
+ } else if (action == "unlink") {
+ if (argc != 4) Usage(1);
+ key_serial_t key = std::stoi(argv[2], nullptr, 16);
+ const std::string keyring = argv[3];
+ return Unlink(key, keyring);
+ } else {
Usage(1);
}
- // Get the keyring id
- key_serial_t key_ring_id;
- if (!GetKeyringId(arg_keyring_desc, &key_ring_id)) {
- PLOG(ERROR) << "Can't find keyring with " << arg_keyring_desc;
- return 1;
- }
-
- std::vector<std::string> cert_dirs = android::base::Split(arg_cert_dirs, ",");
- int start_index = 0;
- for (const auto& cert_dir : cert_dirs) {
- int keys_added = AddKeys(cert_dir, key_ring_id, arg_keyring_desc, start_index);
- start_index += keys_added;
- }
-
- // Prevent new keys to be added.
- if (!android::base::GetBoolProperty("ro.debuggable", false) &&
- keyctl_restrict_keyring(key_ring_id, nullptr, nullptr) < 0) {
- PLOG(ERROR) << "Failed to restrict key ring " << arg_keyring_desc;
- return 1;
- }
-
return 0;
}
diff --git a/libkeyutils/mini_keyctl_utils.cpp b/libkeyutils/mini_keyctl_utils.cpp
new file mode 100644
index 0000000..c4fc96c
--- /dev/null
+++ b/libkeyutils/mini_keyctl_utils.cpp
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <mini_keyctl_utils.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <fstream>
+#include <iostream>
+#include <iterator>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <keyutils.h>
+
+static constexpr int kMaxCertSize = 4096;
+
+std::vector<std::string> SplitBySpace(const std::string& s) {
+ std::istringstream iss(s);
+ return std::vector<std::string>{std::istream_iterator<std::string>{iss},
+ std::istream_iterator<std::string>{}};
+}
+
+int AddCertsFromDir(const std::string& type, const std::string& desc_prefix,
+ const std::string& cert_dir, const std::string& keyring) {
+ key_serial_t keyring_id;
+ if (!GetKeyringId(keyring, &keyring_id)) {
+ LOG(ERROR) << "Can not find keyring id";
+ return 1;
+ }
+
+ std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(cert_dir.c_str()), closedir);
+ if (!dir) {
+ PLOG(WARNING) << "Failed to open directory " << cert_dir;
+ return 1;
+ }
+ int keys_added = 0;
+ struct dirent* dp;
+ while ((dp = readdir(dir.get())) != NULL) {
+ if (dp->d_type != DT_REG) {
+ continue;
+ }
+ std::string cert_path = cert_dir + "/" + dp->d_name;
+ std::string cert_buf;
+ if (!android::base::ReadFileToString(cert_path, &cert_buf, false /* follow_symlinks */)) {
+ LOG(ERROR) << "Failed to read " << cert_path;
+ continue;
+ }
+
+ if (cert_buf.size() > kMaxCertSize) {
+ LOG(ERROR) << "Certficate size too large: " << cert_path;
+ continue;
+ }
+
+ // Add key to keyring.
+ int key_desc_index = keys_added;
+ std::string key_desc = desc_prefix + std::to_string(key_desc_index);
+ key_serial_t key =
+ add_key(type.c_str(), key_desc.c_str(), &cert_buf[0], cert_buf.size(), keyring_id);
+ if (key < 0) {
+ PLOG(ERROR) << "Failed to add key to keyring: " << cert_path;
+ continue;
+ }
+ LOG(INFO) << "Key " << cert_path << " added to " << keyring << " with key id 0x" << std::hex
+ << key;
+ keys_added++;
+ }
+ return 0;
+}
+
+bool GetKeyringId(const std::string& keyring_desc, key_serial_t* keyring_id) {
+ if (!keyring_id) {
+ LOG(ERROR) << "keyring_id is null";
+ return false;
+ }
+
+ // If the keyring id is already a hex number, directly convert it to keyring id
+ try {
+ key_serial_t id = std::stoi(keyring_desc, nullptr, 16);
+ *keyring_id = id;
+ return true;
+ } catch (const std::exception& e) {
+ LOG(INFO) << "search /proc/keys for keyring id";
+ }
+
+ // Only keys allowed by SELinux rules will be shown here.
+ std::ifstream proc_keys_file("/proc/keys");
+ if (!proc_keys_file.is_open()) {
+ PLOG(ERROR) << "Failed to open /proc/keys";
+ return false;
+ }
+
+ std::string line;
+ while (getline(proc_keys_file, line)) {
+ std::vector<std::string> tokens = SplitBySpace(line);
+ if (tokens.size() < 9) {
+ continue;
+ }
+ std::string key_id = tokens[0];
+ std::string key_type = tokens[7];
+ // The key description may contain space.
+ std::string key_desc_prefix = tokens[8];
+ // The prefix has a ":" at the end
+ std::string key_desc_pattern = keyring_desc + ":";
+ if (key_type != "keyring" || key_desc_prefix != key_desc_pattern) {
+ continue;
+ }
+ *keyring_id = std::stoi(key_id, nullptr, 16);
+ return true;
+ }
+ return false;
+}
+
+int Unlink(key_serial_t key, const std::string& keyring) {
+ key_serial_t keyring_id;
+ if (!GetKeyringId(keyring, &keyring_id)) {
+ LOG(ERROR) << "Can't find keyring " << keyring;
+ return 1;
+ }
+
+ if (keyctl_unlink(key, keyring_id) < 0) {
+ PLOG(ERROR) << "Failed to unlink key 0x" << std::hex << key << " from keyring " << keyring_id;
+ return 1;
+ }
+ return 0;
+}
+
+int Add(const std::string& type, const std::string& desc, const std::string& data,
+ const std::string& keyring) {
+ if (data.size() > kMaxCertSize) {
+ LOG(ERROR) << "Certificate too large";
+ return 1;
+ }
+
+ key_serial_t keyring_id;
+ if (!GetKeyringId(keyring, &keyring_id)) {
+ LOG(ERROR) << "Can not find keyring id";
+ return 1;
+ }
+
+ key_serial_t key = add_key(type.c_str(), desc.c_str(), data.c_str(), data.size(), keyring_id);
+
+ if (key < 0) {
+ PLOG(ERROR) << "Failed to add key";
+ return 1;
+ }
+
+ LOG(INFO) << "Key " << desc << " added to " << keyring << " with key id: 0x" << std::hex << key;
+ return 0;
+}
+
+int Padd(const std::string& type, const std::string& desc, const std::string& keyring) {
+ key_serial_t keyring_id;
+ if (!GetKeyringId(keyring, &keyring_id)) {
+ LOG(ERROR) << "Can not find keyring id";
+ return 1;
+ }
+
+ // read from stdin to get the certificates
+ std::istreambuf_iterator<char> begin(std::cin), end;
+ std::string data(begin, end);
+
+ if (data.size() > kMaxCertSize) {
+ LOG(ERROR) << "Certificate too large";
+ return 1;
+ }
+
+ key_serial_t key = add_key(type.c_str(), desc.c_str(), data.c_str(), data.size(), keyring_id);
+
+ if (key < 0) {
+ PLOG(ERROR) << "Failed to add key";
+ return 1;
+ }
+
+ LOG(INFO) << "Key " << desc << " added to " << keyring << " with key id: 0x" << std::hex << key;
+ return 0;
+}
+
+int RestrictKeyring(const std::string& keyring) {
+ key_serial_t keyring_id;
+ if (!GetKeyringId(keyring, &keyring_id)) {
+ LOG(ERROR) << "Cannot find keyring id";
+ return 1;
+ }
+
+ if (keyctl_restrict_keyring(keyring_id, nullptr, nullptr) < 0) {
+ PLOG(ERROR) << "Cannot restrict keyring " << keyring;
+ return 1;
+ }
+ return 0;
+}
diff --git a/libkeyutils/mini_keyctl_utils.h b/libkeyutils/mini_keyctl_utils.h
new file mode 100644
index 0000000..3c69611
--- /dev/null
+++ b/libkeyutils/mini_keyctl_utils.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/keyutils.h"
+
+#include <string>
+
+// Add all files in a directory as certificates to a keyring. |keyring| could be the keyring
+// description or keyring id in hex.
+int AddCertsFromDir(const std::string& type, const std::string& desc_prefix,
+ const std::string& cert_dir, const std::string& keyring);
+
+// Add all the certs from directory path to keyring with keyring_id. Returns the number of keys
+// added. Returns non-zero if any error happens.
+int AddKeys(const std::string& path, const key_serial_t keyring_id, const std::string& type,
+ const std::string& desc, int start_index);
+
+// Add key to a keyring. Returns non-zero if error happens.
+int Add(const std::string& type, const std::string& desc, const std::string& data,
+ const std::string& keyring);
+
+// Add key from stdin to a keyring. Returns non-zero if error happens.
+int Padd(const std::string& type, const std::string& desc, const std::string& keyring);
+
+// Removes the link from a keyring to a key if exists. Return non-zero if error happens.
+int Unlink(key_serial_t key, const std::string& keyring);
+
+// Apply key-linking to a keyring. Return non-zero if error happens.
+int RestrictKeyring(const std::string& keyring);
+
+// Find the keyring id. Because request_key(2) syscall is not available or the key is
+// kernel keyring, the id is looked up from /proc/keys. The keyring description may contain other
+// information in the descritption section depending on the key type, only the first word in the
+// keyring description is used for searching.
+bool GetKeyringId(const std::string& keyring_desc, key_serial_t* keyring_id);
diff --git a/libnativeloader/include/nativeloader/native_loader.h b/libnativeloader/include/nativeloader/native_loader.h
index 260f655..51fb875 100644
--- a/libnativeloader/include/nativeloader/native_loader.h
+++ b/libnativeloader/include/nativeloader/native_loader.h
@@ -36,14 +36,9 @@
__attribute__((visibility("default")))
void InitializeNativeLoader();
-__attribute__((visibility("default")))
-jstring CreateClassLoaderNamespace(JNIEnv* env,
- int32_t target_sdk_version,
- jobject class_loader,
- bool is_shared,
- bool is_for_vendor,
- jstring library_path,
- jstring permitted_path);
+__attribute__((visibility("default"))) jstring CreateClassLoaderNamespace(
+ JNIEnv* env, int32_t target_sdk_version, jobject class_loader, bool is_shared, jstring dex_path,
+ jstring library_path, jstring permitted_path);
__attribute__((visibility("default"))) void* OpenNativeLibrary(
JNIEnv* env, int32_t target_sdk_version, const char* path, jobject class_loader,
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index 043f038..1c2581f 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -31,6 +31,7 @@
#include <list>
#include <memory>
#include <mutex>
+#include <regex>
#include <string>
#include <vector>
@@ -140,10 +141,24 @@
#if defined(__LP64__)
static constexpr const char* kRuntimeApexLibPath = "/apex/com.android.runtime/lib64";
+static constexpr const char* kVendorLibPath = "/vendor/lib64";
+static constexpr const char* kProductLibPath = "/product/lib64:/system/product/lib64";
#else
static constexpr const char* kRuntimeApexLibPath = "/apex/com.android.runtime/lib";
+static constexpr const char* kVendorLibPath = "/vendor/lib";
+static constexpr const char* kProductLibPath = "/product/lib:/system/product/lib";
#endif
+static const std::regex kVendorDexPathRegex("(^|:)/vendor/");
+static const std::regex kProductDexPathRegex("(^|:)(/system)?/product/");
+
+// Define origin of APK if it is from vendor partition or product partition
+typedef enum {
+ APK_ORIGIN_DEFAULT = 0,
+ APK_ORIGIN_VENDOR = 1,
+ APK_ORIGIN_PRODUCT = 2,
+} ApkOrigin;
+
static bool is_debuggable() {
bool debuggable = false;
#ifdef __BIONIC__
@@ -179,7 +194,7 @@
LibraryNamespaces() : initialized_(false) { }
NativeLoaderNamespace* Create(JNIEnv* env, uint32_t target_sdk_version, jobject class_loader,
- bool is_shared, bool is_for_vendor, jstring java_library_path,
+ bool is_shared, jstring dex_path, jstring java_library_path,
jstring java_permitted_path, std::string* error_msg) {
std::string library_path; // empty string by default.
@@ -188,6 +203,8 @@
library_path = library_path_utf_chars.c_str();
}
+ ApkOrigin apk_origin = GetApkOriginFromDexPath(env, dex_path);
+
// (http://b/27588281) This is a workaround for apps using custom
// classloaders and calling System.load() with an absolute path which
// is outside of the classloader library search path.
@@ -234,31 +251,50 @@
std::string system_exposed_libraries = system_public_libraries_;
const char* namespace_name = kClassloaderNamespaceName;
android_namespace_t* vndk_ns = nullptr;
- if (is_for_vendor && !is_shared) {
- LOG_FATAL_IF(is_native_bridge, "Unbundled vendor apk must not use translated architecture");
+ if ((apk_origin == APK_ORIGIN_VENDOR ||
+ (apk_origin == APK_ORIGIN_PRODUCT && target_sdk_version > 29)) &&
+ !is_shared) {
+ LOG_FATAL_IF(is_native_bridge,
+ "Unbundled vendor / product apk must not use translated architecture");
- // For vendor apks, give access to the vendor lib even though
+ // For vendor / product apks, give access to the vendor / product lib even though
// they are treated as unbundled; the libs and apks are still bundled
- // together in the vendor partition.
-#if defined(__LP64__)
- std::string vendor_lib_path = "/vendor/lib64";
-#else
- std::string vendor_lib_path = "/vendor/lib";
-#endif
- library_path = library_path + ":" + vendor_lib_path.c_str();
- permitted_path = permitted_path + ":" + vendor_lib_path.c_str();
+ // together in the vendor / product partition.
+ const char* origin_partition;
+ const char* origin_lib_path;
+
+ switch (apk_origin) {
+ case APK_ORIGIN_VENDOR:
+ origin_partition = "vendor";
+ origin_lib_path = kVendorLibPath;
+ break;
+ case APK_ORIGIN_PRODUCT:
+ origin_partition = "product";
+ origin_lib_path = kProductLibPath;
+ break;
+ default:
+ origin_partition = "unknown";
+ origin_lib_path = "";
+ }
+
+ LOG_FATAL_IF(is_native_bridge, "Unbundled %s apk must not use translated architecture",
+ origin_partition);
+
+ library_path = library_path + ":" + origin_lib_path;
+ permitted_path = permitted_path + ":" + origin_lib_path;
// Also give access to LLNDK libraries since they are available to vendors
system_exposed_libraries = system_exposed_libraries + ":" + system_llndk_libraries_.c_str();
// Give access to VNDK-SP libraries from the 'vndk' namespace.
vndk_ns = android_get_exported_namespace(kVndkNamespaceName);
- LOG_ALWAYS_FATAL_IF(vndk_ns == nullptr,
- "Cannot find \"%s\" namespace for vendor apks", kVndkNamespaceName);
+ LOG_ALWAYS_FATAL_IF(vndk_ns == nullptr, "Cannot find \"%s\" namespace for %s apks",
+ kVndkNamespaceName, origin_partition);
// Different name is useful for debugging
namespace_name = kVendorClassloaderNamespaceName;
- ALOGD("classloader namespace configured for unbundled vendor apk. library_path=%s", library_path.c_str());
+ ALOGD("classloader namespace configured for unbundled %s apk. library_path=%s",
+ origin_partition, library_path.c_str());
} else {
// oem and product public libraries are NOT available to vendor apks, otherwise it
// would be system->vendor violation.
@@ -660,6 +696,28 @@
return nullptr;
}
+ ApkOrigin GetApkOriginFromDexPath(JNIEnv* env, jstring dex_path) {
+ ApkOrigin apk_origin = APK_ORIGIN_DEFAULT;
+
+ if (dex_path != nullptr) {
+ ScopedUtfChars dex_path_utf_chars(env, dex_path);
+
+ if (std::regex_search(dex_path_utf_chars.c_str(), kVendorDexPathRegex)) {
+ apk_origin = APK_ORIGIN_VENDOR;
+ }
+
+ if (std::regex_search(dex_path_utf_chars.c_str(), kProductDexPathRegex)) {
+ LOG_ALWAYS_FATAL_IF(apk_origin == APK_ORIGIN_VENDOR,
+ "Dex path contains both vendor and product partition : %s",
+ dex_path_utf_chars.c_str());
+
+ apk_origin = APK_ORIGIN_PRODUCT;
+ }
+ }
+
+ return apk_origin;
+ }
+
bool initialized_;
std::list<std::pair<jweak, NativeLoaderNamespace>> namespaces_;
std::string system_public_libraries_;
@@ -690,31 +748,20 @@
#endif
}
-jstring CreateClassLoaderNamespace(JNIEnv* env,
- int32_t target_sdk_version,
- jobject class_loader,
- bool is_shared,
- bool is_for_vendor,
- jstring library_path,
+jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
+ bool is_shared, jstring dex_path, jstring library_path,
jstring permitted_path) {
#if defined(__ANDROID__)
std::lock_guard<std::mutex> guard(g_namespaces_mutex);
std::string error_msg;
- bool success = g_namespaces->Create(env,
- target_sdk_version,
- class_loader,
- is_shared,
- is_for_vendor,
- library_path,
- permitted_path,
- &error_msg) != nullptr;
+ bool success = g_namespaces->Create(env, target_sdk_version, class_loader, is_shared, dex_path,
+ library_path, permitted_path, &error_msg) != nullptr;
if (!success) {
return env->NewStringUTF(error_msg.c_str());
}
#else
- UNUSED(env, target_sdk_version, class_loader, is_shared, is_for_vendor,
- library_path, permitted_path);
+ UNUSED(env, target_sdk_version, class_loader, is_shared, dex_path, library_path, permitted_path);
#endif
return nullptr;
}
@@ -779,8 +826,7 @@
// In this case we create an isolated not-shared namespace for it.
std::string create_error_msg;
if ((ns = g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */,
- false /* is_for_vendor */, library_path, nullptr,
- &create_error_msg)) == nullptr) {
+ nullptr, library_path, nullptr, &create_error_msg)) == nullptr) {
*error_msg = strdup(create_error_msg.c_str());
return nullptr;
}
diff --git a/libnativeloader/native_loader_lazy.cpp b/libnativeloader/native_loader_lazy.cpp
index 11ecc43..2eb1203 100644
--- a/libnativeloader/native_loader_lazy.cpp
+++ b/libnativeloader/native_loader_lazy.cpp
@@ -50,10 +50,10 @@
}
jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
- bool is_shared, bool is_for_vendor, jstring library_path,
+ bool is_shared, jstring dex_path, jstring library_path,
jstring permitted_path) {
static auto f = GET_FUNC_PTR(CreateClassLoaderNamespace);
- return f(env, target_sdk_version, class_loader, is_shared, is_for_vendor, library_path,
+ return f(env, target_sdk_version, class_loader, is_shared, dex_path, library_path,
permitted_path);
}
diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp
index 26d0754..9951621 100644
--- a/libprocessgroup/cgroup_map.cpp
+++ b/libprocessgroup/cgroup_map.cpp
@@ -117,7 +117,7 @@
std::string json_doc;
if (!android::base::ReadFileToString(file_name, &json_doc)) {
- LOG(ERROR) << "Failed to read task profiles from " << file_name;
+ PLOG(ERROR) << "Failed to read task profiles from " << file_name;
return false;
}
@@ -185,7 +185,7 @@
// mkdir <path> [mode] [owner] [group]
if (!Mkdir(controller->path(), descriptor.mode(), descriptor.uid(), descriptor.gid())) {
- PLOG(ERROR) << "Failed to create directory for " << controller->name() << " cgroup";
+ LOG(ERROR) << "Failed to create directory for " << controller->name() << " cgroup";
return false;
}
@@ -289,7 +289,7 @@
std::string file_name = StringPrintf("/proc/%d/cgroup", tid);
std::string content;
if (!android::base::ReadFileToString(file_name, &content)) {
- LOG(ERROR) << "Failed to read " << file_name;
+ PLOG(ERROR) << "Failed to read " << file_name;
return false;
}
@@ -323,7 +323,7 @@
CgroupMap::CgroupMap() : cg_file_data_(nullptr), cg_file_size_(0) {
if (!LoadRcFile()) {
- PLOG(ERROR) << "CgroupMap::LoadRcFile called for [" << getpid() << "] failed";
+ LOG(ERROR) << "CgroupMap::LoadRcFile called for [" << getpid() << "] failed";
}
}
@@ -360,27 +360,42 @@
return false;
}
- cg_file_size_ = sb.st_size;
- if (cg_file_size_ < sizeof(CgroupFile)) {
- PLOG(ERROR) << "Invalid file format " << cgroup_rc_path;
+ size_t file_size = sb.st_size;
+ if (file_size < sizeof(CgroupFile)) {
+ LOG(ERROR) << "Invalid file format " << cgroup_rc_path;
return false;
}
- cg_file_data_ = (CgroupFile*)mmap(nullptr, cg_file_size_, PROT_READ, MAP_SHARED, fd, 0);
- if (cg_file_data_ == MAP_FAILED) {
+ CgroupFile* file_data = (CgroupFile*)mmap(nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (file_data == MAP_FAILED) {
PLOG(ERROR) << "Failed to mmap " << cgroup_rc_path;
return false;
}
- if (cg_file_data_->version_ != CgroupFile::FILE_CURR_VERSION) {
- PLOG(ERROR) << cgroup_rc_path << " file version mismatch";
+ if (file_data->version_ != CgroupFile::FILE_CURR_VERSION) {
+ LOG(ERROR) << cgroup_rc_path << " file version mismatch";
+ munmap(file_data, file_size);
return false;
}
+ if (file_size != sizeof(CgroupFile) + file_data->controller_count_ * sizeof(CgroupController)) {
+ LOG(ERROR) << cgroup_rc_path << " file has invalid size";
+ munmap(file_data, file_size);
+ return false;
+ }
+
+ cg_file_data_ = file_data;
+ cg_file_size_ = file_size;
+
return true;
}
-void CgroupMap::Print() {
+void CgroupMap::Print() const {
+ if (!cg_file_data_) {
+ LOG(ERROR) << "CgroupMap::Print called for [" << getpid()
+ << "] failed, RC file was not initialized properly";
+ return;
+ }
LOG(INFO) << "File version = " << cg_file_data_->version_;
LOG(INFO) << "File controller count = " << cg_file_data_->controller_count_;
@@ -397,7 +412,7 @@
// load cgroups.json file
if (!ReadDescriptors(&descriptors)) {
- PLOG(ERROR) << "Failed to load cgroup description file";
+ LOG(ERROR) << "Failed to load cgroup description file";
return false;
}
@@ -412,7 +427,7 @@
// mkdir <CGROUPS_RC_DIR> 0711 system system
if (!Mkdir(CGROUPS_RC_DIR, 0711, "system", "system")) {
- PLOG(ERROR) << "Failed to create directory for <CGROUPS_RC_FILE> file";
+ LOG(ERROR) << "Failed to create directory for <CGROUPS_RC_FILE> file";
return false;
}
@@ -428,7 +443,7 @@
std::string cgroup_rc_path = StringPrintf("%s/%s", CGROUPS_RC_DIR, CGROUPS_RC_FILE);
// chmod 0644 <cgroup_rc_path>
if (fchmodat(AT_FDCWD, cgroup_rc_path.c_str(), 0644, AT_SYMLINK_NOFOLLOW) < 0) {
- LOG(ERROR) << "fchmodat() failed";
+ PLOG(ERROR) << "fchmodat() failed";
return false;
}
@@ -437,6 +452,8 @@
const CgroupController* CgroupMap::FindController(const std::string& name) const {
if (!cg_file_data_) {
+ LOG(ERROR) << "CgroupMap::FindController called for [" << getpid()
+ << "] failed, RC file was not initialized properly";
return nullptr;
}
diff --git a/libprocessgroup/cgroup_map.h b/libprocessgroup/cgroup_map.h
index ba2caf7..1c355cd 100644
--- a/libprocessgroup/cgroup_map.h
+++ b/libprocessgroup/cgroup_map.h
@@ -92,5 +92,5 @@
~CgroupMap();
bool LoadRcFile();
- void Print();
+ void Print() const;
};
diff --git a/libprocessgroup/sched_policy.cpp b/libprocessgroup/sched_policy.cpp
index 026c011..1eefada 100644
--- a/libprocessgroup/sched_policy.cpp
+++ b/libprocessgroup/sched_policy.cpp
@@ -167,7 +167,7 @@
if (!controller) return -1;
if (!controller->GetTaskGroup(tid, &subgroup)) {
- PLOG(ERROR) << "Failed to find cgroup for tid " << tid;
+ LOG(ERROR) << "Failed to find cgroup for tid " << tid;
return -1;
}
return 0;
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index fded417..dcf53f9 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -119,7 +119,7 @@
std::string path;
if (!attribute_->GetPathForTask(tid, &path)) {
- PLOG(ERROR) << "Failed to find cgroup for tid " << tid;
+ LOG(ERROR) << "Failed to find cgroup for tid " << tid;
return false;
}
@@ -174,7 +174,7 @@
if (TEMP_FAILURE_RETRY(write(fd, value.c_str(), value.length())) < 0) {
// If the thread is in the process of exiting, don't flag an error
if (errno != ESRCH) {
- PLOG(ERROR) << "JoinGroup failed to write '" << value << "'; fd=" << fd;
+ PLOG(ERROR) << "AddTidToCgroup failed to write '" << value << "'; fd=" << fd;
return false;
}
}
@@ -187,7 +187,7 @@
if (fd_ >= 0) {
// fd is cached, reuse it
if (!AddTidToCgroup(pid, fd_)) {
- PLOG(ERROR) << "Failed to add task into cgroup";
+ LOG(ERROR) << "Failed to add task into cgroup";
return false;
}
return true;
@@ -206,7 +206,7 @@
return false;
}
if (!AddTidToCgroup(pid, tmp_fd)) {
- PLOG(ERROR) << "Failed to add task into cgroup";
+ LOG(ERROR) << "Failed to add task into cgroup";
return false;
}
@@ -219,7 +219,7 @@
return true;
}
if (!AddTidToCgroup(pid, tmp_fd)) {
- PLOG(ERROR) << "Failed to add task into cgroup";
+ LOG(ERROR) << "Failed to add task into cgroup";
return false;
}
@@ -232,7 +232,7 @@
if (fd_ >= 0) {
// fd is cached, reuse it
if (!AddTidToCgroup(tid, fd_)) {
- PLOG(ERROR) << "Failed to add task into cgroup";
+ LOG(ERROR) << "Failed to add task into cgroup";
return false;
}
return true;
@@ -244,7 +244,7 @@
}
// application-dependent path can't be used with tid
- PLOG(ERROR) << "Application profile can't be applied to a thread";
+ LOG(ERROR) << "Application profile can't be applied to a thread";
return false;
#else
std::string tasks_path = controller_->GetTasksFilePath(path_);
@@ -254,7 +254,7 @@
return true;
}
if (!AddTidToCgroup(tid, tmp_fd)) {
- PLOG(ERROR) << "Failed to add task into cgroup";
+ LOG(ERROR) << "Failed to add task into cgroup";
return false;
}
diff --git a/libunwindstack/Global.cpp b/libunwindstack/Global.cpp
index fdfd705..a20be00 100644
--- a/libunwindstack/Global.cpp
+++ b/libunwindstack/Global.cpp
@@ -77,7 +77,7 @@
// f0000-f2000 0 r-- /system/lib/libc.so
// f2000-f3000 2000 rw- /system/lib/libc.so
MapInfo* map_start = nullptr;
- for (MapInfo* info : *maps) {
+ for (const auto& info : *maps) {
if (map_start != nullptr) {
if (map_start->name == info->name) {
if (info->offset != 0 &&
@@ -96,7 +96,7 @@
}
if (map_start == nullptr && (info->flags & PROT_READ) && info->offset == 0 &&
!info->name.empty()) {
- map_start = info;
+ map_start = info.get();
}
}
}
diff --git a/libunwindstack/Maps.cpp b/libunwindstack/Maps.cpp
index 1e4f72e..5da73e4 100644
--- a/libunwindstack/Maps.cpp
+++ b/libunwindstack/Maps.cpp
@@ -47,9 +47,9 @@
size_t last = maps_.size();
while (first < last) {
size_t index = (first + last) / 2;
- MapInfo* cur = maps_[index];
+ const auto& cur = maps_[index];
if (pc >= cur->start && pc < cur->end) {
- return cur;
+ return cur.get();
} else if (pc < cur->start) {
last = index;
} else {
@@ -67,34 +67,31 @@
if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) {
flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
}
- maps_.push_back(
- new MapInfo(maps_.empty() ? nullptr : maps_.back(), start, end, pgoff, flags, name));
+ maps_.emplace_back(
+ new MapInfo(maps_.empty() ? nullptr : maps_.back().get(), start, end, pgoff,
+ flags, name));
});
}
void Maps::Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
const std::string& name, uint64_t load_bias) {
- MapInfo* map_info =
- new MapInfo(maps_.empty() ? nullptr : maps_.back(), start, end, offset, flags, name);
+ auto map_info =
+ std::make_unique<MapInfo>(maps_.empty() ? nullptr : maps_.back().get(), start, end, offset,
+ flags, name);
map_info->load_bias = load_bias;
- maps_.push_back(map_info);
+ maps_.emplace_back(std::move(map_info));
}
void Maps::Sort() {
std::sort(maps_.begin(), maps_.end(),
- [](const MapInfo* a, const MapInfo* b) { return a->start < b->start; });
+ [](const std::unique_ptr<MapInfo>& a, const std::unique_ptr<MapInfo>& b) {
+ return a->start < b->start; });
// Set the prev_map values on the info objects.
MapInfo* prev_map = nullptr;
- for (MapInfo* map_info : maps_) {
+ for (const auto& map_info : maps_) {
map_info->prev_map = prev_map;
- prev_map = map_info;
- }
-}
-
-Maps::~Maps() {
- for (auto& map : maps_) {
- delete map;
+ prev_map = map_info.get();
}
}
@@ -107,8 +104,9 @@
if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) {
flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
}
- maps_.push_back(
- new MapInfo(maps_.empty() ? nullptr : maps_.back(), start, end, pgoff, flags, name));
+ maps_.emplace_back(
+ new MapInfo(maps_.empty() ? nullptr : maps_.back().get(), start, end, pgoff,
+ flags, name));
});
}
@@ -124,10 +122,6 @@
// New maps will be added at the end without deleting the old ones.
size_t last_map_idx = maps_.size();
if (!Parse()) {
- // Delete any maps added by the Parse call.
- for (size_t i = last_map_idx; i < maps_.size(); i++) {
- delete maps_[i];
- }
maps_.resize(last_map_idx);
return false;
}
@@ -135,17 +129,16 @@
size_t total_entries = maps_.size();
size_t search_map_idx = 0;
for (size_t new_map_idx = last_map_idx; new_map_idx < maps_.size(); new_map_idx++) {
- MapInfo* new_map_info = maps_[new_map_idx];
+ auto& new_map_info = maps_[new_map_idx];
uint64_t start = new_map_info->start;
uint64_t end = new_map_info->end;
uint64_t flags = new_map_info->flags;
std::string* name = &new_map_info->name;
for (size_t old_map_idx = search_map_idx; old_map_idx < last_map_idx; old_map_idx++) {
- MapInfo* info = maps_[old_map_idx];
+ auto& info = maps_[old_map_idx];
if (start == info->start && end == info->end && flags == info->flags && *name == info->name) {
// No need to check
search_map_idx = old_map_idx + 1;
- delete new_map_info;
maps_[new_map_idx] = nullptr;
total_entries--;
break;
@@ -158,7 +151,7 @@
// Never delete these maps, they may be in use. The assumption is
// that there will only every be a handfull of these so waiting
// to destroy them is not too expensive.
- saved_maps_.push_back(info);
+ saved_maps_.emplace_back(std::move(info));
maps_[old_map_idx] = nullptr;
total_entries--;
}
@@ -169,14 +162,14 @@
// Now move out any of the maps that never were found.
for (size_t i = search_map_idx; i < last_map_idx; i++) {
- saved_maps_.push_back(maps_[i]);
+ saved_maps_.emplace_back(std::move(maps_[i]));
maps_[i] = nullptr;
total_entries--;
}
// Sort all of the values such that the nullptrs wind up at the end, then
// resize them away.
- std::sort(maps_.begin(), maps_.end(), [](const auto* a, const auto* b) {
+ std::sort(maps_.begin(), maps_.end(), [](const auto& a, const auto& b) {
if (a == nullptr) {
return false;
} else if (b == nullptr) {
@@ -189,10 +182,4 @@
return true;
}
-LocalUpdatableMaps::~LocalUpdatableMaps() {
- for (auto map_info : saved_maps_) {
- delete map_info;
- }
-}
-
} // namespace unwindstack
diff --git a/libunwindstack/benchmarks/unwind_benchmarks.cpp b/libunwindstack/benchmarks/unwind_benchmarks.cpp
index 8caecc7..de9137a 100644
--- a/libunwindstack/benchmarks/unwind_benchmarks.cpp
+++ b/libunwindstack/benchmarks/unwind_benchmarks.cpp
@@ -92,9 +92,9 @@
// Find the libc.so share library and use that for benchmark purposes.
*build_id_map_info = nullptr;
- for (unwindstack::MapInfo* map_info : maps) {
+ for (auto& map_info : maps) {
if (map_info->offset == 0 && map_info->GetBuildID() != "") {
- *build_id_map_info = map_info;
+ *build_id_map_info = map_info.get();
break;
}
}
diff --git a/libunwindstack/include/unwindstack/Maps.h b/libunwindstack/include/unwindstack/Maps.h
index 67fbed2..1784394 100644
--- a/libunwindstack/include/unwindstack/Maps.h
+++ b/libunwindstack/include/unwindstack/Maps.h
@@ -20,6 +20,7 @@
#include <sys/types.h>
#include <unistd.h>
+#include <memory>
#include <string>
#include <vector>
@@ -37,8 +38,16 @@
class Maps {
public:
+ virtual ~Maps() = default;
+
Maps() = default;
- virtual ~Maps();
+
+ // Maps are not copyable but movable, because they own pointers to MapInfo
+ // objects.
+ Maps(const Maps&) = delete;
+ Maps& operator=(const Maps&) = delete;
+ Maps(Maps&&) = default;
+ Maps& operator=(Maps&&) = default;
MapInfo* Find(uint64_t pc);
@@ -51,11 +60,11 @@
void Sort();
- typedef std::vector<MapInfo*>::iterator iterator;
+ typedef std::vector<std::unique_ptr<MapInfo>>::iterator iterator;
iterator begin() { return maps_.begin(); }
iterator end() { return maps_.end(); }
- typedef std::vector<MapInfo*>::const_iterator const_iterator;
+ typedef std::vector<std::unique_ptr<MapInfo>>::const_iterator const_iterator;
const_iterator begin() const { return maps_.begin(); }
const_iterator end() const { return maps_.end(); }
@@ -63,11 +72,11 @@
MapInfo* Get(size_t index) {
if (index >= maps_.size()) return nullptr;
- return maps_[index];
+ return maps_[index].get();
}
protected:
- std::vector<MapInfo*> maps_;
+ std::vector<std::unique_ptr<MapInfo>> maps_;
};
class RemoteMaps : public Maps {
@@ -90,14 +99,14 @@
class LocalUpdatableMaps : public Maps {
public:
LocalUpdatableMaps() : Maps() {}
- virtual ~LocalUpdatableMaps();
+ virtual ~LocalUpdatableMaps() = default;
bool Reparse();
const std::string GetMapsFile() const override;
private:
- std::vector<MapInfo*> saved_maps_;
+ std::vector<std::unique_ptr<MapInfo>> saved_maps_;
};
class BufferMaps : public Maps {
diff --git a/libunwindstack/tests/MapsTest.cpp b/libunwindstack/tests/MapsTest.cpp
index b4197f2..9e7a6ab 100644
--- a/libunwindstack/tests/MapsTest.cpp
+++ b/libunwindstack/tests/MapsTest.cpp
@@ -61,6 +61,26 @@
ASSERT_EQ(0U, info->load_bias.load());
}
+TEST(MapsTest, map_move) {
+ Maps maps;
+
+ maps.Add(0x1000, 0x2000, 0, PROT_READ, "fake_map", 0);
+ maps.Add(0x3000, 0x4000, 0x10, 0, "", 0x1234);
+ maps.Add(0x5000, 0x6000, 1, 2, "fake_map2", static_cast<uint64_t>(-1));
+
+ Maps maps2 = std::move(maps);
+
+ ASSERT_EQ(3U, maps2.Total());
+ MapInfo* info = maps2.Get(0);
+ ASSERT_EQ(0x1000U, info->start);
+ ASSERT_EQ(0x2000U, info->end);
+ ASSERT_EQ(0U, info->offset);
+ ASSERT_EQ(PROT_READ, info->flags);
+ ASSERT_EQ("fake_map", info->name);
+ ASSERT_EQ(0U, info->elf_offset);
+ ASSERT_EQ(0U, info->load_bias.load());
+}
+
TEST(MapsTest, verify_parse_line) {
MapInfo info(nullptr, 0, 0, 0, 0, "");
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index d88531f..2dc5118 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -49,7 +49,7 @@
std::string str_name(name);
maps_->Add(start, end, offset, flags, name, static_cast<uint64_t>(-1));
if (elf != nullptr) {
- MapInfo* map_info = *--maps_->end();
+ const auto& map_info = *--maps_->end();
map_info->elf.reset(elf);
}
}
@@ -85,7 +85,7 @@
AddMapInfo(0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat");
AddMapInfo(0xa3000, 0xa4000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake.vdex");
- MapInfo* info = *--maps_->end();
+ const auto& info = *--maps_->end();
info->load_bias = 0;
elf = new ElfFake(new MemoryFake);
@@ -98,8 +98,8 @@
elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
AddMapInfo(0xa7000, 0xa8000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake_offset.oat",
elf);
- info = *--maps_->end();
- info->elf_offset = 0x8000;
+ const auto& info2 = *--maps_->end();
+ info2->elf_offset = 0x8000;
process_memory_.reset(new MemoryFake);
}
diff --git a/mkbootimg/unpack_bootimg.py b/mkbootimg/unpack_bootimg.py
index 6b5d5d0..789bf5e 100755
--- a/mkbootimg/unpack_bootimg.py
+++ b/mkbootimg/unpack_bootimg.py
@@ -48,12 +48,12 @@
print('boot_magic: %s' % boot_magic)
kernel_ramdisk_second_info = unpack('10I', args.boot_img.read(10 * 4))
print('kernel_size: %s' % kernel_ramdisk_second_info[0])
- print('kernel load address: %s' % kernel_ramdisk_second_info[1])
+ print('kernel load address: %#x' % kernel_ramdisk_second_info[1])
print('ramdisk size: %s' % kernel_ramdisk_second_info[2])
- print('ramdisk load address: %s' % kernel_ramdisk_second_info[3])
+ print('ramdisk load address: %#x' % kernel_ramdisk_second_info[3])
print('second bootloader size: %s' % kernel_ramdisk_second_info[4])
- print('second bootloader load address: %s' % kernel_ramdisk_second_info[5])
- print('kernel tags load address: %s' % kernel_ramdisk_second_info[6])
+ print('second bootloader load address: %#x' % kernel_ramdisk_second_info[5])
+ print('kernel tags load address: %#x' % kernel_ramdisk_second_info[6])
print('page size: %s' % kernel_ramdisk_second_info[7])
print('boot image header version: %s' % kernel_ramdisk_second_info[8])
print('os version and patch level: %s' % kernel_ramdisk_second_info[9])
@@ -77,7 +77,7 @@
recovery_dtbo_size = unpack('I', args.boot_img.read(1 * 4))[0]
print('recovery dtbo size: %s' % recovery_dtbo_size)
recovery_dtbo_offset = unpack('Q', args.boot_img.read(8))[0]
- print('recovery dtbo offset: %s' % recovery_dtbo_offset)
+ print('recovery dtbo offset: %#x' % recovery_dtbo_offset)
boot_header_size = unpack('I', args.boot_img.read(4))[0]
print('boot header size: %s' % boot_header_size)
else:
@@ -86,7 +86,7 @@
dtb_size = unpack('I', args.boot_img.read(4))[0]
print('dtb size: %s' % dtb_size)
dtb_load_address = unpack('Q', args.boot_img.read(8))[0]
- print('dtb address: %s' % dtb_load_address)
+ print('dtb address: %#x' % dtb_load_address)
else:
dtb_size = 0
@@ -103,10 +103,11 @@
) # header + kernel
image_info_list.append((ramdisk_offset, ramdisk_size, 'ramdisk'))
- second_offset = page_size * (
- num_header_pages + num_kernel_pages + num_ramdisk_pages
- ) # header + kernel + ramdisk
- image_info_list.append((second_offset, second_size, 'second'))
+ if second_size > 0:
+ second_offset = page_size * (
+ num_header_pages + num_kernel_pages + num_ramdisk_pages
+ ) # header + kernel + ramdisk
+ image_info_list.append((second_offset, second_size, 'second'))
if recovery_dtbo_size > 0:
image_info_list.append((recovery_dtbo_offset, recovery_dtbo_size,
diff --git a/rootdir/etc/ld.config.legacy.txt b/rootdir/etc/ld.config.legacy.txt
index 0cde3f2..d4d5c28 100644
--- a/rootdir/etc/ld.config.legacy.txt
+++ b/rootdir/etc/ld.config.legacy.txt
@@ -40,7 +40,7 @@
# Keep in sync with ld.config.txt in the com.android.runtime APEX.
# If a shared library or an executable requests a shared library that
# cannot be loaded into the default namespace, the dynamic linker tries
-# to load the shared library from the runtime namespace.And then, if the
+# to load the shared library from the runtime namespace. And then, if the
# shared library cannot be loaded from the runtime namespace either, the
# dynamic linker tries to load the shared library from the resolv namespace.
# Finally, if all attempts fail, the dynamic linker returns an error.
@@ -94,11 +94,7 @@
namespace.media.permitted.paths = /apex/com.android.media/${LIB}/extractors
namespace.media.links = default
-namespace.media.link.default.shared_libs = %LLNDK_LIBRARIES%
-namespace.media.link.default.shared_libs += libandroid.so
-namespace.media.link.default.shared_libs += libbinder_ndk.so
-namespace.media.link.default.shared_libs += libmediametrics.so
-namespace.media.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
+namespace.media.link.default.allow_all_shared_libs = true
###############################################################################
# "conscrypt" APEX namespace
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 4b2dd07..552d685 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -125,7 +125,7 @@
# Keep in sync with ld.config.txt in the com.android.runtime APEX.
# If a shared library or an executable requests a shared library that
# cannot be loaded into the default namespace, the dynamic linker tries
-# to load the shared library from the runtime namespace.And then, if the
+# to load the shared library from the runtime namespace. And then, if the
# shared library cannot be loaded from the runtime namespace either, the
# dynamic linker tries to load the shared library from the resolv namespace.
# Finally, if all attempts fail, the dynamic linker returns an error.
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index 54f4c98..beb6125 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -66,7 +66,7 @@
# ld.config.txt.
# If a shared library or an executable requests a shared library that
# cannot be loaded into the default namespace, the dynamic linker tries
-# to load the shared library from the runtime namespace.And then, if the
+# to load the shared library from the runtime namespace. And then, if the
# shared library cannot be loaded from the runtime namespace either, the
# dynamic linker tries to load the shared library from the resolv namespace.
# Finally, if all attempts fail, the dynamic linker returns an error.
diff --git a/rootdir/init.rc b/rootdir/init.rc
index d6a67e5..21692bb 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -387,6 +387,7 @@
restorecon_recursive /metadata
mkdir /metadata/vold
chmod 0700 /metadata/vold
+ mkdir /metadata/password_slots 0771 root system
on late-fs
# Ensure that tracefs has the correct permissions.
@@ -585,7 +586,10 @@
restorecon --recursive --skip-ce /data
# load fsverity keys
- exec -- /system/bin/mini-keyctl -c /product/etc/security/cacerts_fsverity,/vendor/etc/security/cacerts_fsverity -k .fs-verity
+ exec -- /system/bin/mini-keyctl dadd asymmetric product_cert /product/etc/security/cacerts_fsverity .fs-verity
+ exec -- /system/bin/mini-keyctl dadd asymmetric vendor_cert /vendor/etc/security/cacerts_fsverity .fs-verity
+ # Prevent future key links to fsverity keyring
+ exec -- /system/bin/mini-keyctl restrict_keyring .fs-verity
# Check any timezone data in /data is newer than the copy in the runtime module, delete if not.
exec - system system -- /system/bin/tzdatacheck /apex/com.android.runtime/etc/tz /data/misc/zoneinfo
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
index 38c5d18..bf3fb42 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -5,7 +5,6 @@
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
- updatable
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
diff --git a/rootdir/init.zygote32_64.rc b/rootdir/init.zygote32_64.rc
index 58bb452..1bab588 100644
--- a/rootdir/init.zygote32_64.rc
+++ b/rootdir/init.zygote32_64.rc
@@ -5,7 +5,6 @@
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
- updatable
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
@@ -22,6 +21,5 @@
group root readproc reserved_disk
socket zygote_secondary stream 660 root system
socket usap_pool_secondary stream 660 root system
- updatable
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index f7dc5f6..6fa210a 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -5,7 +5,6 @@
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
- updatable
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc
index 5829a9d..48461ec 100644
--- a/rootdir/init.zygote64_32.rc
+++ b/rootdir/init.zygote64_32.rc
@@ -5,7 +5,6 @@
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
- updatable
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
@@ -22,6 +21,5 @@
group root readproc reserved_disk
socket zygote_secondary stream 660 root system
socket usap_pool_secondary stream 660 root system
- updatable
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
diff --git a/sdcard/sdcard.cpp b/sdcard/sdcard.cpp
index e1de130..2b35819 100644
--- a/sdcard/sdcard.cpp
+++ b/sdcard/sdcard.cpp
@@ -27,6 +27,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
+#include <vector>
#include <android-base/file.h>
#include <android-base/logging.h>
@@ -99,14 +100,21 @@
static bool sdcardfs_setup(const std::string& source_path, const std::string& dest_path,
uid_t fsuid, gid_t fsgid, bool multi_user, userid_t userid, gid_t gid,
- mode_t mask, bool derive_gid, bool default_normal, bool use_esdfs) {
+ mode_t mask, bool derive_gid, bool default_normal, bool unshared_obb,
+ bool use_esdfs) {
+ // Add new options at the end of the vector.
+ std::vector<std::string> new_opts_list;
+ if (multi_user) new_opts_list.push_back("multiuser,");
+ if (derive_gid) new_opts_list.push_back("derive_gid,");
+ if (default_normal) new_opts_list.push_back("default_normal,");
+ if (unshared_obb) new_opts_list.push_back("unshared_obb,");
// Try several attempts, each time with one less option, to gracefully
// handle older kernels that aren't updated yet.
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i <= new_opts_list.size(); ++i) {
std::string new_opts;
- if (multi_user && i < 3) new_opts += "multiuser,";
- if (derive_gid && i < 2) new_opts += "derive_gid,";
- if (default_normal && i < 1) new_opts += "default_normal,";
+ for (int j = 0; j < new_opts_list.size() - i; ++j) {
+ new_opts += new_opts_list[j];
+ }
auto opts = android::base::StringPrintf("fsuid=%d,fsgid=%d,%smask=%d,userid=%d,gid=%d",
fsuid, fsgid, new_opts.c_str(), mask, userid, gid);
@@ -142,13 +150,14 @@
return true;
}
-static bool sdcardfs_setup_secondary(const std::string& default_path, const std::string& source_path,
- const std::string& dest_path, uid_t fsuid, gid_t fsgid,
- bool multi_user, userid_t userid, gid_t gid, mode_t mask,
- bool derive_gid, bool default_normal, bool use_esdfs) {
+static bool sdcardfs_setup_secondary(const std::string& default_path,
+ const std::string& source_path, const std::string& dest_path,
+ uid_t fsuid, gid_t fsgid, bool multi_user, userid_t userid,
+ gid_t gid, mode_t mask, bool derive_gid, bool default_normal,
+ bool unshared_obb, bool use_esdfs) {
if (use_esdfs) {
return sdcardfs_setup(source_path, dest_path, fsuid, fsgid, multi_user, userid, gid, mask,
- derive_gid, default_normal, use_esdfs);
+ derive_gid, default_normal, unshared_obb, use_esdfs);
} else {
return sdcardfs_setup_bind_remount(default_path, dest_path, gid, mask);
}
@@ -156,7 +165,7 @@
static void run_sdcardfs(const std::string& source_path, const std::string& label, uid_t uid,
gid_t gid, userid_t userid, bool multi_user, bool full_write,
- bool derive_gid, bool default_normal, bool use_esdfs) {
+ bool derive_gid, bool default_normal, bool unshared_obb, bool use_esdfs) {
std::string dest_path_default = "/mnt/runtime/default/" + label;
std::string dest_path_read = "/mnt/runtime/read/" + label;
std::string dest_path_write = "/mnt/runtime/write/" + label;
@@ -167,16 +176,17 @@
// Multi-user storage is fully isolated per user, so "other"
// permissions are completely masked off.
if (!sdcardfs_setup(source_path, dest_path_default, uid, gid, multi_user, userid,
- AID_SDCARD_RW, 0006, derive_gid, default_normal, use_esdfs) ||
+ AID_SDCARD_RW, 0006, derive_gid, default_normal, unshared_obb,
+ use_esdfs) ||
!sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_read, uid, gid,
multi_user, userid, AID_EVERYBODY, 0027, derive_gid,
- default_normal, use_esdfs) ||
+ default_normal, unshared_obb, use_esdfs) ||
!sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_write, uid, gid,
multi_user, userid, AID_EVERYBODY, full_write ? 0007 : 0027,
- derive_gid, default_normal, use_esdfs) ||
+ derive_gid, default_normal, unshared_obb, use_esdfs) ||
!sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_full, uid, gid,
multi_user, userid, AID_EVERYBODY, 0007, derive_gid,
- default_normal, use_esdfs)) {
+ default_normal, unshared_obb, use_esdfs)) {
LOG(FATAL) << "failed to sdcardfs_setup";
}
} else {
@@ -184,16 +194,17 @@
// the Android directories are masked off to a single user
// deep inside attr_from_stat().
if (!sdcardfs_setup(source_path, dest_path_default, uid, gid, multi_user, userid,
- AID_SDCARD_RW, 0006, derive_gid, default_normal, use_esdfs) ||
+ AID_SDCARD_RW, 0006, derive_gid, default_normal, unshared_obb,
+ use_esdfs) ||
!sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_read, uid, gid,
multi_user, userid, AID_EVERYBODY, full_write ? 0027 : 0022,
- derive_gid, default_normal, use_esdfs) ||
+ derive_gid, default_normal, unshared_obb, use_esdfs) ||
!sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_write, uid, gid,
multi_user, userid, AID_EVERYBODY, full_write ? 0007 : 0022,
- derive_gid, default_normal, use_esdfs) ||
+ derive_gid, default_normal, unshared_obb, use_esdfs) ||
!sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_full, uid, gid,
multi_user, userid, AID_EVERYBODY, 0007, derive_gid,
- default_normal, use_esdfs)) {
+ default_normal, unshared_obb, use_esdfs)) {
LOG(FATAL) << "failed to sdcardfs_setup";
}
}
@@ -216,7 +227,8 @@
<< " -U: specify user ID that owns device"
<< " -m: source_path is multi-user"
<< " -w: runtime write mount has full write access"
- << " -P preserve owners on the lower file system";
+ << " -P: preserve owners on the lower file system"
+ << " -o: obb dir doesn't need to be shared between users";
return 1;
}
@@ -230,6 +242,7 @@
bool full_write = false;
bool derive_gid = false;
bool default_normal = false;
+ bool unshared_obb = false;
int i;
struct rlimit rlim;
int fs_version;
@@ -238,7 +251,7 @@
android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
int opt;
- while ((opt = getopt(argc, argv, "u:g:U:mwGi")) != -1) {
+ while ((opt = getopt(argc, argv, "u:g:U:mwGio")) != -1) {
switch (opt) {
case 'u':
uid = strtoul(optarg, NULL, 10);
@@ -261,8 +274,12 @@
case 'i':
default_normal = true;
break;
+ case 'o':
+ unshared_obb = true;
+ break;
case '?':
default:
+ LOG(ERROR) << "Unknown option: '" << opt << "'";
return usage();
}
}
@@ -304,6 +321,6 @@
}
run_sdcardfs(source_path, label, uid, gid, userid, multi_user, full_write, derive_gid,
- default_normal, !should_use_sdcardfs());
+ default_normal, unshared_obb, !should_use_sdcardfs());
return 1;
}
diff --git a/trusty/storage/proxy/proxy.c b/trusty/storage/proxy/proxy.c
index 9a71ae3..c61f7d0 100644
--- a/trusty/storage/proxy/proxy.c
+++ b/trusty/storage/proxy/proxy.c
@@ -39,15 +39,29 @@
static const char* rpmb_devname;
static const char* ss_srv_name = STORAGE_DISK_PROXY_PORT;
-static const char* _sopts = "hp:d:r:";
+static enum dev_type dev_type = MMC_RPMB;
+
+static enum dev_type parse_dev_type(const char* dev_type_name) {
+ if (!strcmp(dev_type_name, "mmc")) {
+ return MMC_RPMB;
+ } else if (!strcmp(dev_type_name, "virt")) {
+ return VIRT_RPMB;
+ } else {
+ return UNKNOWN_RPMB;
+ }
+}
+
+static const char* _sopts = "hp:d:r:t:";
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'},
{0, 0, 0, 0}};
static void show_usage_and_exit(int code) {
- ALOGE("usage: storageproxyd -d <trusty_dev> -p <data_path> -r <rpmb_dev>\n");
+ ALOGE("usage: storageproxyd -d <trusty_dev> -p <data_path> -r <rpmb_dev> -t <dev_type>\n");
+ ALOGE("Available dev types: mmc, virt\n");
exit(code);
}
@@ -195,6 +209,14 @@
rpmb_devname = strdup(optarg);
break;
+ case 't':
+ dev_type = parse_dev_type(optarg);
+ if (dev_type == UNKNOWN_RPMB) {
+ ALOGE("Unrecognized dev type: %s\n", optarg);
+ show_usage_and_exit(EXIT_FAILURE);
+ }
+ break;
+
default:
ALOGE("unrecognized option (%c):\n", opt);
show_usage_and_exit(EXIT_FAILURE);
@@ -226,7 +248,7 @@
if (rc < 0) return EXIT_FAILURE;
/* open rpmb device */
- rc = rpmb_open(rpmb_devname);
+ rc = rpmb_open(rpmb_devname, dev_type);
if (rc < 0) return EXIT_FAILURE;
/* connect to Trusty secure storage server */
diff --git a/trusty/storage/proxy/rpmb.c b/trusty/storage/proxy/rpmb.c
index e706d0a..29827e2 100644
--- a/trusty/storage/proxy/rpmb.c
+++ b/trusty/storage/proxy/rpmb.c
@@ -51,6 +51,7 @@
static int rpmb_fd = -1;
static uint8_t read_buf[4096];
+static enum dev_type dev_type = UNKNOWN_RPMB;
#ifdef RPMB_DEBUG
@@ -68,36 +69,16 @@
#endif
-int rpmb_send(struct storage_msg* msg, const void* r, size_t req_len) {
- int rc;
+static int send_mmc_rpmb_req(int mmc_fd, const struct storage_rpmb_send_req* req) {
struct {
struct mmc_ioc_multi_cmd multi;
struct mmc_ioc_cmd cmd_buf[3];
} mmc = {};
struct mmc_ioc_cmd* cmd = mmc.multi.cmds;
- const struct storage_rpmb_send_req* req = r;
-
- if (req_len < sizeof(*req)) {
- ALOGW("malformed rpmb request: invalid length (%zu < %zu)\n", req_len, sizeof(*req));
- msg->result = STORAGE_ERR_NOT_VALID;
- goto err_response;
- }
-
- size_t expected_len = sizeof(*req) + req->reliable_write_size + req->write_size;
- if (req_len != expected_len) {
- ALOGW("malformed rpmb request: invalid length (%zu != %zu)\n", req_len, expected_len);
- msg->result = STORAGE_ERR_NOT_VALID;
- goto err_response;
- }
+ int rc;
const uint8_t* write_buf = req->payload;
if (req->reliable_write_size) {
- if ((req->reliable_write_size % MMC_BLOCK_SIZE) != 0) {
- ALOGW("invalid reliable write size %u\n", req->reliable_write_size);
- msg->result = STORAGE_ERR_NOT_VALID;
- goto err_response;
- }
-
cmd->write_flag = MMC_WRITE_FLAG_RELW;
cmd->opcode = MMC_WRITE_MULTIPLE_BLOCK;
cmd->flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
@@ -114,12 +95,6 @@
}
if (req->write_size) {
- if ((req->write_size % MMC_BLOCK_SIZE) != 0) {
- ALOGW("invalid write size %u\n", req->write_size);
- msg->result = STORAGE_ERR_NOT_VALID;
- goto err_response;
- }
-
cmd->write_flag = MMC_WRITE_FLAG_W;
cmd->opcode = MMC_WRITE_MULTIPLE_BLOCK;
cmd->flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
@@ -136,12 +111,6 @@
}
if (req->read_size) {
- if (req->read_size % MMC_BLOCK_SIZE != 0 || req->read_size > sizeof(read_buf)) {
- ALOGE("%s: invalid read size %u\n", __func__, req->read_size);
- msg->result = STORAGE_ERR_NOT_VALID;
- goto err_response;
- }
-
cmd->write_flag = MMC_WRITE_FLAG_R;
cmd->opcode = MMC_READ_MULTIPLE_BLOCK;
cmd->flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC, cmd->blksz = MMC_BLOCK_SIZE;
@@ -154,9 +123,92 @@
cmd++;
}
- rc = ioctl(rpmb_fd, MMC_IOC_MULTI_CMD, &mmc.multi);
+ rc = ioctl(mmc_fd, MMC_IOC_MULTI_CMD, &mmc.multi);
if (rc < 0) {
ALOGE("%s: mmc ioctl failed: %d, %s\n", __func__, rc, strerror(errno));
+ }
+ return rc;
+}
+
+static int send_virt_rpmb_req(int rpmb_fd, void* read_buf, size_t read_size, const void* payload,
+ size_t payload_size) {
+ int rc;
+ uint16_t res_count = read_size / MMC_BLOCK_SIZE;
+ uint16_t cmd_count = payload_size / MMC_BLOCK_SIZE;
+ rc = write(rpmb_fd, &res_count, sizeof(res_count));
+ if (rc < 0) {
+ return rc;
+ }
+ rc = write(rpmb_fd, &cmd_count, sizeof(cmd_count));
+ if (rc < 0) {
+ return rc;
+ }
+ rc = write(rpmb_fd, payload, payload_size);
+ if (rc < 0) {
+ return rc;
+ }
+ rc = read(rpmb_fd, read_buf, read_size);
+ return rc;
+}
+
+int rpmb_send(struct storage_msg* msg, const void* r, size_t req_len) {
+ int rc;
+ const struct storage_rpmb_send_req* req = r;
+
+ if (req_len < sizeof(*req)) {
+ ALOGW("malformed rpmb request: invalid length (%zu < %zu)\n", req_len, sizeof(*req));
+ msg->result = STORAGE_ERR_NOT_VALID;
+ goto err_response;
+ }
+
+ size_t expected_len = sizeof(*req) + req->reliable_write_size + req->write_size;
+ if (req_len != expected_len) {
+ ALOGW("malformed rpmb request: invalid length (%zu != %zu)\n", req_len, expected_len);
+ msg->result = STORAGE_ERR_NOT_VALID;
+ goto err_response;
+ }
+
+ if ((req->reliable_write_size % MMC_BLOCK_SIZE) != 0) {
+ ALOGW("invalid reliable write size %u\n", req->reliable_write_size);
+ msg->result = STORAGE_ERR_NOT_VALID;
+ goto err_response;
+ }
+
+ if ((req->write_size % MMC_BLOCK_SIZE) != 0) {
+ ALOGW("invalid write size %u\n", req->write_size);
+ msg->result = STORAGE_ERR_NOT_VALID;
+ goto err_response;
+ }
+
+ if (req->read_size % MMC_BLOCK_SIZE != 0 || req->read_size > sizeof(read_buf)) {
+ ALOGE("%s: invalid read size %u\n", __func__, req->read_size);
+ msg->result = STORAGE_ERR_NOT_VALID;
+ goto err_response;
+ }
+
+ if (dev_type == MMC_RPMB) {
+ rc = send_mmc_rpmb_req(rpmb_fd, req);
+ if (rc < 0) {
+ msg->result = STORAGE_ERR_GENERIC;
+ goto err_response;
+ }
+ } else if (dev_type == VIRT_RPMB) {
+ size_t payload_size = req->reliable_write_size + req->write_size;
+ rc = send_virt_rpmb_req(rpmb_fd, read_buf, req->read_size, req->payload, payload_size);
+ if (rc < 0) {
+ ALOGE("send_virt_rpmb_req failed: %d, %s\n", rc, strerror(errno));
+ msg->result = STORAGE_ERR_GENERIC;
+ goto err_response;
+ }
+ if (rc != req->read_size) {
+ ALOGE("send_virt_rpmb_req got incomplete response: "
+ "(size %d, expected %d)\n",
+ rc, req->read_size);
+ msg->result = STORAGE_ERR_GENERIC;
+ goto err_response;
+ }
+ } else {
+ ALOGE("Unsupported dev_type\n");
msg->result = STORAGE_ERR_GENERIC;
goto err_response;
}
@@ -178,8 +230,9 @@
return ipc_respond(msg, NULL, 0);
}
-int rpmb_open(const char* rpmb_devname) {
+int rpmb_open(const char* rpmb_devname, enum dev_type open_dev_type) {
int rc;
+ dev_type = open_dev_type;
rc = open(rpmb_devname, O_RDWR, 0);
if (rc < 0) {
diff --git a/trusty/storage/proxy/rpmb.h b/trusty/storage/proxy/rpmb.h
index 5107361..4c330c9 100644
--- a/trusty/storage/proxy/rpmb.h
+++ b/trusty/storage/proxy/rpmb.h
@@ -18,6 +18,8 @@
#include <stdint.h>
#include <trusty/interface/storage.h>
-int rpmb_open(const char* rpmb_devname);
+enum dev_type { UNKNOWN_RPMB, MMC_RPMB, VIRT_RPMB };
+
+int rpmb_open(const char* rpmb_devname, enum dev_type dev_type);
int rpmb_send(struct storage_msg* msg, const void* r, size_t req_len);
void rpmb_close(void);