Merge "debuggerd: don't display fault addr for manually sent signals."
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 45d26f8..be390d9 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -360,7 +360,7 @@
adb_auth_verified(t);
t->failed_auth_attempts = 0;
} else {
- if (t->failed_auth_attempts++ > 10) adb_sleep_ms(1000);
+ if (t->failed_auth_attempts++ > 256) adb_sleep_ms(1000);
send_auth_request(t);
}
} else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
diff --git a/adb/adb_auth.cpp b/adb/adb_auth.cpp
index 446c3df..0b07158 100644
--- a/adb/adb_auth.cpp
+++ b/adb/adb_auth.cpp
@@ -64,12 +64,14 @@
p->msg.command = A_AUTH;
p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
- p->msg.data_length = key.size();
+
+ // adbd expects a null-terminated string.
+ p->msg.data_length = key.size() + 1;
send_packet(p, t);
}
void send_auth_response(uint8_t* token, size_t token_size, atransport* t) {
- RSA* key = t->NextKey();
+ std::shared_ptr<RSA> key = t->NextKey();
if (key == nullptr) {
// No more private keys to try, send the public key.
send_auth_publickey(t);
@@ -79,12 +81,7 @@
LOG(INFO) << "Calling send_auth_response";
apacket* p = get_apacket();
- int ret = adb_auth_sign(key, token, token_size, p->data);
-
- // Stop sharing this key.
- RSA_free(key);
- key = nullptr;
-
+ int ret = adb_auth_sign(key.get(), token, token_size, p->data);
if (!ret) {
D("Error signing the token");
put_apacket(p);
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index 723ded5..59b80d8 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -20,6 +20,7 @@
#include "adb.h"
#include <deque>
+#include <memory>
#include <openssl/rsa.h>
@@ -43,7 +44,7 @@
void adb_auth_init();
int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig);
std::string adb_auth_get_userkey();
-std::deque<RSA*> adb_auth_get_private_keys();
+std::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys();
static inline bool adb_auth_generate_token(void*, size_t) { abort(); }
static inline bool adb_auth_verify(void*, size_t, void*, int) { abort(); }
@@ -53,7 +54,7 @@
static inline int adb_auth_sign(void*, const unsigned char*, size_t, unsigned char*) { abort(); }
static inline std::string adb_auth_get_userkey() { abort(); }
-static inline std::deque<RSA*> adb_auth_get_private_keys() { abort(); }
+static inline std::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys() { abort(); }
void adbd_auth_init(void);
void adbd_cloexec_auth_socket();
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index ce269cc..4f4f382 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -16,16 +16,18 @@
#define TRACE_TAG AUTH
-#include "adb_auth.h"
-#include "adb.h"
-#include "adb_utils.h"
-#include "sysdeps.h"
-
+#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#if defined(__linux__)
+#include <sys/inotify.h>
+#endif
+#include <map>
#include <mutex>
+#include <set>
+#include <string>
#include <android-base/errors.h>
#include <android-base/file.h>
@@ -39,10 +41,16 @@
#include <openssl/rsa.h>
#include <openssl/sha.h>
+#include "adb.h"
+#include "adb_auth.h"
+#include "adb_utils.h"
+#include "sysdeps.h"
#include "sysdeps/mutex.h"
-static std::mutex& g_key_list_mutex = *new std::mutex;
-static std::deque<RSA*>& g_key_list = *new std::deque<RSA*>;
+static std::mutex& g_keys_mutex = *new std::mutex;
+static std::map<std::string, std::shared_ptr<RSA>>& g_keys =
+ *new std::map<std::string, std::shared_ptr<RSA>>;
+static std::map<int, std::string>& g_monitored_paths = *new std::map<int, std::string>;
static std::string get_user_info() {
LOG(INFO) << "get_user_info...";
@@ -146,8 +154,23 @@
return ret;
}
-static bool read_key(const std::string& file) {
- LOG(INFO) << "read_key '" << file << "'...";
+static std::string hash_key(RSA* key) {
+ unsigned char* pubkey = nullptr;
+ int len = i2d_RSA_PUBKEY(key, &pubkey);
+ if (len < 0) {
+ LOG(ERROR) << "failed to encode RSA public key";
+ return std::string();
+ }
+
+ std::string result;
+ result.resize(SHA256_DIGEST_LENGTH);
+ SHA256(pubkey, len, reinterpret_cast<unsigned char*>(&result[0]));
+ OPENSSL_free(pubkey);
+ return result;
+}
+
+static bool read_key_file(const std::string& file) {
+ LOG(INFO) << "read_key_file '" << file << "'...";
std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file.c_str(), "r"), fclose);
if (!fp) {
@@ -162,10 +185,66 @@
return false;
}
- g_key_list.push_back(key);
+ std::lock_guard<std::mutex> lock(g_keys_mutex);
+ std::string fingerprint = hash_key(key);
+ if (g_keys.find(fingerprint) != g_keys.end()) {
+ LOG(INFO) << "ignoring already-loaded key: " << file;
+ RSA_free(key);
+ } else {
+ g_keys[fingerprint] = std::shared_ptr<RSA>(key, RSA_free);
+ }
+
return true;
}
+static bool read_keys(const std::string& path, bool allow_dir = true) {
+ LOG(INFO) << "read_keys '" << path << "'...";
+
+ struct stat st;
+ if (stat(path.c_str(), &st) != 0) {
+ PLOG(ERROR) << "failed to stat '" << path << "'";
+ return false;
+ }
+
+ if (S_ISREG(st.st_mode)) {
+ if (!android::base::EndsWith(path, ".adb_key")) {
+ LOG(INFO) << "skipping non-adb_key '" << path << "'";
+ return false;
+ }
+
+ return read_key_file(path);
+ } else if (S_ISDIR(st.st_mode)) {
+ if (!allow_dir) {
+ // inotify isn't recursive. It would break expectations to load keys in nested
+ // directories but not monitor them for new keys.
+ LOG(WARNING) << "refusing to recurse into directory '" << path << "'";
+ return false;
+ }
+
+ std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
+ if (!dir) {
+ PLOG(ERROR) << "failed to open directory '" << path << "'";
+ return false;
+ }
+
+ bool result = false;
+ while (struct dirent* dent = readdir(dir.get())) {
+ std::string name = dent->d_name;
+
+ // We can't use dent->d_type here because it's not available on Windows.
+ if (name == "." || name == "..") {
+ continue;
+ }
+
+ result |= read_keys((path + OS_PATH_SEPARATOR + name).c_str(), false);
+ }
+ return result;
+ }
+
+ LOG(ERROR) << "unexpected type for '" << path << "': 0x" << std::hex << st.st_mode;
+ return false;
+}
+
static std::string get_user_key_path() {
const std::string home = adb_get_homedir_path(true);
LOG(DEBUG) << "adb_get_homedir_path returned '" << home << "'";
@@ -200,31 +279,29 @@
}
}
- return read_key(path);
+ return read_key_file(path);
}
-static void get_vendor_keys() {
+static std::set<std::string> get_vendor_keys() {
const char* adb_keys_path = getenv("ADB_VENDOR_KEYS");
if (adb_keys_path == nullptr) {
- return;
+ return std::set<std::string>();
}
+ std::set<std::string> result;
for (const auto& path : android::base::Split(adb_keys_path, ENV_PATH_SEPARATOR_STR)) {
- if (!read_key(path.c_str())) {
- PLOG(ERROR) << "Failed to read '" << path << "'";
- }
+ result.emplace(path);
}
+ return result;
}
-std::deque<RSA*> adb_auth_get_private_keys() {
- std::deque<RSA*> result;
+std::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys() {
+ std::deque<std::shared_ptr<RSA>> result;
- // Copy all the currently known keys, increasing their reference count so they're
- // usable until both we and the caller have freed our pointers.
- std::lock_guard<std::mutex> lock(g_key_list_mutex);
- for (const auto& key : g_key_list) {
- RSA_up_ref(key); // Since we're handing out another pointer to this key...
- result.push_back(key);
+ // Copy all the currently known keys.
+ std::lock_guard<std::mutex> lock(g_keys_mutex);
+ for (const auto& it : g_keys) {
+ result.push_back(it.second);
}
// Add a sentinel to the list. Our caller uses this to mean "out of private keys,
@@ -270,6 +347,77 @@
return (generate_key(filename) == 0);
}
+#if defined(__linux__)
+static void adb_auth_inotify_update(int fd, unsigned fd_event, void*) {
+ LOG(INFO) << "adb_auth_inotify_update called";
+ if (!(fd_event & FDE_READ)) {
+ return;
+ }
+
+ char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
+ while (true) {
+ ssize_t rc = TEMP_FAILURE_RETRY(unix_read(fd, buf, sizeof(buf)));
+ if (rc == -1) {
+ if (errno == EAGAIN) {
+ LOG(INFO) << "done reading inotify fd";
+ break;
+ }
+ PLOG(FATAL) << "read of inotify event failed";
+ }
+
+ // The read potentially returned multiple events.
+ char* start = buf;
+ char* end = buf + rc;
+
+ while (start < end) {
+ inotify_event* event = reinterpret_cast<inotify_event*>(start);
+ auto root_it = g_monitored_paths.find(event->wd);
+ if (root_it == g_monitored_paths.end()) {
+ LOG(FATAL) << "observed inotify event for unmonitored path, wd = " << event->wd;
+ }
+
+ std::string path = root_it->second;
+ if (event->len > 0) {
+ path += '/';
+ path += event->name;
+ }
+
+ if (event->mask & (IN_CREATE | IN_MOVED_TO)) {
+ if (event->mask & IN_ISDIR) {
+ LOG(INFO) << "ignoring new directory at '" << path << "'";
+ } else {
+ LOG(INFO) << "observed new file at '" << path << "'";
+ read_keys(path, false);
+ }
+ } else {
+ LOG(WARNING) << "unmonitored event for " << path << ": 0x" << std::hex
+ << event->mask;
+ }
+
+ start += sizeof(struct inotify_event) + event->len;
+ }
+ }
+}
+
+static void adb_auth_inotify_init(const std::set<std::string>& paths) {
+ LOG(INFO) << "adb_auth_inotify_init...";
+ int infd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK);
+ for (const std::string& path : paths) {
+ int wd = inotify_add_watch(infd, path.c_str(), IN_CREATE | IN_MOVED_TO);
+ if (wd < 0) {
+ PLOG(ERROR) << "failed to inotify_add_watch on path '" << path;
+ continue;
+ }
+
+ g_monitored_paths[wd] = path;
+ LOG(INFO) << "watch descriptor " << wd << " registered for " << path;
+ }
+
+ fdevent* event = fdevent_create(infd, adb_auth_inotify_update, nullptr);
+ fdevent_add(event, FDE_READ);
+}
+#endif
+
void adb_auth_init() {
LOG(INFO) << "adb_auth_init...";
@@ -278,6 +426,13 @@
return;
}
- std::lock_guard<std::mutex> lock(g_key_list_mutex);
- get_vendor_keys();
+ const auto& key_paths = get_vendor_keys();
+
+#if defined(__linux__)
+ adb_auth_inotify_init(key_paths);
+#endif
+
+ for (const std::string& path : key_paths) {
+ read_keys(path.c_str());
+ }
}
diff --git a/adb/transport.cpp b/adb/transport.cpp
index e0216e3..f5ef174 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -1076,10 +1076,10 @@
}
}
-RSA* atransport::NextKey() {
+std::shared_ptr<RSA> atransport::NextKey() {
if (keys_.empty()) keys_ = adb_auth_get_private_keys();
- RSA* result = keys_[0];
+ std::shared_ptr<RSA> result = keys_[0];
keys_.pop_front();
return result;
}
diff --git a/adb/transport.h b/adb/transport.h
index d41c8bd..959681f 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -21,6 +21,7 @@
#include <deque>
#include <list>
+#include <memory>
#include <string>
#include <unordered_set>
@@ -107,7 +108,7 @@
return type == kTransportLocal && local_port_for_emulator_ == -1;
}
- RSA* NextKey();
+ std::shared_ptr<RSA> NextKey();
unsigned char token[TOKEN_SIZE] = {};
size_t failed_auth_attempts = 0;
@@ -160,7 +161,7 @@
// A list of adisconnect callbacks called when the transport is kicked.
std::list<adisconnect*> disconnects_;
- std::deque<RSA*> keys_;
+ std::deque<std::shared_ptr<RSA>> keys_;
DISALLOW_COPY_AND_ASSIGN(atransport);
};
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 61cceb0..c578d65 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -193,8 +193,6 @@
}
ALOGV("reading tid");
- fcntl(fd, F_SETFL, O_NONBLOCK);
-
pollfd pollfds[1];
pollfds[0].fd = fd;
pollfds[0].events = POLLIN;
@@ -828,7 +826,7 @@
socklen_t alen = sizeof(ss);
ALOGV("waiting for connection\n");
- int fd = accept4(s, addrp, &alen, SOCK_CLOEXEC);
+ int fd = accept4(s, addrp, &alen, SOCK_CLOEXEC | SOCK_NONBLOCK);
if (fd == -1) {
ALOGE("accept failed: %s\n", strerror(errno));
continue;
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index c097d04..1f2408f 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -97,19 +97,40 @@
};
static struct {
- char img_name[13];
- char sig_name[13];
+ char img_name[17];
+ char sig_name[17];
char part_name[9];
bool is_optional;
+ bool is_secondary;
} images[] = {
- {"boot.img", "boot.sig", "boot", false},
- {"recovery.img", "recovery.sig", "recovery", true},
- {"system.img", "system.sig", "system", false},
- {"vendor.img", "vendor.sig", "vendor", true},
+ {"boot.img", "boot.sig", "boot", false, false},
+ {"boot_other.img", "boot.sig", "boot", true, true},
+ {"recovery.img", "recovery.sig", "recovery", true, false},
+ {"system.img", "system.sig", "system", false, false},
+ {"system_other.img", "system.sig", "system", true, true},
+ {"vendor.img", "vendor.sig", "vendor", true, false},
+ {"vendor_other.img", "vendor.sig", "vendor", true, true},
};
-static std::string find_item(const char* item, const char* product) {
+static std::string find_item_given_name(const char* img_name, const char* product) {
+ if(product) {
+ std::string path = get_my_path();
+ path.erase(path.find_last_of('/'));
+ return android::base::StringPrintf("%s/../../../target/product/%s/%s",
+ path.c_str(), product, img_name);
+ }
+
+ char *dir = getenv("ANDROID_PRODUCT_OUT");
+ if (dir == nullptr || dir[0] == '\0') {
+ die("neither -p product specified nor ANDROID_PRODUCT_OUT set");
+ }
+
+ return android::base::StringPrintf("%s/%s", dir, img_name);
+}
+
+std::string find_item(const char* item, const char* product) {
const char *fn;
+
if (!strcmp(item,"boot")) {
fn = "boot.img";
} else if(!strcmp(item,"recovery")) {
@@ -129,19 +150,7 @@
return "";
}
- if (product) {
- std::string path = get_my_path();
- path.erase(path.find_last_of('/'));
- return android::base::StringPrintf("%s/../../../target/product/%s/%s",
- path.c_str(), product, fn);
- }
-
- char* dir = getenv("ANDROID_PRODUCT_OUT");
- if (dir == nullptr || dir[0] == '\0') {
- die("neither -p product specified nor ANDROID_PRODUCT_OUT set");
- }
-
- return android::base::StringPrintf("%s/%s", dir, fn);
+ return find_item_given_name(fn, product);
}
static int64_t get_file_size(int fd) {
@@ -307,8 +316,13 @@
"\n"
"commands:\n"
" update <filename> Reflash device from update.zip.\n"
+ " Sets the flashed slot as active.\n"
" flashall Flash boot, system, vendor, and --\n"
- " if found -- recovery.\n"
+ " if found -- recovery. If the device\n"
+ " supports slots, the slot that has\n"
+ " been flashed to is set as active.\n"
+ " Secondary images may be flashed to\n"
+ " an inactive slot.\n"
" flash <partition> [ <filename> ] Write a file to a flash partition.\n"
" flashing lock Locks the device. Prevents flashing.\n"
" flashing unlock Unlocks the device. Allows flashing\n"
@@ -331,7 +345,7 @@
" override the fs type and/or size\n"
" the bootloader reports.\n"
" getvar <variable> Display a bootloader variable.\n"
- " set_active <suffix> Sets the active slot. If slots are\n"
+ " set_active <slot> Sets the active slot. If slots are\n"
" not supported, this does nothing.\n"
" boot <kernel> [ <ramdisk> [ <second> ] ] Download and boot kernel.\n"
" flash:raw boot <kernel> [ <ramdisk> [ <second> ] ]\n"
@@ -368,19 +382,24 @@
" (default: 2048).\n"
" -S <size>[K|M|G] Automatically sparse files greater\n"
" than 'size'. 0 to disable.\n"
- " --slot <suffix> Specify slot suffix to be used if the\n"
- " device supports slots. This will be\n"
- " added to all partition names that use\n"
- " slots. 'all' can be given to refer\n"
- " to all slots. 'other' can be given to\n"
- " refer to a non-current slot. If this\n"
- " flag is not used, slotted partitions\n"
- " will default to the current active slot.\n"
- " -a, --set-active[=<suffix>] Sets the active slot. If no suffix is\n"
+ " --slot <slot> Specify slot name to be used if the\n"
+ " device supports slots. All operations\n"
+ " on partitions that support slots will\n"
+ " be done on the slot specified.\n"
+ " 'all' can be given to refer to all slots.\n"
+ " 'other' can be given to refer to a\n"
+ " non-current slot. If this flag is not\n"
+ " used, slotted partitions will default\n"
+ " to the current active slot.\n"
+ " -a, --set-active[=<slot>] Sets the active slot. If no slot is\n"
" provided, this will default to the value\n"
" given by --slot. If slots are not\n"
- " supported, this does nothing. This will\n"
- " run after all non-reboot commands.\n"
+ " supported, this sets the current slot\n"
+ " to be active. This will run after all\n"
+ " non-reboot commands.\n"
+ " --skip-secondary Will not flash secondary slots when\n"
+ " performing a flashall or update. This\n"
+ " will preserve data on other slots.\n"
" --unbuffered Do not buffer input or output.\n"
" --version Display version.\n"
" -h, --help show this message.\n"
@@ -782,83 +801,138 @@
}
}
-static std::vector<std::string> get_suffixes(Transport* transport) {
+static std::string get_current_slot(Transport* transport)
+{
+ std::string current_slot;
+ if (fb_getvar(transport, "current-slot", ¤t_slot)) {
+ if (current_slot == "_a") return "a"; // Legacy support
+ if (current_slot == "_b") return "b"; // Legacy support
+ return current_slot;
+ }
+ return "";
+}
+
+// Legacy support
+static std::vector<std::string> get_suffixes_obsolete(Transport* transport) {
std::vector<std::string> suffixes;
std::string suffix_list;
if (!fb_getvar(transport, "slot-suffixes", &suffix_list)) {
- die("Could not get suffixes.\n");
+ return suffixes;
}
- return android::base::Split(suffix_list, ",");
+ suffixes = android::base::Split(suffix_list, ",");
+ // Unfortunately some devices will return an error message in the
+ // guise of a valid value. If we only see only one suffix, it's probably
+ // not real.
+ if (suffixes.size() == 1) {
+ suffixes.clear();
+ }
+ return suffixes;
}
-static std::string verify_slot(Transport* transport, const char *slot, bool allow_all) {
- if (strcmp(slot, "all") == 0) {
+// Legacy support
+static bool supports_AB_obsolete(Transport* transport) {
+ return !get_suffixes_obsolete(transport).empty();
+}
+
+static int get_slot_count(Transport* transport) {
+ std::string var;
+ int count;
+ if (!fb_getvar(transport, "slot-count", &var)) {
+ if (supports_AB_obsolete(transport)) return 2; // Legacy support
+ }
+ if (!android::base::ParseInt(var.c_str(), &count)) return 0;
+ return count;
+}
+
+static bool supports_AB(Transport* transport) {
+ return get_slot_count(transport) >= 2;
+}
+
+// Given a current slot, this returns what the 'other' slot is.
+static std::string get_other_slot(const std::string& current_slot, int count) {
+ if (count == 0) return "";
+
+ char next = (current_slot[0] - 'a' + 1)%count + 'a';
+ return std::string(1, next);
+}
+
+static std::string get_other_slot(Transport* transport, const std::string& current_slot) {
+ return get_other_slot(current_slot, get_slot_count(transport));
+}
+
+static std::string get_other_slot(Transport* transport, int count) {
+ return get_other_slot(get_current_slot(transport), count);
+}
+
+static std::string get_other_slot(Transport* transport) {
+ return get_other_slot(get_current_slot(transport), get_slot_count(transport));
+}
+
+static std::string verify_slot(Transport* transport, const std::string& slot_name, bool allow_all) {
+ std::string slot = slot_name;
+ if (slot == "_a") slot = "a"; // Legacy support
+ if (slot == "_b") slot = "b"; // Legacy support
+ if (slot == "all") {
if (allow_all) {
return "all";
} else {
- std::vector<std::string> suffixes = get_suffixes(transport);
- if (!suffixes.empty()) {
- return suffixes[0];
+ int count = get_slot_count(transport);
+ if (count > 0) {
+ return "a";
} else {
die("No known slots.");
}
}
}
- std::vector<std::string> suffixes = get_suffixes(transport);
+ int count = get_slot_count(transport);
+ if (count == 0) die("Device does not support slots.\n");
- if (strcmp(slot, "other") == 0) {
- std::string current_slot;
- if (!fb_getvar(transport, "current-slot", ¤t_slot)) {
- die("Failed to identify current slot.");
+ if (slot == "other") {
+ std::string other = get_other_slot(transport, count);
+ if (other == "") {
+ die("No known slots.");
}
- if (!suffixes.empty()) {
- for (size_t i = 0; i < suffixes.size(); i++) {
- if (current_slot == suffixes[i])
- return suffixes[(i+1)%suffixes.size()];
- }
- } else {
- die("No known slots.");
- }
+ return other;
}
- for (const std::string &suffix : suffixes) {
- if (suffix == slot)
- return slot;
+ if (slot.size() == 1 && (slot[0]-'a' >= 0 && slot[0]-'a' < count)) return slot;
+
+ fprintf(stderr, "Slot %s does not exist. supported slots are:\n", slot.c_str());
+ for (int i=0; i<count; i++) {
+ fprintf(stderr, "%c\n", (char)(i + 'a'));
}
- fprintf(stderr, "Slot %s does not exist. supported slots are:\n", slot);
- for (const std::string &suffix : suffixes) {
- fprintf(stderr, "%s\n", suffix.c_str());
- }
+
exit(1);
}
-static std::string verify_slot(Transport* transport, const char *slot) {
+static std::string verify_slot(Transport* transport, const std::string& slot) {
return verify_slot(transport, slot, true);
}
-static void do_for_partition(Transport* transport, const char *part, const char *slot,
+static void do_for_partition(Transport* transport, const std::string& part, const std::string& slot,
const std::function<void(const std::string&)>& func, bool force_slot) {
std::string has_slot;
std::string current_slot;
- if (!fb_getvar(transport, std::string("has-slot:")+part, &has_slot)) {
+ if (!fb_getvar(transport, "has-slot:" + part, &has_slot)) {
/* If has-slot is not supported, the answer is no. */
has_slot = "no";
}
if (has_slot == "yes") {
- if (!slot || slot[0] == 0) {
- if (!fb_getvar(transport, "current-slot", ¤t_slot)) {
+ if (slot == "") {
+ current_slot = get_current_slot(transport);
+ if (current_slot == "") {
die("Failed to identify current slot.\n");
}
- func(std::string(part) + current_slot);
+ func(part + "_" + current_slot);
} else {
- func(std::string(part) + slot);
+ func(part + '_' + slot);
}
} else {
- if (force_slot && slot && slot[0]) {
+ if (force_slot && slot != "") {
fprintf(stderr, "Warning: %s does not support slots, and slot %s was requested.\n",
- part, slot);
+ part.c_str(), slot.c_str());
}
func(part);
}
@@ -869,18 +943,17 @@
* partition names. If force_slot is true, it will fail if a slot is specified, and the given
* partition does not support slots.
*/
-static void do_for_partitions(Transport* transport, const char *part, const char *slot,
+static void do_for_partitions(Transport* transport, const std::string& part, const std::string& slot,
const std::function<void(const std::string&)>& func, bool force_slot) {
std::string has_slot;
- if (slot && strcmp(slot, "all") == 0) {
- if (!fb_getvar(transport, std::string("has-slot:") + part, &has_slot)) {
- die("Could not check if partition %s has slot.", part);
+ if (slot == "all") {
+ if (!fb_getvar(transport, "has-slot:" + part, &has_slot)) {
+ die("Could not check if partition %s has slot.", part.c_str());
}
if (has_slot == "yes") {
- std::vector<std::string> suffixes = get_suffixes(transport);
- for (std::string &suffix : suffixes) {
- do_for_partition(transport, part, suffix.c_str(), func, force_slot);
+ for (int i=0; i < get_slot_count(transport); i++) {
+ do_for_partition(transport, part, std::string(1, (char)(i + 'a')), func, force_slot);
}
} else {
do_for_partition(transport, part, "", func, force_slot);
@@ -907,7 +980,28 @@
fb_queue_command("signature", "installing signature");
}
-static void do_update(Transport* transport, const char* filename, const char* slot_override, bool erase_first) {
+// Sets slot_override as the active slot. If slot_override is blank,
+// set current slot as active instead. This clears slot-unbootable.
+static void set_active(Transport* transport, const std::string& slot_override) {
+ std::string separator = "";
+ if (!supports_AB(transport)) {
+ if (supports_AB_obsolete(transport)) {
+ separator = "_"; // Legacy support
+ } else {
+ return;
+ }
+ }
+ if (slot_override != "") {
+ fb_set_active((separator + slot_override).c_str());
+ } else {
+ std::string current_slot = get_current_slot(transport);
+ if (current_slot != "") {
+ fb_set_active((separator + current_slot).c_str());
+ }
+ }
+}
+
+static void do_update(Transport* transport, const char* filename, const std::string& slot_override, bool erase_first, bool skip_secondary) {
queue_info_dump();
fb_queue_query_save("product", cur_product, sizeof(cur_product));
@@ -928,7 +1022,30 @@
setup_requirements(reinterpret_cast<char*>(data), sz);
+ std::string secondary;
+ if (!skip_secondary) {
+ if (slot_override != "") {
+ secondary = get_other_slot(transport, slot_override);
+ } else {
+ secondary = get_other_slot(transport);
+ }
+ if (secondary == "") {
+ if (supports_AB(transport)) {
+ fprintf(stderr, "Warning: Could not determine slot for secondary images. Ignoring.\n");
+ }
+ skip_secondary = true;
+ }
+ }
for (size_t i = 0; i < arraysize(images); ++i) {
+ const char* slot = slot_override.c_str();
+ if (images[i].is_secondary) {
+ if (!skip_secondary) {
+ slot = secondary.c_str();
+ } else {
+ continue;
+ }
+ }
+
int fd = unzip_to_file(zip, images[i].img_name);
if (fd == -1) {
if (images[i].is_optional) {
@@ -953,49 +1070,74 @@
* program exits.
*/
};
- do_for_partitions(transport, images[i].part_name, slot_override, update, false);
+ do_for_partitions(transport, images[i].part_name, slot, update, false);
}
CloseArchive(zip);
+ if (slot_override == "all") {
+ set_active(transport, "a");
+ } else {
+ set_active(transport, slot_override);
+ }
}
-static void do_send_signature(const char* filename) {
- if (android::base::EndsWith(filename, ".img") == false) {
- return;
- }
+static void do_send_signature(const std::string& fn) {
+ std::size_t extension_loc = fn.find(".img");
+ if (extension_loc == std::string::npos) return;
- std::string sig_path = filename;
- sig_path.erase(sig_path.size() - 4);
- sig_path += ".sig";
+ std::string fs_sig = fn.substr(0, extension_loc) + ".sig";
int64_t sz;
- void* data = load_file(sig_path, &sz);
+ void* data = load_file(fs_sig.c_str(), &sz);
if (data == nullptr) return;
fb_queue_download("signature", data, sz);
fb_queue_command("signature", "installing signature");
}
-static void do_flashall(Transport* transport, const char* slot_override, int erase_first) {
+static void do_flashall(Transport* transport, const std::string& slot_override, int erase_first, bool skip_secondary) {
+ std::string fname;
queue_info_dump();
fb_queue_query_save("product", cur_product, sizeof(cur_product));
- std::string fname = find_item("info", product);
+ fname = find_item("info", product);
if (fname.empty()) die("cannot find android-info.txt");
int64_t sz;
- void* data = load_file(fname, &sz);
+ void* data = load_file(fname.c_str(), &sz);
if (data == nullptr) die("could not load android-info.txt: %s", strerror(errno));
setup_requirements(reinterpret_cast<char*>(data), sz);
+ std::string secondary;
+ if (!skip_secondary) {
+ if (slot_override != "") {
+ secondary = get_other_slot(transport, slot_override);
+ } else {
+ secondary = get_other_slot(transport);
+ }
+ if (secondary == "") {
+ if (supports_AB(transport)) {
+ fprintf(stderr, "Warning: Could not determine slot for secondary images. Ignoring.\n");
+ }
+ skip_secondary = true;
+ }
+ }
+
for (size_t i = 0; i < arraysize(images); i++) {
- fname = find_item(images[i].part_name, product);
+ const char* slot = NULL;
+ if (images[i].is_secondary) {
+ if (!skip_secondary) slot = secondary.c_str();
+ } else {
+ slot = slot_override.c_str();
+ }
+ if (!slot) continue;
+ fname = find_item_given_name(images[i].img_name, product);
fastboot_buffer buf;
if (!load_buf(transport, fname.c_str(), &buf)) {
if (images[i].is_optional) continue;
- die("could not load '%s': %s", images[i].img_name, strerror(errno));
+ die("could not load '%s': %s\n", images[i].img_name, strerror(errno));
}
auto flashall = [&](const std::string &partition) {
@@ -1005,7 +1147,13 @@
}
flash_buf(partition.c_str(), &buf);
};
- do_for_partitions(transport, images[i].part_name, slot_override, flashall, false);
+ do_for_partitions(transport, images[i].part_name, slot, flashall, false);
+ }
+
+ if (slot_override == "all") {
+ set_active(transport, "a");
+ } else {
+ set_active(transport, slot_override);
}
}
@@ -1184,6 +1332,7 @@
bool wants_reboot = false;
bool wants_reboot_bootloader = false;
bool wants_set_active = false;
+ bool skip_secondary = false;
bool erase_first = true;
void *data;
int64_t sz;
@@ -1207,6 +1356,7 @@
{"slot", required_argument, 0, 0},
{"set_active", optional_argument, 0, 'a'},
{"set-active", optional_argument, 0, 'a'},
+ {"skip-secondary", no_argument, 0, 0},
{0, 0, 0, 0}
};
@@ -1288,6 +1438,12 @@
return 0;
} else if (strcmp("slot", longopts[longindex].name) == 0) {
slot_override = std::string(optarg);
+ } else if (strcmp("skip-secondary", longopts[longindex].name) == 0 ) {
+ skip_secondary = true;
+ } else {
+ fprintf(stderr, "Internal error in options processing for %s\n",
+ longopts[longindex].name);
+ return 1;
}
break;
default:
@@ -1319,17 +1475,23 @@
return 1;
}
- if (slot_override != "")
- slot_override = verify_slot(transport, slot_override.c_str());
- if (next_active != "")
- next_active = verify_slot(transport, next_active.c_str(), false);
+ if (!supports_AB(transport) && supports_AB_obsolete(transport)) {
+ fprintf(stderr, "Warning: Device A/B support is outdated. Bootloader update required.\n");
+ }
+ if (slot_override != "") slot_override = verify_slot(transport, slot_override);
+ if (next_active != "") next_active = verify_slot(transport, next_active, false);
if (wants_set_active) {
if (next_active == "") {
if (slot_override == "") {
- wants_set_active = false;
+ std::string current_slot;
+ if (fb_getvar(transport, "current-slot", ¤t_slot)) {
+ next_active = verify_slot(transport, current_slot, false);
+ } else {
+ wants_set_active = false;
+ }
} else {
- next_active = verify_slot(transport, slot_override.c_str(), false);
+ next_active = verify_slot(transport, slot_override, false);
}
}
}
@@ -1352,7 +1514,7 @@
fb_queue_erase(partition.c_str());
};
- do_for_partitions(transport, argv[1], slot_override.c_str(), erase, true);
+ do_for_partitions(transport, argv[1], slot_override, erase, true);
skip(2);
} else if(!strncmp(*argv, "format", strlen("format"))) {
char *overrides;
@@ -1387,7 +1549,7 @@
}
fb_perform_format(transport, partition.c_str(), 0, type_override, size_override);
};
- do_for_partitions(transport, argv[1], slot_override.c_str(), format, true);
+ do_for_partitions(transport, argv[1], slot_override, format, true);
skip(2);
} else if(!strcmp(*argv, "signature")) {
require(2);
@@ -1454,7 +1616,7 @@
}
do_flash(transport, partition.c_str(), fname.c_str());
};
- do_for_partitions(transport, pname, slot_override.c_str(), flash, true);
+ do_for_partitions(transport, pname, slot_override, flash, true);
} else if(!strcmp(*argv, "flash:raw")) {
char *kname = argv[2];
char *rname = 0;
@@ -1474,23 +1636,32 @@
auto flashraw = [&](const std::string &partition) {
fb_queue_flash(partition.c_str(), data, sz);
};
- do_for_partitions(transport, argv[1], slot_override.c_str(), flashraw, true);
+ do_for_partitions(transport, argv[1], slot_override, flashraw, true);
} else if(!strcmp(*argv, "flashall")) {
skip(1);
- do_flashall(transport, slot_override.c_str(), erase_first);
+ if (slot_override == "all") {
+ fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
+ do_flashall(transport, slot_override, erase_first, true);
+ } else {
+ do_flashall(transport, slot_override, erase_first, skip_secondary);
+ }
wants_reboot = true;
} else if(!strcmp(*argv, "update")) {
+ bool slot_all = (slot_override == "all");
+ if (slot_all) {
+ fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
+ }
if (argc > 1) {
- do_update(transport, argv[1], slot_override.c_str(), erase_first);
+ do_update(transport, argv[1], slot_override, erase_first, skip_secondary || slot_all);
skip(2);
} else {
- do_update(transport, "update.zip", slot_override.c_str(), erase_first);
+ do_update(transport, "update.zip", slot_override, erase_first, skip_secondary || slot_all);
skip(1);
}
wants_reboot = 1;
} else if(!strcmp(*argv, "set_active")) {
require(2);
- std::string slot = verify_slot(transport, argv[1], false);
+ std::string slot = verify_slot(transport, std::string(argv[1]), false);
fb_set_active(slot.c_str());
skip(2);
} else if(!strcmp(*argv, "oem")) {
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 1b3893f..4a85689 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -905,3 +905,22 @@
return 0;
}
+
+int fs_mgr_early_setup_verity(struct fstab_rec *fstab_rec)
+{
+ if ((fstab_rec->fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
+ int rc = fs_mgr_setup_verity(fstab_rec);
+ if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
+ INFO("Verity disabled");
+ return FS_MGR_EARLY_SETUP_VERITY_NO_VERITY;
+ } else if (rc == FS_MGR_SETUP_VERITY_SUCCESS) {
+ return FS_MGR_EARLY_SETUP_VERITY_SUCCESS;
+ } else {
+ return FS_MGR_EARLY_SETUP_VERITY_FAIL;
+ }
+ } else if (device_is_secure()) {
+ ERROR("Verity must be enabled for early mounted partitions on secured devices.\n");
+ return FS_MGR_EARLY_SETUP_VERITY_FAIL;
+ }
+ return FS_MGR_EARLY_SETUP_VERITY_NO_VERITY;
+}
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 5b92db7..b302354 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -210,9 +210,8 @@
return f;
}
-struct fstab *fs_mgr_read_fstab(const char *fstab_path)
+struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
{
- FILE *fstab_file;
int cnt, entries;
ssize_t len;
size_t alloc_len = 0;
@@ -224,12 +223,6 @@
#define FS_OPTIONS_LEN 1024
char tmp_fs_options[FS_OPTIONS_LEN];
- fstab_file = fopen(fstab_path, "r");
- if (!fstab_file) {
- ERROR("Cannot open file %s\n", fstab_path);
- return 0;
- }
-
entries = 0;
while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
/* if the last character is a newline, shorten the string by 1 byte */
@@ -255,7 +248,6 @@
/* Allocate and init the fstab structure */
fstab = calloc(1, sizeof(struct fstab));
fstab->num_entries = entries;
- fstab->fstab_filename = strdup(fstab_path);
fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec));
fseek(fstab_file, 0, SEEK_SET);
@@ -338,18 +330,34 @@
ERROR("Error updating for slotselect\n");
goto err;
}
- fclose(fstab_file);
free(line);
return fstab;
err:
- fclose(fstab_file);
free(line);
if (fstab)
fs_mgr_free_fstab(fstab);
return NULL;
}
+struct fstab *fs_mgr_read_fstab(const char *fstab_path)
+{
+ FILE *fstab_file;
+ struct fstab *fstab;
+
+ fstab_file = fopen(fstab_path, "r");
+ if (!fstab_file) {
+ ERROR("Cannot open file %s\n", fstab_path);
+ return NULL;
+ }
+ fstab = fs_mgr_read_fstab_file(fstab_file);
+ if (fstab) {
+ fstab->fstab_filename = strdup(fstab_path);
+ }
+ fclose(fstab_file);
+ return fstab;
+}
+
void fs_mgr_free_fstab(struct fstab *fstab)
{
int i;
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 67104cc..767b3b3 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -341,17 +341,6 @@
return 0;
}
-static int test_access(char *device) {
- int tries = 25;
- while (tries--) {
- if (!access(device, F_OK) || errno != ENOENT) {
- return 0;
- }
- usleep(40 * 1000);
- }
- return -1;
-}
-
static int check_verity_restart(const char *fname)
{
char buffer[VERITY_KMSG_BUFSIZE + 1];
@@ -1031,11 +1020,6 @@
fstab->blk_device = verity_blk_name;
verity_blk_name = 0;
- // make sure we've set everything up properly
- if (test_access(fstab->blk_device) < 0) {
- goto out;
- }
-
retval = FS_MGR_SETUP_VERITY_SUCCESS;
out:
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 3c27ede..17d0277 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -17,6 +17,7 @@
#ifndef __CORE_FS_MGR_H
#define __CORE_FS_MGR_H
+#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <linux/dm-ioctl.h>
@@ -72,6 +73,7 @@
typedef void (*fs_mgr_verity_state_callback)(struct fstab_rec *fstab,
const char *mount_point, int mode, int status);
+struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file);
struct fstab *fs_mgr_read_fstab(const char *fstab_path);
void fs_mgr_free_fstab(struct fstab *fstab);
@@ -111,6 +113,11 @@
int fs_mgr_do_format(struct fstab_rec *fstab, bool reserve_footer);
+#define FS_MGR_EARLY_SETUP_VERITY_NO_VERITY -2
+#define FS_MGR_EARLY_SETUP_VERITY_FAIL -1
+#define FS_MGR_EARLY_SETUP_VERITY_SUCCESS 0
+int fs_mgr_early_setup_verity(struct fstab_rec *fstab);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/cutils/process_name.h b/include/cutils/process_name.h
deleted file mode 100644
index 1e72e5c..0000000
--- a/include/cutils/process_name.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-/**
- * Gives the current process a name.
- */
-
-#ifndef __PROCESS_NAME_H
-#define __PROCESS_NAME_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Sets the current process name.
- *
- * Warning: This leaks a string every time you call it. Use judiciously!
- */
-void set_process_name(const char* process_name);
-
-/** Gets the current process name. */
-const char* get_process_name(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __PROCESS_NAME_H */
diff --git a/init/devices.cpp b/init/devices.cpp
index 373177e..830b74c 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -44,6 +44,7 @@
#include <android-base/file.h>
#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
#include <cutils/list.h>
#include <cutils/uevent.h>
@@ -601,14 +602,17 @@
return name;
}
+#define DEVPATH_LEN 96
+#define MAX_DEV_NAME 64
+
static void handle_block_device_event(struct uevent *uevent)
{
const char *base = "/dev/block/";
const char *name;
- char devpath[96];
+ char devpath[DEVPATH_LEN];
char **links = NULL;
- name = parse_device_name(uevent, 64);
+ name = parse_device_name(uevent, MAX_DEV_NAME);
if (!name)
return;
@@ -622,8 +626,6 @@
uevent->major, uevent->minor, links);
}
-#define DEVPATH_LEN 96
-
static bool assemble_devpath(char *devpath, const char *dirname,
const char *devname)
{
@@ -657,7 +659,7 @@
char devpath[DEVPATH_LEN] = {0};
char **links = NULL;
- name = parse_device_name(uevent, 64);
+ name = parse_device_name(uevent, MAX_DEV_NAME);
if (!name)
return;
@@ -900,7 +902,8 @@
}
#define UEVENT_MSG_LEN 2048
-void handle_device_fd()
+
+static inline void handle_device_fd_with(void (handle_uevent)(struct uevent*))
{
char msg[UEVENT_MSG_LEN+2];
int n;
@@ -913,21 +916,28 @@
struct uevent uevent;
parse_event(msg, &uevent);
-
- if (selinux_status_updated() > 0) {
- struct selabel_handle *sehandle2;
- sehandle2 = selinux_android_file_context_handle();
- if (sehandle2) {
- selabel_close(sehandle);
- sehandle = sehandle2;
- }
- }
-
- handle_device_event(&uevent);
- handle_firmware_event(&uevent);
+ handle_uevent(&uevent);
}
}
+void handle_device_fd()
+{
+ handle_device_fd_with(
+ [](struct uevent *uevent) {
+ if (selinux_status_updated() > 0) {
+ struct selabel_handle *sehandle2;
+ sehandle2 = selinux_android_file_context_handle();
+ if (sehandle2) {
+ selabel_close(sehandle);
+ sehandle = sehandle2;
+ }
+ }
+
+ handle_device_event(uevent);
+ handle_firmware_event(uevent);
+ });
+}
+
/* Coldboot walks parts of the /sys tree and pokes the uevent files
** to cause the kernel to regenerate device add events that happened
** before init's device manager was started
@@ -979,6 +989,65 @@
}
}
+static void early_uevent_handler(struct uevent *uevent, const char *base, bool is_block)
+{
+ const char *name;
+ char devpath[DEVPATH_LEN];
+
+ if (is_block && strncmp(uevent->subsystem, "block", 5))
+ return;
+
+ name = parse_device_name(uevent, MAX_DEV_NAME);
+ if (!name) {
+ LOG(ERROR) << "Failed to parse dev name from uevent: " << uevent->action
+ << " " << uevent->partition_name << " " << uevent->partition_num
+ << " " << uevent->major << ":" << uevent->minor;
+ return;
+ }
+
+ snprintf(devpath, sizeof(devpath), "%s%s", base, name);
+ make_dir(base, 0755);
+
+ dev_t dev = makedev(uevent->major, uevent->minor);
+ mode_t mode = 0600 | (is_block ? S_IFBLK : S_IFCHR);
+ mknod(devpath, mode, dev);
+}
+
+void early_create_dev(const std::string& syspath, early_device_type dev_type)
+{
+ android::base::unique_fd dfd(open(syspath.c_str(), O_RDONLY));
+ if (dfd < 0) {
+ LOG(ERROR) << "Failed to open " << syspath;
+ return;
+ }
+
+ android::base::unique_fd fd(openat(dfd, "uevent", O_WRONLY));
+ if (fd < 0) {
+ LOG(ERROR) << "Failed to open " << syspath << "/uevent";
+ return;
+ }
+
+ fcntl(device_fd, F_SETFL, O_NONBLOCK);
+
+ write(fd, "add\n", 4);
+ handle_device_fd_with(dev_type == EARLY_BLOCK_DEV ?
+ [](struct uevent *uevent) {
+ early_uevent_handler(uevent, "/dev/block/", true);
+ } :
+ [](struct uevent *uevent) {
+ early_uevent_handler(uevent, "/dev/", false);
+ });
+}
+
+int early_device_socket_open() {
+ device_fd = uevent_open_socket(256*1024, true);
+ return device_fd < 0;
+}
+
+void early_device_socket_close() {
+ close(device_fd);
+}
+
void device_init() {
sehandle = selinux_android_file_context_handle();
selinux_status_open(true);
diff --git a/init/devices.h b/init/devices.h
index 6cb0a77..8e9ab7d 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -21,6 +21,13 @@
extern void handle_device_fd();
extern void device_init(void);
+
+enum early_device_type { EARLY_BLOCK_DEV, EARLY_CHAR_DEV };
+
+extern int early_device_socket_open();
+extern void early_device_socket_close();
+extern void early_create_dev(const std::string& syspath, early_device_type dev_type);
+
extern int add_dev_perms(const char *name, const char *attr,
mode_t perm, unsigned int uid,
unsigned int gid, unsigned short prefix,
diff --git a/init/init.cpp b/init/init.cpp
index 78d71a8..957527b 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -54,6 +54,7 @@
#include "action.h"
#include "bootchart.h"
#include "devices.h"
+#include "fs_mgr.h"
#include "import_parser.h"
#include "init.h"
#include "init_parser.h"
@@ -342,9 +343,6 @@
}
static void process_kernel_cmdline() {
- // Don't expose the raw commandline to unprivileged processes.
- chmod("/proc/cmdline", 0440);
-
// The first pass does the common stuff, and finds if we are in qemu.
// The second pass is only necessary for qemu to export all kernel params
// as properties.
@@ -461,6 +459,104 @@
}
}
+/* Returns a new path consisting of base_path and the file name in reference_path. */
+static std::string get_path(const std::string& base_path, const std::string& reference_path) {
+ std::string::size_type pos = reference_path.rfind('/');
+ if (pos == std::string::npos) {
+ return base_path + '/' + reference_path;
+ } else {
+ return base_path + reference_path.substr(pos);
+ }
+}
+
+/* Imports the fstab info from cmdline. */
+static std::string import_cmdline_fstab() {
+ std::string prefix, fstab, fstab_full;
+
+ import_kernel_cmdline(false,
+ [&](const std::string& key, const std::string& value, bool in_qemu __attribute__((__unused__))) {
+ if (key == "android.early.prefix") {
+ prefix = value;
+ } else if (key == "android.early.fstab") {
+ fstab = value;
+ }
+ });
+ if (!fstab.empty()) {
+ // Convert "mmcblk0p09+/odm+ext4+ro+verify" to "mmcblk0p09 /odm ext4 ro verify"
+ std::replace(fstab.begin(), fstab.end(), '+', ' ');
+ for (const auto& entry : android::base::Split(fstab, "\n")) {
+ fstab_full += prefix + entry + '\n';
+ }
+ }
+ return fstab_full;
+}
+
+/* Early mount vendor and ODM partitions. The fstab info is read from kernel cmdline. */
+static void early_mount() {
+ std::string fstab_string = import_cmdline_fstab();
+ if (fstab_string.empty()) {
+ LOG(INFO) << "Failed to load vendor fstab from kernel cmdline";
+ return;
+ }
+ FILE *fstab_file = fmemopen((void *)fstab_string.c_str(), fstab_string.length(), "r");
+ if (!fstab_file) {
+ PLOG(ERROR) << "Failed to open fstab string as FILE";
+ return;
+ }
+ std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_file(fstab_file), fs_mgr_free_fstab);
+ fclose(fstab_file);
+ if (!fstab) {
+ LOG(ERROR) << "Failed to parse fstab string: " << fstab_string;
+ return;
+ }
+ LOG(INFO) << "Loaded vendor fstab from cmdline";
+
+ if (early_device_socket_open()) {
+ LOG(ERROR) << "Failed to open device uevent socket";
+ return;
+ }
+
+ /* Create /dev/device-mapper for dm-verity */
+ early_create_dev("/sys/devices/virtual/misc/device-mapper", EARLY_CHAR_DEV);
+
+ for (int i = 0; i < fstab->num_entries; ++i) {
+ struct fstab_rec *rec = &fstab->recs[i];
+ std::string mount_point = rec->mount_point;
+ std::string syspath = rec->blk_device;
+
+ if (mount_point != "/vendor" && mount_point != "/odm")
+ continue;
+
+ /* Create mount target under /dev/block/ from sysfs via uevent */
+ LOG(INFO) << "Mounting " << mount_point << " from " << syspath << "...";
+ char *devpath = strdup(get_path("/dev/block", syspath).c_str());
+ if (!devpath) {
+ PLOG(ERROR) << "Failed to strdup dev path in early mount " << syspath;
+ continue;
+ }
+ rec->blk_device = devpath;
+ early_create_dev(syspath, EARLY_BLOCK_DEV);
+
+ int rc = fs_mgr_early_setup_verity(rec);
+ if (rc == FS_MGR_EARLY_SETUP_VERITY_SUCCESS) {
+ /* Mount target is changed to /dev/block/dm-<n>; initiate its creation from sysfs counterpart */
+ early_create_dev(get_path("/sys/devices/virtual/block", rec->blk_device), EARLY_BLOCK_DEV);
+ } else if (rc == FS_MGR_EARLY_SETUP_VERITY_FAIL) {
+ LOG(ERROR) << "Failed to set up dm-verity on " << rec->blk_device;
+ continue;
+ } else { /* FS_MGR_EARLY_SETUP_VERITY_NO_VERITY */
+ LOG(INFO) << "dm-verity disabled on debuggable device; mount directly on " << rec->blk_device;
+ }
+
+ mkdir(mount_point.c_str(), 0755);
+ rc = mount(rec->blk_device, mount_point.c_str(), rec->fs_type, rec->flags, rec->fs_options);
+ if (rc) {
+ PLOG(ERROR) << "Failed to mount on " << rec->blk_device;
+ }
+ }
+ early_device_socket_close();
+}
+
int main(int argc, char** argv) {
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
@@ -477,6 +573,9 @@
bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);
+ // Don't expose the raw commandline to unprivileged processes.
+ chmod("/proc/cmdline", 0440);
+
// Get the basic filesystem setup we need put together in the initramdisk
// on / and then we'll let the rc file figure out the rest.
if (is_first_stage) {
@@ -489,6 +588,7 @@
mount("sysfs", "/sys", "sysfs", 0, NULL);
mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
+ early_mount();
}
// Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
@@ -541,6 +641,8 @@
restorecon("/dev/__properties__");
restorecon("/property_contexts");
restorecon_recursive("/sys");
+ restorecon_recursive("/dev/block");
+ restorecon("/dev/device-mapper");
epoll_fd = epoll_create1(EPOLL_CLOEXEC);
if (epoll_fd == -1) {
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 4f26034..8624d13 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -42,7 +42,6 @@
"load_file.c",
"native_handle.c",
"open_memstream.c",
- "process_name.c",
"record_stream.c",
"sched_policy.c",
"sockets.cpp",
diff --git a/libcutils/process_name.c b/libcutils/process_name.c
deleted file mode 100644
index 5d28b6f..0000000
--- a/libcutils/process_name.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2008 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 <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#if defined(__linux__)
-#include <sys/prctl.h>
-#endif
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <cutils/process_name.h>
-#if defined(__ANDROID__)
-#include <cutils/properties.h>
-#endif
-
-#define PROCESS_NAME_DEVICE "/sys/qemu_trace/process_name"
-
-static const char* process_name = "unknown";
-#if defined(__ANDROID__)
-static int running_in_emulator = -1;
-#endif
-
-void set_process_name(const char* new_name) {
-#if defined(__ANDROID__)
- char propBuf[PROPERTY_VALUE_MAX];
-#endif
-
- if (new_name == NULL) {
- return;
- }
-
- // We never free the old name. Someone else could be using it.
- int len = strlen(new_name);
- char* copy = (char*) malloc(len + 1);
- strcpy(copy, new_name);
- process_name = (const char*) copy;
-
-#if defined(__linux__)
- if (len < 16) {
- prctl(PR_SET_NAME, (unsigned long) new_name, 0, 0, 0);
- } else {
- prctl(PR_SET_NAME, (unsigned long) new_name + len - 15, 0, 0, 0);
- }
-#endif
-
-#if defined(__ANDROID__)
- // If we know we are not running in the emulator, then return.
- if (running_in_emulator == 0) {
- return;
- }
-
- // If the "running_in_emulator" variable has not been initialized,
- // then do it now.
- if (running_in_emulator == -1) {
- property_get("ro.kernel.qemu", propBuf, "");
- if (propBuf[0] == '1') {
- running_in_emulator = 1;
- } else {
- running_in_emulator = 0;
- return;
- }
- }
-
- // If the emulator was started with the "-trace file" command line option
- // then we want to record the process name in the trace even if we are
- // not currently tracing instructions (so that we will know the process
- // name when we do start tracing instructions). We do not need to execute
- // this code if we are just running in the emulator without the "-trace"
- // command line option, but we don't know that here and this function
- // isn't called frequently enough to bother optimizing that case.
- int fd = open(PROCESS_NAME_DEVICE, O_RDWR);
- if (fd < 0)
- return;
- write(fd, process_name, strlen(process_name) + 1);
- close(fd);
-#endif
-}
-
-const char* get_process_name(void) {
- return process_name;
-}
diff --git a/liblog/logd_writer.c b/liblog/logd_writer.c
index 059f170..ed82902 100644
--- a/liblog/logd_writer.c
+++ b/liblog/logd_writer.c
@@ -67,12 +67,9 @@
int i, ret = 0;
if (logdLoggerWrite.context.sock < 0) {
- i = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0));
+ i = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
if (i < 0) {
ret = -errno;
- } else if (TEMP_FAILURE_RETRY(fcntl(i, F_SETFL, O_NONBLOCK)) < 0) {
- ret = -errno;
- close(i);
} else {
struct sockaddr_un un;
memset(&un, 0, sizeof(struct sockaddr_un));
diff --git a/libpixelflinger/codeflinger/CodeCache.cpp b/libpixelflinger/codeflinger/CodeCache.cpp
index 4b498c1..ae38519 100644
--- a/libpixelflinger/codeflinger/CodeCache.cpp
+++ b/libpixelflinger/codeflinger/CodeCache.cpp
@@ -23,7 +23,6 @@
#include <sys/mman.h>
#include <cutils/ashmem.h>
-#include <cutils/atomic.h>
#define LOG_TAG "CodeCache"
#include <cutils/log.h>
@@ -101,7 +100,7 @@
}
Assembly::Assembly(size_t size)
- : mCount(1), mSize(0)
+ : mCount(0), mSize(0)
{
mBase = (uint32_t*)mspace_malloc(getMspace(), size);
LOG_ALWAYS_FATAL_IF(mBase == NULL,
@@ -117,12 +116,12 @@
void Assembly::incStrong(const void*) const
{
- android_atomic_inc(&mCount);
+ mCount.fetch_add(1, std::memory_order_relaxed);
}
void Assembly::decStrong(const void*) const
{
- if (android_atomic_dec(&mCount) == 1) {
+ if (mCount.fetch_sub(1, std::memory_order_acq_rel) == 1) {
delete this;
}
}
diff --git a/libpixelflinger/codeflinger/CodeCache.h b/libpixelflinger/codeflinger/CodeCache.h
index c0e0684..9326453 100644
--- a/libpixelflinger/codeflinger/CodeCache.h
+++ b/libpixelflinger/codeflinger/CodeCache.h
@@ -19,6 +19,7 @@
#ifndef ANDROID_CODECACHE_H
#define ANDROID_CODECACHE_H
+#include <atomic>
#include <stdint.h>
#include <pthread.h>
#include <sys/types.h>
@@ -69,7 +70,7 @@
typedef void weakref_type;
private:
- mutable int32_t mCount;
+ mutable std::atomic<int32_t> mCount;
uint32_t* mBase;
size_t mSize;
};
diff --git a/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp b/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp
index 5f58797..63642c4 100644
--- a/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp
+++ b/libpixelflinger/tests/arch-arm64/assembler/arm64_assembler_test.cpp
@@ -34,7 +34,6 @@
#include <sys/mman.h>
#include <cutils/ashmem.h>
-#include <cutils/atomic.h>
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
diff --git a/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp b/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp
index b680b60..e8c4626 100644
--- a/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp
+++ b/libpixelflinger/tests/arch-mips64/assembler/mips64_assembler_test.cpp
@@ -34,7 +34,6 @@
#include <sys/mman.h>
#include <cutils/ashmem.h>
-#include <cutils/atomic.h>
#include <cutils/log.h>
#define __STDC_FORMAT_MACROS