Merge "Merge Android Pie into master"
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 38c6f62..a8fe736 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -891,6 +891,10 @@
// child side of the fork
pipe_read.reset();
+ // android::base::Pipe unconditionally opens the pipe with O_CLOEXEC.
+ // Undo this manually.
+ fcntl(pipe_write.get(), F_SETFD, 0);
+
char reply_fd[30];
snprintf(reply_fd, sizeof(reply_fd), "%d", pipe_write.get());
// child process
diff --git a/adb/adb_unique_fd.cpp b/adb/adb_unique_fd.cpp
index 2079be1..dec73bc 100644
--- a/adb/adb_unique_fd.cpp
+++ b/adb/adb_unique_fd.cpp
@@ -21,45 +21,8 @@
#include "sysdeps.h"
-#if !defined(_WIN32)
-bool Pipe(unique_fd* read, unique_fd* write, int flags) {
- int pipefd[2];
-#if !defined(__APPLE__)
- if (pipe2(pipefd, flags) != 0) {
- return false;
- }
-#else
- // Darwin doesn't have pipe2. Implement it ourselves.
- if (flags != 0 && (flags & ~(O_CLOEXEC | O_NONBLOCK)) != 0) {
- errno = EINVAL;
- return false;
- }
-
- if (pipe(pipefd) != 0) {
- return false;
- }
-
- if (flags & O_CLOEXEC) {
- if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) != 0 ||
- fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) != 0) {
- adb_close(pipefd[0]);
- adb_close(pipefd[1]);
- return false;
- }
- }
-
- if (flags & O_NONBLOCK) {
- if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) != 0 ||
- fcntl(pipefd[1], F_SETFL, O_NONBLOCK) != 0) {
- adb_close(pipefd[0]);
- adb_close(pipefd[1]);
- return false;
- }
- }
-#endif
-
- read->reset(pipefd[0]);
- write->reset(pipefd[1]);
- return true;
+#if defined(_WIN32)
+void AdbCloser::Close(int fd) {
+ adb_close(fd);
}
#endif
diff --git a/adb/adb_unique_fd.h b/adb/adb_unique_fd.h
index bad501a..d47213d 100644
--- a/adb/adb_unique_fd.h
+++ b/adb/adb_unique_fd.h
@@ -21,15 +21,15 @@
#include <android-base/unique_fd.h>
+#if defined(_WIN32)
// Helper to automatically close an FD when it goes out of scope.
struct AdbCloser {
static void Close(int fd);
};
using unique_fd = android::base::unique_fd_impl<AdbCloser>;
-
-#if !defined(_WIN32)
-bool Pipe(unique_fd* read, unique_fd* write, int flags = 0);
+#else
+using unique_fd = android::base::unique_fd;
#endif
template <typename T>
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 0c3327f..ffac315 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -274,10 +274,6 @@
return android_dir;
}
-void AdbCloser::Close(int fd) {
- adb_close(fd);
-}
-
int syntax_error(const char* fmt, ...) {
fprintf(stderr, "adb: usage: ");
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 1b20157..03b3287 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -43,7 +43,7 @@
export_include_dirs: ["tombstoned/include"],
}
-// Utility library to tombstoned and get an output fd.
+// Utility library to talk to tombstoned and get an output fd.
cc_library_static {
name: "libtombstoned_client_static",
defaults: ["debuggerd_defaults"],
@@ -166,6 +166,9 @@
local_include_dirs: ["libdebuggerd/include"],
export_include_dirs: ["libdebuggerd/include"],
+ // Needed for private/bionic_fdsan.h
+ include_dirs: ["bionic/libc"],
+
static_libs: [
"libbacktrace",
"libunwindstack",
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 40cf6c3..93f7572 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -249,24 +249,48 @@
}
static void ReadCrashInfo(unique_fd& fd, siginfo_t* siginfo,
- std::unique_ptr<unwindstack::Regs>* regs, uintptr_t* abort_address) {
+ std::unique_ptr<unwindstack::Regs>* regs, uintptr_t* abort_msg_address,
+ uintptr_t* fdsan_table_address) {
std::aligned_storage<sizeof(CrashInfo) + 1, alignof(CrashInfo)>::type buf;
+ CrashInfo* crash_info = reinterpret_cast<CrashInfo*>(&buf);
ssize_t rc = TEMP_FAILURE_RETRY(read(fd.get(), &buf, sizeof(buf)));
if (rc == -1) {
PLOG(FATAL) << "failed to read target ucontext";
- } else if (rc != sizeof(CrashInfo)) {
- LOG(FATAL) << "read " << rc << " bytes when reading target crash information, expected "
- << sizeof(CrashInfo);
+ } else {
+ ssize_t expected_size = 0;
+ switch (crash_info->header.version) {
+ case 1:
+ expected_size = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataV1);
+ break;
+
+ case 2:
+ expected_size = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataV2);
+ break;
+
+ default:
+ LOG(FATAL) << "unexpected CrashInfo version: " << crash_info->header.version;
+ break;
+ };
+
+ if (rc != expected_size) {
+ LOG(FATAL) << "read " << rc << " bytes when reading target crash information, expected "
+ << expected_size;
+ }
}
- CrashInfo* crash_info = reinterpret_cast<CrashInfo*>(&buf);
- if (crash_info->version != 1) {
- LOG(FATAL) << "version mismatch, expected 1, received " << crash_info->version;
- }
+ *fdsan_table_address = 0;
+ switch (crash_info->header.version) {
+ case 2:
+ *fdsan_table_address = crash_info->data.v2.fdsan_table_address;
+ case 1:
+ *abort_msg_address = crash_info->data.v1.abort_msg_address;
+ *siginfo = crash_info->data.v1.siginfo;
+ regs->reset(Regs::CreateFromUcontext(Regs::CurrentArch(), &crash_info->data.v1.ucontext));
+ break;
- *siginfo = crash_info->siginfo;
- regs->reset(Regs::CreateFromUcontext(Regs::CurrentArch(), &crash_info->ucontext));
- *abort_address = crash_info->abort_msg_address;
+ default:
+ __builtin_unreachable();
+ }
}
// Wait for a process to clone and return the child's pid.
@@ -369,7 +393,8 @@
ATRACE_NAME("after reparent");
pid_t pseudothread_tid;
DebuggerdDumpType dump_type;
- uintptr_t abort_address = 0;
+ uintptr_t abort_msg_address = 0;
+ uintptr_t fdsan_table_address = 0;
Initialize(argv);
ParseArgs(argc, argv, &pseudothread_tid, &dump_type);
@@ -387,7 +412,7 @@
OpenFilesList open_files;
{
ATRACE_NAME("open files");
- populate_open_files_list(g_target_thread, &open_files);
+ populate_open_files_list(&open_files, g_target_thread);
}
// In order to reduce the duration that we pause the process for, we ptrace
@@ -429,7 +454,8 @@
if (thread == g_target_thread) {
// Read the thread's registers along with the rest of the crash info out of the pipe.
- ReadCrashInfo(input_pipe, &siginfo, &info.registers, &abort_address);
+ ReadCrashInfo(input_pipe, &siginfo, &info.registers, &abort_msg_address,
+ &fdsan_table_address);
info.siginfo = &siginfo;
info.signo = info.siginfo->si_signo;
} else {
@@ -504,8 +530,8 @@
g_output_fd = std::move(devnull);
}
- LOG(INFO) << "performing dump of process " << target_process << " (target tid = " << g_target_thread
- << ")";
+ LOG(INFO) << "performing dump of process " << target_process
+ << " (target tid = " << g_target_thread << ")";
int signo = siginfo.si_signo;
bool fatal_signal = signo != DEBUGGER_SIGNAL;
@@ -541,9 +567,16 @@
ATRACE_NAME("dump_backtrace");
dump_backtrace(std::move(g_output_fd), map.get(), thread_info, g_target_thread);
} else {
- ATRACE_NAME("engrave_tombstone");
- engrave_tombstone(std::move(g_output_fd), map.get(), process_memory.get(), thread_info,
- g_target_thread, abort_address, &open_files, &amfd_data);
+ {
+ ATRACE_NAME("fdsan table dump");
+ populate_fdsan_table(&open_files, process_memory, fdsan_table_address);
+ }
+
+ {
+ ATRACE_NAME("engrave_tombstone");
+ engrave_tombstone(std::move(g_output_fd), map.get(), process_memory.get(), thread_info,
+ g_target_thread, abort_msg_address, &open_files, &amfd_data);
+ }
}
if (fatal_signal) {
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 615fb46..91e6f71 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -108,6 +108,7 @@
int saved_errno_;
};
+extern "C" void* android_fdsan_get_fd_table();
extern "C" void debuggerd_fallback_handler(siginfo_t*, ucontext_t*, void*);
static debuggerd_callbacks_t g_callbacks;
@@ -286,6 +287,7 @@
siginfo_t* siginfo;
void* ucontext;
uintptr_t abort_msg;
+ uintptr_t fdsan_table;
};
// Logging and contacting debuggerd requires free file descriptors, which we might not have.
@@ -330,23 +332,23 @@
}
// ucontext_t is absurdly large on AArch64, so piece it together manually with writev.
- uint32_t version = 1;
- constexpr size_t expected =
- sizeof(version) + sizeof(siginfo_t) + sizeof(ucontext_t) + sizeof(uintptr_t);
+ uint32_t version = 2;
+ constexpr size_t expected = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataV2);
errno = 0;
if (fcntl(output_write.get(), F_SETPIPE_SZ, expected) < static_cast<int>(expected)) {
- fatal_errno("failed to set pipe bufer size");
+ fatal_errno("failed to set pipe buffer size");
}
- struct iovec iovs[4] = {
+ struct iovec iovs[5] = {
{.iov_base = &version, .iov_len = sizeof(version)},
{.iov_base = thread_info->siginfo, .iov_len = sizeof(siginfo_t)},
{.iov_base = thread_info->ucontext, .iov_len = sizeof(ucontext_t)},
{.iov_base = &thread_info->abort_msg, .iov_len = sizeof(uintptr_t)},
+ {.iov_base = &thread_info->fdsan_table, .iov_len = sizeof(uintptr_t)},
};
- ssize_t rc = TEMP_FAILURE_RETRY(writev(output_write.get(), iovs, 4));
+ ssize_t rc = TEMP_FAILURE_RETRY(writev(output_write.get(), iovs, 5));
if (rc == -1) {
fatal_errno("failed to write crash info");
} else if (rc != expected) {
@@ -504,6 +506,7 @@
.siginfo = info,
.ucontext = context,
.abort_msg = reinterpret_cast<uintptr_t>(abort_message),
+ .fdsan_table = reinterpret_cast<uintptr_t>(android_fdsan_get_fd_table()),
};
// Set PR_SET_DUMPABLE to 1, so that crash_dump can ptrace us.
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/open_files_list.h b/debuggerd/libdebuggerd/include/libdebuggerd/open_files_list.h
index 4727ca4..d47f2dd 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/open_files_list.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/open_files_list.h
@@ -14,23 +14,31 @@
* limitations under the License.
*/
-#ifndef _DEBUGGERD_OPEN_FILES_LIST_H
-#define _DEBUGGERD_OPEN_FILES_LIST_H
+#pragma once
+#include <stdint.h>
#include <sys/types.h>
+#include <map>
+#include <optional>
#include <string>
#include <utility>
-#include <vector>
#include "utility.h"
-typedef std::vector<std::pair<int, std::string>> OpenFilesList;
+struct FDInfo {
+ std::optional<std::string> path;
+ std::optional<uint64_t> fdsan_owner;
+};
-/* Populates the given list with open files for the given process. */
-void populate_open_files_list(pid_t pid, OpenFilesList* list);
+using OpenFilesList = std::map<int, FDInfo>;
-/* Dumps the open files list to the log. */
+// Populates the given list with open files for the given process.
+void populate_open_files_list(OpenFilesList* list, pid_t pid);
+
+// Populates the given list with the target process's fdsan table.
+void populate_fdsan_table(OpenFilesList* list, std::shared_ptr<unwindstack::Memory> memory,
+ uint64_t fdsan_table_address);
+
+// Dumps the open files list to the log.
void dump_open_files_list(log_t* log, const OpenFilesList& files, const char* prefix);
-
-#endif // _DEBUGGERD_OPEN_FILES_LIST_H
diff --git a/debuggerd/libdebuggerd/open_files_list.cpp b/debuggerd/libdebuggerd/open_files_list.cpp
index b12703e..1fdf236 100644
--- a/debuggerd/libdebuggerd/open_files_list.cpp
+++ b/debuggerd/libdebuggerd/open_files_list.cpp
@@ -32,10 +32,12 @@
#include <android-base/file.h>
#include <log/log.h>
+#include <unwindstack/Memory.h>
#include "libdebuggerd/utility.h"
+#include "private/bionic_fdsan.h"
-void populate_open_files_list(pid_t pid, OpenFilesList* list) {
+void populate_open_files_list(OpenFilesList* list, pid_t pid) {
std::string fd_dir_name = "/proc/" + std::to_string(pid) + "/fd";
std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(fd_dir_name.c_str()), closedir);
if (dir == nullptr) {
@@ -53,17 +55,84 @@
std::string path = fd_dir_name + "/" + std::string(de->d_name);
std::string target;
if (android::base::Readlink(path, &target)) {
- list->emplace_back(fd, target);
+ (*list)[fd].path = target;
} else {
+ (*list)[fd].path = "???";
ALOGE("failed to readlink %s: %s", path.c_str(), strerror(errno));
- list->emplace_back(fd, "???");
}
}
}
+void populate_fdsan_table(OpenFilesList* list, std::shared_ptr<unwindstack::Memory> memory,
+ uint64_t fdsan_table_address) {
+ constexpr size_t inline_fds = sizeof(FdTable::entries) / sizeof(*FdTable::entries);
+ static_assert(inline_fds == 128);
+ size_t entry_offset = offsetof(FdTable, entries);
+ for (size_t i = 0; i < inline_fds; ++i) {
+ uint64_t address = fdsan_table_address + entry_offset + sizeof(FdEntry) * i;
+ FdEntry entry;
+ if (!memory->Read(address, &entry, sizeof(entry))) {
+ ALOGE("failed to read fdsan table entry %zu: %s", i, strerror(errno));
+ return;
+ }
+ ALOGE("fd %zu = %#" PRIx64, i, entry.close_tag.load());
+ if (entry.close_tag) {
+ (*list)[i].fdsan_owner = entry.close_tag.load();
+ }
+ }
+
+ size_t overflow_offset = offsetof(FdTable, overflow);
+ uintptr_t overflow = 0;
+ if (!memory->Read(fdsan_table_address + overflow_offset, &overflow, sizeof(overflow))) {
+ ALOGE("failed to read fdsan table overflow pointer: %s", strerror(errno));
+ return;
+ }
+
+ if (!overflow) {
+ return;
+ }
+
+ size_t overflow_length;
+ if (!memory->Read(overflow, &overflow_length, sizeof(overflow_length))) {
+ ALOGE("failed to read fdsan overflow table length: %s", strerror(errno));
+ return;
+ }
+
+ if (overflow_length > 131072) {
+ ALOGE("unreasonable large fdsan overflow table size %zu, bailing out", overflow_length);
+ return;
+ }
+
+ for (size_t i = 0; i < overflow_length; ++i) {
+ int fd = i + inline_fds;
+ uint64_t address = overflow + offsetof(FdTableOverflow, entries) + i * sizeof(FdEntry);
+ FdEntry entry;
+ if (!memory->Read(address, &entry, sizeof(entry))) {
+ ALOGE("failed to read fdsan overflow entry for fd %d: %s", fd, strerror(errno));
+ return;
+ }
+ if (entry.close_tag) {
+ (*list)[fd].fdsan_owner = entry.close_tag;
+ }
+ }
+ return;
+}
+
void dump_open_files_list(log_t* log, const OpenFilesList& files, const char* prefix) {
- for (auto& file : files) {
- _LOG(log, logtype::OPEN_FILES, "%sfd %i: %s\n", prefix, file.first, file.second.c_str());
+ for (auto& [fd, entry] : files) {
+ const std::optional<std::string>& path = entry.path;
+ const std::optional<uint64_t>& fdsan_owner = entry.fdsan_owner;
+ if (path && fdsan_owner) {
+ _LOG(log, logtype::OPEN_FILES, "%sfd %i: %s (owned by %#" PRIx64 ")\n", prefix, fd,
+ path->c_str(), *fdsan_owner);
+ } else if (path && !fdsan_owner) {
+ _LOG(log, logtype::OPEN_FILES, "%sfd %i: %s (unowned)\n", prefix, fd, path->c_str());
+ } else if (!path && fdsan_owner) {
+ _LOG(log, logtype::OPEN_FILES, "%sfd %i: <MISSING> (owned by %#" PRIx64 ")\n", prefix, fd,
+ *fdsan_owner);
+ } else {
+ ALOGE("OpenFilesList contains an entry (fd %d) with no path or owner", fd);
+ }
}
}
diff --git a/debuggerd/libdebuggerd/test/open_files_list_test.cpp b/debuggerd/libdebuggerd/test/open_files_list_test.cpp
index acac72c..d7036fd 100644
--- a/debuggerd/libdebuggerd/test/open_files_list_test.cpp
+++ b/debuggerd/libdebuggerd/test/open_files_list_test.cpp
@@ -34,13 +34,13 @@
// Get the list of open files for this process.
OpenFilesList list;
- populate_open_files_list(getpid(), &list);
+ populate_open_files_list(&list, getpid());
// Verify our open file is in the list.
bool found = false;
- for (auto& file : list) {
+ for (auto& file : list) {
if (file.first == tf.fd) {
- EXPECT_EQ(file.second, std::string(tf.path));
+ EXPECT_EQ(file.second.path.value_or(""), std::string(tf.path));
found = true;
break;
}
diff --git a/debuggerd/protocol.h b/debuggerd/protocol.h
index 6903b0e..bfd0fbb 100644
--- a/debuggerd/protocol.h
+++ b/debuggerd/protocol.h
@@ -81,9 +81,24 @@
};
// Sent from handler to crash_dump via pipe.
-struct __attribute__((__packed__)) CrashInfo {
- uint32_t version; // must be 1.
+struct __attribute__((__packed__)) CrashInfoHeader {
+ uint32_t version;
+};
+
+struct __attribute__((__packed__)) CrashInfoDataV1 {
siginfo_t siginfo;
ucontext_t ucontext;
uintptr_t abort_msg_address;
};
+
+struct __attribute__((__packed__)) CrashInfoDataV2 : public CrashInfoDataV1 {
+ uintptr_t fdsan_table_address;
+};
+
+struct __attribute__((__packed__)) CrashInfo {
+ CrashInfoHeader header;
+ union {
+ CrashInfoDataV1 v1;
+ CrashInfoDataV2 v2;
+ } data;
+};
diff --git a/fs_mgr/fs_mgr_dm_linear.cpp b/fs_mgr/fs_mgr_dm_linear.cpp
index aa68ceb..a91e92e 100644
--- a/fs_mgr/fs_mgr_dm_linear.cpp
+++ b/fs_mgr/fs_mgr_dm_linear.cpp
@@ -80,13 +80,17 @@
}
static bool CreateLogicalPartition(const std::string& block_device, const LpMetadata& metadata,
- const LpMetadataPartition& partition, std::string* path) {
+ const LpMetadataPartition& partition, bool force_writable,
+ std::string* path) {
DeviceMapper& dm = DeviceMapper::Instance();
DmTable table;
if (!CreateDmTable(block_device, metadata, partition, &table)) {
return false;
}
+ if (force_writable) {
+ table.set_readonly(false);
+ }
std::string name = GetPartitionName(partition);
if (!dm.CreateDevice(name, table)) {
return false;
@@ -106,8 +110,12 @@
return true;
}
for (const auto& partition : metadata->partitions) {
+ if (!partition.num_extents) {
+ LINFO << "Skipping zero-length logical partition: " << GetPartitionName(partition);
+ continue;
+ }
std::string path;
- if (!CreateLogicalPartition(block_device, *metadata.get(), partition, &path)) {
+ if (!CreateLogicalPartition(block_device, *metadata.get(), partition, false, &path)) {
LERROR << "Could not create logical partition: " << GetPartitionName(partition);
return false;
}
@@ -116,7 +124,8 @@
}
bool CreateLogicalPartition(const std::string& block_device, uint32_t metadata_slot,
- const std::string& partition_name, std::string* path) {
+ const std::string& partition_name, bool force_writable,
+ std::string* path) {
auto metadata = ReadMetadata(block_device.c_str(), metadata_slot);
if (!metadata) {
LOG(ERROR) << "Could not read partition table.";
@@ -124,7 +133,8 @@
}
for (const auto& partition : metadata->partitions) {
if (GetPartitionName(partition) == partition_name) {
- return CreateLogicalPartition(block_device, *metadata.get(), partition, path);
+ return CreateLogicalPartition(block_device, *metadata.get(), partition, force_writable,
+ path);
}
}
LERROR << "Could not find any partition with name: " << partition_name;
diff --git a/fs_mgr/include/fs_mgr_dm_linear.h b/fs_mgr/include/fs_mgr_dm_linear.h
index cac475c..f15c450 100644
--- a/fs_mgr/include/fs_mgr_dm_linear.h
+++ b/fs_mgr/include/fs_mgr_dm_linear.h
@@ -41,9 +41,11 @@
// Create a block device for a single logical partition, given metadata and
// the partition name. On success, a path to the partition's block device is
-// returned.
+// returned. If |force_writable| is true, the "readonly" flag will be ignored
+// so the partition can be flashed.
bool CreateLogicalPartition(const std::string& block_device, uint32_t metadata_slot,
- const std::string& partition_name, std::string* path);
+ const std::string& partition_name, bool force_writable,
+ std::string* path);
// Destroy the block device for a logical partition, by name.
bool DestroyLogicalPartition(const std::string& name);
diff --git a/init/Android.bp b/init/Android.bp
index d42ab8a..84a78e2 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -92,6 +92,7 @@
cc_library_static {
name: "libinit",
+ recovery_available: true,
defaults: ["init_defaults"],
srcs: [
"action.cpp",
@@ -107,7 +108,6 @@
"first_stage_mount.cpp",
"import_parser.cpp",
"init.cpp",
- "init_first_stage.cpp",
"keychords.cpp",
"modalias_handler.cpp",
"parser.cpp",
@@ -138,29 +138,21 @@
},
}
-/*
-This is not yet ready, see the below TODOs for what is missing
-
cc_binary {
- // TODO: Missing,
- //LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
- //LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
-
- name: "init",
+ name: "init_second_stage",
+ recovery_available: true,
+ stem: "init",
defaults: ["init_defaults"],
+ static_libs: ["libinit"],
required: [
"e2fsdroid",
"mke2fs",
"sload_f2fs",
"make_f2fs",
],
- static_executable: true,
srcs: ["main.cpp"],
- symlinks: [
- "sbin/ueventd",
- ],
+ symlinks: ["ueventd"],
}
-*/
// Tests
// ------------------------------------------------------------------------------
diff --git a/init/Android.mk b/init/Android.mk
index 9d9d368..d20509b 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -41,35 +41,35 @@
include $(CLEAR_VARS)
LOCAL_CPPFLAGS := $(init_cflags)
-LOCAL_SRC_FILES := main.cpp
+LOCAL_SRC_FILES := \
+ devices.cpp \
+ first_stage_mount.cpp \
+ init_first_stage.cpp \
+ reboot_utils.cpp \
+ selinux.cpp \
+ uevent_listener.cpp \
+ util.cpp \
-LOCAL_MODULE:= init
+LOCAL_MODULE := init
+
+LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
LOCAL_STATIC_LIBRARIES := \
- libinit \
- libbootloader_message \
libfs_mgr \
libfec \
libfec_rs \
- libhidl-gen-utils \
libsquashfs_utils \
liblogwrap \
libext4_utils \
libseccomp_policy \
libcrypto_utils \
libsparse \
- libprocessgroup \
libavb \
libkeyutils \
- libprotobuf-cpp-lite \
- libpropertyinfoserializer \
- libpropertyinfoparser \
liblp \
-
-shared_libs := \
libcutils \
libbase \
liblog \
@@ -77,27 +77,11 @@
libdl \
libz \
libselinux \
-
-ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
-# init is static executable for non-system-as-root devices, because the dynamic linker
-# and shared libs are not available before /system is mounted, but init has to run
-# before the partition is mounted.
-LOCAL_STATIC_LIBRARIES += $(shared_libs) libc++_static
-LOCAL_FORCE_STATIC_EXECUTABLE := true
-else
-LOCAL_SHARED_LIBRARIES := $(shared_libs) libc++
-endif
-shared_libs :=
+ libcap \
LOCAL_REQUIRED_MODULES := \
- e2fsdroid \
- mke2fs \
- sload_f2fs \
- make_f2fs \
-
-# Create symlinks.
-LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT)/sbin; \
- ln -sf ../init $(TARGET_ROOT_OUT)/sbin/ueventd; \
+ init_second_stage \
+ init_second_stage.recovery \
LOCAL_SANITIZE := signed-integer-overflow
include $(BUILD_EXECUTABLE)
diff --git a/init/init.cpp b/init/init.cpp
index ad80c98..b550f1b 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -565,8 +565,6 @@
android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter);
}
-int first_stage_main(int argc, char** argv);
-
int main(int argc, char** argv) {
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
@@ -578,10 +576,6 @@
return SubcontextMain(argc, argv, &function_map);
}
- if (getenv("INIT_SECOND_STAGE") == nullptr) {
- return first_stage_main(argc, argv);
- }
-
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
}
@@ -617,7 +611,6 @@
if (avb_version) property_set("ro.boot.avb_version", avb_version);
// Clean up our environment.
- unsetenv("INIT_SECOND_STAGE");
unsetenv("INIT_STARTED_AT");
unsetenv("INIT_SELINUX_TOOK");
unsetenv("INIT_AVB_VERSION");
diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp
index ef9ce81..b367f2a 100644
--- a/init/init_first_stage.cpp
+++ b/init/init_first_stage.cpp
@@ -51,7 +51,7 @@
});
}
-int first_stage_main(int argc, char** argv) {
+int main(int argc, char** argv) {
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
}
@@ -141,17 +141,15 @@
// Unneeded? It's an ext4 file system so shouldn't it have the right domain already?
// We're in the kernel domain, so re-exec init to transition to the init domain now
// that the SELinux policy has been loaded.
- if (selinux_android_restorecon("/init", 0) == -1) {
- PLOG(FATAL) << "restorecon failed of /init failed";
+ if (selinux_android_restorecon("/system/bin/init", 0) == -1) {
+ PLOG(FATAL) << "restorecon failed of /system/bin/init failed";
}
- setenv("INIT_SECOND_STAGE", "true", 1);
-
static constexpr uint32_t kNanosecondsPerMillisecond = 1e6;
uint64_t start_ms = start_time.time_since_epoch().count() / kNanosecondsPerMillisecond;
setenv("INIT_STARTED_AT", std::to_string(start_ms).c_str(), 1);
- const char* path = argv[0];
+ const char* path = "/system/bin/init";
const char* args[] = {path, nullptr};
execv(path, const_cast<char**>(args));
@@ -164,3 +162,7 @@
} // namespace init
} // namespace android
+
+int main(int argc, char** argv) {
+ return android::init::main(argc, argv);
+}
diff --git a/libbacktrace/include/backtrace/BacktraceMap.h b/libbacktrace/include/backtrace/BacktraceMap.h
index c564271..a9cfce4 100644
--- a/libbacktrace/include/backtrace/BacktraceMap.h
+++ b/libbacktrace/include/backtrace/BacktraceMap.h
@@ -31,7 +31,6 @@
#include <deque>
#include <iterator>
-#include <memory>
#include <string>
#include <vector>
diff --git a/libutils/CallStack.cpp b/libutils/CallStack.cpp
index 2a83bd9..bd6015e 100644
--- a/libutils/CallStack.cpp
+++ b/libutils/CallStack.cpp
@@ -16,15 +16,16 @@
#define LOG_TAG "CallStack"
+#include <utils/CallStack.h>
+
+#include <memory>
+
#include <utils/Printer.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <backtrace/Backtrace.h>
-#define CALLSTACK_WEAK // Don't generate weak definitions.
-#include <utils/CallStack.h>
-
namespace android {
CallStack::CallStack() {
@@ -75,26 +76,4 @@
}
}
-// The following four functions may be used via weak symbol references from libutils.
-// Clients assume that if any of these symbols are available, then deleteStack() is.
-
-CallStack::CallStackUPtr CallStack::getCurrentInternal(int ignoreDepth) {
- CallStack::CallStackUPtr stack(new CallStack());
- stack->update(ignoreDepth + 1);
- return stack;
-}
-
-void CallStack::logStackInternal(const char* logtag, const CallStack* stack,
- android_LogPriority priority) {
- stack->log(logtag, priority);
-}
-
-String8 CallStack::stackToStringInternal(const char* prefix, const CallStack* stack) {
- return stack->toString(prefix);
-}
-
-void CallStack::deleteStack(CallStack* stack) {
- delete stack;
-}
-
}; // namespace android
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
index 3f1e79a..9074850 100644
--- a/libutils/RefBase.cpp
+++ b/libutils/RefBase.cpp
@@ -17,41 +17,30 @@
#define LOG_TAG "RefBase"
// #define LOG_NDEBUG 0
-#include <memory>
-
#include <utils/RefBase.h>
#include <utils/CallStack.h>
-#include <utils/Mutex.h>
-
#ifndef __unused
#define __unused __attribute__((__unused__))
#endif
-// Compile with refcounting debugging enabled.
-#define DEBUG_REFS 0
-
-// The following three are ignored unless DEBUG_REFS is set.
+// compile with refcounting debugging enabled
+#define DEBUG_REFS 0
// whether ref-tracking is enabled by default, if not, trackMe(true, false)
// needs to be called explicitly
-#define DEBUG_REFS_ENABLED_BY_DEFAULT 0
+#define DEBUG_REFS_ENABLED_BY_DEFAULT 0
// whether callstack are collected (significantly slows things down)
-#define DEBUG_REFS_CALLSTACK_ENABLED 1
+#define DEBUG_REFS_CALLSTACK_ENABLED 1
// folder where stack traces are saved when DEBUG_REFS is enabled
// this folder needs to exist and be writable
-#define DEBUG_REFS_CALLSTACK_PATH "/data/debug"
+#define DEBUG_REFS_CALLSTACK_PATH "/data/debug"
// log all reference counting operations
-#define PRINT_REFS 0
-
-// Continue after logging a stack trace if ~RefBase discovers that reference
-// count has never been incremented. Normally we conspicuously crash in that
-// case.
-#define DEBUG_REFBASE_DESTRUCTION 1
+#define PRINT_REFS 0
// ---------------------------------------------------------------------------
@@ -195,7 +184,7 @@
char inc = refs->ref >= 0 ? '+' : '-';
ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
#if DEBUG_REFS_CALLSTACK_ENABLED
- CallStack::logStack(LOG_TAG, refs->stack.get());
+ refs->stack.log(LOG_TAG);
#endif
refs = refs->next;
}
@@ -209,14 +198,14 @@
char inc = refs->ref >= 0 ? '+' : '-';
ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
#if DEBUG_REFS_CALLSTACK_ENABLED
- CallStack::logStack(LOG_TAG, refs->stack.get());
+ refs->stack.log(LOG_TAG);
#endif
refs = refs->next;
}
}
if (dumpStack) {
ALOGE("above errors at:");
- CallStack::logStack(LOG_TAG);
+ CallStack stack(LOG_TAG);
}
}
@@ -290,7 +279,7 @@
this);
int rc = open(name, O_RDWR | O_CREAT | O_APPEND, 644);
if (rc >= 0) {
- (void)write(rc, text.string(), text.length());
+ write(rc, text.string(), text.length());
close(rc);
ALOGD("STACK TRACE for %p saved in %s", this, name);
}
@@ -305,7 +294,7 @@
ref_entry* next;
const void* id;
#if DEBUG_REFS_CALLSTACK_ENABLED
- CallStack::CallStackUPtr stack;
+ CallStack stack;
#endif
int32_t ref;
};
@@ -322,7 +311,7 @@
ref->ref = mRef;
ref->id = id;
#if DEBUG_REFS_CALLSTACK_ENABLED
- ref->stack = CallStack::getCurrent(2);
+ ref->stack.update(2);
#endif
ref->next = *refs;
*refs = ref;
@@ -357,7 +346,7 @@
ref = ref->next;
}
- CallStack::logStack(LOG_TAG);
+ CallStack stack(LOG_TAG);
}
}
@@ -384,7 +373,7 @@
inc, refs->id, refs->ref);
out->append(buf);
#if DEBUG_REFS_CALLSTACK_ENABLED
- out->append(CallStack::stackToString("\t\t", refs->stack.get()));
+ out->append(refs->stack.toString("\t\t"));
#else
out->append("\t\t(call stacks disabled)");
#endif
@@ -711,16 +700,16 @@
if (mRefs->mWeak.load(std::memory_order_relaxed) == 0) {
delete mRefs;
}
- } else if (mRefs->mStrong.load(std::memory_order_relaxed) == INITIAL_STRONG_VALUE) {
+ } else if (mRefs->mStrong.load(std::memory_order_relaxed)
+ == INITIAL_STRONG_VALUE) {
// We never acquired a strong reference on this object.
-#if DEBUG_REFBASE_DESTRUCTION
- // Treating this as fatal is prone to causing boot loops. For debugging, it's
- // better to treat as non-fatal.
- ALOGD("RefBase: Explicit destruction, weak count = %d (in %p)", mRefs->mWeak.load(), this);
- CallStack::logStack(LOG_TAG);
-#else
- LOG_ALWAYS_FATAL("RefBase: Explicit destruction, weak count = %d", mRefs->mWeak.load());
-#endif
+ LOG_ALWAYS_FATAL_IF(mRefs->mWeak.load() != 0,
+ "RefBase: Explicit destruction with non-zero weak "
+ "reference count");
+ // TODO: Always report if we get here. Currently MediaMetadataRetriever
+ // C++ objects are inconsistently managed and sometimes get here.
+ // There may be other cases, but we believe they should all be fixed.
+ delete mRefs;
}
// For debugging purposes, clear mRefs. Ineffective against outstanding wp's.
const_cast<weakref_impl*&>(mRefs) = nullptr;
diff --git a/libutils/include/utils/CallStack.h b/libutils/include/utils/CallStack.h
index a7b1d10..0c1b875 100644
--- a/libutils/include/utils/CallStack.h
+++ b/libutils/include/utils/CallStack.h
@@ -17,8 +17,6 @@
#ifndef ANDROID_CALLSTACK_H
#define ANDROID_CALLSTACK_H
-#include <memory>
-
#include <android/log.h>
#include <backtrace/backtrace_constants.h>
#include <utils/String8.h>
@@ -27,11 +25,6 @@
#include <stdint.h>
#include <sys/types.h>
-#ifndef CALLSTACK_WEAK
-#define CALLSTACK_WEAK __attribute__((weak))
-#endif
-#define ALWAYS_INLINE __attribute__((always_inline))
-
namespace android {
class Printer;
@@ -43,7 +36,7 @@
CallStack();
// Create a callstack with the current thread's stack trace.
// Immediately dump it to logcat using the given logtag.
- CallStack(const char* logtag, int32_t ignoreDepth = 1);
+ CallStack(const char* logtag, int32_t ignoreDepth=1);
~CallStack();
// Reset the stack frames (same as creating an empty call stack).
@@ -51,7 +44,7 @@
// Immediately collect the stack traces for the specified thread.
// The default is to dump the stack of the current call.
- void update(int32_t ignoreDepth = 1, pid_t tid = BACKTRACE_CURRENT_THREAD);
+ void update(int32_t ignoreDepth=1, pid_t tid=BACKTRACE_CURRENT_THREAD);
// Dump a stack trace to the log using the supplied logtag.
void log(const char* logtag,
@@ -70,58 +63,7 @@
// Get the count of stack frames that are in this call stack.
size_t size() const { return mFrameLines.size(); }
- // DO NOT USE ANYTHING BELOW HERE. The following public members are expected
- // to disappear again shortly, once a better replacement facility exists.
- // The replacement facility will be incompatible!
-
- // Debugging accesses to some basic functionality. These use weak symbols to
- // avoid introducing a dependency on libutilscallstack. Such a dependency from
- // libutils results in a cyclic build dependency. These routines can be called
- // from within libutils. But if the actual library is unavailable, they do
- // nothing.
- //
- // DO NOT USE THESE. They will disappear.
- struct StackDeleter {
- void operator()(CallStack* stack) { deleteStack(stack); }
- };
-
- typedef std::unique_ptr<CallStack, StackDeleter> CallStackUPtr;
-
- // Return current call stack if possible, nullptr otherwise.
- static CallStackUPtr ALWAYS_INLINE getCurrent(int32_t ignoreDepth = 1) {
- if (reinterpret_cast<uintptr_t>(getCurrentInternal) == 0) {
- ALOGW("CallStack::getCurrentInternal not linked, returning null");
- return CallStackUPtr(nullptr);
- } else {
- return getCurrentInternal(ignoreDepth);
- }
- }
- static void ALWAYS_INLINE logStack(const char* logtag, CallStack* stack = getCurrent().get(),
- android_LogPriority priority = ANDROID_LOG_DEBUG) {
- if (reinterpret_cast<uintptr_t>(logStackInternal) != 0 && stack != nullptr) {
- logStackInternal(logtag, stack, priority);
- } else {
- ALOGW("CallStack::logStackInternal not linked");
- }
- }
- static String8 ALWAYS_INLINE stackToString(const char* prefix = nullptr,
- const CallStack* stack = getCurrent().get()) {
- if (reinterpret_cast<uintptr_t>(stackToStringInternal) != 0 && stack != nullptr) {
- return stackToStringInternal(prefix, stack);
- } else {
- return String8("<CallStack package not linked>");
- }
- }
-
- private:
- static CallStackUPtr CALLSTACK_WEAK getCurrentInternal(int32_t ignoreDepth);
- static void CALLSTACK_WEAK logStackInternal(const char* logtag, const CallStack* stack,
- android_LogPriority priority);
- static String8 CALLSTACK_WEAK stackToStringInternal(const char* prefix, const CallStack* stack);
- // The deleter is only invoked on non-null pointers. Hence it will never be
- // invoked if CallStack is not linked.
- static void CALLSTACK_WEAK deleteStack(CallStack* stack);
-
+private:
Vector<String8> mFrameLines;
};
diff --git a/rootdir/init.rc b/rootdir/init.rc
index bc4a309..bf22951 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -751,7 +751,7 @@
## Daemon processes to be run by init.
##
-service ueventd /sbin/ueventd
+service ueventd /system/bin/ueventd
class core
critical
seclabel u:r:ueventd:s0