diff options
57 files changed, 874 insertions, 723 deletions
diff --git a/adb/Android.mk b/adb/Android.mk index 819bad10b..efdff5d34 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -8,14 +8,12 @@ LOCAL_PATH:= $(call my-dir) adb_host_sanitize := adb_target_sanitize := -adb_version := $(shell git -C $(LOCAL_PATH) rev-parse --short=12 HEAD 2>/dev/null)-android - ADB_COMMON_CFLAGS := \ -Wall -Wextra -Werror \ -Wno-unused-parameter \ -Wno-missing-field-initializers \ -Wvla \ - -DADB_REVISION='"$(adb_version)"' \ + -DADB_REVISION=\"$(BUILD_NUMBER_FROM_FILE)\" \ ADB_COMMON_posix_CFLAGS := \ -Wexit-time-destructors \ diff --git a/adb/adb.cpp b/adb/adb.cpp index 39e71e5f3..0181daa60 100644 --- a/adb/adb.cpp +++ b/adb/adb.cpp @@ -31,6 +31,8 @@ #include <time.h> #include <chrono> +#include <condition_variable> +#include <mutex> #include <string> #include <thread> #include <vector> @@ -48,6 +50,7 @@ #include "adb_io.h" #include "adb_listeners.h" #include "adb_utils.h" +#include "sysdeps/chrono.h" #include "transport.h" #if !ADB_HOST @@ -313,19 +316,15 @@ void parse_banner(const std::string& banner, atransport* t) { if (type == "bootloader") { D("setting connection_state to kCsBootloader"); t->SetConnectionState(kCsBootloader); - update_transports(); } else if (type == "device") { D("setting connection_state to kCsDevice"); t->SetConnectionState(kCsDevice); - update_transports(); } else if (type == "recovery") { D("setting connection_state to kCsRecovery"); t->SetConnectionState(kCsRecovery); - update_transports(); } else if (type == "sideload") { D("setting connection_state to kCsSideload"); t->SetConnectionState(kCsSideload); - update_transports(); } else { D("setting connection_state to kCsHost"); t->SetConnectionState(kCsHost); @@ -353,6 +352,8 @@ static void handle_new_connection(atransport* t, apacket* p) { send_auth_request(t); } #endif + + update_transports(); } void handle_packet(apacket *p, atransport *t) @@ -1229,4 +1230,50 @@ int handle_host_request(const char* service, TransportType type, return ret - 1; return -1; } + +static auto& init_mutex = *new std::mutex(); +static auto& init_cv = *new std::condition_variable(); +static bool device_scan_complete = false; +static bool transports_ready = false; + +void update_transport_status() { + bool result = iterate_transports([](const atransport* t) { + if (t->type == kTransportUsb && t->online != 1) { + return false; + } + return true; + }); + + D("update_transport_status: transports_ready = %s", result ? "true" : "false"); + + bool ready; + + { + std::lock_guard<std::mutex> lock(init_mutex); + transports_ready = result; + ready = transports_ready && device_scan_complete; + } + + if (ready) { + D("update_transport_status: notifying"); + init_cv.notify_all(); + } +} + +void adb_notify_device_scan_complete() { + D("device scan complete"); + + { + std::lock_guard<std::mutex> lock(init_mutex); + device_scan_complete = true; + } + + update_transport_status(); +} + +void adb_wait_for_device_initialization() { + std::unique_lock<std::mutex> lock(init_mutex); + init_cv.wait_for(lock, 3s, []() { return device_scan_complete && transports_ready; }); +} + #endif // ADB_HOST @@ -228,4 +228,18 @@ void SendConnectOnHost(atransport* t); void parse_banner(const std::string&, atransport* t); +// On startup, the adb server needs to wait until all of the connected devices are ready. +// To do this, we need to know when the scan has identified all of the potential new transports, and +// when each transport becomes ready. +// TODO: Do this for mDNS as well, instead of just USB? + +// We've found all of the transports we potentially care about. +void adb_notify_device_scan_complete(); + +// One or more transports have changed status, check to see if we're ready. +void update_transport_status(); + +// Wait until device scan has completed and every transport is ready, or a timeout elapses. +void adb_wait_for_device_initialization(); + #endif diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp index b6568875c..4f3ff25df 100644 --- a/adb/adb_client.cpp +++ b/adb/adb_client.cpp @@ -28,12 +28,15 @@ #include <sys/stat.h> #include <sys/types.h> +#include <condition_variable> +#include <mutex> #include <string> #include <thread> #include <vector> #include <android-base/stringprintf.h> #include <android-base/strings.h> +#include <android-base/thread_annotations.h> #include <cutils/sockets.h> #include "adb_io.h" @@ -177,9 +180,8 @@ int adb_connect(const std::string& service, std::string* error) { } else { fprintf(stderr, "* daemon started successfully\n"); } - // Give the server some time to start properly and detect devices. - std::this_thread::sleep_for(3s); - // fall through to _adb_connect + // The server will wait until it detects all of its connected devices before acking. + // Fall through to _adb_connect. } else { // If a server is already running, check its version matches. int version = ADB_SERVER_VERSION - 1; diff --git a/adb/client/main.cpp b/adb/client/main.cpp index 606203cb4..fe5099c35 100644 --- a/adb/client/main.cpp +++ b/adb/client/main.cpp @@ -156,33 +156,38 @@ int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply } #endif - // Inform our parent that we are up and running. - - // Any error output written to stderr now goes to adb.log. We could - // keep around a copy of the stderr fd and use that to write any errors - // encountered by the following code, but that is probably overkill. + // Wait for the USB scan to complete before notifying the parent that we're up. + // We need to perform this in a thread, because we would otherwise block the event loop. + std::thread notify_thread([ack_reply_fd]() { + adb_wait_for_device_initialization(); + + // Any error output written to stderr now goes to adb.log. We could + // keep around a copy of the stderr fd and use that to write any errors + // encountered by the following code, but that is probably overkill. #if defined(_WIN32) - const HANDLE ack_reply_handle = cast_int_to_handle(ack_reply_fd); - const CHAR ack[] = "OK\n"; - const DWORD bytes_to_write = arraysize(ack) - 1; - DWORD written = 0; - if (!WriteFile(ack_reply_handle, ack, bytes_to_write, &written, NULL)) { - fatal("adb: cannot write ACK to handle 0x%p: %s", ack_reply_handle, - android::base::SystemErrorCodeToString(GetLastError()).c_str()); - } - if (written != bytes_to_write) { - fatal("adb: cannot write %lu bytes of ACK: only wrote %lu bytes", - bytes_to_write, written); - } - CloseHandle(ack_reply_handle); + const HANDLE ack_reply_handle = cast_int_to_handle(ack_reply_fd); + const CHAR ack[] = "OK\n"; + const DWORD bytes_to_write = arraysize(ack) - 1; + DWORD written = 0; + if (!WriteFile(ack_reply_handle, ack, bytes_to_write, &written, NULL)) { + fatal("adb: cannot write ACK to handle 0x%p: %s", ack_reply_handle, + android::base::SystemErrorCodeToString(GetLastError()).c_str()); + } + if (written != bytes_to_write) { + fatal("adb: cannot write %lu bytes of ACK: only wrote %lu bytes", bytes_to_write, + written); + } + CloseHandle(ack_reply_handle); #else - // TODO(danalbert): Can't use SendOkay because we're sending "OK\n", not - // "OKAY". - if (!android::base::WriteStringToFd("OK\n", ack_reply_fd)) { - fatal_errno("error writing ACK to fd %d", ack_reply_fd); - } - unix_close(ack_reply_fd); + // TODO(danalbert): Can't use SendOkay because we're sending "OK\n", not + // "OKAY". + if (!android::base::WriteStringToFd("OK\n", ack_reply_fd)) { + fatal_errno("error writing ACK to fd %d", ack_reply_fd); + } + unix_close(ack_reply_fd); #endif + }); + notify_thread.detach(); } D("Event loop starting"); diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp index d39884ac7..7539e5a9f 100644 --- a/adb/client/usb_libusb.cpp +++ b/adb/client/usb_libusb.cpp @@ -159,6 +159,22 @@ static std::string get_device_address(libusb_device* device) { libusb_get_device_address(device)); } +#if defined(__linux__) +static std::string get_device_serial_path(libusb_device* device) { + uint8_t ports[7]; + int port_count = libusb_get_port_numbers(device, ports, 7); + if (port_count < 0) return ""; + + std::string path = + StringPrintf("/sys/bus/usb/devices/%d-%d", libusb_get_bus_number(device), ports[0]); + for (int port = 1; port < port_count; ++port) { + path += StringPrintf(".%d", ports[port]); + } + path += "/serial"; + return path; +} +#endif + static bool endpoint_is_output(uint8_t endpoint) { return (endpoint & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT; } @@ -291,49 +307,67 @@ static void poll_for_devices() { } } - libusb_device_handle* handle_raw; + bool writable = true; + libusb_device_handle* handle_raw = nullptr; rc = libusb_open(device, &handle_raw); - if (rc != 0) { - LOG(WARNING) << "failed to open usb device at " << device_address << ": " - << libusb_error_name(rc); - continue; - } - unique_device_handle handle(handle_raw); - LOG(DEBUG) << "successfully opened adb device at " << device_address << ", " - << StringPrintf("bulk_in = %#x, bulk_out = %#x", bulk_in, bulk_out); - - device_serial.resize(255); - rc = libusb_get_string_descriptor_ascii( - handle_raw, device_desc.iSerialNumber, - reinterpret_cast<unsigned char*>(&device_serial[0]), device_serial.length()); if (rc == 0) { - LOG(WARNING) << "received empty serial from device at " << device_address; - continue; - } else if (rc < 0) { - LOG(WARNING) << "failed to get serial from device at " << device_address - << libusb_error_name(rc); - continue; - } - device_serial.resize(rc); - - // WARNING: this isn't released via RAII. - rc = libusb_claim_interface(handle.get(), interface_num); - if (rc != 0) { - LOG(WARNING) << "failed to claim adb interface for device '" << device_serial << "'" - << libusb_error_name(rc); - continue; - } + LOG(DEBUG) << "successfully opened adb device at " << device_address << ", " + << StringPrintf("bulk_in = %#x, bulk_out = %#x", bulk_in, bulk_out); + + device_serial.resize(255); + rc = libusb_get_string_descriptor_ascii( + handle_raw, device_desc.iSerialNumber, + reinterpret_cast<unsigned char*>(&device_serial[0]), device_serial.length()); + if (rc == 0) { + LOG(WARNING) << "received empty serial from device at " << device_address; + continue; + } else if (rc < 0) { + LOG(WARNING) << "failed to get serial from device at " << device_address + << libusb_error_name(rc); + continue; + } + device_serial.resize(rc); - for (uint8_t endpoint : {bulk_in, bulk_out}) { - rc = libusb_clear_halt(handle.get(), endpoint); + // WARNING: this isn't released via RAII. + rc = libusb_claim_interface(handle.get(), interface_num); if (rc != 0) { - LOG(WARNING) << "failed to clear halt on device '" << device_serial - << "' endpoint 0x" << std::hex << endpoint << ": " - << libusb_error_name(rc); - libusb_release_interface(handle.get(), interface_num); + LOG(WARNING) << "failed to claim adb interface for device '" << device_serial + << "'" << libusb_error_name(rc); continue; } + + for (uint8_t endpoint : {bulk_in, bulk_out}) { + rc = libusb_clear_halt(handle.get(), endpoint); + if (rc != 0) { + LOG(WARNING) << "failed to clear halt on device '" << device_serial + << "' endpoint 0x" << std::hex << endpoint << ": " + << libusb_error_name(rc); + libusb_release_interface(handle.get(), interface_num); + continue; + } + } + } else { + LOG(WARNING) << "failed to open usb device at " << device_address << ": " + << libusb_error_name(rc); + writable = false; + +#if defined(__linux__) + // libusb doesn't think we should be messing around with devices we don't have + // write access to, but Linux at least lets us get the serial number anyway. + if (!android::base::ReadFileToString(get_device_serial_path(device), + &device_serial)) { + // We don't actually want to treat an unknown serial as an error because + // devices aren't able to communicate a serial number in early bringup. + // http://b/20883914 + device_serial = "unknown"; + } + device_serial = android::base::Trim(device_serial); +#else + // On Mac OS and Windows, we're screwed. But I don't think this situation actually + // happens on those OSes. + continue; +#endif } auto result = std::make_unique<usb_handle>(device_address, device_serial, @@ -346,12 +380,15 @@ static void poll_for_devices() { usb_handles[device_address] = std::move(result); } - register_usb_transport(usb_handle_raw, device_serial.c_str(), device_address.c_str(), 1); + register_usb_transport(usb_handle_raw, device_serial.c_str(), device_address.c_str(), + writable); LOG(INFO) << "registered new usb device '" << device_serial << "'"; } libusb_free_device_list(list, 1); + adb_notify_device_scan_complete(); + std::this_thread::sleep_for(500ms); } } diff --git a/adb/client/usb_osx.cpp b/adb/client/usb_osx.cpp index e4a543bba..e36675493 100644 --- a/adb/client/usb_osx.cpp +++ b/adb/client/usb_osx.cpp @@ -38,6 +38,7 @@ #include <android-base/logging.h> #include <android-base/stringprintf.h> +#include <android-base/thread_annotations.h> #include "adb.h" #include "transport.h" @@ -429,7 +430,7 @@ static void RunLoopThread() { VLOG(USB) << "RunLoopThread done"; } -static void usb_cleanup() { +static void usb_cleanup() NO_THREAD_SAFETY_ANALYSIS { VLOG(USB) << "usb_cleanup"; // Wait until usb operations in RunLoopThread finish, and prevent further operations. operate_device_lock.lock(); diff --git a/adb/diagnose_usb.cpp b/adb/diagnose_usb.cpp index 0f067b0ec..9f721bf5f 100644 --- a/adb/diagnose_usb.cpp +++ b/adb/diagnose_usb.cpp @@ -25,13 +25,14 @@ #if defined(__linux__) #include <grp.h> +#include <pwd.h> #endif static const char kPermissionsHelpUrl[] = "http://developer.android.com/tools/device.html"; -// Returns a message describing any potential problems we find with udev, or nullptr if we can't -// find plugdev information (i.e. udev is not installed). -static const char* GetUdevProblem() { +// Returns a message describing any potential problems we find with udev, or an empty string if we +// can't find plugdev information (i.e. udev is not installed). +static std::string GetUdevProblem() { #if defined(__linux__) errno = 0; group* plugdev_group = getgrnam("plugdev"); @@ -41,43 +42,45 @@ static const char* GetUdevProblem() { perror("failed to read plugdev group info"); } // We can't give any generally useful advice here, just let the caller print the help URL. - return nullptr; + return ""; } - // getgroups(2) indicates that the group_member() may not check the egid so we check it + // getgroups(2) indicates that the GNU group_member(3) may not check the egid so we check it // additionally just to be sure. if (group_member(plugdev_group->gr_gid) || getegid() == plugdev_group->gr_gid) { // The user is in plugdev so the problem is likely with the udev rules. - return "verify udev rules"; + return "user in plugdev group; are your udev rules wrong?"; } - return "udev requires plugdev group membership"; + passwd* pwd = getpwuid(getuid()); + return android::base::StringPrintf("user %s is not in the plugdev group", + pwd ? pwd->pw_name : "?"); #else - return nullptr; + return ""; #endif } // Short help text must be a single line, and will look something like: -// no permissions (reason); see <URL> +// +// no permissions (reason); see [URL] std::string UsbNoPermissionsShortHelpText() { std::string help_text = "no permissions"; - const char* problem = GetUdevProblem(); - if (problem != nullptr) { - help_text += android::base::StringPrintf(" (%s)", problem); - } + std::string problem(GetUdevProblem()); + if (!problem.empty()) help_text += " (" + problem + ")"; return android::base::StringPrintf("%s; see [%s]", help_text.c_str(), kPermissionsHelpUrl); } -// Long help text can span multiple lines and should provide more detailed information. +// Long help text can span multiple lines but doesn't currently provide more detailed information: +// +// insufficient permissions for device: reason +// See [URL] for more information std::string UsbNoPermissionsLongHelpText() { std::string header = "insufficient permissions for device"; - const char* problem = GetUdevProblem(); - if (problem != nullptr) { - header += android::base::StringPrintf(": %s", problem); - } + std::string problem(GetUdevProblem()); + if (!problem.empty()) header += ": " + problem; - return android::base::StringPrintf("%s.\nSee [%s] for more information.", - header.c_str(), kPermissionsHelpUrl); + return android::base::StringPrintf("%s\nSee [%s] for more information", header.c_str(), + kPermissionsHelpUrl); } diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp index 72c9eef42..b28de4b52 100644 --- a/adb/fdevent.cpp +++ b/adb/fdevent.cpp @@ -26,15 +26,19 @@ #include <unistd.h> #include <atomic> +#include <functional> #include <list> +#include <mutex> #include <unordered_map> #include <vector> #include <android-base/logging.h> #include <android-base/stringprintf.h> +#include <android-base/thread_annotations.h> #include "adb_io.h" #include "adb_trace.h" +#include "adb_unique_fd.h" #include "adb_utils.h" #if !ADB_HOST @@ -75,6 +79,10 @@ static std::atomic<bool> terminate_loop(false); static bool main_thread_valid; static unsigned long main_thread_id; +static auto& run_queue_notify_fd = *new unique_fd(); +static auto& run_queue_mutex = *new std::mutex(); +static auto& run_queue GUARDED_BY(run_queue_mutex) = *new std::vector<std::function<void()>>(); + void check_main_thread() { if (main_thread_valid) { CHECK_EQ(main_thread_id, adb_thread_id()); @@ -112,8 +120,7 @@ static std::string dump_fde(const fdevent* fde) { return android::base::StringPrintf("(fdevent %d %s)", fde->fd, state.c_str()); } -fdevent *fdevent_create(int fd, fd_func func, void *arg) -{ +fdevent* fdevent_create(int fd, fd_func func, void* arg) { check_main_thread(); fdevent *fde = (fdevent*) malloc(sizeof(fdevent)); if(fde == 0) return 0; @@ -122,8 +129,7 @@ fdevent *fdevent_create(int fd, fd_func func, void *arg) return fde; } -void fdevent_destroy(fdevent *fde) -{ +void fdevent_destroy(fdevent* fde) { check_main_thread(); if(fde == 0) return; if(!(fde->state & FDE_CREATED)) { @@ -278,8 +284,7 @@ static void fdevent_process() { } } -static void fdevent_call_fdfunc(fdevent* fde) -{ +static void fdevent_call_fdfunc(fdevent* fde) { unsigned events = fde->events; fde->events = 0; CHECK(fde->state & FDE_PENDING); @@ -292,10 +297,7 @@ static void fdevent_call_fdfunc(fdevent* fde) #include <sys/ioctl.h> -static void fdevent_subproc_event_func(int fd, unsigned ev, - void* /* userdata */) -{ - +static void fdevent_subproc_event_func(int fd, unsigned ev, void* /* userdata */) { D("subproc handling on fd = %d, ev = %x", fd, ev); CHECK_GE(fd, 0); @@ -342,8 +344,7 @@ static void fdevent_subproc_event_func(int fd, unsigned ev, } } -void fdevent_subproc_setup() -{ +static void fdevent_subproc_setup() { int s[2]; if(adb_socketpair(s)) { @@ -358,12 +359,63 @@ void fdevent_subproc_setup() } #endif // !ADB_HOST -void fdevent_loop() -{ +static void fdevent_run_flush() REQUIRES(run_queue_mutex) { + for (auto& f : run_queue) { + f(); + } + run_queue.clear(); +} + +static void fdevent_run_func(int fd, unsigned ev, void* /* userdata */) { + CHECK_GE(fd, 0); + CHECK(ev & FDE_READ); + + char buf[1024]; + + // Empty the fd. + if (adb_read(fd, buf, sizeof(buf)) == -1) { + PLOG(FATAL) << "failed to empty run queue notify fd"; + } + + std::lock_guard<std::mutex> lock(run_queue_mutex); + fdevent_run_flush(); +} + +static void fdevent_run_setup() { + std::lock_guard<std::mutex> lock(run_queue_mutex); + CHECK(run_queue_notify_fd.get() == -1); + int s[2]; + if (adb_socketpair(s) != 0) { + PLOG(FATAL) << "failed to create run queue notify socketpair"; + } + + run_queue_notify_fd.reset(s[0]); + fdevent* fde = fdevent_create(s[1], fdevent_run_func, nullptr); + CHECK(fde != nullptr); + fdevent_add(fde, FDE_READ); + + fdevent_run_flush(); +} + +void fdevent_run_on_main_thread(std::function<void()> fn) { + std::lock_guard<std::mutex> lock(run_queue_mutex); + run_queue.push_back(std::move(fn)); + + // run_queue_notify_fd could still be -1 if we're called before fdevent has finished setting up. + // In that case, rely on the setup code to flush the queue without a notification being needed. + if (run_queue_notify_fd != -1) { + if (adb_write(run_queue_notify_fd.get(), "", 1) != 1) { + PLOG(FATAL) << "failed to write to run queue notify fd"; + } + } +} + +void fdevent_loop() { set_main_thread(); #if !ADB_HOST fdevent_subproc_setup(); #endif // !ADB_HOST + fdevent_run_setup(); while (true) { if (terminate_loop) { @@ -393,6 +445,11 @@ size_t fdevent_installed_count() { void fdevent_reset() { g_poll_node_map.clear(); g_pending_list.clear(); + + std::lock_guard<std::mutex> lock(run_queue_mutex); + run_queue_notify_fd.reset(); + run_queue.clear(); + main_thread_valid = false; terminate_loop = false; } diff --git a/adb/fdevent.h b/adb/fdevent.h index e32845afc..896400ad5 100644 --- a/adb/fdevent.h +++ b/adb/fdevent.h @@ -20,6 +20,8 @@ #include <stddef.h> #include <stdint.h> /* for int64_t */ +#include <functional> + /* events that may be observed */ #define FDE_READ 0x0001 #define FDE_WRITE 0x0002 @@ -78,6 +80,9 @@ void fdevent_loop(); void check_main_thread(); +// Queue an operation to run on the main thread. +void fdevent_run_on_main_thread(std::function<void()> fn); + // The following functions are used only for tests. void fdevent_terminate_loop(); size_t fdevent_installed_count(); diff --git a/adb/fdevent_test.cpp b/adb/fdevent_test.cpp index bdb973a01..86e020957 100644 --- a/adb/fdevent_test.cpp +++ b/adb/fdevent_test.cpp @@ -173,3 +173,24 @@ TEST_F(FdeventTest, invalid_fd) { std::thread thread(InvalidFdThreadFunc); thread.join(); } + +TEST_F(FdeventTest, run_on_main_thread) { + std::vector<int> vec; + + PrepareThread(); + std::thread thread(fdevent_loop); + + for (int i = 0; i < 100; ++i) { + fdevent_run_on_main_thread([i, &vec]() { + check_main_thread(); + vec.push_back(i); + }); + } + + TerminateThread(thread); + + ASSERT_EQ(100u, vec.size()); + for (int i = 0; i < 100; ++i) { + ASSERT_EQ(i, vec[i]); + } +} diff --git a/adb/fdevent_test.h b/adb/fdevent_test.h index f4215ae19..5ca49ac08 100644 --- a/adb/fdevent_test.h +++ b/adb/fdevent_test.h @@ -53,11 +53,11 @@ class FdeventTest : public ::testing::Test { size_t GetAdditionalLocalSocketCount() { #if ADB_HOST - // dummy socket installed in PrepareThread() - return 1; -#else - // dummy socket and one more socket installed in fdevent_subproc_setup() + // dummy socket installed in PrepareThread() + fdevent_run_on_main_thread socket return 2; +#else + // dummy socket + fdevent_run_on_main_thread + fdevent_subproc_setup() sockets + return 3; #endif } diff --git a/adb/transport.cpp b/adb/transport.cpp index cc8c16252..20de6421e 100644 --- a/adb/transport.cpp +++ b/adb/transport.cpp @@ -400,8 +400,27 @@ asocket* create_device_tracker(void) { return &tracker->socket; } +// Check if all of the USB transports are connected. +bool iterate_transports(std::function<bool(const atransport*)> fn) { + std::lock_guard<std::mutex> lock(transport_lock); + for (const auto& t : transport_list) { + if (!fn(t)) { + return false; + } + } + for (const auto& t : pending_list) { + if (!fn(t)) { + return false; + } + } + return true; +} + // Call this function each time the transport list has changed. void update_transports() { + update_transport_status(); + + // Notify `adb track-devices` clients. std::string transports = list_transports(false); device_tracker* tracker = device_tracker_list; diff --git a/adb/transport.h b/adb/transport.h index 8c15d663d..e129355ba 100644 --- a/adb/transport.h +++ b/adb/transport.h @@ -198,6 +198,10 @@ atransport* acquire_one_transport(TransportType type, const char* serial, bool* void kick_transport(atransport* t); void update_transports(void); +// Iterates across all of the current and pending transports. +// Stops iteration and returns false if fn returns false, otherwise returns true. +bool iterate_transports(std::function<bool(const atransport*)> fn); + void init_transport_registration(void); void init_mdns_transport_discovery(void); std::string list_transports(bool long_listing); diff --git a/adb/transport_mdns.cpp b/adb/transport_mdns.cpp index e49b1c668..3603f0974 100644 --- a/adb/transport_mdns.cpp +++ b/adb/transport_mdns.cpp @@ -24,6 +24,8 @@ #include <arpa/inet.h> #endif +#include <thread> + #include <android-base/stringprintf.h> #include <dns_sd.h> @@ -262,19 +264,22 @@ static void DNSSD_API register_mdns_transport(DNSServiceRef sdRef, } } -void init_mdns_transport_discovery(void) { - DNSServiceErrorType errorCode = - DNSServiceBrowse(&service_ref, 0, 0, kADBServiceType, nullptr, - register_mdns_transport, nullptr); +void init_mdns_transport_discovery_thread(void) { + DNSServiceErrorType errorCode = DNSServiceBrowse(&service_ref, 0, 0, kADBServiceType, nullptr, + register_mdns_transport, nullptr); if (errorCode != kDNSServiceErr_NoError) { D("Got %d initiating mDNS browse.", errorCode); return; } - fdevent_install(&service_ref_fde, - adb_DNSServiceRefSockFD(service_ref), - pump_service_ref, - &service_ref); - fdevent_set(&service_ref_fde, FDE_READ); + fdevent_run_on_main_thread([]() { + fdevent_install(&service_ref_fde, adb_DNSServiceRefSockFD(service_ref), pump_service_ref, + &service_ref); + fdevent_set(&service_ref_fde, FDE_READ); + }); +} + +void init_mdns_transport_discovery(void) { + std::thread(init_mdns_transport_discovery_thread).detach(); } diff --git a/fastboot/Android.mk b/fastboot/Android.mk index 2c578a90e..e675d7d60 100644 --- a/fastboot/Android.mk +++ b/fastboot/Android.mk @@ -14,8 +14,6 @@ LOCAL_PATH:= $(call my-dir) -fastboot_version := $(shell git -C $(LOCAL_PATH) rev-parse --short=12 HEAD 2>/dev/null)-android - include $(CLEAR_VARS) LOCAL_C_INCLUDES := \ @@ -39,7 +37,7 @@ LOCAL_MODULE_TAGS := debug LOCAL_MODULE_HOST_OS := darwin linux windows LOCAL_CFLAGS += -Wall -Wextra -Werror -Wunreachable-code -LOCAL_CFLAGS += -DFASTBOOT_REVISION='"$(fastboot_version)"' +LOCAL_CFLAGS += -DFASTBOOT_REVISION=\"$(BUILD_NUMBER_FROM_FILE)\" LOCAL_SRC_FILES_linux := usb_linux.cpp LOCAL_STATIC_LIBRARIES_linux := libselinux diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index e438801ba..5d5ac9b80 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -75,7 +75,6 @@ using android::base::unique_fd; char cur_product[FB_RESPONSE_SZ + 1]; static const char* serial = nullptr; -static const char* product = nullptr; static const char* cmdline = nullptr; static unsigned short vendor_id = 0; static int long_listing = 0; @@ -108,66 +107,46 @@ struct fastboot_buffer { }; static struct { - char img_name[17]; - char sig_name[17]; - char part_name[9]; + const char* nickname; + const char* img_name; + const char* sig_name; + const char* part_name; bool is_optional; bool is_secondary; } images[] = { - {"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}, - {"vbmeta.img", "vbmeta.sig", "vbmeta", true, false}, - {"dtbo.img", "dtbo.sig", "dtbo", true, false}, + // clang-format off + { "boot", "boot.img", "boot.sig", "boot", false, false }, + { nullptr, "boot_other.img", "boot.sig", "boot", true, true }, + { "dtbo", "dtbo.img", "dtbo.sig", "dtbo", true, false }, + { "recovery", "recovery.img", "recovery.sig", "recovery", true, false }, + { "system", "system.img", "system.sig", "system", false, false }, + { nullptr, "system_other.img", "system.sig", "system", true, true }, + { "vbmeta", "vbmeta.img", "vbmeta.sig", "vbmeta", true, false }, + { "vendor", "vendor.img", "vendor.sig", "vendor", true, false }, + { nullptr, "vendor_other.img", "vendor.sig", "vendor", true, true }, + // clang-format on }; -static std::string find_item_given_name(const char* img_name, const char* product) { - if(product) { - std::string path = android::base::GetExecutablePath(); - 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"); +static std::string find_item_given_name(const char* img_name) { + char* dir = getenv("ANDROID_PRODUCT_OUT"); if (dir == nullptr || dir[0] == '\0') { - die("neither -p product specified nor ANDROID_PRODUCT_OUT set"); + die("ANDROID_PRODUCT_OUT not 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")) { - fn = "recovery.img"; - } else if(!strcmp(item,"system")) { - fn = "system.img"; - } else if(!strcmp(item,"vendor")) { - fn = "vendor.img"; - } else if(!strcmp(item,"vbmeta")) { - fn = "vbmeta.img"; - } else if(!strcmp(item,"dtbo")) { - fn = "dtbo.img"; - } else if(!strcmp(item,"userdata")) { - fn = "userdata.img"; - } else if(!strcmp(item,"cache")) { - fn = "cache.img"; - } else if(!strcmp(item,"info")) { - fn = "android-info.txt"; - } else { - fprintf(stderr,"unknown partition '%s'\n", item); - return ""; +std::string find_item(const char* item) { + for (size_t i = 0; i < arraysize(images); ++i) { + if (images[i].nickname && !strcmp(images[i].nickname, item)) { + return find_item_given_name(images[i].img_name); + } } - return find_item_given_name(fn, product); + if (!strcmp(item, "userdata")) return find_item_given_name("userdata.img"); + if (!strcmp(item, "cache")) return find_item_given_name("cache.img"); + + fprintf(stderr, "unknown partition '%s'\n", item); + return ""; } static int64_t get_file_size(int fd) { @@ -391,7 +370,6 @@ static void usage() { " For ethernet, provide an address in the\n" " form <protocol>:<hostname>[:port] where\n" " <protocol> is either tcp or udp.\n" - " -p <product> Specify product name.\n" " -c <cmdline> Override kernel commandline.\n" " -i <vendor id> Specify a custom USB vendor id.\n" " -b, --base <base_addr> Specify a custom kernel base\n" @@ -627,7 +605,7 @@ static void delete_fbemarker_tmpdir(const std::string& dir) { } } -static int unzip_to_file(ZipArchiveHandle zip, char* entry_name) { +static int unzip_to_file(ZipArchiveHandle zip, const char* entry_name) { unique_fd fd(make_temporary_fd()); if (fd == -1) { fprintf(stderr, "failed to create temporary file for '%s': %s\n", @@ -1081,9 +1059,9 @@ static void do_flash(Transport* transport, const char* pname, const char* fname) flash_buf(pname, &buf); } -static void do_update_signature(ZipArchiveHandle zip, char* fn) { +static void do_update_signature(ZipArchiveHandle zip, const char* filename) { int64_t sz; - void* data = unzip_file(zip, fn, &sz); + void* data = unzip_file(zip, filename, &sz); if (data == nullptr) return; fb_queue_download("signature", data, sz); fb_queue_command("signature", "installing signature"); @@ -1210,7 +1188,7 @@ static void do_flashall(Transport* transport, const std::string& slot_override, fb_queue_query_save("product", cur_product, sizeof(cur_product)); - fname = find_item("info", product); + fname = find_item_given_name("android-info.txt"); if (fname.empty()) die("cannot find android-info.txt"); int64_t sz; @@ -1242,7 +1220,7 @@ static void do_flashall(Transport* transport, const std::string& slot_override, slot = slot_override.c_str(); } if (!slot) continue; - fname = find_item_given_name(images[i].img_name, product); + fname = find_item_given_name(images[i].img_name); fastboot_buffer buf; if (!load_buf(transport, fname.c_str(), &buf)) { if (images[i].is_optional) continue; @@ -1509,7 +1487,7 @@ int main(int argc, char **argv) serial = getenv("ANDROID_SERIAL"); while (1) { - int c = getopt_long(argc, argv, "wub:k:n:r:t:s:S:lp:c:i:m:ha::", longopts, &longindex); + int c = getopt_long(argc, argv, "wub:k:n:r:t:s:S:lc:i:m:ha::", longopts, &longindex); if (c < 0) { break; } @@ -1549,9 +1527,6 @@ int main(int argc, char **argv) page_size = (unsigned)strtoul(optarg, nullptr, 0); if (!page_size) die("invalid page size"); break; - case 'p': - product = optarg; - break; case 'r': ramdisk_offset = strtoul(optarg, 0, 16); break; @@ -1764,7 +1739,7 @@ int main(int argc, char **argv) fname = argv[2]; skip(3); } else { - fname = find_item(pname, product); + fname = find_item(pname); skip(2); } if (fname.empty()) die("cannot determine image filename for '%s'", pname); diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 6e9069e5d..60ce43eba 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -1046,8 +1046,7 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, } int fs_stat = 0; - int force_check = do_quota_with_shutdown_check(fstab->recs[i].blk_device, - fstab->recs[i].fs_type, + int force_check = do_quota_with_shutdown_check(n_blk_device, fstab->recs[i].fs_type, &fstab->recs[i], &fs_stat); if ((fstab->recs[i].fs_mgr_flags & MF_CHECK) || force_check) { diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp index 94cea5790..31babfec2 100644 --- a/fs_mgr/fs_mgr_avb.cpp +++ b/fs_mgr/fs_mgr_avb.cpp @@ -483,44 +483,55 @@ FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const std::string& device_file_by // Only allow two verify results: // - AVB_SLOT_VERIFY_RESULT_OK. // - AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION (for UNLOCKED state). - if (verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION) { - if (!avb_verifier->IsDeviceUnlocked()) { - LERROR << "ERROR_VERIFICATION isn't allowed"; + // If the device is UNLOCKED, i.e., |allow_verification_error| is true for + // AvbSlotVerify(), then the following return values are all non-fatal: + // * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION + // * AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED + // * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX + // The latter two results were checked by bootloader prior to start fs_mgr so + // we just need to handle the first result here. See *dummy* operations in + // FsManagerAvbOps and the comments in external/avb/libavb/avb_slot_verify.h + // for more details. + switch (verify_result) { + case AVB_SLOT_VERIFY_RESULT_OK: + avb_handle->status_ = kFsManagerAvbHandleSuccess; + break; + case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION: + if (!avb_verifier->IsDeviceUnlocked()) { + LERROR << "ERROR_VERIFICATION isn't allowed when the device is LOCKED"; + return nullptr; + } + avb_handle->status_ = kFsManagerAvbHandleErrorVerification; + break; + default: + LERROR << "avb_slot_verify failed, result: " << verify_result; return nullptr; - } - } else if (verify_result != AVB_SLOT_VERIFY_RESULT_OK) { - LERROR << "avb_slot_verify failed, result: " << verify_result; - return nullptr; } - // Sets the MAJOR.MINOR for init to set it into "ro.boot.avb_version". - avb_handle->avb_version_ = - android::base::StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR); - // Verifies vbmeta images against the digest passed from bootloader. if (!avb_verifier->VerifyVbmetaImages(*avb_handle->avb_slot_data_)) { LERROR << "VerifyVbmetaImages failed"; return nullptr; - } else { - // Checks whether FLAGS_HASHTREE_DISABLED is set. - AvbVBMetaImageHeader vbmeta_header; - avb_vbmeta_image_header_to_host_byte_order( - (AvbVBMetaImageHeader*)avb_handle->avb_slot_data_->vbmeta_images[0].vbmeta_data, - &vbmeta_header); - - bool hashtree_disabled = - ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED); - if (hashtree_disabled) { - avb_handle->status_ = kFsManagerAvbHandleHashtreeDisabled; - return avb_handle; - } } - if (verify_result == AVB_SLOT_VERIFY_RESULT_OK) { - avb_handle->status_ = kFsManagerAvbHandleSuccess; - return avb_handle; + // Sets the MAJOR.MINOR for init to set it into "ro.boot.avb_version". + avb_handle->avb_version_ = + android::base::StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR); + + // Checks whether FLAGS_HASHTREE_DISABLED is set. + AvbVBMetaImageHeader vbmeta_header; + avb_vbmeta_image_header_to_host_byte_order( + (AvbVBMetaImageHeader*)avb_handle->avb_slot_data_->vbmeta_images[0].vbmeta_data, + &vbmeta_header); + + bool hashtree_disabled = + ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED); + if (hashtree_disabled) { + avb_handle->status_ = kFsManagerAvbHandleHashtreeDisabled; } - return nullptr; + + LINFO << "Returning avb_handle with status: " << avb_handle->status_; + return avb_handle; } bool FsManagerAvbHandle::SetUpAvb(struct fstab_rec* fstab_entry, bool wait_for_verity_dev) { @@ -528,11 +539,12 @@ bool FsManagerAvbHandle::SetUpAvb(struct fstab_rec* fstab_entry, bool wait_for_v if (!avb_slot_data_ || avb_slot_data_->num_vbmeta_images < 1) { return false; } + + if (status_ == kFsManagerAvbHandleUninitialized) return false; if (status_ == kFsManagerAvbHandleHashtreeDisabled) { LINFO << "AVB HASHTREE disabled on:" << fstab_entry->mount_point; return true; } - if (status_ != kFsManagerAvbHandleSuccess) return false; std::string partition_name(basename(fstab_entry->mount_point)); if (!avb_validate_utf8((const uint8_t*)partition_name.c_str(), partition_name.length())) { diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp index 0bf173bd8..5fa10bc6e 100644 --- a/fs_mgr/fs_mgr_verity.cpp +++ b/fs_mgr/fs_mgr_verity.cpp @@ -663,7 +663,7 @@ int load_verity_state(struct fstab_rec* fstab, int* mode) { /* use the kernel parameter if set */ std::string veritymode; if (fs_mgr_get_boot_config("veritymode", &veritymode)) { - if (veritymode.compare("enforcing")) { + if (veritymode == "enforcing") { *mode = VERITY_MODE_DEFAULT; } return 0; diff --git a/fs_mgr/include/fs_mgr_avb.h b/fs_mgr/include/fs_mgr_avb.h index a66ff42cc..65ff99417 100644 --- a/fs_mgr/include/fs_mgr_avb.h +++ b/fs_mgr/include/fs_mgr_avb.h @@ -25,9 +25,10 @@ #include "fs_mgr.h" enum FsManagerAvbHandleStatus { + kFsManagerAvbHandleUninitialized = -1, kFsManagerAvbHandleSuccess = 0, kFsManagerAvbHandleHashtreeDisabled = 1, - kFsManagerAvbHandleFail = 2, + kFsManagerAvbHandleErrorVerification = 2, }; class FsManagerAvbHandle; @@ -88,7 +89,7 @@ class FsManagerAvbHandle { }; protected: - FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kFsManagerAvbHandleFail) {} + FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kFsManagerAvbHandleUninitialized) {} private: AvbSlotVerifyData* avb_slot_data_; diff --git a/init/README.md b/init/README.md index 9fc8d47f4..72b6c6bdd 100644 --- a/init/README.md +++ b/init/README.md @@ -356,9 +356,9 @@ Commands Init halts executing commands until the forked process exits. `exec_start <service>` -> Start service a given service and halt processing of additional init commands - until it returns. It functions similarly to the `exec` command, but uses an - existing service definition instead of providing them as arguments. +> Start a given service and halt the processing of additional init commands + until it returns. The command functions similarly to the `exec` command, + but uses an existing service definition in place of the exec argument vector. `export <name> <value>` > Set the environment variable _name_ equal to _value_ in the diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp index 285aa6edf..7dd9227b3 100644 --- a/libbacktrace/Android.bp +++ b/libbacktrace/Android.bp @@ -110,7 +110,7 @@ cc_library { "libunwind", ], - static_libs: ["libcutils"], + static_libs: ["libasync_safe", "libcutils"], }, }, } diff --git a/libbacktrace/BacktraceAsyncSafeLog.h b/libbacktrace/BacktraceAsyncSafeLog.h new file mode 100644 index 000000000..14f51be24 --- /dev/null +++ b/libbacktrace/BacktraceAsyncSafeLog.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2014 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. + */ + +#ifndef _LIBBACKTRACE_BACKTRACE_ASYNC_SAFE_LOG_H +#define _LIBBACKTRACE_BACKTRACE_ASYNC_SAFE_LOG_H + +#if defined(__ANDROID__) + +#include <async_safe/log.h> + +// Logging macros for use in signal handler, only available on target. +#define BACK_ASYNC_SAFE_LOGW(format, ...) \ + async_safe_format_log(ANDROID_LOG_WARN, "libbacktrace", "%s: " format, __PRETTY_FUNCTION__, \ + ##__VA_ARGS__) + +#define BACK_ASYNC_SAFE_LOGE(format, ...) \ + async_safe_format_log(ANDROID_LOG_ERROR, "libbacktrace", "%s: " format, __PRETTY_FUNCTION__, \ + ##__VA_ARGS__) + +#else + +#define BACK_ASYNC_SAFE_LOGW(format, ...) + +#define BACK_ASYNC_SAFE_LOGE(format, ...) + +#endif + +#endif // _LIBBACKTRACE_BACKTRACE_ASYNC_SAFE_LOG_H diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp index d7a3b011e..fb76b858d 100644 --- a/libbacktrace/BacktraceCurrent.cpp +++ b/libbacktrace/BacktraceCurrent.cpp @@ -31,8 +31,8 @@ #include <backtrace/Backtrace.h> #include <backtrace/BacktraceMap.h> +#include "BacktraceAsyncSafeLog.h" #include "BacktraceCurrent.h" -#include "BacktraceLog.h" #include "ThreadEntry.h" #include "thread_utils.h" @@ -47,7 +47,7 @@ bool BacktraceCurrent::ReadWord(uintptr_t ptr, word_t* out_value) { *out_value = *reinterpret_cast<word_t*>(ptr); return true; } else { - BACK_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr)); + BACK_ASYNC_SAFE_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr)); *out_value = static_cast<word_t>(-1); return false; } @@ -114,7 +114,8 @@ class ErrnoRestorer { static void SignalLogOnly(int, siginfo_t*, void*) { ErrnoRestorer restore; - BACK_LOGE("pid %d, tid %d: Received a spurious signal %d\n", getpid(), gettid(), THREAD_SIGNAL); + BACK_ASYNC_SAFE_LOGE("pid %d, tid %d: Received a spurious signal %d\n", getpid(), gettid(), + THREAD_SIGNAL); } static void SignalHandler(int, siginfo_t*, void* sigcontext) { @@ -122,7 +123,7 @@ static void SignalHandler(int, siginfo_t*, void* sigcontext) { ThreadEntry* entry = ThreadEntry::Get(getpid(), gettid(), false); if (!entry) { - BACK_LOGE("pid %d, tid %d entry not found", getpid(), gettid()); + BACK_ASYNC_SAFE_LOGE("pid %d, tid %d entry not found", getpid(), gettid()); return; } @@ -141,7 +142,7 @@ static void SignalHandler(int, siginfo_t*, void* sigcontext) { entry->Wake(); } else { // At this point, it is possible that entry has been freed, so just exit. - BACK_LOGE("Timed out waiting for unwind thread to indicate it completed."); + BACK_ASYNC_SAFE_LOGE("Timed out waiting for unwind thread to indicate it completed."); } } @@ -159,7 +160,7 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; sigemptyset(&act.sa_mask); if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) { - BACK_LOGE("sigaction failed: %s", strerror(errno)); + BACK_ASYNC_SAFE_LOGE("sigaction failed: %s", strerror(errno)); ThreadEntry::Remove(entry); pthread_mutex_unlock(&g_sigaction_mutex); error_ = BACKTRACE_UNWIND_ERROR_INTERNAL; @@ -212,7 +213,7 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { // Wait for the thread to indicate it is done with the ThreadEntry. if (!entry->Wait(3)) { // Send a warning, but do not mark as a failure to unwind. - BACK_LOGW("Timed out waiting for signal handler to indicate it finished."); + BACK_ASYNC_SAFE_LOGW("Timed out waiting for signal handler to indicate it finished."); } } else { // Check to see if the thread has disappeared. @@ -220,7 +221,7 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST; } else { error_ = BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT; - BACK_LOGE("Timed out waiting for signal handler to get ucontext data."); + BACK_ASYNC_SAFE_LOGE("Timed out waiting for signal handler to get ucontext data."); } } diff --git a/libbacktrace/ThreadEntry.cpp b/libbacktrace/ThreadEntry.cpp index 084c1aa91..9bd59e4a2 100644 --- a/libbacktrace/ThreadEntry.cpp +++ b/libbacktrace/ThreadEntry.cpp @@ -21,7 +21,7 @@ #include <time.h> #include <ucontext.h> -#include "BacktraceLog.h" +#include "BacktraceAsyncSafeLog.h" #include "ThreadEntry.h" // Initialize static member variables. @@ -106,7 +106,7 @@ bool ThreadEntry::Wait(int value) { while (wait_value_ != value) { int ret = pthread_cond_timedwait(&wait_cond_, &wait_mutex_, &ts); if (ret != 0) { - BACK_LOGW("pthread_cond_timedwait for value %d failed: %s", value, strerror(ret)); + BACK_ASYNC_SAFE_LOGW("pthread_cond_timedwait for value %d failed: %s", value, strerror(ret)); wait_completed = false; break; } diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp index a2dd67776..2b3443f3f 100644 --- a/libcutils/fs_config.cpp +++ b/libcutils/fs_config.cpp @@ -92,6 +92,9 @@ static const struct fs_path_config android_dirs[] = { { 00755, AID_ROOT, AID_ROOT, 0, 0 }, // clang-format on }; +#ifndef __ANDROID_VNDK__ +auto __for_testing_only__android_dirs = android_dirs; +#endif // Rules for files. // These rules are applied based on "first match", so they @@ -238,6 +241,9 @@ static const struct fs_path_config android_files[] = { { 00644, AID_ROOT, AID_ROOT, 0, 0 }, // clang-format on }; +#ifndef __ANDROID_VNDK__ +auto __for_testing_only__android_files = android_files; +#endif static size_t strip(const char* path, size_t len, const char suffix[]) { if (len < strlen(suffix)) return len; diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h index bbba8536e..fdead2379 100644 --- a/libcutils/include/private/android_filesystem_config.h +++ b/libcutils/include/private/android_filesystem_config.h @@ -53,7 +53,7 @@ #include <sys/cdefs.h> #include <sys/types.h> -#if defined(__ANDROID__) +#if defined(__BIONIC__) #include <linux/capability.h> #else #include "android_filesystem_capability.h" diff --git a/libcutils/tests/Android.bp b/libcutils/tests/Android.bp index a0b1d7ba3..788419038 100644 --- a/libcutils/tests/Android.bp +++ b/libcutils/tests/Android.bp @@ -27,7 +27,8 @@ cc_defaults { "test_str_parms.cpp", "android_get_control_socket_test.cpp", "android_get_control_file_test.cpp", - "multiuser_test.cpp" + "multiuser_test.cpp", + "fs_config.cpp", ], }, diff --git a/libcutils/tests/AshmemTest.cpp b/libcutils/tests/AshmemTest.cpp index 51c679f5d..a87e23e30 100644 --- a/libcutils/tests/AshmemTest.cpp +++ b/libcutils/tests/AshmemTest.cpp @@ -14,10 +14,11 @@ * limitations under the License. */ -#include <sys/mman.h> +#include <android-base/unique_fd.h> #include <cutils/ashmem.h> #include <gtest/gtest.h> -#include <android-base/unique_fd.h> +#include <linux/fs.h> +#include <sys/mman.h> using android::base::unique_fd; @@ -29,8 +30,8 @@ void TestCreateRegion(size_t size, unique_fd &fd, int prot) { ASSERT_EQ(0, ashmem_set_prot_region(fd, prot)); } -void TestMmap(const unique_fd &fd, size_t size, int prot, void **region) { - *region = mmap(nullptr, size, prot, MAP_SHARED, fd, 0); +void TestMmap(const unique_fd& fd, size_t size, int prot, void** region, off_t off = 0) { + *region = mmap(nullptr, size, prot, MAP_SHARED, fd, off); ASSERT_NE(MAP_FAILED, *region); } @@ -38,6 +39,10 @@ void TestProtDenied(const unique_fd &fd, size_t size, int prot) { EXPECT_EQ(MAP_FAILED, mmap(nullptr, size, prot, MAP_SHARED, fd, 0)); } +void TestProtIs(const unique_fd& fd, int prot) { + EXPECT_EQ(prot, ioctl(fd, ASHMEM_GET_PROT_MASK)); +} + void FillData(uint8_t* data, size_t dataLen) { for (size_t i = 0; i < dataLen; i++) { data[i] = i & 0xFF; @@ -101,6 +106,63 @@ TEST(AshmemTest, ForkTest) { EXPECT_EQ(0, munmap(region2, size)); } +TEST(AshmemTest, FileOperationsTest) { + unique_fd fd; + void* region; + + // Allocate a 4-page buffer, but leave page-sized holes on either side + constexpr size_t size = PAGE_SIZE * 4; + constexpr size_t dataSize = PAGE_SIZE * 2; + constexpr size_t holeSize = PAGE_SIZE; + ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE)); + ASSERT_NO_FATAL_FAILURE(TestMmap(fd, dataSize, PROT_READ | PROT_WRITE, ®ion, holeSize)); + + uint8_t data[dataSize]; + FillData(data, dataSize); + memcpy(region, data, dataSize); + + constexpr off_t dataStart = holeSize; + constexpr off_t dataEnd = dataStart + dataSize; + + // The sequence of seeks below looks something like this: + // + // [ ][data][data][ ] + // --^ lseek(99, SEEK_SET) + // ------^ lseek(dataStart, SEEK_CUR) + // ------^ lseek(0, SEEK_DATA) + // ------------^ lseek(dataStart, SEEK_HOLE) + // ^-- lseek(-99, SEEK_END) + // ^------ lseek(-dataStart, SEEK_CUR) + const struct { + // lseek() parameters + off_t offset; + int whence; + // Expected lseek() return value + off_t ret; + } seeks[] = { + {99, SEEK_SET, 99}, {dataStart, SEEK_CUR, dataStart + 99}, + {0, SEEK_DATA, dataStart}, {dataStart, SEEK_HOLE, dataEnd}, + {-99, SEEK_END, size - 99}, {-dataStart, SEEK_CUR, dataEnd - 99}, + }; + for (const auto& cfg : seeks) { + errno = 0; + auto off = lseek(fd, cfg.offset, cfg.whence); + ASSERT_EQ(cfg.ret, off) << "lseek(" << cfg.offset << ", " << cfg.whence << ") failed" + << (errno ? ": " : "") << (errno ? strerror(errno) : ""); + + if (off >= dataStart && off < dataEnd) { + off_t dataOff = off - dataStart; + ssize_t readSize = dataSize - dataOff; + uint8_t buf[readSize]; + + ASSERT_EQ(readSize, TEMP_FAILURE_RETRY(read(fd, buf, readSize))); + EXPECT_EQ(0, memcmp(buf, data + dataOff, readSize)); + } + } + + EXPECT_EQ(0, munmap(region, dataSize)); +} + TEST(AshmemTest, ProtTest) { unique_fd fd; constexpr size_t size = PAGE_SIZE; @@ -108,13 +170,25 @@ TEST(AshmemTest, ProtTest) { ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ)); TestProtDenied(fd, size, PROT_WRITE); + TestProtIs(fd, PROT_READ); ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ, ®ion)); EXPECT_EQ(0, munmap(region, size)); ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_WRITE)); TestProtDenied(fd, size, PROT_READ); + TestProtIs(fd, PROT_WRITE); ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_WRITE, ®ion)); EXPECT_EQ(0, munmap(region, size)); + + ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE)); + TestProtIs(fd, PROT_READ | PROT_WRITE); + ASSERT_EQ(0, ashmem_set_prot_region(fd, PROT_READ)); + errno = 0; + ASSERT_EQ(-1, ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE)) + << "kernel shouldn't allow adding protection bits"; + EXPECT_EQ(EINVAL, errno); + TestProtIs(fd, PROT_READ); + TestProtDenied(fd, size, PROT_WRITE); } TEST(AshmemTest, ForkProtTest) { diff --git a/libcutils/tests/fs_config.cpp b/libcutils/tests/fs_config.cpp new file mode 100644 index 000000000..3917a0b2e --- /dev/null +++ b/libcutils/tests/fs_config.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2017 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 <string> + +#include <gtest/gtest.h> + +#include <android-base/strings.h> + +#include <private/android_filesystem_config.h> + +extern const struct fs_path_config* __for_testing_only__android_dirs; +extern const struct fs_path_config* __for_testing_only__android_files; + +static void check_one(const struct fs_path_config* paths, const std::string& prefix, + const std::string& alternate) { + for (size_t idx = 0; paths[idx].prefix; ++idx) { + std::string path(paths[idx].prefix); + if (android::base::StartsWith(path, prefix.c_str())) { + path = alternate + path.substr(prefix.length()); + size_t second; + for (second = 0; paths[second].prefix; ++second) { + if (path == paths[second].prefix) break; + } + if (!paths[second].prefix) { + // guaranteed to fail expectations, trigger test failure with + // a message that reports the violation as an inequality. + EXPECT_STREQ((prefix + path.substr(alternate.length())).c_str(), path.c_str()); + } + } + } +} + +static void check_two(const struct fs_path_config* paths, const std::string& prefix) { + ASSERT_FALSE(paths == nullptr); + std::string alternate = "system/" + prefix; + check_one(paths, prefix, alternate); + check_one(paths, alternate, prefix); +} + +TEST(fs_config, vendor_dirs_alias) { + check_two(__for_testing_only__android_dirs, "vendor/"); +} + +TEST(fs_config, vendor_files_alias) { + check_two(__for_testing_only__android_files, "vendor/"); +} + +TEST(fs_config, oem_dirs_alias) { + check_two(__for_testing_only__android_dirs, "oem/"); +} + +TEST(fs_config, oem_files_alias) { + check_two(__for_testing_only__android_files, "oem/"); +} + +TEST(fs_config, odm_dirs_alias) { + check_two(__for_testing_only__android_dirs, "odm/"); +} + +TEST(fs_config, odm_files_alias) { + check_two(__for_testing_only__android_files, "odm/"); +} diff --git a/libmemunreachable/.clang-format b/libmemunreachable/.clang-format new file mode 120000 index 000000000..fd0645fdf --- /dev/null +++ b/libmemunreachable/.clang-format @@ -0,0 +1 @@ +../.clang-format-2
\ No newline at end of file diff --git a/libmemunreachable/Android.bp b/libmemunreachable/Android.bp index 2867f6495..cdac76bab 100644 --- a/libmemunreachable/Android.bp +++ b/libmemunreachable/Android.bp @@ -9,8 +9,16 @@ cc_defaults { clang: true, shared_libs: [ "libbase", - "liblog", ], + + target: { + android: { + static_libs: ["libasync_safe"], + }, + host: { + shared_libs: ["liblog"], + } + }, } cc_library_shared { diff --git a/libmemunreachable/HeapWalker.cpp b/libmemunreachable/HeapWalker.cpp index 62366f2ef..c365ae5b5 100644 --- a/libmemunreachable/HeapWalker.cpp +++ b/libmemunreachable/HeapWalker.cpp @@ -42,11 +42,9 @@ bool HeapWalker::Allocation(uintptr_t begin, uintptr_t end) { } else { Range overlap = inserted.first->first; if (overlap != range) { - ALOGE("range %p-%p overlaps with existing range %p-%p", - reinterpret_cast<void*>(begin), - reinterpret_cast<void*>(end), - reinterpret_cast<void*>(overlap.begin), - reinterpret_cast<void*>(overlap.end)); + MEM_ALOGE("range %p-%p overlaps with existing range %p-%p", reinterpret_cast<void*>(begin), + reinterpret_cast<void*>(end), reinterpret_cast<void*>(overlap.begin), + reinterpret_cast<void*>(overlap.end)); } return false; } @@ -154,7 +152,7 @@ static bool MapOverPage(void* addr) { void* ret = mmap(page, page_size, PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED, -1, 0); if (ret == MAP_FAILED) { - ALOGE("failed to map page at %p: %s", page, strerror(errno)); + MEM_ALOGE("failed to map page at %p: %s", page, strerror(errno)); return false; } @@ -167,7 +165,7 @@ void HeapWalker::HandleSegFault(ScopedSignalHandler& handler, int signal, siginf handler.reset(); return; } - ALOGW("failed to read page at %p, signal %d", si->si_addr, signal); + MEM_ALOGW("failed to read page at %p, signal %d", si->si_addr, signal); if (!MapOverPage(si->si_addr)) { handler.reset(); } diff --git a/libmemunreachable/LeakPipe.cpp b/libmemunreachable/LeakPipe.cpp index 080f8a7d5..78117e2b6 100644 --- a/libmemunreachable/LeakPipe.cpp +++ b/libmemunreachable/LeakPipe.cpp @@ -44,11 +44,11 @@ bool LeakPipe::SendFd(int sock, int fd) { int ret = sendmsg(sock, &hdr, 0); if (ret < 0) { - ALOGE("failed to send fd: %s", strerror(errno)); + MEM_ALOGE("failed to send fd: %s", strerror(errno)); return false; } if (ret == 0) { - ALOGE("eof when sending fd"); + MEM_ALOGE("eof when sending fd"); return false; } @@ -71,17 +71,17 @@ int LeakPipe::ReceiveFd(int sock) { int ret = recvmsg(sock, &hdr, 0); if (ret < 0) { - ALOGE("failed to receive fd: %s", strerror(errno)); + MEM_ALOGE("failed to receive fd: %s", strerror(errno)); return -1; } if (ret == 0) { - ALOGE("eof when receiving fd"); + MEM_ALOGE("eof when receiving fd"); return -1; } struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr); if (cmsg == NULL || cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) { - ALOGE("missing fd while receiving fd"); + MEM_ALOGE("missing fd while receiving fd"); return -1; } diff --git a/libmemunreachable/LeakPipe.h b/libmemunreachable/LeakPipe.h index 3f4e0b70d..3ea2d8f3e 100644 --- a/libmemunreachable/LeakPipe.h +++ b/libmemunreachable/LeakPipe.h @@ -36,7 +36,7 @@ class LeakPipe { LeakPipe() { int ret = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sv_); if (ret < 0) { - LOG_ALWAYS_FATAL("failed to create socketpair: %s", strerror(errno)); + MEM_LOG_ALWAYS_FATAL("failed to create socketpair: %s", strerror(errno)); } } @@ -105,10 +105,10 @@ class LeakPipe { bool Send(const T& value) { ssize_t ret = TEMP_FAILURE_RETRY(write(fd_, &value, sizeof(T))); if (ret < 0) { - ALOGE("failed to send value: %s", strerror(errno)); + MEM_ALOGE("failed to send value: %s", strerror(errno)); return false; } else if (static_cast<size_t>(ret) != sizeof(T)) { - ALOGE("eof while writing value"); + MEM_ALOGE("eof while writing value"); return false; } @@ -124,10 +124,10 @@ class LeakPipe { ssize_t ret = TEMP_FAILURE_RETRY(write(fd_, vector.data(), size)); if (ret < 0) { - ALOGE("failed to send vector: %s", strerror(errno)); + MEM_ALOGE("failed to send vector: %s", strerror(errno)); return false; } else if (static_cast<size_t>(ret) != size) { - ALOGE("eof while writing vector"); + MEM_ALOGE("eof while writing vector"); return false; } @@ -143,10 +143,10 @@ class LeakPipe { bool Receive(T* value) { ssize_t ret = TEMP_FAILURE_RETRY(read(fd_, reinterpret_cast<void*>(value), sizeof(T))); if (ret < 0) { - ALOGE("failed to receive value: %s", strerror(errno)); + MEM_ALOGE("failed to receive value: %s", strerror(errno)); return false; } else if (static_cast<size_t>(ret) != sizeof(T)) { - ALOGE("eof while receiving value"); + MEM_ALOGE("eof while receiving value"); return false; } @@ -166,10 +166,10 @@ class LeakPipe { while (size > 0) { ssize_t ret = TEMP_FAILURE_RETRY(read(fd_, ptr, size)); if (ret < 0) { - ALOGE("failed to send vector: %s", strerror(errno)); + MEM_ALOGE("failed to send vector: %s", strerror(errno)); return false; } else if (ret == 0) { - ALOGE("eof while reading vector"); + MEM_ALOGE("eof while reading vector"); return false; } size -= ret; diff --git a/libmemunreachable/MemUnreachable.cpp b/libmemunreachable/MemUnreachable.cpp index ac19a6615..e7c0beb56 100644 --- a/libmemunreachable/MemUnreachable.cpp +++ b/libmemunreachable/MemUnreachable.cpp @@ -78,51 +78,49 @@ static void HeapIterate(const Mapping& heap_mapping, bool MemUnreachable::CollectAllocations(const allocator::vector<ThreadInfo>& threads, const allocator::vector<Mapping>& mappings) { - ALOGI("searching process %d for allocations", pid_); + MEM_ALOGI("searching process %d for allocations", pid_); allocator::vector<Mapping> heap_mappings{mappings}; allocator::vector<Mapping> anon_mappings{mappings}; allocator::vector<Mapping> globals_mappings{mappings}; allocator::vector<Mapping> stack_mappings{mappings}; - if (!ClassifyMappings(mappings, heap_mappings, anon_mappings, - globals_mappings, stack_mappings)) { + if (!ClassifyMappings(mappings, heap_mappings, anon_mappings, globals_mappings, stack_mappings)) { return false; } for (auto it = heap_mappings.begin(); it != heap_mappings.end(); it++) { - ALOGV("Heap mapping %" PRIxPTR "-%" PRIxPTR " %s", it->begin, it->end, it->name); - HeapIterate(*it, [&](uintptr_t base, size_t size) { - heap_walker_.Allocation(base, base + size); - }); + MEM_ALOGV("Heap mapping %" PRIxPTR "-%" PRIxPTR " %s", it->begin, it->end, it->name); + HeapIterate(*it, + [&](uintptr_t base, size_t size) { heap_walker_.Allocation(base, base + size); }); } for (auto it = anon_mappings.begin(); it != anon_mappings.end(); it++) { - ALOGV("Anon mapping %" PRIxPTR "-%" PRIxPTR " %s", it->begin, it->end, it->name); + MEM_ALOGV("Anon mapping %" PRIxPTR "-%" PRIxPTR " %s", it->begin, it->end, it->name); heap_walker_.Allocation(it->begin, it->end); } for (auto it = globals_mappings.begin(); it != globals_mappings.end(); it++) { - ALOGV("Globals mapping %" PRIxPTR "-%" PRIxPTR " %s", it->begin, it->end, it->name); + MEM_ALOGV("Globals mapping %" PRIxPTR "-%" PRIxPTR " %s", it->begin, it->end, it->name); heap_walker_.Root(it->begin, it->end); } for (auto thread_it = threads.begin(); thread_it != threads.end(); thread_it++) { for (auto it = stack_mappings.begin(); it != stack_mappings.end(); it++) { if (thread_it->stack.first >= it->begin && thread_it->stack.first <= it->end) { - ALOGV("Stack %" PRIxPTR "-%" PRIxPTR " %s", thread_it->stack.first, it->end, it->name); + MEM_ALOGV("Stack %" PRIxPTR "-%" PRIxPTR " %s", thread_it->stack.first, it->end, it->name); heap_walker_.Root(thread_it->stack.first, it->end); } } heap_walker_.Root(thread_it->regs); } - ALOGI("searching done"); + MEM_ALOGI("searching done"); return true; } bool MemUnreachable::GetUnreachableMemory(allocator::vector<Leak>& leaks, size_t limit, size_t* num_leaks, size_t* leak_bytes) { - ALOGI("sweeping process %d for unreachable memory", pid_); + MEM_ALOGI("sweeping process %d for unreachable memory", pid_); leaks.clear(); if (!heap_walker_.DetectLeaks()) { @@ -133,9 +131,9 @@ bool MemUnreachable::GetUnreachableMemory(allocator::vector<Leak>& leaks, allocator::vector<Range> leaked1{allocator_}; heap_walker_.Leaked(leaked1, 0, num_leaks, leak_bytes); - ALOGI("sweeping done"); + MEM_ALOGI("sweeping done"); - ALOGI("folding related leaks"); + MEM_ALOGI("folding related leaks"); LeakFolding folding(allocator_, heap_walker_); if (!folding.FoldLeaks()) { @@ -188,7 +186,7 @@ bool MemUnreachable::GetUnreachableMemory(allocator::vector<Leak>& leaks, std::min(leak->size, Leak::contents_length)); } - ALOGI("folding done"); + MEM_ALOGI("folding done"); std::sort(leaks.begin(), leaks.end(), [](const Leak& a, const Leak& b) { return a.total_size > b.total_size; @@ -276,7 +274,7 @@ bool GetUnreachableMemory(UnreachableMemoryInfo& info, size_t limit) { ///////////////////////////////////////////// // Collection thread ///////////////////////////////////////////// - ALOGI("collecting thread info for process %d...", parent_pid); + MEM_ALOGI("collecting thread info for process %d...", parent_pid); ThreadCapture thread_capture(parent_pid, heap); allocator::vector<ThreadInfo> thread_info(heap); @@ -351,7 +349,7 @@ bool GetUnreachableMemory(UnreachableMemoryInfo& info, size_t limit) { } else { // Nothing left to do in the collection thread, return immediately, // releasing all the captured threads. - ALOGI("collection thread done"); + MEM_ALOGI("collection thread done"); return 0; } }}; @@ -397,10 +395,10 @@ bool GetUnreachableMemory(UnreachableMemoryInfo& info, size_t limit) { return false; } - ALOGI("unreachable memory detection done"); - ALOGE("%zu bytes in %zu allocation%s unreachable out of %zu bytes in %zu allocation%s", - info.leak_bytes, info.num_leaks, plural(info.num_leaks), - info.allocation_bytes, info.num_allocations, plural(info.num_allocations)); + MEM_ALOGI("unreachable memory detection done"); + MEM_ALOGE("%zu bytes in %zu allocation%s unreachable out of %zu bytes in %zu allocation%s", + info.leak_bytes, info.num_leaks, plural(info.num_leaks), info.allocation_bytes, + info.num_allocations, plural(info.num_allocations)); return true; } @@ -517,7 +515,7 @@ bool LogUnreachableMemory(bool log_contents, size_t limit) { } for (auto it = info.leaks.begin(); it != info.leaks.end(); it++) { - ALOGE("%s", it->ToString(log_contents).c_str()); + MEM_ALOGE("%s", it->ToString(log_contents).c_str()); } return true; } diff --git a/libmemunreachable/PtracerThread.cpp b/libmemunreachable/PtracerThread.cpp index 4e3c41e54..73b0493af 100644 --- a/libmemunreachable/PtracerThread.cpp +++ b/libmemunreachable/PtracerThread.cpp @@ -70,7 +70,7 @@ PtracerThread::PtracerThread(const std::function<int()>& func) : child_pid_(0) { stack_ = std::make_unique<Stack>(PTHREAD_STACK_MIN); if (stack_->top() == nullptr) { - LOG_ALWAYS_FATAL("failed to mmap child stack: %s", strerror(errno)); + MEM_LOG_ALWAYS_FATAL("failed to mmap child stack: %s", strerror(errno)); } func_ = std::function<int()>{[&, func]() -> int { @@ -102,7 +102,7 @@ bool PtracerThread::Start() { CLONE_VM|CLONE_FS|CLONE_FILES/*|CLONE_UNTRACED*/, reinterpret_cast<void*>(&func_)); if (child_pid_ < 0) { - ALOGE("failed to clone child: %s", strerror(errno)); + MEM_ALOGE("failed to clone child: %s", strerror(errno)); return false; } @@ -120,7 +120,7 @@ int PtracerThread::Join() { int status; int ret = TEMP_FAILURE_RETRY(waitpid(child_pid_, &status, __WALL)); if (ret < 0) { - ALOGE("waitpid %d failed: %s", child_pid_, strerror(errno)); + MEM_ALOGE("waitpid %d failed: %s", child_pid_, strerror(errno)); return -1; } @@ -131,7 +131,7 @@ int PtracerThread::Join() { } else if (WIFSIGNALED(status)) { return -WTERMSIG(status); } else { - ALOGE("unexpected status %x", status); + MEM_ALOGE("unexpected status %x", status); return -1; } } diff --git a/libmemunreachable/ScopedPipe.h b/libmemunreachable/ScopedPipe.h index 9beef9a59..7f449533d 100644 --- a/libmemunreachable/ScopedPipe.h +++ b/libmemunreachable/ScopedPipe.h @@ -26,7 +26,7 @@ class ScopedPipe { ScopedPipe() : pipefd_{-1, -1} { int ret = pipe2(pipefd_, O_CLOEXEC); if (ret < 0) { - LOG_ALWAYS_FATAL("failed to open pipe"); + MEM_LOG_ALWAYS_FATAL("failed to open pipe"); } } ~ScopedPipe() { diff --git a/libmemunreachable/ScopedSignalHandler.h b/libmemunreachable/ScopedSignalHandler.h index 1fd9d4d71..ada2ae4ef 100644 --- a/libmemunreachable/ScopedSignalHandler.h +++ b/libmemunreachable/ScopedSignalHandler.h @@ -37,22 +37,18 @@ class ScopedSignalHandler { template <class F> void install(int signal, F&& f) { - LOG_ALWAYS_FATAL_IF(signal_ != -1, "ScopedSignalHandler already installed"); + MEM_LOG_ALWAYS_FATAL_IF(signal_ != -1, "ScopedSignalHandler already installed"); handler_ = SignalFn(std::allocator_arg, allocator_, - [=](int signal, siginfo_t* si, void* uctx) { - f(*this, signal, si, uctx); - }); - - struct sigaction act{}; - act.sa_sigaction = [](int signal, siginfo_t* si, void* uctx) { - handler_(signal, si, uctx); - }; + [=](int signal, siginfo_t* si, void* uctx) { f(*this, signal, si, uctx); }); + + struct sigaction act {}; + act.sa_sigaction = [](int signal, siginfo_t* si, void* uctx) { handler_(signal, si, uctx); }; act.sa_flags = SA_SIGINFO; int ret = sigaction(signal, &act, &old_act_); if (ret < 0) { - LOG_ALWAYS_FATAL("failed to install segfault handler: %s", strerror(errno)); + MEM_LOG_ALWAYS_FATAL("failed to install segfault handler: %s", strerror(errno)); } signal_ = signal; @@ -62,7 +58,7 @@ class ScopedSignalHandler { if (signal_ != -1) { int ret = sigaction(signal_, &old_act_, NULL); if (ret < 0) { - ALOGE("failed to uninstall segfault handler"); + MEM_ALOGE("failed to uninstall segfault handler"); } handler_ = SignalFn{}; signal_ = -1; diff --git a/libmemunreachable/ThreadCapture.cpp b/libmemunreachable/ThreadCapture.cpp index 9155c2928..3891f2d3d 100644 --- a/libmemunreachable/ThreadCapture.cpp +++ b/libmemunreachable/ThreadCapture.cpp @@ -110,7 +110,7 @@ bool ThreadCaptureImpl::ListThreads(TidList& tids) { android::base::unique_fd fd(open(path, O_CLOEXEC | O_DIRECTORY | O_RDONLY)); if (fd == -1) { - ALOGE("failed to open %s: %s", path, strerror(errno)); + MEM_ALOGE("failed to open %s: %s", path, strerror(errno)); return false; } @@ -126,7 +126,7 @@ bool ThreadCaptureImpl::ListThreads(TidList& tids) { do { nread = syscall(SYS_getdents64, fd.get(), dirent_buf, sizeof(dirent_buf)); if (nread < 0) { - ALOGE("failed to get directory entries from %s: %s", path, strerror(errno)); + MEM_ALOGE("failed to get directory entries from %s: %s", path, strerror(errno)); return false; } else if (nread > 0) { ssize_t off = 0; @@ -177,8 +177,7 @@ bool ThreadCaptureImpl::CaptureThreads() { void ThreadCaptureImpl::PtraceDetach(pid_t tid, unsigned int signal) { void* sig_ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(signal)); if (ptrace(PTRACE_DETACH, tid, NULL, sig_ptr) < 0 && errno != ESRCH) { - ALOGE("failed to detach from thread %d of process %d: %s", tid, pid_, - strerror(errno)); + MEM_ALOGE("failed to detach from thread %d of process %d: %s", tid, pid_, strerror(errno)); } } @@ -187,8 +186,7 @@ void ThreadCaptureImpl::PtraceDetach(pid_t tid, unsigned int signal) { int ThreadCaptureImpl::PtraceAttach(pid_t tid) { int ret = ptrace(PTRACE_SEIZE, tid, NULL, NULL); if (ret < 0) { - ALOGE("failed to attach to thread %d of process %d: %s", tid, pid_, - strerror(errno)); + MEM_ALOGE("failed to attach to thread %d of process %d: %s", tid, pid_, strerror(errno)); return -1; } @@ -200,8 +198,7 @@ int ThreadCaptureImpl::PtraceAttach(pid_t tid) { if (errno == ESRCH) { return 0; } else { - ALOGE("failed to interrupt thread %d of process %d: %s", tid, pid_, - strerror(errno)); + MEM_ALOGE("failed to interrupt thread %d of process %d: %s", tid, pid_, strerror(errno)); PtraceDetach(tid, 0); return -1; } @@ -219,8 +216,7 @@ bool ThreadCaptureImpl::PtraceThreadInfo(pid_t tid, ThreadInfo& thread_info) { iovec.iov_len = sizeof(regs); if (ptrace(PTRACE_GETREGSET, tid, reinterpret_cast<void*>(NT_PRSTATUS), &iovec)) { - ALOGE("ptrace getregset for thread %d of process %d failed: %s", - tid, pid_, strerror(errno)); + MEM_ALOGE("ptrace getregset for thread %d of process %d failed: %s", tid, pid_, strerror(errno)); return false; } @@ -258,15 +254,13 @@ int ThreadCaptureImpl::CaptureThread(pid_t tid) { int status = 0; if (TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL)) < 0) { - ALOGE("failed to wait for pause of thread %d of process %d: %s", tid, pid_, - strerror(errno)); + MEM_ALOGE("failed to wait for pause of thread %d of process %d: %s", tid, pid_, strerror(errno)); PtraceDetach(tid, 0); return -1; } if (!WIFSTOPPED(status)) { - ALOGE("thread %d of process %d was not paused after waitpid, killed?", - tid, pid_); + MEM_ALOGE("thread %d of process %d was not paused after waitpid, killed?", tid, pid_); return 0; } @@ -285,8 +279,8 @@ int ThreadCaptureImpl::CaptureThread(pid_t tid) { // normal ptrace interrupt stop break; default: - ALOGE("unexpected signal %d with PTRACE_EVENT_STOP for thread %d of process %d", - signal, tid, pid_); + MEM_ALOGE("unexpected signal %d with PTRACE_EVENT_STOP for thread %d of process %d", signal, + tid, pid_); return -1; } } else { diff --git a/libmemunreachable/log.h b/libmemunreachable/log.h index cdfbfd9d6..1725c53d7 100644 --- a/libmemunreachable/log.h +++ b/libmemunreachable/log.h @@ -19,6 +19,32 @@ #define LOG_TAG "libmemunreachable" +#if defined(__ANDROID__) + +#include <async_safe/log.h> + +#define MEM_ALOGE(...) async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, ##__VA_ARGS__) +#define MEM_ALOGW(...) async_safe_format_log(ANDROID_LOG_WARN, LOG_TAG, ##__VA_ARGS__) +#define MEM_ALOGI(...) async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG, ##__VA_ARGS__) +#define MEM_ALOGV(...) async_safe_format_log(ANDROID_LOG_VERBOSE, LOG_TAG, ##__VA_ARGS__) + +#define MEM_LOG_ALWAYS_FATAL(...) async_safe_fatal(__VA_ARGS__) + +#define MEM_LOG_ALWAYS_FATAL_IF(cond, ...) \ + ((__predict_false(cond)) ? async_safe_fatal(__VA_ARGS__) : (void)0) + +#else + #include <log/log.h> +#define MEM_ALOGW ALOGW +#define MEM_ALOGE ALOGE +#define MEM_ALOGV ALOGV +#define MEM_ALOGI ALOGI + +#define MEM_LOG_ALWAYS_FATAL LOG_ALWAYS_FATAL +#define MEM_LOG_ALWAYS_FATAL_IF LOG_ALWAYS_FATAL_IF + +#endif + #endif // LIBMEMUNREACHABLE_LOG_H_ diff --git a/libmemunreachable/tests/DisableMalloc_test.cpp b/libmemunreachable/tests/DisableMalloc_test.cpp index ea5c22c88..4e6155b81 100644 --- a/libmemunreachable/tests/DisableMalloc_test.cpp +++ b/libmemunreachable/tests/DisableMalloc_test.cpp @@ -74,7 +74,7 @@ TEST_F(DisableMallocTest, deadlock_new) { { alarm(100ms); ScopedDisableMalloc disable_malloc; - char* ptr = new(char); + char* ptr = new (std::nothrow)(char); ASSERT_NE(ptr, nullptr); delete(ptr); } @@ -89,6 +89,8 @@ TEST_F(DisableMallocTest, deadlock_delete) { alarm(250ms); ScopedDisableMalloc disable_malloc; delete(ptr); + // Force ptr usage or this code gets optimized away by the arm64 compiler. + ASSERT_NE(ptr, nullptr); } }, ""); } diff --git a/libmemunreachable/tests/MemUnreachable_test.cpp b/libmemunreachable/tests/MemUnreachable_test.cpp index 2ae3db83e..71da3655a 100644 --- a/libmemunreachable/tests/MemUnreachable_test.cpp +++ b/libmemunreachable/tests/MemUnreachable_test.cpp @@ -23,8 +23,6 @@ #include <memunreachable/memunreachable.h> -void* ptr; - class HiddenPointer { public: explicit HiddenPointer(size_t size = 256) { @@ -92,10 +90,12 @@ TEST(MemunreachableTest, stack) { } } +void* g_ptr; + TEST(MemunreachableTest, global) { HiddenPointer hidden_ptr; - ptr = hidden_ptr.Get(); + g_ptr = hidden_ptr.Get(); { UnreachableMemoryInfo info; @@ -104,7 +104,7 @@ TEST(MemunreachableTest, global) { ASSERT_EQ(0U, info.leaks.size()); } - ptr = NULL; + g_ptr = nullptr; { UnreachableMemoryInfo info; @@ -126,7 +126,7 @@ TEST(MemunreachableTest, global) { TEST(MemunreachableTest, tls) { HiddenPointer hidden_ptr; pthread_key_t key; - pthread_key_create(&key, NULL); + pthread_key_create(&key, nullptr); pthread_setspecific(key, hidden_ptr.Get()); diff --git a/libmemunreachable/tests/ThreadCapture_test.cpp b/libmemunreachable/tests/ThreadCapture_test.cpp index 41ed84ee0..44aabd755 100644 --- a/libmemunreachable/tests/ThreadCapture_test.cpp +++ b/libmemunreachable/tests/ThreadCapture_test.cpp @@ -55,7 +55,7 @@ class ThreadListTest : public ::testing::TestWithParam<int> { threads_.reserve(threads); tids_.reserve(threads); for (unsigned int i = 0; i < threads; i++) { - threads_.emplace_back([&, i, threads, this]() { + threads_.emplace_back([&, threads, this]() { { std::lock_guard<std::mutex> lk(m_); tids_.push_back(gettid()); diff --git a/toolbox/Android.mk b/toolbox/Android.mk index aa755ed7f..d6ead1a09 100644 --- a/toolbox/Android.mk +++ b/toolbox/Android.mk @@ -95,13 +95,3 @@ LOCAL_C_INCLUDES += $(LOCAL_PATH)/upstream-netbsd/include/ LOCAL_MODULE := grep LOCAL_POST_INSTALL_CMD := $(hide) $(foreach t,egrep fgrep,ln -sf grep $(TARGET_OUT)/bin/$(t);) include $(BUILD_EXECUTABLE) - - -# We build gzip separately, so it can provide gunzip and zcat too. -include $(CLEAR_VARS) -LOCAL_MODULE := gzip -LOCAL_SRC_FILES := gzip.c -LOCAL_CFLAGS += -Wall -Werror -LOCAL_SHARED_LIBRARIES += libz -LOCAL_POST_INSTALL_CMD := $(hide) $(foreach t,gunzip zcat,ln -sf gzip $(TARGET_OUT)/bin/$(t);) -include $(BUILD_EXECUTABLE) diff --git a/toolbox/gzip.c b/toolbox/gzip.c deleted file mode 100644 index 62c451830..000000000 --- a/toolbox/gzip.c +++ /dev/null @@ -1,261 +0,0 @@ -/* gzip.c - gzip/gunzip/zcat tools for gzip data - * - * Copyright 2017 The Android Open Source Project - * - * GZIP RFC: http://www.ietf.org/rfc/rfc1952.txt - -TODO: port to toybox. - -*/ - -#define _GNU_SOURCE - -#include <errno.h> -#include <error.h> -#include <fcntl.h> -#include <getopt.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> - -#include <zlib.h> - -// toybox-style flags/globals. -#define FLAG_c 1 -#define FLAG_d 2 -#define FLAG_f 4 -#define FLAG_k 8 -static struct { - int optflags; -} toys; -static struct { - int level; -} TT; - -static void xstat(const char *path, struct stat *sb) -{ - if (stat(path, sb)) error(1, errno, "stat %s", path); -} - -static void fix_time(const char *path, struct stat *sb) -{ - struct timespec times[] = { sb->st_atim, sb->st_mtim }; - - if (utimensat(AT_FDCWD, path, times, 0)) error(1, errno, "utimes"); -} - -static FILE *xfdopen(const char *name, int flags, mode_t open_mode, - const char *mode) -{ - FILE *fp; - int fd; - - if (!strcmp(name, "-")) fd = dup((*mode == 'r') ? 0 : 1); - else fd = open(name, flags, open_mode); - - if (fd == -1) error(1, errno, "open %s (%s)", name, mode); - fp = fdopen(fd, mode); - if (fp == NULL) error(1, errno, "fopen %s (%s)", name, mode); - return fp; -} - -static gzFile xgzopen(const char *name, int flags, mode_t open_mode, - const char *mode) -{ - gzFile f; - int fd; - - if (!strcmp(name, "-")) fd = dup((*mode == 'r') ? 0 : 1); - else fd = open(name, flags, open_mode); - - if (fd == -1) error(1, errno, "open %s (%s)", name, mode); - f = gzdopen(fd, mode); - if (f == NULL) error(1, errno, "gzdopen %s (%s)", name, mode); - return f; -} - -static void gzfatal(gzFile f, char *what) -{ - int err; - const char *msg = gzerror(f, &err); - - error(1, (err == Z_ERRNO) ? errno : 0, "%s: %s", what, msg); -} - -static void gunzip(char *arg) -{ - struct stat sb; - char buf[BUFSIZ]; - int len, both_files; - char *in_name, *out_name; - gzFile in; - FILE *out; - - // "gunzip x.gz" will decompress "x.gz" to "x". - len = strlen(arg); - if (len > 3 && !strcmp(arg+len-3, ".gz")) { - in_name = strdup(arg); - out_name = strdup(arg); - out_name[len-3] = '\0'; - } else if (!strcmp(arg, "-")) { - // "-" means stdin; assume output to stdout. - // TODO: require -f to read compressed data from tty? - in_name = strdup("-"); - out_name = strdup("-"); - } else error(1, 0, "unknown suffix"); - - if (toys.optflags&FLAG_c) { - free(out_name); - out_name = strdup("-"); - } - - both_files = strcmp(in_name, "-") && strcmp(out_name, "-"); - if (both_files) xstat(in_name, &sb); - - in = xgzopen(in_name, O_RDONLY, 0, "r"); - out = xfdopen(out_name, O_CREAT|O_WRONLY|((toys.optflags&FLAG_f)?0:O_EXCL), - both_files?sb.st_mode:0666, "w"); - - while ((len = gzread(in, buf, sizeof(buf))) > 0) { - if (fwrite(buf, 1, len, out) != (size_t) len) error(1, errno, "fwrite"); - } - if (len < 0) gzfatal(in, "gzread"); - if (fclose(out)) error(1, errno, "fclose"); - if (gzclose(in) != Z_OK) error(1, 0, "gzclose"); - - if (both_files) fix_time(out_name, &sb); - if (!(toys.optflags&(FLAG_c|FLAG_k))) unlink(in_name); - free(in_name); - free(out_name); -} - -static void gzip(char *in_name) -{ - char buf[BUFSIZ]; - size_t len; - char *out_name; - FILE *in; - gzFile out; - struct stat sb; - int both_files; - - if (toys.optflags&FLAG_c) { - out_name = strdup("-"); - } else { - if (asprintf(&out_name, "%s.gz", in_name) == -1) { - error(1, errno, "asprintf"); - } - } - - both_files = strcmp(in_name, "-") && strcmp(out_name, "-"); - if (both_files) xstat(in_name, &sb); - - snprintf(buf, sizeof(buf), "w%d", TT.level); - in = xfdopen(in_name, O_RDONLY, 0, "r"); - out = xgzopen(out_name, O_CREAT|O_WRONLY|((toys.optflags&FLAG_f)?0:O_EXCL), - both_files?sb.st_mode:0, buf); - - while ((len = fread(buf, 1, sizeof(buf), in)) > 0) { - if (gzwrite(out, buf, len) != (int) len) gzfatal(out, "gzwrite"); - } - if (ferror(in)) error(1, errno, "fread"); - if (fclose(in)) error(1, errno, "fclose"); - if (gzclose(out) != Z_OK) error(1, 0, "gzclose"); - - if (both_files) fix_time(out_name, &sb); - if (!(toys.optflags&(FLAG_c|FLAG_k))) unlink(in_name); - free(out_name); -} - -static void do_file(char *arg) -{ - if (toys.optflags&FLAG_d) gunzip(arg); - else gzip(arg); -} - -static void usage() -{ - char *cmd = basename(getprogname()); - - printf("usage: %s [-c] [-d] [-f] [-#] [FILE...]\n", cmd); - printf("\n"); - if (!strcmp(cmd, "zcat")) { - printf("Decompress files to stdout. Like `gzip -dc`.\n"); - printf("\n"); - printf("-c\tOutput to stdout\n"); - printf("-f\tForce: allow read from tty\n"); - } else if (!strcmp(cmd, "gunzip")) { - printf("Decompress files. With no files, decompresses stdin to stdout.\n"); - printf("On success, the input files are removed and replaced by new\n"); - printf("files without the .gz suffix.\n"); - printf("\n"); - printf("-c\tOutput to stdout\n"); - printf("-f\tForce: allow read from tty\n"); - printf("-k\tKeep input files (don't remove)\n"); - } else { // gzip - printf("Compress files. With no files, compresses stdin to stdout.\n"); - printf("On success, the input files are removed and replaced by new\n"); - printf("files with the .gz suffix.\n"); - printf("\n"); - printf("-c\tOutput to stdout\n"); - printf("-d\tDecompress (act as gunzip)\n"); - printf("-f\tForce: allow overwrite of output file\n"); - printf("-k\tKeep input files (don't remove)\n"); - printf("-#\tCompression level 1-9 (1:fastest, 6:default, 9:best)\n"); - } - printf("\n"); -} - -int main(int argc, char *argv[]) -{ - char *cmd = basename(argv[0]); - int opt_ch; - - toys.optflags = 0; - TT.level = 6; - - if (!strcmp(cmd, "gunzip")) { - // gunzip == gzip -d - toys.optflags = FLAG_d; - } else if (!strcmp(cmd, "zcat")) { - // zcat == gzip -dc - toys.optflags = (FLAG_c|FLAG_d); - } - - while ((opt_ch = getopt(argc, argv, "cdfhk123456789")) != -1) { - switch (opt_ch) { - case 'c': toys.optflags |= FLAG_c; break; - case 'd': toys.optflags |= FLAG_d; break; - case 'f': toys.optflags |= FLAG_f; break; - case 'k': toys.optflags |= FLAG_k; break; - - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - TT.level = opt_ch - '0'; - break; - - default: - usage(); - return 1; - } - } - - if (optind == argc) { - // With no arguments, we go from stdin to stdout. - toys.optflags |= FLAG_c; - do_file("-"); - return 0; - } - - // Otherwise process each file in turn. - while (optind < argc) do_file(argv[optind++]); - return 0; -} diff --git a/trusty/Android.bp b/trusty/Android.bp index 1b2e2c776..9681488d8 100644 --- a/trusty/Android.bp +++ b/trusty/Android.bp @@ -1,3 +1,4 @@ subdirs = [ "libtrusty", + "storage/*", ] diff --git a/trusty/storage/interface/Android.bp b/trusty/storage/interface/Android.bp new file mode 100644 index 000000000..a551c37aa --- /dev/null +++ b/trusty/storage/interface/Android.bp @@ -0,0 +1,20 @@ +// +// Copyright (C) 2015 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. +// + +cc_library_static { + name: "libtrustystorageinterface", + export_include_dirs: ["include"], +} diff --git a/trusty/storage/interface/Android.mk b/trusty/storage/interface/Android.mk deleted file mode 100644 index 15cb6f3d5..000000000 --- a/trusty/storage/interface/Android.mk +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright (C) 2015 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. -# - -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := libtrustystorageinterface - -LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include - -include $(BUILD_STATIC_LIBRARY) diff --git a/trusty/storage/lib/Android.bp b/trusty/storage/lib/Android.bp new file mode 100644 index 000000000..5eb3f0778 --- /dev/null +++ b/trusty/storage/lib/Android.bp @@ -0,0 +1,35 @@ +// +// Copyright (C) 2015 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. +// + +cc_library_static { + name: "libtrustystorage", + + srcs: ["storage.c"], + + export_include_dirs: ["include"], + + static_libs: [ + "liblog", + "libtrusty", + "libtrustystorageinterface", + ], + + cflags: [ + "-fvisibility=hidden", + "-Wall", + "-Werror", + ] +} diff --git a/trusty/storage/lib/Android.mk b/trusty/storage/lib/Android.mk deleted file mode 100644 index 7e0fc9da4..000000000 --- a/trusty/storage/lib/Android.mk +++ /dev/null @@ -1,37 +0,0 @@ -# -# Copyright (C) 2015 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. -# - -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := libtrustystorage - -LOCAL_SRC_FILES := \ - storage.c \ - -LOCAL_CLFAGS = -fvisibility=hidden -Wall -Werror - -LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include -LOCAL_C_INCLUDES := $(LOCAL_PATH)/include - -LOCAL_STATIC_LIBRARIES := \ - liblog \ - libtrusty \ - libtrustystorageinterface - -include $(BUILD_STATIC_LIBRARY) - diff --git a/trusty/storage/proxy/Android.bp b/trusty/storage/proxy/Android.bp new file mode 100644 index 000000000..eb34df014 --- /dev/null +++ b/trusty/storage/proxy/Android.bp @@ -0,0 +1,38 @@ +// +// Copyright (C) 2016 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. +// + +cc_binary { + name: "storageproxyd", + + srcs: [ + "ipc.c", + "rpmb.c", + "storage.c", + "proxy.c", + ], + + shared_libs: ["liblog"], + + static_libs: [ + "libtrustystorageinterface", + "libtrusty", + ], + + cflags: [ + "-Wall", + "-Werror", + ] +} diff --git a/trusty/storage/proxy/Android.mk b/trusty/storage/proxy/Android.mk deleted file mode 100644 index 745e302d8..000000000 --- a/trusty/storage/proxy/Android.mk +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright (C) 2016 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. -# - -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := storageproxyd - -LOCAL_C_INCLUDES += bionic/libc/kernel/uapi - -LOCAL_SRC_FILES := \ - ipc.c \ - rpmb.c \ - storage.c \ - proxy.c - -LOCAL_CLFAGS = -Wall -Werror - -LOCAL_SHARED_LIBRARIES := \ - liblog \ - -LOCAL_STATIC_LIBRARIES := \ - libtrustystorageinterface \ - libtrusty - -include $(BUILD_EXECUTABLE) - diff --git a/trusty/storage/proxy/proxy.c b/trusty/storage/proxy/proxy.c index d645ac01c..27e58917f 100644 --- a/trusty/storage/proxy/proxy.c +++ b/trusty/storage/proxy/proxy.c @@ -229,7 +229,6 @@ static void parse_args(int argc, char *argv[]) int main(int argc, char *argv[]) { int rc; - uint retry_cnt; /* drop privileges */ if (drop_privs() < 0) diff --git a/trusty/storage/tests/Android.bp b/trusty/storage/tests/Android.bp new file mode 100644 index 000000000..3eff3f27a --- /dev/null +++ b/trusty/storage/tests/Android.bp @@ -0,0 +1,36 @@ +// +// Copyright (C) 2016 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. +// + +cc_test { + name: "secure-storage-unit-test", + + cflags: [ + "-g", + "-Wall", + "-Werror", + "-std=gnu++11", + "-Wno-missing-field-initializers", + ], + + static_libs: [ + "libtrustystorageinterface", + "libtrustystorage", + "libtrusty", + "liblog", + ], + + srcs: ["main.cpp"], +} diff --git a/trusty/storage/tests/Android.mk b/trusty/storage/tests/Android.mk deleted file mode 100644 index 71c904df1..000000000 --- a/trusty/storage/tests/Android.mk +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright (C) 2016 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. -# - -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_MODULE := secure-storage-unit-test -LOCAL_CFLAGS += -g -Wall -Werror -std=gnu++11 -Wno-missing-field-initializers -LOCAL_STATIC_LIBRARIES := \ - libtrustystorageinterface \ - libtrustystorage \ - libtrusty \ - liblog -LOCAL_SRC_FILES := main.cpp -include $(BUILD_NATIVE_TEST) - |