Merge "Create /metadata/apex/[sessions]."
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 3286959..3d5d9db 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
}
@@ -1003,7 +1005,8 @@
#endif /* !defined(_WIN32) */
}
-static bool wait_for_device(const char* service) {
+static bool wait_for_device(const char* service,
+ std::optional<std::chrono::milliseconds> timeout = std::nullopt) {
std::vector<std::string> components = android::base::Split(service, "-");
if (components.size() < 3 || components.size() > 4) {
fprintf(stderr, "adb: couldn't parse 'wait-for' command: %s\n", service);
@@ -1041,6 +1044,13 @@
}
std::string cmd = format_host_command(android::base::Join(components, "-").c_str());
+ if (timeout) {
+ std::thread([timeout]() {
+ std::this_thread::sleep_for(*timeout);
+ fprintf(stderr, "timeout expired while waiting for device\n");
+ _exit(1);
+ }).detach();
+ }
return adb_command(cmd);
}
@@ -1082,8 +1092,21 @@
}
// Wait for the device to go away.
+ TransportType previous_type;
+ const char* previous_serial;
+ TransportId previous_id;
+ adb_get_transport(&previous_type, &previous_serial, &previous_id);
+
adb_set_transport(kTransportAny, nullptr, transport_id);
wait_for_device("wait-for-disconnect");
+
+ // Wait for the device to come back.
+ // If we were using a specific transport ID, there's nothing we can wait for.
+ if (previous_id == 0) {
+ adb_set_transport(previous_type, previous_serial, 0);
+ wait_for_device("wait-for-device", 3000ms);
+ }
+
return true;
}
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index a44ff43..f4458a2 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -270,29 +270,15 @@
bool started = false;
bool running = true;
while (running) {
- int timeout = -1;
- if (!bound || !started) {
- timeout = 5000 /*ms*/;
- }
-
adb_pollfd pfd[2] = {
{ .fd = control_fd_.get(), .events = POLLIN, .revents = 0 },
{ .fd = monitor_event_fd_.get(), .events = POLLIN, .revents = 0 },
};
- int rc = TEMP_FAILURE_RETRY(adb_poll(pfd, 2, timeout));
+ int rc = TEMP_FAILURE_RETRY(adb_poll(pfd, 2, -1));
if (rc == -1) {
PLOG(FATAL) << "poll on USB control fd failed";
} else if (rc == 0) {
- // Something in the kernel presumably went wrong.
- // Close our endpoints, wait for a bit, and then try again.
- StopWorker();
- aio_context_.reset();
- read_fd_.reset();
- write_fd_.reset();
- control_fd_.reset();
- std::this_thread::sleep_for(5s);
- HandleError("didn't receive FUNCTIONFS_ENABLE, retrying");
- return;
+ LOG(FATAL) << "poll on USB control fd returned 0";
}
if (pfd[1].revents) {
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/base/mapped_file.cpp b/base/mapped_file.cpp
index faa845d..7c65dc3 100644
--- a/base/mapped_file.cpp
+++ b/base/mapped_file.cpp
@@ -41,7 +41,14 @@
HANDLE handle =
CreateFileMapping(reinterpret_cast<HANDLE>(_get_osfhandle(fd)), nullptr,
(prot & PROT_WRITE) ? PAGE_READWRITE : PAGE_READONLY, 0, 0, nullptr);
- if (handle == nullptr) return nullptr;
+ if (handle == nullptr) {
+ // http://b/119818070 "app crashes when reading asset of zero length".
+ // Return a MappedFile that's only valid for reading the size.
+ if (length == 0) {
+ return std::unique_ptr<MappedFile>(new MappedFile{nullptr, 0, 0, nullptr});
+ }
+ return nullptr;
+ }
void* base = MapViewOfFile(handle, (prot & PROT_WRITE) ? FILE_MAP_ALL_ACCESS : FILE_MAP_READ, 0,
file_offset, file_length);
if (base == nullptr) {
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index ed955ea..ea49798 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -293,6 +293,8 @@
{"kernel_panic,dsps", 166},
{"kernel_panic,wcnss", 167},
{"kernel_panic,_sde_encoder_phys_cmd_handle_ppdone_timeout", 168},
+ {"recovery,quiescent", 169},
+ {"reboot,quiescent", 170},
};
// Converts a string value representing the reason the system booted to an
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/libfiemap_writer/fiemap_writer.cpp b/fs_mgr/libfiemap_writer/fiemap_writer.cpp
index 99a1a2f..5b77280 100644
--- a/fs_mgr/libfiemap_writer/fiemap_writer.cpp
+++ b/fs_mgr/libfiemap_writer/fiemap_writer.cpp
@@ -501,12 +501,13 @@
}
if (!extents->empty() && block == last_block + 1) {
- extents->back().fe_length++;
+ extents->back().fe_length += s.st_blksize;
} else {
- extents->push_back(fiemap_extent{.fe_logical = block_number,
- .fe_physical = block,
- .fe_length = 1,
- .fe_flags = 0});
+ extents->push_back(
+ fiemap_extent{.fe_logical = block_number,
+ .fe_physical = static_cast<uint64_t>(block) * s.st_blksize,
+ .fe_length = static_cast<uint64_t>(s.st_blksize),
+ .fe_flags = 0});
}
last_block = block;
}
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/libasyncio/Android.bp b/libasyncio/Android.bp
index 0fd2a3a..4ab439d 100644
--- a/libasyncio/Android.bp
+++ b/libasyncio/Android.bp
@@ -27,7 +27,6 @@
name: "libasyncio",
defaults: ["libasyncio_defaults"],
vendor_available: true,
- double_loadable: true,
recovery_available: true,
host_supported: true,
srcs: [
diff --git a/libcutils/include/cutils/native_handle.h b/libcutils/include/cutils/native_handle.h
index 10f5bc0..f6cae36 100644
--- a/libcutils/include/cutils/native_handle.h
+++ b/libcutils/include/cutils/native_handle.h
@@ -23,6 +23,9 @@
extern "C" {
#endif
+#define NATIVE_HANDLE_MAX_FDS 1024
+#define NATIVE_HANDLE_MAX_INTS 1024
+
/* Declare a char array for use with native_handle_init */
#define NATIVE_HANDLE_DECLARE_STORAGE(name, maxFds, maxInts) \
alignas(native_handle_t) char (name)[ \
diff --git a/libcutils/native_handle.cpp b/libcutils/native_handle.cpp
index 66f7a3d..b409e5b 100644
--- a/libcutils/native_handle.cpp
+++ b/libcutils/native_handle.cpp
@@ -22,9 +22,6 @@
#include <string.h>
#include <unistd.h>
-static const int kMaxNativeFds = 1024;
-static const int kMaxNativeInts = 1024;
-
native_handle_t* native_handle_init(char* storage, int numFds, int numInts) {
if ((uintptr_t) storage % alignof(native_handle_t)) {
errno = EINVAL;
@@ -39,7 +36,8 @@
}
native_handle_t* native_handle_create(int numFds, int numInts) {
- if (numFds < 0 || numInts < 0 || numFds > kMaxNativeFds || numInts > kMaxNativeInts) {
+ if (numFds < 0 || numInts < 0 || numFds > NATIVE_HANDLE_MAX_FDS ||
+ numInts > NATIVE_HANDLE_MAX_INTS) {
errno = EINVAL;
return NULL;
}
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/libmemtrack/Android.bp b/libmemtrack/Android.bp
index 320b851..4e4554a 100644
--- a/libmemtrack/Android.bp
+++ b/libmemtrack/Android.bp
@@ -6,7 +6,6 @@
vndk: {
enabled: true,
},
- double_loadable: true,
srcs: ["memtrack.cpp"],
export_include_dirs: ["include"],
local_include_dirs: ["include"],
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/libprocinfo/Android.bp b/libprocinfo/Android.bp
index 27cda93..15f03d0 100644
--- a/libprocinfo/Android.bp
+++ b/libprocinfo/Android.bp
@@ -31,7 +31,6 @@
vndk: {
enabled: true,
},
- double_loadable: true,
host_supported: true,
srcs: [
"process.cpp",
diff --git a/libunwindstack/include/unwindstack/Memory.h b/libunwindstack/include/unwindstack/Memory.h
index dba41d1..b3beb6e 100644
--- a/libunwindstack/include/unwindstack/Memory.h
+++ b/libunwindstack/include/unwindstack/Memory.h
@@ -101,7 +101,7 @@
size_t Size() { return size_; }
- void Clear();
+ void Clear() override;
protected:
size_t size_ = 0;
diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h
index 878ced3..1c2a81c 100644
--- a/libunwindstack/include/unwindstack/Regs.h
+++ b/libunwindstack/include/unwindstack/Regs.h
@@ -18,6 +18,7 @@
#define _LIBUNWINDSTACK_REGS_H
#include <stdint.h>
+#include <unistd.h>
#include <functional>
#include <string>
diff --git a/libusbhost/Android.bp b/libusbhost/Android.bp
index 39bf3a5..fc6f305 100644
--- a/libusbhost/Android.bp
+++ b/libusbhost/Android.bp
@@ -20,7 +20,6 @@
vndk: {
enabled: true,
},
- double_loadable: true,
host_supported: true,
srcs: ["usbhost.c"],
cflags: ["-Werror"],
diff --git a/libutils/RefBase_test.cpp b/libutils/RefBase_test.cpp
index 2e0cf6e..b594ca5 100644
--- a/libutils/RefBase_test.cpp
+++ b/libutils/RefBase_test.cpp
@@ -45,6 +45,44 @@
bool* mDeleted;
};
+// A version of Foo that ensures that all objects are allocated at the same
+// address. No more than one can be allocated at a time. Thread-hostile.
+class FooFixedAlloc : public RefBase {
+public:
+ static void* operator new(size_t size) {
+ if (mAllocCount != 0) {
+ abort();
+ }
+ mAllocCount = 1;
+ if (theMemory == nullptr) {
+ theMemory = malloc(size);
+ }
+ return theMemory;
+ }
+
+ static void operator delete(void *p) {
+ if (mAllocCount != 1 || p != theMemory) {
+ abort();
+ }
+ mAllocCount = 0;
+ }
+
+ FooFixedAlloc(bool* deleted_check) : mDeleted(deleted_check) {
+ *mDeleted = false;
+ }
+
+ ~FooFixedAlloc() {
+ *mDeleted = true;
+ }
+private:
+ bool* mDeleted;
+ static int mAllocCount;
+ static void* theMemory;
+};
+
+int FooFixedAlloc::mAllocCount(0);
+void* FooFixedAlloc::theMemory(nullptr);
+
TEST(RefBase, StrongMoves) {
bool isDeleted;
Foo* foo = new Foo(&isDeleted);
@@ -90,6 +128,91 @@
ASSERT_FALSE(isDeleted) << "Deletion on wp destruction should no longer occur";
}
+TEST(RefBase, Comparisons) {
+ bool isDeleted, isDeleted2;
+ Foo* foo = new Foo(&isDeleted);
+ Foo* foo2 = new Foo(&isDeleted2);
+ sp<Foo> sp1(foo);
+ sp<Foo> sp2(foo2);
+ wp<Foo> wp1(sp1);
+ wp<Foo> wp2(sp1);
+ wp<Foo> wp3(sp2);
+ ASSERT_TRUE(wp1 == wp2);
+ ASSERT_TRUE(wp1 == sp1);
+ ASSERT_TRUE(wp3 == sp2);
+ ASSERT_TRUE(wp1 != sp2);
+ ASSERT_TRUE(wp1 <= wp2);
+ ASSERT_TRUE(wp1 >= wp2);
+ ASSERT_FALSE(wp1 != wp2);
+ ASSERT_FALSE(wp1 > wp2);
+ ASSERT_FALSE(wp1 < wp2);
+ ASSERT_FALSE(sp1 == sp2);
+ ASSERT_TRUE(sp1 != sp2);
+ bool sp1_smaller = sp1 < sp2;
+ wp<Foo>wp_smaller = sp1_smaller ? wp1 : wp3;
+ wp<Foo>wp_larger = sp1_smaller ? wp3 : wp1;
+ ASSERT_TRUE(wp_smaller < wp_larger);
+ ASSERT_TRUE(wp_smaller != wp_larger);
+ ASSERT_TRUE(wp_smaller <= wp_larger);
+ ASSERT_FALSE(wp_smaller == wp_larger);
+ ASSERT_FALSE(wp_smaller > wp_larger);
+ ASSERT_FALSE(wp_smaller >= wp_larger);
+ sp2 = nullptr;
+ ASSERT_TRUE(isDeleted2);
+ ASSERT_FALSE(isDeleted);
+ ASSERT_FALSE(wp3 == sp2);
+ // Comparison results on weak pointers should not be affected.
+ ASSERT_TRUE(wp_smaller < wp_larger);
+ ASSERT_TRUE(wp_smaller != wp_larger);
+ ASSERT_TRUE(wp_smaller <= wp_larger);
+ ASSERT_FALSE(wp_smaller == wp_larger);
+ ASSERT_FALSE(wp_smaller > wp_larger);
+ ASSERT_FALSE(wp_smaller >= wp_larger);
+ wp2 = nullptr;
+ ASSERT_FALSE(wp1 == wp2);
+ ASSERT_TRUE(wp1 != wp2);
+ wp1.clear();
+ ASSERT_TRUE(wp1 == wp2);
+ ASSERT_FALSE(wp1 != wp2);
+ wp3.clear();
+ ASSERT_TRUE(wp1 == wp3);
+ ASSERT_FALSE(wp1 != wp3);
+ ASSERT_FALSE(isDeleted);
+ sp1.clear();
+ ASSERT_TRUE(isDeleted);
+ ASSERT_TRUE(sp1 == sp2);
+}
+
+// Check whether comparison against dead wp works, even if the object referenced
+// by the new wp happens to be at the same address.
+TEST(RefBase, ReplacedComparison) {
+ bool isDeleted, isDeleted2;
+ FooFixedAlloc* foo = new FooFixedAlloc(&isDeleted);
+ sp<FooFixedAlloc> sp1(foo);
+ wp<FooFixedAlloc> wp1(sp1);
+ ASSERT_TRUE(wp1 == sp1);
+ sp1.clear(); // Deallocates the object.
+ ASSERT_TRUE(isDeleted);
+ FooFixedAlloc* foo2 = new FooFixedAlloc(&isDeleted2);
+ ASSERT_FALSE(isDeleted2);
+ ASSERT_EQ(foo, foo2); // Not technically a legal comparison, but ...
+ sp<FooFixedAlloc> sp2(foo2);
+ wp<FooFixedAlloc> wp2(sp2);
+ ASSERT_TRUE(sp2 == wp2);
+ ASSERT_FALSE(sp2 != wp2);
+ ASSERT_TRUE(sp2 != wp1);
+ ASSERT_FALSE(sp2 == wp1);
+ ASSERT_FALSE(sp2 == sp1); // sp1 is null.
+ ASSERT_FALSE(wp1 == wp2); // wp1 refers to old object.
+ ASSERT_TRUE(wp1 != wp2);
+ ASSERT_TRUE(wp1 > wp2 || wp1 < wp2);
+ ASSERT_TRUE(wp1 >= wp2 || wp1 <= wp2);
+ ASSERT_FALSE(wp1 >= wp2 && wp1 <= wp2);
+ ASSERT_FALSE(wp1 == nullptr);
+ wp1 = sp2;
+ ASSERT_TRUE(wp1 == wp2);
+ ASSERT_FALSE(wp1 != wp2);
+}
// Set up a situation in which we race with visit2AndRremove() to delete
// 2 strong references. Bar destructor checks that there are no early
diff --git a/libutils/include/utils/RefBase.h b/libutils/include/utils/RefBase.h
index 1780cf2..730d631 100644
--- a/libutils/include/utils/RefBase.h
+++ b/libutils/include/utils/RefBase.h
@@ -171,6 +171,8 @@
#define ANDROID_REF_BASE_H
#include <atomic>
+#include <functional>
+#include <type_traits> // for common_type.
#include <stdint.h>
#include <sys/types.h>
@@ -192,19 +194,26 @@
// ---------------------------------------------------------------------------
#define COMPARE_WEAK(_op_) \
-inline bool operator _op_ (const sp<T>& o) const { \
- return m_ptr _op_ o.m_ptr; \
-} \
-inline bool operator _op_ (const T* o) const { \
- return m_ptr _op_ o; \
-} \
-template<typename U> \
-inline bool operator _op_ (const sp<U>& o) const { \
- return m_ptr _op_ o.m_ptr; \
-} \
template<typename U> \
inline bool operator _op_ (const U* o) const { \
return m_ptr _op_ o; \
+} \
+/* Needed to handle type inference for nullptr: */ \
+inline bool operator _op_ (const T* o) const { \
+ return m_ptr _op_ o; \
+}
+
+template<template<typename C> class comparator, typename T, typename U>
+static inline bool _wp_compare_(T* a, U* b) {
+ return comparator<typename std::common_type<T*, U*>::type>()(a, b);
+}
+
+// Use std::less and friends to avoid undefined behavior when ordering pointers
+// to different objects.
+#define COMPARE_WEAK_FUNCTIONAL(_op_, _compare_) \
+template<typename U> \
+inline bool operator _op_ (const U* o) const { \
+ return _wp_compare_<_compare_>(m_ptr, o); \
}
// ---------------------------------------------------------------------------
@@ -395,39 +404,51 @@
COMPARE_WEAK(==)
COMPARE_WEAK(!=)
- COMPARE_WEAK(>)
- COMPARE_WEAK(<)
- COMPARE_WEAK(<=)
- COMPARE_WEAK(>=)
+ COMPARE_WEAK_FUNCTIONAL(>, std::greater)
+ COMPARE_WEAK_FUNCTIONAL(<, std::less)
+ COMPARE_WEAK_FUNCTIONAL(<=, std::less_equal)
+ COMPARE_WEAK_FUNCTIONAL(>=, std::greater_equal)
- inline bool operator == (const wp<T>& o) const {
- return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
- }
template<typename U>
inline bool operator == (const wp<U>& o) const {
- return m_ptr == o.m_ptr;
+ return m_refs == o.m_refs; // Implies m_ptr == o.mptr; see invariants below.
}
- inline bool operator > (const wp<T>& o) const {
- return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
+ template<typename U>
+ inline bool operator == (const sp<U>& o) const {
+ // Just comparing m_ptr fields is often dangerous, since wp<> may refer to an older
+ // object at the same address.
+ if (o == nullptr) {
+ return m_ptr == nullptr;
+ } else {
+ return m_refs == o->getWeakRefs(); // Implies m_ptr == o.mptr.
+ }
}
+
+ template<typename U>
+ inline bool operator != (const sp<U>& o) const {
+ return !(*this == o);
+ }
+
template<typename U>
inline bool operator > (const wp<U>& o) const {
- return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
+ if (m_ptr == o.m_ptr) {
+ return _wp_compare_<std::greater>(m_refs, o.m_refs);
+ } else {
+ return _wp_compare_<std::greater>(m_ptr, o.m_ptr);
+ }
}
- inline bool operator < (const wp<T>& o) const {
- return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
- }
template<typename U>
inline bool operator < (const wp<U>& o) const {
- return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
+ if (m_ptr == o.m_ptr) {
+ return _wp_compare_<std::less>(m_refs, o.m_refs);
+ } else {
+ return _wp_compare_<std::less>(m_ptr, o.m_ptr);
+ }
}
- inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
- inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
- inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
private:
@@ -446,6 +467,22 @@
// ---------------------------------------------------------------------------
// No user serviceable parts below here.
+// Implementation invariants:
+// Either
+// 1) m_ptr and m_refs are both null, or
+// 2) m_refs == m_ptr->mRefs, or
+// 3) *m_ptr is no longer live, and m_refs points to the weakref_type object that corresponded
+// to m_ptr while it was live. *m_refs remains live while a wp<> refers to it.
+//
+// The m_refs field in a RefBase object is allocated on construction, unique to that RefBase
+// object, and never changes. Thus if two wp's have identical m_refs fields, they are either both
+// null or point to the same object. If two wp's have identical m_ptr fields, they either both
+// point to the same live object and thus have the same m_ref fields, or at least one of the
+// objects is no longer live.
+//
+// Note that the above comparison operations go out of their way to provide an ordering consistent
+// with ordinary pointer comparison; otherwise they could ignore m_ptr, and just compare m_refs.
+
template<typename T>
wp<T>::wp(T* other)
: m_ptr(other)
@@ -595,6 +632,7 @@
{
if (m_ptr) {
m_refs->decWeak(this);
+ m_refs = 0;
m_ptr = 0;
}
}
diff --git a/libutils/include/utils/StrongPointer.h b/libutils/include/utils/StrongPointer.h
index 1571129..9cd7c75 100644
--- a/libutils/include/utils/StrongPointer.h
+++ b/libutils/include/utils/StrongPointer.h
@@ -17,6 +17,9 @@
#ifndef ANDROID_STRONG_POINTER_H
#define ANDROID_STRONG_POINTER_H
+#include <functional>
+#include <type_traits> // for common_type.
+
// ---------------------------------------------------------------------------
namespace android {
@@ -24,13 +27,12 @@
// ---------------------------------------------------------------------------
-#define COMPARE(_op_) \
-inline bool operator _op_ (const sp<T>& o) const { \
- return m_ptr _op_ o.m_ptr; \
-} \
-inline bool operator _op_ (const T* o) const { \
- return m_ptr _op_ o; \
-} \
+// TODO: Maybe remove sp<> ? wp<> comparison? These are dangerous: If the wp<>
+// was created before the sp<>, and they point to different objects, they may
+// compare equal even if they are entirely unrelated. E.g. CameraService
+// currently performa such comparisons.
+
+#define COMPARE_STRONG(_op_) \
template<typename U> \
inline bool operator _op_ (const sp<U>& o) const { \
return m_ptr _op_ o.m_ptr; \
@@ -39,14 +41,27 @@
inline bool operator _op_ (const U* o) const { \
return m_ptr _op_ o; \
} \
-inline bool operator _op_ (const wp<T>& o) const { \
- return m_ptr _op_ o.m_ptr; \
-} \
-template<typename U> \
-inline bool operator _op_ (const wp<U>& o) const { \
- return m_ptr _op_ o.m_ptr; \
+/* Needed to handle type inference for nullptr: */ \
+inline bool operator _op_ (const T* o) const { \
+ return m_ptr _op_ o; \
}
+template<template<typename C> class comparator, typename T, typename U>
+static inline bool _sp_compare_(T* a, U* b) {
+ return comparator<typename std::common_type<T*, U*>::type>()(a, b);
+}
+
+// Use std::less and friends to avoid undefined behavior when ordering pointers
+// to different objects.
+#define COMPARE_STRONG_FUNCTIONAL(_op_, _compare_) \
+template<typename U> \
+inline bool operator _op_ (const sp<U>& o) const { \
+ return _sp_compare_<_compare_>(m_ptr, o.m_ptr); \
+} \
+template<typename U> \
+inline bool operator _op_ (const U* o) const { \
+ return _sp_compare_<_compare_>(m_ptr, o); \
+}
// ---------------------------------------------------------------------------
template<typename T>
@@ -89,12 +104,23 @@
// Operators
- COMPARE(==)
- COMPARE(!=)
- COMPARE(>)
- COMPARE(<)
- COMPARE(<=)
- COMPARE(>=)
+ COMPARE_STRONG(==)
+ COMPARE_STRONG(!=)
+ COMPARE_STRONG_FUNCTIONAL(>, std::greater)
+ COMPARE_STRONG_FUNCTIONAL(<, std::less)
+ COMPARE_STRONG_FUNCTIONAL(<=, std::less_equal)
+ COMPARE_STRONG_FUNCTIONAL(>=, std::greater_equal)
+
+ // Punt these to the wp<> implementation.
+ template<typename U>
+ inline bool operator == (const wp<U>& o) const {
+ return o == *this;
+ }
+
+ template<typename U>
+ inline bool operator != (const wp<U>& o) const {
+ return o != *this;
+ }
private:
template<typename Y> friend class sp;
diff --git a/libvndksupport/linker.c b/libvndksupport/linker.c
index 821940a..84c2132 100644
--- a/libvndksupport/linker.c
+++ b/libvndksupport/linker.c
@@ -20,6 +20,8 @@
#define LOG_TAG "vndksupport"
#include <log/log.h>
+#include <sys/types.h>
+#include <unistd.h>
__attribute__((weak)) extern struct android_namespace_t* android_get_exported_namespace(const char*);
__attribute__((weak)) extern void* android_dlopen_ext(const char*, int, const android_dlextinfo*);
@@ -46,6 +48,11 @@
}
int android_is_in_vendor_process() {
+ // Special case init, since when init runs, ld.config.<ver>.txt hasn't been
+ // loaded (sysprop service isn't up for init to know <ver>).
+ if (getpid() == 1) {
+ return 0;
+ }
if (android_get_exported_namespace == NULL) {
ALOGD("android_get_exported_namespace() not available. Assuming system process.");
return 0;
diff --git a/rootdir/etc/ld.config.legacy.txt b/rootdir/etc/ld.config.legacy.txt
index e624b5a..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.
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 1e742a7..7cac972 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -588,7 +588,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