diff options
-rw-r--r-- | adb/Android.mk | 89 | ||||
-rw-r--r-- | adb/adb.cpp (renamed from adb/adb.c) | 30 | ||||
-rw-r--r-- | adb/adb.h | 9 | ||||
-rw-r--r-- | adb/adb_auth.cpp (renamed from adb/adb_auth.c) | 0 | ||||
-rw-r--r-- | adb/adb_auth.h | 14 | ||||
-rw-r--r-- | adb/adb_auth_client.cpp (renamed from adb/adb_auth_client.c) | 37 | ||||
-rw-r--r-- | adb/adb_auth_host.cpp (renamed from adb/adb_auth_host.c) | 41 | ||||
-rw-r--r-- | adb/adb_client.cpp (renamed from adb/adb_client.c) | 9 | ||||
-rw-r--r-- | adb/adb_client.h | 2 | ||||
-rw-r--r-- | adb/adb_io.cpp | 4 | ||||
-rw-r--r-- | adb/adb_io_test.cpp | 14 | ||||
-rw-r--r-- | adb/adb_listeners.cpp (renamed from adb/adb_listeners.c) | 94 | ||||
-rw-r--r-- | adb/adb_main.cpp (renamed from adb/adb_main.c) | 8 | ||||
-rw-r--r-- | adb/commandline.cpp (renamed from adb/commandline.c) | 158 | ||||
-rw-r--r-- | adb/console.cpp (renamed from adb/console.c) | 2 | ||||
-rw-r--r-- | adb/file_sync_client.cpp (renamed from adb/file_sync_client.c) | 17 | ||||
-rw-r--r-- | adb/file_sync_service.cpp (renamed from adb/file_sync_service.c) | 22 | ||||
-rw-r--r-- | adb/framebuffer_service.cpp (renamed from adb/framebuffer_service.c) | 3 | ||||
-rw-r--r-- | adb/get_my_path_darwin.c | 2 | ||||
-rw-r--r-- | adb/get_my_path_linux.cpp (renamed from adb/get_my_path_linux.c) | 6 | ||||
-rw-r--r-- | adb/get_my_path_windows.cpp (renamed from adb/get_my_path_windows.c) | 4 | ||||
-rw-r--r-- | adb/jdwp_service.cpp (renamed from adb/jdwp_service.c) | 9 | ||||
-rw-r--r-- | adb/qemu_tracing.cpp (renamed from adb/qemu_tracing.c) | 0 | ||||
-rw-r--r-- | adb/remount_service.cpp (renamed from adb/remount_service.c) | 109 | ||||
-rw-r--r-- | adb/remount_service.h | 25 | ||||
-rw-r--r-- | adb/services.cpp (renamed from adb/services.c) | 30 | ||||
-rw-r--r-- | adb/set_verity_enable_state_service.cpp (renamed from adb/set_verity_enable_state_service.c) | 5 | ||||
-rw-r--r-- | adb/sockets.cpp (renamed from adb/sockets.c) | 103 | ||||
-rw-r--r-- | adb/test_track_devices.cpp (renamed from adb/test_track_devices.c) | 0 | ||||
-rw-r--r-- | adb/test_track_jdwp.cpp (renamed from adb/test_track_jdwp.c) | 0 | ||||
-rwxr-xr-x | adb/tests/test_adb.py | 24 | ||||
-rw-r--r-- | adb/transport.cpp (renamed from adb/transport.c) | 18 | ||||
-rw-r--r-- | adb/transport.h | 2 | ||||
-rw-r--r-- | adb/transport_local.cpp (renamed from adb/transport_local.c) | 0 | ||||
-rw-r--r-- | adb/transport_usb.cpp (renamed from adb/transport_usb.c) | 0 | ||||
-rw-r--r-- | adb/usb_linux.cpp (renamed from adb/usb_linux.c) | 9 | ||||
-rw-r--r-- | adb/usb_windows.cpp (renamed from adb/usb_windows.c) | 0 | ||||
-rw-r--r-- | adf/libadf/Android.mk | 1 | ||||
-rw-r--r-- | adf/libadf/tests/Android.mk | 1 | ||||
-rw-r--r-- | adf/libadf/tests/adf_test.cpp | 12 | ||||
-rw-r--r-- | adf/libadfhwc/Android.mk | 2 | ||||
-rw-r--r-- | base/.clang-format | 11 | ||||
-rw-r--r-- | base/Android.mk | 98 | ||||
-rw-r--r-- | base/CPPLINT.cfg | 2 | ||||
-rw-r--r-- | base/file.cpp (renamed from libutils/file.cpp) | 48 | ||||
-rw-r--r-- | base/file_test.cpp (renamed from libutils/tests/file_test.cpp) | 27 | ||||
-rw-r--r-- | base/include/base/file.h (renamed from include/utils/file.h) | 12 | ||||
-rw-r--r-- | base/include/base/macros.h | 188 | ||||
-rw-r--r-- | base/include/base/stringprintf.h (renamed from include/utils/stringprintf.h) | 12 | ||||
-rw-r--r-- | base/include/base/strings.h | 47 | ||||
-rw-r--r-- | base/stringprintf.cpp (renamed from libutils/stringprintf.cpp) | 18 | ||||
-rw-r--r-- | base/stringprintf_test.cpp (renamed from libutils/tests/stringprintf_test.cpp) | 14 | ||||
-rw-r--r-- | base/strings.cpp | 111 | ||||
-rw-r--r-- | base/strings_test.cpp | 142 | ||||
-rw-r--r-- | debuggerd/Android.mk | 7 | ||||
-rw-r--r-- | debuggerd/elf_utils.cpp | 119 | ||||
-rw-r--r-- | debuggerd/elf_utils.h | 27 | ||||
-rw-r--r-- | debuggerd/mips64/crashglue.S | 48 | ||||
-rw-r--r-- | debuggerd/mips64/machine.cpp | 100 | ||||
-rw-r--r-- | debuggerd/tombstone.cpp | 141 | ||||
-rw-r--r-- | debuggerd/utility.h | 4 | ||||
-rw-r--r-- | fastboot/Android.mk | 5 | ||||
-rw-r--r-- | fastboot/bootimg_utils.cpp (renamed from fastboot/bootimg.c) | 10 | ||||
-rw-r--r-- | fastboot/bootimg_utils.h | 49 | ||||
-rw-r--r-- | fastboot/fastboot.cpp (renamed from fastboot/fastboot.c) | 110 | ||||
-rw-r--r-- | fastboot/fastboot.h | 10 | ||||
-rw-r--r-- | fastboot/fs.h | 8 | ||||
-rw-r--r-- | fastboot/usb.h | 8 | ||||
-rw-r--r-- | fs_mgr/fs_mgr.c | 7 | ||||
-rw-r--r-- | fs_mgr/fs_mgr_fstab.c | 5 | ||||
-rw-r--r-- | fs_mgr/fs_mgr_verity.c | 349 | ||||
-rw-r--r-- | fs_mgr/include/fs_mgr.h | 11 | ||||
-rw-r--r-- | healthd/BatteryMonitor.cpp | 10 | ||||
-rw-r--r-- | healthd/healthd.cpp | 3 | ||||
-rw-r--r-- | healthd/healthd.h | 1 | ||||
-rw-r--r-- | healthd/healthd_mode_charger.cpp | 74 | ||||
-rw-r--r-- | include/backtrace/Backtrace.h | 6 | ||||
-rw-r--r-- | include/ctest/ctest.h | 70 | ||||
-rw-r--r-- | include/private/android_filesystem_config.h | 8 | ||||
-rw-r--r-- | include/private/android_logger.h | 42 | ||||
-rw-r--r-- | include/system/audio.h | 14 | ||||
-rw-r--r-- | init/Android.mk | 6 | ||||
-rw-r--r-- | init/bootchart.cpp | 18 | ||||
-rw-r--r-- | init/builtins.cpp | 97 | ||||
-rwxr-xr-x | init/grab-bootchart.sh | 11 | ||||
-rw-r--r-- | init/init.cpp | 190 | ||||
-rw-r--r-- | init/init.h | 53 | ||||
-rw-r--r-- | init/init_parser.cpp | 72 | ||||
-rw-r--r-- | init/init_parser.h | 3 | ||||
-rw-r--r-- | init/init_parser_test.cpp | 134 | ||||
-rw-r--r-- | init/keywords.h | 12 | ||||
-rw-r--r-- | init/property_service.cpp | 2 | ||||
-rw-r--r-- | init/readme.txt | 47 | ||||
-rw-r--r-- | init/signal_handler.cpp | 85 | ||||
-rw-r--r-- | init/util.cpp | 8 | ||||
-rw-r--r-- | init/util_test.cpp | 6 | ||||
-rw-r--r-- | libbacktrace/BacktraceImpl.cpp | 95 | ||||
-rwxr-xr-x | libbacktrace/BacktraceImpl.h | 4 | ||||
-rw-r--r-- | libbacktrace/backtrace_test.cpp | 315 | ||||
-rw-r--r-- | libcutils/native_handle.c | 8 | ||||
-rw-r--r-- | libcutils/sched_policy.c | 26 | ||||
-rw-r--r-- | liblog/Android.mk | 36 | ||||
-rw-r--r-- | liblog/README | 27 | ||||
-rw-r--r-- | liblog/event.logtags | 36 | ||||
-rw-r--r-- | liblog/logd_write.c | 36 | ||||
-rw-r--r-- | liblog/logd_write_kern.c | 2 | ||||
-rw-r--r-- | libnativebridge/tests/CompleteFlow_test.cpp | 1 | ||||
-rw-r--r-- | libnetutils/dhcp_utils.c | 6 | ||||
-rw-r--r-- | libpixelflinger/Android.mk | 18 | ||||
-rw-r--r-- | libutils/Android.mk | 2 | ||||
-rw-r--r-- | libutils/tests/Android.mk | 2 | ||||
-rw-r--r-- | libziparchive/Android.mk | 3 | ||||
-rw-r--r-- | libziparchive/testdata/declaredlength.zip | bin | 0 -> 886 bytes | |||
-rw-r--r-- | libziparchive/zip_archive.cc | 169 | ||||
-rw-r--r-- | libziparchive/zip_archive_test.cc | 16 | ||||
-rw-r--r-- | libzipfile/zipfile.c | 4 | ||||
-rw-r--r-- | logcat/logcat.cpp | 80 | ||||
-rw-r--r-- | logcat/tests/logcat_test.cpp | 6 | ||||
-rw-r--r-- | logd/Android.mk | 11 | ||||
-rw-r--r-- | logd/CommandListener.cpp | 16 | ||||
-rw-r--r-- | logd/CommandListener.h | 11 | ||||
-rw-r--r-- | logd/FlushCommand.cpp | 2 | ||||
-rw-r--r-- | logd/FlushCommand.h | 4 | ||||
-rw-r--r-- | logd/LogAudit.cpp | 41 | ||||
-rw-r--r-- | logd/LogBuffer.cpp | 70 | ||||
-rw-r--r-- | logd/LogBuffer.h | 11 | ||||
-rw-r--r-- | logd/LogBufferElement.cpp | 9 | ||||
-rw-r--r-- | logd/LogBufferElement.h | 11 | ||||
-rw-r--r-- | logd/LogReader.cpp | 38 | ||||
-rw-r--r-- | logd/LogStatistics.cpp | 109 | ||||
-rw-r--r-- | logd/LogStatistics.h | 5 | ||||
-rw-r--r-- | logd/LogTimes.cpp | 24 | ||||
-rw-r--r-- | logd/LogTimes.h | 11 | ||||
-rw-r--r-- | logd/README.property | 6 | ||||
-rw-r--r-- | logd/main.cpp | 139 | ||||
-rw-r--r-- | logd/tests/logd_test.cpp | 158 | ||||
-rw-r--r-- | netcfg/Android.mk | 8 | ||||
-rw-r--r-- | netcfg/MODULE_LICENSE_APACHE2 | 0 | ||||
-rw-r--r-- | netcfg/NOTICE | 190 | ||||
-rw-r--r-- | netcfg/netcfg.c | 114 | ||||
-rw-r--r-- | rootdir/init.environ.rc.in | 1 | ||||
-rw-r--r-- | rootdir/init.rc | 31 | ||||
-rw-r--r-- | rootdir/ueventd.rc | 1 | ||||
-rw-r--r-- | sdcard/Android.mk | 2 | ||||
-rw-r--r-- | toolbox/Android.mk | 5 | ||||
-rw-r--r-- | toolbox/getsebool.c | 104 | ||||
-rw-r--r-- | toolbox/prlimit.c | 76 | ||||
-rw-r--r-- | toolbox/ps.c | 28 | ||||
-rw-r--r-- | toolbox/setsebool.c | 46 | ||||
-rw-r--r-- | toolbox/smd.c | 42 | ||||
-rw-r--r-- | toolbox/wipe.c | 176 |
151 files changed, 3529 insertions, 2498 deletions
diff --git a/adb/Android.mk b/adb/Android.mk index adad69f..8d38077 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -17,14 +17,14 @@ ADB_CLANG := # small by moving common files into a static library. Hopefully some day we can # get enough of adb in here that we no longer need minadb. https://b/17626262 LIBADB_SRC_FILES := \ - adb.c \ - adb_auth.c \ + adb.cpp \ + adb_auth.cpp \ adb_io.cpp \ - adb_listeners.c \ - sockets.c \ - transport.c \ - transport_local.c \ - transport_usb.c \ + adb_listeners.cpp \ + sockets.cpp \ + transport.cpp \ + transport_local.cpp \ + transport_usb.cpp \ LIBADB_CFLAGS := \ -Wall -Werror \ @@ -32,9 +32,20 @@ LIBADB_CFLAGS := \ -Wno-missing-field-initializers \ -fvisibility=hidden \ -LIBADB_darwin_SRC_FILES := fdevent.cpp get_my_path_darwin.c usb_osx.c -LIBADB_linux_SRC_FILES := fdevent.cpp get_my_path_linux.c usb_linux.c -LIBADB_windows_SRC_FILES := get_my_path_windows.c sysdeps_win32.c usb_windows.c +LIBADB_darwin_SRC_FILES := \ + fdevent.cpp \ + get_my_path_darwin.c \ + usb_osx.c \ + +LIBADB_linux_SRC_FILES := \ + fdevent.cpp \ + get_my_path_linux.cpp \ + usb_linux.cpp \ + +LIBADB_windows_SRC_FILES := \ + get_my_path_windows.cpp \ + sysdeps_win32.c \ + usb_windows.cpp \ include $(CLEAR_VARS) LOCAL_CLANG := $(ADB_CLANG) @@ -42,10 +53,10 @@ LOCAL_MODULE := libadbd LOCAL_CFLAGS := $(LIBADB_CFLAGS) -DADB_HOST=0 LOCAL_SRC_FILES := \ $(LIBADB_SRC_FILES) \ - adb_auth_client.c \ + adb_auth_client.cpp \ fdevent.cpp \ - jdwp_service.c \ - qemu_tracing.c \ + jdwp_service.cpp \ + qemu_tracing.cpp \ usb_linux_client.c \ include $(BUILD_STATIC_LIBRARY) @@ -57,7 +68,7 @@ LOCAL_CFLAGS := $(LIBADB_CFLAGS) -DADB_HOST=1 LOCAL_SRC_FILES := \ $(LIBADB_SRC_FILES) \ $(LIBADB_$(HOST_OS)_SRC_FILES) \ - adb_auth_host.c \ + adb_auth_host.cpp \ # Even though we're building a static library (and thus there's no link step for # this to take effect), this adds the SSL includes to our path. @@ -79,20 +90,19 @@ LOCAL_MODULE := adbd_test LOCAL_CFLAGS := -DADB_HOST=0 $(LIBADB_CFLAGS) LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS) LOCAL_STATIC_LIBRARIES := libadbd -LOCAL_SHARED_LIBRARIES := liblog libcutils libutils +LOCAL_SHARED_LIBRARIES := liblog libbase libcutils include $(BUILD_NATIVE_TEST) include $(CLEAR_VARS) LOCAL_CLANG := $(ADB_CLANG) LOCAL_MODULE := adb_test LOCAL_CFLAGS := -DADB_HOST=1 $(LIBADB_CFLAGS) -LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS) services.c -LOCAL_SHARED_LIBRARIES := liblog +LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS) services.cpp +LOCAL_SHARED_LIBRARIES := liblog libbase LOCAL_STATIC_LIBRARIES := \ libadb \ libcrypto_static \ libcutils \ - libutils \ ifeq ($(HOST_OS),linux) LOCAL_LDLIBS += -lrt -ldl -lpthread @@ -126,16 +136,12 @@ endif LOCAL_CLANG := $(ADB_CLANG) LOCAL_SRC_FILES := \ - adb_main.c \ - console.c \ - commandline.c \ - adb_client.c \ - services.c \ - file_sync_client.c \ - -ifneq ($(USE_SYSDEPS_WIN32),) - LOCAL_SRC_FILES += sysdeps_win32.c -endif + adb_main.cpp \ + console.cpp \ + commandline.cpp \ + adb_client.cpp \ + services.cpp \ + file_sync_client.cpp \ LOCAL_CFLAGS += \ -Wall -Werror \ @@ -148,12 +154,11 @@ LOCAL_MODULE_TAGS := debug LOCAL_STATIC_LIBRARIES := \ libadb \ - libzipfile \ libcrypto_static \ $(EXTRA_STATIC_LIBS) \ ifeq ($(USE_SYSDEPS_WIN32),) - LOCAL_STATIC_LIBRARIES += libcutils + LOCAL_STATIC_LIBRARIES += libcutils endif LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk @@ -176,25 +181,25 @@ include $(CLEAR_VARS) LOCAL_CLANG := $(ADB_CLANG) LOCAL_SRC_FILES := \ - adb_main.c \ - services.c \ - file_sync_service.c \ - framebuffer_service.c \ - remount_service.c \ - set_verity_enable_state_service.c \ + adb_main.cpp \ + services.cpp \ + file_sync_service.cpp \ + framebuffer_service.cpp \ + remount_service.cpp \ + set_verity_enable_state_service.cpp \ LOCAL_CFLAGS := \ - -O2 \ - -g \ - -DADB_HOST=0 \ - -D_GNU_SOURCE \ - -Wall -Wno-unused-parameter -Werror -Wno-deprecated-declarations \ + -DADB_HOST=0 \ + -D_GNU_SOURCE \ + -Wall -Werror \ + -Wno-unused-parameter \ + -Wno-deprecated-declarations \ ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT))) LOCAL_CFLAGS += -DALLOW_ADBD_ROOT=1 endif -ifneq (,$(filter userdebug,$(TARGET_BUILD_VARIANT))) +ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT))) LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1 endif @@ -140,10 +140,13 @@ void adb_trace_init(void) } } -apacket *get_apacket(void) +apacket* get_apacket(void) { - apacket *p = malloc(sizeof(apacket)); - if(p == 0) fatal("failed to allocate an apacket"); + apacket* p = reinterpret_cast<apacket*>(malloc(sizeof(apacket))); + if (p == nullptr) { + fatal("failed to allocate an apacket"); + } + memset(p, 0, sizeof(apacket) - MAX_PAYLOAD); return p; } @@ -293,7 +296,7 @@ void send_connect(atransport *t) } #if ADB_HOST -static char *connection_state_name(atransport *t) +static const char* connection_state_name(atransport *t) { if (t == NULL) { return "unknown"; @@ -713,8 +716,8 @@ int handle_forward_request(const char* service, transport_type ttype, char* seri // Create the list of forward redirections. int buffer_size = format_listeners(NULL, 0); // Add one byte for the trailing zero. - char* buffer = malloc(buffer_size + 1); - if (buffer == NULL) { + char* buffer = reinterpret_cast<char*>(malloc(buffer_size + 1)); + if (buffer == nullptr) { sendfailmsg(reply_fd, "not enough memory"); return 1; } @@ -740,7 +743,7 @@ int handle_forward_request(const char* service, transport_type ttype, char* seri if (!strncmp(service, "forward:",8) || !strncmp(service, "killforward:",12)) { - char *local, *remote, *err; + char *local, *remote; int r; atransport *transport; @@ -777,6 +780,7 @@ int handle_forward_request(const char* service, transport_type ttype, char* seri } } + const char* err; transport = acquire_one_transport(CS_ANY, ttype, serial, &err); if (!transport) { sendfailmsg(reply_fd, err); @@ -835,7 +839,6 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r // "transport-local:" is used for switching transport to the only local transport // "transport-any:" is used for switching transport to the only transport if (!strncmp(service, "transport", strlen("transport"))) { - char* error_string = "unknown failure"; transport_type type = kTransportAny; if (!strncmp(service, "transport-usb", strlen("transport-usb"))) { @@ -849,6 +852,7 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r serial = service; } + const char* error_string = "unknown failure"; transport = acquire_one_transport(CS_ANY, type, serial, &error_string); if (transport) { @@ -911,8 +915,8 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r } if(!strncmp(service,"get-serialno",strlen("get-serialno"))) { - char *out = "unknown"; - transport = acquire_one_transport(CS_ANY, ttype, serial, NULL); + const char *out = "unknown"; + transport = acquire_one_transport(CS_ANY, ttype, serial, NULL); if (transport && transport->serial) { out = transport->serial; } @@ -920,8 +924,8 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r return 0; } if(!strncmp(service,"get-devpath",strlen("get-devpath"))) { - char *out = "unknown"; - transport = acquire_one_transport(CS_ANY, ttype, serial, NULL); + const char *out = "unknown"; + transport = acquire_one_transport(CS_ANY, ttype, serial, NULL); if (transport && transport->devpath) { out = transport->devpath; } @@ -938,7 +942,7 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r if(!strncmp(service,"get-state",strlen("get-state"))) { transport = acquire_one_transport(CS_ANY, ttype, serial, NULL); - char *state = connection_state_name(transport); + const char *state = connection_state_name(transport); send_msg_with_okay(reply_fd, state, strlen(state)); return 0; } @@ -239,8 +239,8 @@ struct alistener fdevent fde; int fd; - const char *local_name; - const char *connect_to; + char *local_name; + char *connect_to; atransport *transport; adisconnect disconnect; }; @@ -298,9 +298,6 @@ int handle_forward_request(const char* service, transport_type ttype, char* seri #if !ADB_HOST void framebuffer_service(int fd, void *cookie); -// Allow enable-verity to write to system and vendor block devices -int make_block_device_writable(const char* dev); -void remount_service(int fd, void *cookie); void set_verity_enabled_state_service(int fd, void* cookie); #endif @@ -348,7 +345,7 @@ void usb_kick(usb_handle *h); int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol); #endif -int adb_commandline(int argc, char **argv); +int adb_commandline(int argc, const char **argv); int connection_state(atransport *t); diff --git a/adb/adb_auth.c b/adb/adb_auth.cpp index c236b64..c236b64 100644 --- a/adb/adb_auth.c +++ b/adb/adb_auth.cpp diff --git a/adb/adb_auth.h b/adb/adb_auth.h index cece5e3..e0425ad 100644 --- a/adb/adb_auth.h +++ b/adb/adb_auth.h @@ -23,7 +23,6 @@ extern "C" { extern int auth_enabled; -void adb_auth_init(void); int adb_auth_keygen(const char* filename); void adb_auth_verified(atransport *t); @@ -40,7 +39,9 @@ void send_auth_publickey(atransport *t); #if ADB_HOST -int adb_auth_sign(void *key, void *token, size_t token_size, void *sig); +void adb_auth_init(void); +int adb_auth_sign(void *key, const unsigned char* token, size_t token_size, + unsigned char* sig); void *adb_auth_nextkey(void *current); int adb_auth_get_userkey(unsigned char *data, size_t len); @@ -50,12 +51,17 @@ static inline void adb_auth_confirm_key(unsigned char *data, size_t len, atransp #else // !ADB_HOST -static inline int adb_auth_sign(void* key, void *token, size_t token_size, void *sig) { return 0; } +static inline int adb_auth_sign(void* key, const unsigned char* token, + size_t token_size, unsigned char* sig) { + return 0; +} static inline void *adb_auth_nextkey(void *current) { return NULL; } static inline int adb_auth_get_userkey(unsigned char *data, size_t len) { return 0; } +void adbd_auth_init(void); +void adbd_cloexec_auth_socket(); int adb_auth_generate_token(void *token, size_t token_size); -int adb_auth_verify(void *token, void *sig, int siglen); +int adb_auth_verify(uint8_t* token, uint8_t* sig, int siglen); void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t); #endif // ADB_HOST diff --git a/adb/adb_auth_client.c b/adb/adb_auth_client.cpp index 7be883c..5dadcd9 100644 --- a/adb/adb_auth_client.c +++ b/adb/adb_auth_client.cpp @@ -37,7 +37,7 @@ struct adb_public_key { RSAPublicKey key; }; -static char *key_paths[] = { +static const char *key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", NULL @@ -53,7 +53,6 @@ static bool needs_retry = false; static void read_keys(const char *file, struct listnode *list) { - struct adb_public_key *key; FILE *f; char buf[MAX_PAYLOAD]; char *sep; @@ -67,8 +66,9 @@ static void read_keys(const char *file, struct listnode *list) while (fgets(buf, sizeof(buf), f)) { /* Allocate 4 extra bytes to decode the base64 data in-place */ - key = calloc(1, sizeof(*key) + 4); - if (!key) { + auto key = reinterpret_cast<adb_public_key*>( + calloc(1, sizeof(adb_public_key) + 4)); + if (key == nullptr) { D("Can't malloc key\n"); break; } @@ -109,8 +109,8 @@ static void free_keys(struct listnode *list) static void load_keys(struct listnode *list) { - char *path; - char **paths = key_paths; + const char* path; + const char** paths = key_paths; struct stat buf; list_init(list); @@ -138,10 +138,9 @@ int adb_auth_generate_token(void *token, size_t token_size) return ret * token_size; } -int adb_auth_verify(void *token, void *sig, int siglen) +int adb_auth_verify(uint8_t* token, uint8_t* sig, int siglen) { struct listnode *item; - struct adb_public_key *key; struct listnode key_list; int ret = 0; @@ -151,7 +150,7 @@ int adb_auth_verify(void *token, void *sig, int siglen) load_keys(&key_list); list_for_each(item, &key_list) { - key = node_to_item(item, struct adb_public_key, node); + adb_public_key* key = node_to_item(item, struct adb_public_key, node); ret = RSA_verify(&key->key, sig, siglen, token, SHA_DIGEST_SIZE); if (ret) break; @@ -250,19 +249,23 @@ static void adb_auth_listener(int fd, unsigned events, void *data) } } -void adb_auth_init(void) -{ - int fd, ret; - - fd = android_get_control_socket("adbd"); - if (fd < 0) { +void adbd_cloexec_auth_socket() { + int fd = android_get_control_socket("adbd"); + if (fd == -1) { D("Failed to get adbd socket\n"); return; } fcntl(fd, F_SETFD, FD_CLOEXEC); +} - ret = listen(fd, 4); - if (ret < 0) { +void adbd_auth_init(void) { + int fd = android_get_control_socket("adbd"); + if (fd == -1) { + D("Failed to get adbd socket\n"); + return; + } + + if (listen(fd, 4) == -1) { D("Failed to listen on '%d'\n", fd); return; } diff --git a/adb/adb_auth_host.c b/adb/adb_auth_host.cpp index 1d48667..aba23d4 100644 --- a/adb/adb_auth_host.c +++ b/adb/adb_auth_host.cpp @@ -157,7 +157,7 @@ static int write_public_keyfile(RSA *private_key, const char *private_key_path) RSAPublicKey pkey; FILE *outfile = NULL; char path[PATH_MAX], info[MAX_PAYLOAD]; - uint8_t *encoded = NULL; + uint8_t* encoded = nullptr; size_t encoded_length; int ret = 0; @@ -191,8 +191,8 @@ static int write_public_keyfile(RSA *private_key, const char *private_key_path) encoded_length = 1 + ((sizeof(pkey) + 2) / 3 * 4); #endif - encoded = malloc(encoded_length); - if (encoded == NULL) { + encoded = reinterpret_cast<uint8_t*>(malloc(encoded_length)); + if (encoded == nullptr) { D("Allocation failure"); goto out; } @@ -272,18 +272,16 @@ out: static int read_key(const char *file, struct listnode *list) { - struct adb_private_key *key; - FILE *f; - D("read_key '%s'\n", file); - f = fopen(file, "r"); + FILE* f = fopen(file, "r"); if (!f) { D("Failed to open '%s'\n", file); return 0; } - key = malloc(sizeof(*key)); + adb_private_key* key = reinterpret_cast<adb_private_key*>( + malloc(sizeof(adb_private_key))); if (!key) { D("Failed to alloc key\n"); fclose(f); @@ -390,7 +388,8 @@ static void get_vendor_keys(struct listnode *list) } } -int adb_auth_sign(void *node, void *token, size_t token_size, void *sig) +int adb_auth_sign(void *node, const unsigned char* token, size_t token_size, + unsigned char* sig) { unsigned int len; struct adb_private_key *key = node_to_item(node, struct adb_private_key, node); @@ -433,31 +432,33 @@ void *adb_auth_nextkey(void *current) int adb_auth_get_userkey(unsigned char *data, size_t len) { char path[PATH_MAX]; - char *file; - int ret; - - ret = get_user_keyfilepath(path, sizeof(path) - 4); + int ret = get_user_keyfilepath(path, sizeof(path) - 4); if (ret < 0 || ret >= (signed)(sizeof(path) - 4)) { D("Error getting user key filename"); return 0; } strcat(path, ".pub"); - file = load_file(path, (unsigned*)&ret); - if (!file) { + // TODO(danalbert): ReadFileToString + unsigned size; + char* file_data = reinterpret_cast<char*>(load_file(path, &size)); + if (file_data == nullptr) { D("Can't load '%s'\n", path); return 0; } - if (len < (size_t)(ret + 1)) { - D("%s: Content too large ret=%d\n", path, ret); + if (len < (size_t)(size + 1)) { + D("%s: Content too large ret=%d\n", path, size); + free(file_data); return 0; } - memcpy(data, file, ret); - data[ret] = '\0'; + memcpy(data, file_data, size); + free(file_data); + file_data = nullptr; + data[size] = '\0'; - return ret + 1; + return size + 1; } int adb_auth_keygen(const char* filename) { diff --git a/adb/adb_client.c b/adb/adb_client.cpp index 5d2bbd7..a485aa2 100644 --- a/adb/adb_client.c +++ b/adb/adb_client.cpp @@ -28,7 +28,6 @@ #define TRACE_TAG TRACE_ADB #include "adb_client.h" #include "adb_io.h" -#include "zipfile/zipfile.h" static transport_type __adb_transport = kTransportAny; static const char* __adb_serial = NULL; @@ -115,7 +114,7 @@ static int switch_socket_transport(int fd) if (__adb_serial) snprintf(service, sizeof service, "host:transport:%s", __adb_serial); else { - char* transport_type = "???"; + const char* transport_type = "???"; switch (__adb_transport) { case kTransportUsb: @@ -328,8 +327,8 @@ int adb_command(const char *service) char *adb_query(const char *service) { char buf[5]; - unsigned n; - char *tmp; + unsigned long n; + char* tmp; D("adb_query: %s\n", service); int fd = adb_connect(service); @@ -347,7 +346,7 @@ char *adb_query(const char *service) goto oops; } - tmp = malloc(n + 1); + tmp = reinterpret_cast<char*>(malloc(n + 1)); if(tmp == 0) goto oops; if(!ReadFdExactly(fd, tmp, n) == 0) { diff --git a/adb/adb_client.h b/adb/adb_client.h index 6ba3b38..9af176f 100644 --- a/adb/adb_client.h +++ b/adb/adb_client.h @@ -47,7 +47,7 @@ int adb_get_emulator_console_port(void); * is zero, or more than one emulator connected (or if you use -s <serial> * with a <serial> that does not designate an emulator) */ -int adb_send_emulator_command(int argc, char** argv); +int adb_send_emulator_command(int argc, const char** argv); /* return verbose error string from last operation */ const char *adb_error(void); diff --git a/adb/adb_io.cpp b/adb/adb_io.cpp index ca208ad..4dd9f4d 100644 --- a/adb/adb_io.cpp +++ b/adb/adb_io.cpp @@ -33,7 +33,7 @@ bool ReadFdExactly(int fd, void* buf, size_t len) { D("readx: fd=%d wanted=%zu\n", fd, len); while (len > 0) { - int r = TEMP_FAILURE_RETRY(adb_read(fd, p, len)); + int r = adb_read(fd, p, len); if (r > 0) { len -= r; p += r; @@ -69,7 +69,7 @@ bool WriteFdExactly(int fd, const void* buf, size_t len) { #endif while (len > 0) { - r = TEMP_FAILURE_RETRY(adb_write(fd, p, len)); + r = adb_write(fd, p, len); if (r == -1) { D("writex: fd=%d error %d: %s\n", fd, errno, strerror(errno)); if (errno == EAGAIN) { diff --git a/adb/adb_io_test.cpp b/adb/adb_io_test.cpp index 330d9ce..0c69bc9 100644 --- a/adb/adb_io_test.cpp +++ b/adb/adb_io_test.cpp @@ -24,7 +24,7 @@ #include <string> -#include "utils/file.h" +#include "base/file.h" class TemporaryFile { public: @@ -55,7 +55,7 @@ TEST(io, ReadFdExactly_whole) { TemporaryFile tf; ASSERT_NE(-1, tf.fd); - ASSERT_TRUE(android::WriteStringToFd(expected, tf.fd)) << strerror(errno); + ASSERT_TRUE(android::base::WriteStringToFd(expected, tf.fd)) << strerror(errno); ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0)); // Test reading the whole file. @@ -69,7 +69,7 @@ TEST(io, ReadFdExactly_eof) { TemporaryFile tf; ASSERT_NE(-1, tf.fd); - ASSERT_TRUE(android::WriteStringToFd(expected, tf.fd)) << strerror(errno); + ASSERT_TRUE(android::base::WriteStringToFd(expected, tf.fd)) << strerror(errno); ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0)); // Test that not having enough data will fail. @@ -83,7 +83,7 @@ TEST(io, ReadFdExactly_partial) { TemporaryFile tf; ASSERT_NE(-1, tf.fd); - ASSERT_TRUE(android::WriteStringToFd(input, tf.fd)) << strerror(errno); + ASSERT_TRUE(android::base::WriteStringToFd(input, tf.fd)) << strerror(errno); ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0)); // Test reading a partial file. @@ -106,7 +106,7 @@ TEST(io, WriteFdExactly_whole) { ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0)); std::string s; - ASSERT_TRUE(android::ReadFdToString(tf.fd, &s)); + ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s)); EXPECT_STREQ(expected, s.c_str()); } @@ -123,7 +123,7 @@ TEST(io, WriteFdExactly_partial) { expected.pop_back(); std::string s; - ASSERT_TRUE(android::ReadFdToString(tf.fd, &s)); + ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s)); EXPECT_EQ(expected, s); } @@ -137,6 +137,6 @@ TEST(io, WriteStringFully) { ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0)); std::string s; - ASSERT_TRUE(android::ReadFdToString(tf.fd, &s)); + ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s)); EXPECT_STREQ(str, s.c_str()); } diff --git a/adb/adb_listeners.c b/adb/adb_listeners.cpp index f68b876..84b9c64 100644 --- a/adb/adb_listeners.c +++ b/adb/adb_listeners.cpp @@ -54,24 +54,26 @@ void ss_listener_event_func(int _fd, unsigned ev, void *_l) } } -void listener_event_func(int _fd, unsigned ev, void *_l) +void listener_event_func(int _fd, unsigned ev, void* _l) { - alistener *l = _l; + alistener* listener = reinterpret_cast<alistener*>(_l); asocket *s; - if(ev & FDE_READ) { + if (ev & FDE_READ) { struct sockaddr addr; socklen_t alen; int fd; alen = sizeof(addr); fd = adb_socket_accept(_fd, &addr, &alen); - if(fd < 0) return; + if (fd < 0) { + return; + } s = create_local_socket(fd); - if(s) { - s->transport = l->transport; - connect_to_remote(s, l->connect_to); + if (s) { + s->transport = listener->transport; + connect_to_remote(s, listener->connect_to); return; } @@ -102,11 +104,9 @@ static void free_listener(alistener* l) free(l); } -void listener_disconnect(void* _l, atransport* t) +void listener_disconnect(void* listener, atransport* t) { - alistener* l = _l; - - free_listener(l); + free_listener(reinterpret_cast<alistener*>(listener)); } int local_name_to_fd(const char *name) @@ -220,20 +220,16 @@ install_status_t install_listener(const char *local_name, atransport* transport, int no_rebind) { - alistener *l; + for (alistener* l = listener_list.next; l != &listener_list; l = l->next) { + if (strcmp(local_name, l->local_name) == 0) { + char* cto; - //printf("install_listener('%s','%s')\n", local_name, connect_to); - - for(l = listener_list.next; l != &listener_list; l = l->next){ - if(strcmp(local_name, l->local_name) == 0) { - char *cto; - - /* can't repurpose a smartsocket */ + /* can't repurpose a smartsocket */ if(l->connect_to[0] == '*') { return INSTALL_STATUS_INTERNAL_ERROR; } - /* can't repurpose a listener if 'no_rebind' is true */ + /* can't repurpose a listener if 'no_rebind' is true */ if (no_rebind) { return INSTALL_STATUS_CANNOT_REBIND; } @@ -243,7 +239,6 @@ install_status_t install_listener(const char *local_name, return INSTALL_STATUS_INTERNAL_ERROR; } - //printf("rebinding '%s' to '%s'\n", local_name, connect_to); free((void*) l->connect_to); l->connect_to = cto; if (l->transport != transport) { @@ -255,38 +250,51 @@ install_status_t install_listener(const char *local_name, } } - if((l = calloc(1, sizeof(alistener))) == 0) goto nomem; - if((l->local_name = strdup(local_name)) == 0) goto nomem; - if((l->connect_to = strdup(connect_to)) == 0) goto nomem; + alistener* listener = reinterpret_cast<alistener*>( + calloc(1, sizeof(alistener))); + if (listener == nullptr) { + goto nomem; + } + + listener->local_name = strdup(local_name); + if (listener->local_name == nullptr) { + goto nomem; + } + listener->connect_to = strdup(connect_to); + if (listener->connect_to == nullptr) { + goto nomem; + } - l->fd = local_name_to_fd(local_name); - if(l->fd < 0) { - free((void*) l->local_name); - free((void*) l->connect_to); - free(l); + listener->fd = local_name_to_fd(local_name); + if (listener->fd < 0) { + free(listener->local_name); + free(listener->connect_to); + free(listener); printf("cannot bind '%s'\n", local_name); - return -2; + return INSTALL_STATUS_CANNOT_BIND; } - close_on_exec(l->fd); - if(!strcmp(l->connect_to, "*smartsocket*")) { - fdevent_install(&l->fde, l->fd, ss_listener_event_func, l); + close_on_exec(listener->fd); + if (!strcmp(listener->connect_to, "*smartsocket*")) { + fdevent_install(&listener->fde, listener->fd, ss_listener_event_func, + listener); } else { - fdevent_install(&l->fde, l->fd, listener_event_func, l); + fdevent_install(&listener->fde, listener->fd, listener_event_func, + listener); } - fdevent_set(&l->fde, FDE_READ); + fdevent_set(&listener->fde, FDE_READ); - l->next = &listener_list; - l->prev = listener_list.prev; - l->next->prev = l; - l->prev->next = l; - l->transport = transport; + listener->next = &listener_list; + listener->prev = listener_list.prev; + listener->next->prev = listener; + listener->prev->next = listener; + listener->transport = transport; if (transport) { - l->disconnect.opaque = l; - l->disconnect.func = listener_disconnect; - add_transport_disconnect(transport, &l->disconnect); + listener->disconnect.opaque = listener; + listener->disconnect.func = listener_disconnect; + add_transport_disconnect(transport, &listener->disconnect); } return INSTALL_STATUS_OK; diff --git a/adb/adb_main.c b/adb/adb_main.cpp index f8475c7..1d9cc3b 100644 --- a/adb/adb_main.c +++ b/adb/adb_main.cpp @@ -273,10 +273,14 @@ int adb_main(int is_daemon, int server_port) exit(1); } #else + // We need to call this even if auth isn't enabled because the file + // descriptor will always be open. + adbd_cloexec_auth_socket(); + property_get("ro.adb.secure", value, "0"); auth_enabled = !strcmp(value, "1"); if (auth_enabled) - adb_auth_init(); + adbd_auth_init(); // Our external storage path may be different than apps, since // we aren't able to bind mount after dropping root. @@ -387,7 +391,7 @@ int main(int argc, char **argv) adb_sysdeps_init(); adb_trace_init(); D("Handling commandline()\n"); - return adb_commandline(argc - 1, argv + 1); + return adb_commandline(argc - 1, const_cast<const char**>(argv + 1)); #else /* If adbd runs inside the emulator this will enable adb tracing via * adb-debug qemud service in the emulator. */ diff --git a/adb/commandline.c b/adb/commandline.cpp index a8ad7bd..4538b04 100644 --- a/adb/commandline.c +++ b/adb/commandline.cpp @@ -40,31 +40,31 @@ #include "adb_io.h" #include "file_sync_service.h" -static int do_cmd(transport_type ttype, char* serial, char *cmd, ...); +static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...); -void get_my_path(char *s, size_t maxLen); int find_sync_dirs(const char *srcarg, - char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out); -int install_app(transport_type transport, char* serial, int argc, char** argv); -int install_multiple_app(transport_type transport, char* serial, int argc, char** argv); -int uninstall_app(transport_type transport, char* serial, int argc, char** argv); + char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out, + char **oem_srcdir_out); +int install_app(transport_type transport, const char* serial, int argc, + const char** argv); +int install_multiple_app(transport_type transport, const char* serial, int argc, + const char** argv); +int uninstall_app(transport_type transport, const char* serial, int argc, + const char** argv); static const char *gProductOutPath = NULL; extern int gListenAll; static char *product_file(const char *extra) { - int n; - char *x; - if (gProductOutPath == NULL) { fprintf(stderr, "adb: Product directory not specified; " "use -p or define ANDROID_PRODUCT_OUT\n"); exit(1); } - n = strlen(gProductOutPath) + strlen(extra) + 2; - x = malloc(n); + int n = strlen(gProductOutPath) + strlen(extra) + 2; + char* x = reinterpret_cast<char*>(malloc(n)); if (x == 0) { fprintf(stderr, "adb: Out of memory (product_file())\n"); exit(1); @@ -207,7 +207,7 @@ void help() " adb get-serialno - prints: <serial-number>\n" " adb get-devpath - prints: <device-path>\n" " adb status-window - continuously print device status for a specified device\n" - " adb remount - remounts the /system and /vendor (if present) partitions on the device read-write\n" + " adb remount - remounts the /system, /vendor (if present) and /oem (if present) partitions on the device read-write\n" " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n" " adb reboot-bootloader - reboots the device into the bootloader\n" " adb root - restarts the adbd daemon with root permissions\n" @@ -223,9 +223,9 @@ void help() "adb sync notes: adb sync [ <directory> ]\n" " <localdir> can be interpreted in several ways:\n" "\n" - " - If <directory> is not specified, /system, /vendor (if present), and /data partitions will be updated.\n" + " - If <directory> is not specified, /system, /vendor (if present), /oem (if present) and /data partitions will be updated.\n" "\n" - " - If it is \"system\", \"vendor\" or \"data\", only the corresponding partition\n" + " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n" " is updated.\n" "\n" "environmental variables:\n" @@ -422,7 +422,6 @@ int interactive_shell(void) { adb_thread_t thr; int fdi, fd; - int *fds; fd = adb_connect("shell:"); if(fd < 0) { @@ -431,7 +430,7 @@ int interactive_shell(void) } fdi = 0; //dup(0); - fds = malloc(sizeof(int) * 2); + int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2)); fds[0] = fd; fds[1] = fdi; @@ -464,7 +463,6 @@ int adb_download_buffer(const char *service, const char *fn, const void* data, i char buf[4096]; unsigned total; int fd; - const unsigned char *ptr; sprintf(buf,"%s:%d", service, sz); fd = adb_connect(buf); @@ -477,7 +475,7 @@ int adb_download_buffer(const char *service, const char *fn, const void* data, i opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt)); total = sz; - ptr = data; + const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data); if(progress) { char *x = strrchr(service, ':'); @@ -557,14 +555,15 @@ int adb_download(const char *service, const char *fn, unsigned progress) * we hang up. */ int adb_sideload_host(const char* fn) { - uint8_t* data; unsigned sz; size_t xfer = 0; int status; + int last_percent = -1; + int opt = SIDELOAD_HOST_BLOCK_SIZE; printf("loading: '%s'", fn); fflush(stdout); - data = load_file(fn, &sz); + uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz)); if (data == 0) { printf("\n"); fprintf(stderr, "* cannot read '%s' *\n", fn); @@ -582,10 +581,8 @@ int adb_sideload_host(const char* fn) { goto done; } - int opt = SIDELOAD_HOST_BLOCK_SIZE; opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt)); - int last_percent = -1; for (;;) { if (!ReadFdExactly(fd, buf, 8)) { fprintf(stderr, "* failed to read command: %s\n", adb_error()); @@ -739,13 +736,12 @@ static char *escape_arg(const char *s) * ppp dev:/dev/omap_csmi_tty0 <ppp options> * */ -int ppp(int argc, char **argv) +int ppp(int argc, const char **argv) { #if defined(_WIN32) fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]); return -1; #else - char *adb_service_name; pid_t pid; int fd; @@ -756,8 +752,7 @@ int ppp(int argc, char **argv) return 1; } - adb_service_name = argv[1]; - + const char* adb_service_name = argv[1]; fd = adb_connect(adb_service_name); if(fd < 0) { @@ -807,7 +802,8 @@ int ppp(int argc, char **argv) #endif /* !defined(_WIN32) */ } -static int send_shellcommand(transport_type transport, char* serial, char* buf) +static int send_shellcommand(transport_type transport, const char* serial, + char* buf) { int fd, ret; @@ -828,7 +824,8 @@ static int send_shellcommand(transport_type transport, char* serial, char* buf) return ret; } -static int logcat(transport_type transport, char* serial, int argc, char **argv) +static int logcat(transport_type transport, const char* serial, int argc, + const char** argv) { char buf[4096]; @@ -877,7 +874,7 @@ static int mkdirs(const char *path) return 0; } -static int backup(int argc, char** argv) { +static int backup(int argc, const char** argv) { char buf[4096]; char default_name[32]; const char* filename = strcpy(default_name, "./backup.ab"); @@ -933,7 +930,7 @@ static int backup(int argc, char** argv) { return 0; } -static int restore(int argc, char** argv) { +static int restore(int argc, const char** argv) { const char* filename; int fd, tarFd; @@ -1102,8 +1099,9 @@ static const char *find_product_out_path(const char *hint) return path_buf; } -static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2, - int *show_progress, int *copy_attrs) { +static void parse_push_pull_args(const char **arg, int narg, char const **path1, + char const **path2, int *show_progress, + int *copy_attrs) { *show_progress = 0; *copy_attrs = 0; @@ -1130,7 +1128,7 @@ static void parse_push_pull_args(char **arg, int narg, char const **path1, char } } -int adb_commandline(int argc, char **argv) +int adb_commandline(int argc, const char **argv) { char buf[4096]; int no_daemon = 0; @@ -1139,8 +1137,8 @@ int adb_commandline(int argc, char **argv) int persist = 0; int r; transport_type ttype = kTransportAny; - char* serial = NULL; - char* server_port_str = NULL; + const char* serial = NULL; + const char* server_port_str = NULL; /* If defined, this should be an absolute path to * the directory containing all of the various system images @@ -1274,7 +1272,7 @@ int adb_commandline(int argc, char **argv) /* handle wait-for-* prefix */ if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) { - char* service = argv[0]; + const char* service = argv[0]; if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) { if (ttype == kTransportUsb) { service = "wait-for-usb"; @@ -1308,7 +1306,7 @@ int adb_commandline(int argc, char **argv) /* adb_connect() commands */ if (!strcmp(argv[0], "devices")) { char *tmp; - char *listopt; + const char *listopt; if (argc < 2) listopt = ""; else if (argc == 2 && !strcmp(argv[1], "-l")) @@ -1635,7 +1633,9 @@ int adb_commandline(int argc, char **argv) return uninstall_app(ttype, serial, argc, argv); } else if (!strcmp(argv[0], "sync")) { - char *srcarg, *android_srcpath, *data_srcpath, *vendor_srcpath; + const char* srcarg; + char *system_srcpath, *data_srcpath, *vendor_srcpath, *oem_srcpath; + int listonly = 0; int ret; @@ -1655,18 +1655,22 @@ int adb_commandline(int argc, char **argv) } else { return usage(); } - ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath, &vendor_srcpath); + ret = find_sync_dirs(srcarg, &system_srcpath, &data_srcpath, &vendor_srcpath, + &oem_srcpath); if (ret != 0) return usage(); - if (android_srcpath != NULL) - ret = do_sync_sync(android_srcpath, "/system", listonly); + if (system_srcpath != NULL) + ret = do_sync_sync(system_srcpath, "/system", listonly); if (ret == 0 && vendor_srcpath != NULL) ret = do_sync_sync(vendor_srcpath, "/vendor", listonly); + if(ret == 0 && oem_srcpath != NULL) + ret = do_sync_sync(oem_srcpath, "/oem", listonly); if (ret == 0 && data_srcpath != NULL) ret = do_sync_sync(data_srcpath, "/data", listonly); - free(android_srcpath); + free(system_srcpath); free(vendor_srcpath); + free(oem_srcpath); free(data_srcpath); return ret; } @@ -1736,9 +1740,9 @@ int adb_commandline(int argc, char **argv) } #define MAX_ARGV_LENGTH 16 -static int do_cmd(transport_type ttype, char* serial, char *cmd, ...) +static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...) { - char *argv[MAX_ARGV_LENGTH]; + const char *argv[MAX_ARGV_LENGTH]; int argc; va_list ap; @@ -1772,54 +1776,65 @@ static int do_cmd(transport_type ttype, char* serial, char *cmd, ...) } int find_sync_dirs(const char *srcarg, - char **android_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out) + char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out, + char **oem_srcdir_out) { - char *android_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL; + char *system_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL, *oem_srcdir = NULL; struct stat st; if(srcarg == NULL) { - android_srcdir = product_file("system"); + system_srcdir = product_file("system"); data_srcdir = product_file("data"); vendor_srcdir = product_file("vendor"); - /* Check if vendor partition exists */ + oem_srcdir = product_file("oem"); + // Check if vendor partition exists. if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode)) vendor_srcdir = NULL; + // Check if oem partition exists. + if (lstat(oem_srcdir, &st) || !S_ISDIR(st.st_mode)) + oem_srcdir = NULL; } else { - /* srcarg may be "data", "system" or NULL. - * if srcarg is NULL, then both data and system are synced - */ + // srcarg may be "data", "system", "vendor", "oem" or NULL. + // If srcarg is NULL, then all partitions are synced. if(strcmp(srcarg, "system") == 0) { - android_srcdir = product_file("system"); + system_srcdir = product_file("system"); } else if(strcmp(srcarg, "data") == 0) { data_srcdir = product_file("data"); } else if(strcmp(srcarg, "vendor") == 0) { vendor_srcdir = product_file("vendor"); + } else if(strcmp(srcarg, "oem") == 0) { + oem_srcdir = product_file("oem"); } else { - /* It's not "system", "vendor", or "data". - */ + // It's not "system", "data", "vendor", or "oem". return 1; } } - if(android_srcdir_out != NULL) - *android_srcdir_out = android_srcdir; + if(system_srcdir_out != NULL) + *system_srcdir_out = system_srcdir; else - free(android_srcdir); + free(system_srcdir); if(vendor_srcdir_out != NULL) *vendor_srcdir_out = vendor_srcdir; else free(vendor_srcdir); + if(oem_srcdir_out != NULL) + *oem_srcdir_out = oem_srcdir; + else + free(oem_srcdir); + if(data_srcdir_out != NULL) - *data_srcdir_out = data_srcdir; - else - free(data_srcdir); + *data_srcdir_out = data_srcdir; + else + free(data_srcdir); + return 0; } -static int pm_command(transport_type transport, char* serial, - int argc, char** argv) +static int pm_command(transport_type transport, const char* serial, + int argc, const char** argv) { char buf[4096]; @@ -1836,7 +1851,8 @@ static int pm_command(transport_type transport, char* serial, return 0; } -int uninstall_app(transport_type transport, char* serial, int argc, char** argv) +int uninstall_app(transport_type transport, const char* serial, int argc, + const char** argv) { /* if the user choose the -k option, we refuse to do it until devices are out with the option to uninstall the remaining data somehow (adb/ui) */ @@ -1854,7 +1870,7 @@ int uninstall_app(transport_type transport, char* serial, int argc, char** argv) return pm_command(transport, serial, argc, argv); } -static int delete_file(transport_type transport, char* serial, char* filename) +static int delete_file(transport_type transport, const char* serial, char* filename) { char buf[4096]; char* quoted; @@ -1879,7 +1895,8 @@ static const char* get_basename(const char* filename) } } -int install_app(transport_type transport, char* serial, int argc, char** argv) +int install_app(transport_type transport, const char* serial, int argc, + const char** argv) { static const char *const DATA_DEST = "/data/local/tmp/%s"; static const char *const SD_DEST = "/sdcard/tmp/%s"; @@ -1897,7 +1914,7 @@ int install_app(transport_type transport, char* serial, int argc, char** argv) // All other arguments passed through verbatim. int last_apk = -1; for (i = argc - 1; i >= 0; i--) { - char* file = argv[i]; + const char* file = argv[i]; char* dot = strrchr(file, '.'); if (dot && !strcasecmp(dot, ".apk")) { if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) { @@ -1915,7 +1932,7 @@ int install_app(transport_type transport, char* serial, int argc, char** argv) return -1; } - char* apk_file = argv[last_apk]; + const char* apk_file = argv[last_apk]; char apk_dest[PATH_MAX]; snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file)); int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */); @@ -1932,7 +1949,8 @@ cleanup_apk: return err; } -int install_multiple_app(transport_type transport, char* serial, int argc, char** argv) +int install_multiple_app(transport_type transport, const char* serial, int argc, + const char** argv) { char buf[1024]; int i; @@ -1943,7 +1961,7 @@ int install_multiple_app(transport_type transport, char* serial, int argc, char* // All other arguments passed through verbatim. int first_apk = -1; for (i = argc - 1; i >= 0; i--) { - char* file = argv[i]; + const char* file = argv[i]; char* dot = strrchr(file, '.'); if (dot && !strcasecmp(dot, ".apk")) { if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) { @@ -1998,7 +2016,7 @@ int install_multiple_app(transport_type transport, char* serial, int argc, char* // Valid session, now stream the APKs int success = 1; for (i = first_apk; i < argc; i++) { - char* file = argv[i]; + const char* file = argv[i]; if (stat(file, &sb) == -1) { fprintf(stderr, "Failed to stat %s\n", file); success = 0; diff --git a/adb/console.c b/adb/console.cpp index b813d33..452ee41 100644 --- a/adb/console.c +++ b/adb/console.cpp @@ -24,7 +24,7 @@ static int connect_to_console(void) } -int adb_send_emulator_command(int argc, char** argv) +int adb_send_emulator_command(int argc, const char** argv) { int fd, nn; diff --git a/adb/file_sync_client.c b/adb/file_sync_client.cpp index 3a0c666..4ba730b 100644 --- a/adb/file_sync_client.c +++ b/adb/file_sync_client.cpp @@ -32,7 +32,6 @@ #include "adb_client.h" #include "adb_io.h" #include "file_sync_service.h" -#include "zipfile/zipfile.h" static unsigned long long total_bytes; static long long start_time; @@ -580,7 +579,8 @@ copyinfo *mkcopyinfo(const char *spath, const char *dpath, int ssize = slen + nlen + 2; int dsize = dlen + nlen + 2; - copyinfo *ci = malloc(sizeof(copyinfo) + ssize + dsize); + copyinfo *ci = reinterpret_cast<copyinfo*>( + malloc(sizeof(copyinfo) + ssize + dsize)); if(ci == 0) { fprintf(stderr,"out of memory\n"); abort(); @@ -684,14 +684,14 @@ static int copy_local_dir_remote(int fd, const char *lpath, const char *rpath, i if((lpath[0] == 0) || (rpath[0] == 0)) return -1; if(lpath[strlen(lpath) - 1] != '/') { int tmplen = strlen(lpath)+2; - char *tmp = malloc(tmplen); + char *tmp = reinterpret_cast<char*>(malloc(tmplen)); if(tmp == 0) return -1; snprintf(tmp, tmplen, "%s/",lpath); lpath = tmp; } if(rpath[strlen(rpath) - 1] != '/') { int tmplen = strlen(rpath)+2; - char *tmp = malloc(tmplen); + char *tmp = reinterpret_cast<char*>(malloc(tmplen)); if(tmp == 0) return -1; snprintf(tmp, tmplen, "%s/",rpath); rpath = tmp; @@ -784,7 +784,8 @@ int do_sync_push(const char *lpath, const char *rpath, int show_progress) name++; } int tmplen = strlen(name) + strlen(rpath) + 2; - char *tmp = malloc(strlen(name) + strlen(rpath) + 2); + char *tmp = reinterpret_cast<char*>( + malloc(strlen(name) + strlen(rpath) + 2)); if(tmp == 0) return 1; snprintf(tmp, tmplen, "%s/%s", rpath, name); rpath = tmp; @@ -872,7 +873,7 @@ static int remote_build_list(int syncfd, copyinfo **filelist, return 0; } -static int set_time_and_mode(const char *lpath, unsigned int time, unsigned int mode) +static int set_time_and_mode(const char *lpath, time_t time, unsigned int mode) { struct utimbuf times = { time, time }; int r1 = utime(lpath, ×); @@ -890,7 +891,7 @@ static char *add_slash_to_path(const char *path) { if (path[strlen(path) - 1] != '/') { size_t len = strlen(path) + 2; - char *path_with_slash = malloc(len); + char *path_with_slash = reinterpret_cast<char*>(malloc(len)); if (path_with_slash == NULL) return NULL; snprintf(path_with_slash, len, "%s/", path); @@ -999,7 +1000,7 @@ int do_sync_pull(const char *rpath, const char *lpath, int show_progress, int co name++; } int tmplen = strlen(name) + strlen(lpath) + 2; - char *tmp = malloc(tmplen); + char *tmp = reinterpret_cast<char*>(malloc(tmplen)); if(tmp == 0) return 1; snprintf(tmp, tmplen, "%s/%s", lpath, name); lpath = tmp; diff --git a/adb/file_sync_service.c b/adb/file_sync_service.cpp index 0b289e8..ac01678 100644 --- a/adb/file_sync_service.c +++ b/adb/file_sync_service.cpp @@ -33,15 +33,11 @@ #include "file_sync_service.h" #include "private/android_filesystem_config.h" -/* TODO: use fs_config to configure permissions on /data */ -static bool is_on_system(const char *name) { - const char *SYSTEM = "/system/"; - return (strncmp(SYSTEM, name, strlen(SYSTEM)) == 0); -} - -static bool is_on_vendor(const char *name) { - const char *VENDOR = "/vendor/"; - return (strncmp(VENDOR, name, strlen(VENDOR)) == 0); +static bool should_use_fs_config(const char* path) { + // TODO: use fs_config to configure permissions on /data. + return strncmp("/system/", path, strlen("/system/")) == 0 || + strncmp("/vendor/", path, strlen("/vendor/")) == 0 || + strncmp("/oem/", path, strlen("/oem/")) == 0; } static int mkdirs(char *name) @@ -59,7 +55,7 @@ static int mkdirs(char *name) x = adb_dirstart(x); if(x == 0) return 0; *x = 0; - if (is_on_system(name) || is_on_vendor(name)) { + if (should_use_fs_config(name)) { fs_config(name, 1, &uid, &gid, &mode, &cap); } ret = adb_mkdir(name, mode); @@ -151,7 +147,7 @@ done: msg.dent.size = 0; msg.dent.time = 0; msg.dent.namelen = 0; - return !WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) ? 0 : -1; + return WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) ? 0 : -1; } static int fail_message(int s, const char *reason) @@ -368,7 +364,7 @@ static int do_send(int s, char *path, char *buffer) if(*tmp == '/') { tmp++; } - if (is_on_system(path) || is_on_vendor(path)) { + if (should_use_fs_config(path)) { fs_config(tmp, 0, &uid, &gid, &mode, &cap); } return handle_send_file(s, path, uid, gid, mode, buffer, do_unlink); @@ -420,7 +416,7 @@ void file_sync_service(int fd, void *cookie) char name[1025]; unsigned namelen; - char *buffer = malloc(SYNC_DATA_MAX); + char *buffer = reinterpret_cast<char*>(malloc(SYNC_DATA_MAX)); if(buffer == 0) goto fail; for(;;) { diff --git a/adb/framebuffer_service.c b/adb/framebuffer_service.cpp index 9d17d2c..7baad8b 100644 --- a/adb/framebuffer_service.c +++ b/adb/framebuffer_service.cpp @@ -62,10 +62,11 @@ void framebuffer_service(int fd, void *cookie) int fd_screencap; int w, h, f; int fds[2]; + pid_t pid; if (pipe2(fds, O_CLOEXEC) < 0) goto pipefail; - pid_t pid = fork(); + pid = fork(); if (pid < 0) goto done; if (pid == 0) { diff --git a/adb/get_my_path_darwin.c b/adb/get_my_path_darwin.c index ff1396c..b0c962e 100644 --- a/adb/get_my_path_darwin.c +++ b/adb/get_my_path_darwin.c @@ -17,6 +17,8 @@ #import <Carbon/Carbon.h> #include <unistd.h> +#include "adb.h" + void get_my_path(char *s, size_t maxLen) { CFBundleRef mainBundle = CFBundleGetMainBundle(); diff --git a/adb/get_my_path_linux.c b/adb/get_my_path_linux.cpp index 179c3dd..11c0b21 100644 --- a/adb/get_my_path_linux.c +++ b/adb/get_my_path_linux.cpp @@ -14,10 +14,12 @@ * limitations under the License. */ -#include <sys/types.h> -#include <unistd.h> #include <limits.h> #include <stdio.h> +#include <sys/types.h> +#include <unistd.h> + +#include "adb.h" void get_my_path(char *exe, size_t maxLen) { diff --git a/adb/get_my_path_windows.c b/adb/get_my_path_windows.cpp index ddf2816..9d23e1c 100644 --- a/adb/get_my_path_windows.c +++ b/adb/get_my_path_windows.cpp @@ -14,10 +14,12 @@ * limitations under the License. */ -#include <limits.h> #include <assert.h> +#include <limits.h> #include <windows.h> +#include "adb.h" + void get_my_path(char *exe, size_t maxLen) { char *r; diff --git a/adb/jdwp_service.c b/adb/jdwp_service.cpp index 3074e42..f0b4ba7 100644 --- a/adb/jdwp_service.c +++ b/adb/jdwp_service.cpp @@ -194,7 +194,8 @@ static void jdwp_process_event(int, unsigned, void*); /* forward */ static JdwpProcess* jdwp_process_alloc( int socket ) { - JdwpProcess* proc = calloc(1,sizeof(*proc)); + JdwpProcess* proc = reinterpret_cast<JdwpProcess*>( + calloc(1, sizeof(*proc))); if (proc == NULL) { D("not enough memory to create new JDWP process\n"); @@ -234,7 +235,7 @@ jdwp_process_alloc( int socket ) static void jdwp_process_event( int socket, unsigned events, void* _proc ) { - JdwpProcess* proc = _proc; + JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc); if (events & FDE_READ) { if (proc->pid < 0) { @@ -601,7 +602,7 @@ jdwp_socket_ready( asocket* s ) asocket* create_jdwp_service_socket( void ) { - JdwpSocket* s = calloc(sizeof(*s),1); + JdwpSocket* s = reinterpret_cast<JdwpSocket*>(calloc(sizeof(*s), 1)); if (s == NULL) return NULL; @@ -696,7 +697,7 @@ jdwp_tracker_enqueue( asocket* s, apacket* p ) asocket* create_jdwp_tracker_service_socket( void ) { - JdwpTracker* t = calloc(sizeof(*t),1); + JdwpTracker* t = reinterpret_cast<JdwpTracker*>(calloc(sizeof(*t), 1)); if (t == NULL) return NULL; diff --git a/adb/qemu_tracing.c b/adb/qemu_tracing.cpp index f31eae8..f31eae8 100644 --- a/adb/qemu_tracing.c +++ b/adb/qemu_tracing.cpp diff --git a/adb/remount_service.c b/adb/remount_service.cpp index 414b316..a83d5b1 100644 --- a/adb/remount_service.c +++ b/adb/remount_service.cpp @@ -23,6 +23,8 @@ #include <sys/mount.h> #include <unistd.h> +#include <string> + #include "sysdeps.h" #define TRACE_TAG TRACE_ADB @@ -32,10 +34,10 @@ static int system_ro = 1; static int vendor_ro = 1; +static int oem_ro = 1; /* Returns the device used to mount a directory in /proc/mounts */ -static char *find_mount(const char *dir) -{ +static std::string find_mount(const char *dir) { FILE* fp; struct mntent* mentry; char* device = NULL; @@ -45,7 +47,7 @@ static char *find_mount(const char *dir) } while ((mentry = getmntent(fp)) != NULL) { if (strcmp(dir, mentry->mnt_dir) == 0) { - device = strdup(mentry->mnt_fsname); + device = mentry->mnt_fsname; break; } } @@ -53,64 +55,53 @@ static char *find_mount(const char *dir) return device; } -static int hasVendorPartition() -{ - struct stat info; - if (!lstat("/vendor", &info)) - if ((info.st_mode & S_IFMT) == S_IFDIR) - return true; - return false; +static bool has_partition(const char* path) { + struct stat sb; + return (lstat(path, &sb) == 0 && S_ISDIR(sb.st_mode)); } -int make_block_device_writable(const char* dev) -{ - int fd = -1; - int OFF = 0; - int rc = -1; - - if (!dev) - goto errout; - - fd = unix_open(dev, O_RDONLY | O_CLOEXEC); - if (fd < 0) - goto errout; - - if (ioctl(fd, BLKROSET, &OFF)) { - goto errout; +int make_block_device_writable(const std::string& dev) { + int fd = unix_open(dev.c_str(), O_RDONLY | O_CLOEXEC); + if (fd == -1) { + return -1; } - rc = 0; - -errout: - if (fd >= 0) { - adb_close(fd); + int result = -1; + int OFF = 0; + if (!ioctl(fd, BLKROSET, &OFF)) { + result = 0; } - return rc; -} - -/* Init mounts /system as read only, remount to enable writes. */ -static int remount(const char* dir, int* dir_ro) -{ - char *dev = 0; - int rc = -1; + adb_close(fd); - dev = find_mount(dir); + return result; +} - if (!dev || make_block_device_writable(dev)) { - goto errout; +// Init mounts /system as read only, remount to enable writes. +static int remount(const char* dir, int* dir_ro) { + std::string dev(find_mount(dir)); + if (dev.empty() || make_block_device_writable(dev)) { + return -1; } - rc = mount(dev, dir, "none", MS_REMOUNT, NULL); + int rc = mount(dev.c_str(), dir, "none", MS_REMOUNT, NULL); *dir_ro = rc; - -errout: - free(dev); return rc; } -void remount_service(int fd, void *cookie) -{ - char buffer[200]; +static bool remount_partition(int fd, const char* partition, int* ro) { + if (!has_partition(partition)) { + return true; + } + if (remount(partition, ro)) { + char buf[200]; + snprintf(buf, sizeof(buf), "remount of %s failed: %s\n", partition, strerror(errno)); + WriteStringFully(fd, buf); + return false; + } + return true; +} + +void remount_service(int fd, void* cookie) { char prop_buf[PROPERTY_VALUE_MAX]; if (getuid() != 0) { @@ -133,6 +124,7 @@ void remount_service(int fd, void *cookie) if (system_verified || vendor_verified) { // Allow remount but warn of likely bad effects bool both = system_verified && vendor_verified; + char buffer[200]; snprintf(buffer, sizeof(buffer), "dm_verity is enabled on the %s%s%s partition%s.\n", system_verified ? "system" : "", @@ -147,23 +139,12 @@ void remount_service(int fd, void *cookie) WriteStringFully(fd, buffer); } - if (remount("/system", &system_ro)) { - snprintf(buffer, sizeof(buffer), "remount of system failed: %s\n",strerror(errno)); - WriteStringFully(fd, buffer); - } - - if (hasVendorPartition()) { - if (remount("/vendor", &vendor_ro)) { - snprintf(buffer, sizeof(buffer), "remount of vendor failed: %s\n",strerror(errno)); - WriteStringFully(fd, buffer); - } - } + bool success = true; + success &= remount_partition(fd, "/system", &system_ro); + success &= remount_partition(fd, "/vendor", &vendor_ro); + success &= remount_partition(fd, "/oem", &oem_ro); - if (!system_ro && (!vendor_ro || !hasVendorPartition())) - WriteStringFully(fd, "remount succeeded\n"); - else { - WriteStringFully(fd, "remount failed\n"); - } + WriteStringFully(fd, success ? "remount succeeded\n" : "remount failed\n"); adb_close(fd); } diff --git a/adb/remount_service.h b/adb/remount_service.h new file mode 100644 index 0000000..e1763cf --- /dev/null +++ b/adb/remount_service.h @@ -0,0 +1,25 @@ +/* + * 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. + */ + +#ifndef _REMOUNT_SERVICE_H_ +#define _REMOUNT_SERVICE_H_ + +#include <string> + +int make_block_device_writable(const std::string&); +void remount_service(int, void*); + +#endif diff --git a/adb/services.c b/adb/services.cpp index 84f2137..e7bf6b0 100644 --- a/adb/services.c +++ b/adb/services.cpp @@ -38,6 +38,7 @@ #include "adb.h" #include "adb_io.h" #include "file_sync_service.h" +#include "remount_service.h" #include "transport.h" typedef struct stinfo stinfo; @@ -51,7 +52,7 @@ struct stinfo { void *service_bootstrap_func(void *x) { - stinfo *sti = x; + stinfo* sti = reinterpret_cast<stinfo*>(x); sti->func(sti->fd, sti->cookie); free(sti); return 0; @@ -161,7 +162,7 @@ cleanup: void reverse_service(int fd, void* arg) { - const char* command = arg; + const char* command = reinterpret_cast<const char*>(arg); if (handle_forward_request(command, kTransportAny, NULL, fd) < 0) { sendfailmsg(fd, "not a reverse forwarding command"); @@ -174,23 +175,23 @@ void reverse_service(int fd, void* arg) static int create_service_thread(void (*func)(int, void *), void *cookie) { - stinfo *sti; - adb_thread_t t; int s[2]; - - if(adb_socketpair(s)) { + if (adb_socketpair(s)) { printf("cannot create service socket pair\n"); return -1; } D("socketpair: (%d,%d)", s[0], s[1]); - sti = malloc(sizeof(stinfo)); - if(sti == 0) fatal("cannot allocate stinfo"); + stinfo* sti = reinterpret_cast<stinfo*>(malloc(sizeof(stinfo))); + if (sti == nullptr) { + fatal("cannot allocate stinfo"); + } sti->func = func; sti->cookie = cookie; sti->fd = s[1]; - if(adb_thread_create( &t, service_bootstrap_func, sti)){ + adb_thread_t t; + if (adb_thread_create(&t, service_bootstrap_func, sti)) { free(sti); adb_close(s[0]); adb_close(s[1]); @@ -359,7 +360,6 @@ static void subproc_waiter_service(int fd, void *cookie) static int create_subproc_thread(const char *name, const subproc_mode mode) { - stinfo *sti; adb_thread_t t; int ret_fd; pid_t pid = -1; @@ -384,7 +384,7 @@ static int create_subproc_thread(const char *name, const subproc_mode mode) } D("create_subproc ret_fd=%d pid=%d\n", ret_fd, pid); - sti = malloc(sizeof(stinfo)); + stinfo* sti = reinterpret_cast<stinfo*>(malloc(sizeof(stinfo))); if(sti == 0) fatal("cannot allocate stinfo"); sti->func = subproc_waiter_service; sti->cookie = (void*) (uintptr_t) pid; @@ -512,11 +512,11 @@ struct state_info { static void wait_for_state(int fd, void* cookie) { - struct state_info* sinfo = cookie; - char* err = "unknown error"; + state_info* sinfo = reinterpret_cast<state_info*>(cookie); D("wait_for_state %d\n", sinfo->state); + const char* err = "unknown error"; atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err); if(t != 0) { WriteFdExactly(fd, "OKAY", 4); @@ -635,7 +635,7 @@ static void connect_service(int fd, void* cookie) { char buf[4096]; char resp[4096]; - char *host = cookie; + char *host = reinterpret_cast<char*>(cookie); if (!strncmp(host, "emu:", 4)) { connect_emulator(host + 4, buf, sizeof(buf)); @@ -656,7 +656,7 @@ asocket* host_service_to_socket(const char* name, const char *serial) if (!strcmp(name,"track-devices")) { return create_device_tracker(); } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) { - struct state_info* sinfo = malloc(sizeof(struct state_info)); + auto sinfo = reinterpret_cast<state_info*>(malloc(sizeof(state_info))); if (serial) sinfo->serial = strdup(serial); diff --git a/adb/set_verity_enable_state_service.c b/adb/set_verity_enable_state_service.cpp index 184674d..139b074 100644 --- a/adb/set_verity_enable_state_service.c +++ b/adb/set_verity_enable_state_service.cpp @@ -26,6 +26,7 @@ #include "cutils/properties.h" #include "ext4_sb.h" #include "fs_mgr.h" +#include "remount_service.h" #include "sysdeps.h" #define FSTAB_PREFIX "/fstab." @@ -90,7 +91,7 @@ static int set_verity_enabled_state(int fd, const char *block_device, uint32_t magic_number; const uint32_t new_magic = enable ? VERITY_METADATA_MAGIC_NUMBER : VERITY_METADATA_MAGIC_DISABLE; - uint64_t device_length; + uint64_t device_length = 0; int device = -1; int retval = -1; @@ -140,7 +141,7 @@ static int set_verity_enabled_state(int fd, const char *block_device, if (magic_number != VERITY_METADATA_MAGIC_NUMBER && magic_number != VERITY_METADATA_MAGIC_DISABLE) { write_console(fd, - "Couldn't find verity metadata at offset %"PRIu64"!\n", + "Couldn't find verity metadata at offset %" PRIu64 "!\n", device_length); goto errout; } diff --git a/adb/sockets.c b/adb/sockets.cpp index d34f8c6..12bc8d8 100644 --- a/adb/sockets.c +++ b/adb/sockets.cpp @@ -284,98 +284,101 @@ static void local_socket_close_locked(asocket *s) insert_local_socket(s, &local_socket_closing_list); } -static void local_socket_event_func(int fd, unsigned ev, void *_s) +static void local_socket_event_func(int fd, unsigned ev, void* _s) { - asocket *s = _s; - + asocket* s = reinterpret_cast<asocket*>(_s); D("LS(%d): event_func(fd=%d(==%d), ev=%04x)\n", s->id, s->fd, fd, ev); /* put the FDE_WRITE processing before the FDE_READ ** in order to simplify the code. */ - if(ev & FDE_WRITE){ - apacket *p; - - while((p = s->pkt_first) != 0) { - while(p->len > 0) { + if (ev & FDE_WRITE) { + apacket* p; + while ((p = s->pkt_first) != nullptr) { + while (p->len > 0) { int r = adb_write(fd, p->ptr, p->len); - if(r > 0) { - p->ptr += r; - p->len -= r; - continue; - } - if(r < 0) { + if (r == -1) { /* returning here is ok because FDE_READ will ** be processed in the next iteration loop */ - if(errno == EAGAIN) return; - if(errno == EINTR) continue; + if (errno == EAGAIN) { + return; + } + } else if (r > 0) { + p->ptr += r; + p->len -= r; + continue; } + D(" closing after write because r=%d and errno is %d\n", r, errno); s->close(s); return; } - if(p->len == 0) { + if (p->len == 0) { s->pkt_first = p->next; - if(s->pkt_first == 0) s->pkt_last = 0; + if (s->pkt_first == 0) { + s->pkt_last = 0; + } put_apacket(p); } } - /* if we sent the last packet of a closing socket, - ** we can now destroy it. - */ + /* if we sent the last packet of a closing socket, + ** we can now destroy it. + */ if (s->closing) { D(" closing because 'closing' is set after write\n"); s->close(s); return; } - /* no more packets queued, so we can ignore - ** writable events again and tell our peer - ** to resume writing - */ + /* no more packets queued, so we can ignore + ** writable events again and tell our peer + ** to resume writing + */ fdevent_del(&s->fde, FDE_WRITE); s->peer->ready(s->peer); } - if(ev & FDE_READ){ + if (ev & FDE_READ) { apacket *p = get_apacket(); unsigned char *x = p->data; size_t avail = MAX_PAYLOAD; int r; int is_eof = 0; - while(avail > 0) { + while (avail > 0) { r = adb_read(fd, x, avail); - D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu\n", s->id, s->fd, r, r<0?errno:0, avail); - if(r > 0) { + D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu\n", + s->id, s->fd, r, r < 0 ? errno : 0, avail); + if (r == -1) { + if (errno == EAGAIN) { + break; + } + } else if (r > 0) { avail -= r; x += r; continue; } - if(r < 0) { - if(errno == EAGAIN) break; - if(errno == EINTR) continue; - } - /* r = 0 or unhandled error */ + /* r = 0 or unhandled error */ is_eof = 1; break; } D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d\n", s->id, s->fd, r, is_eof, s->fde.force_eof); - if((avail == MAX_PAYLOAD) || (s->peer == 0)) { + if ((avail == MAX_PAYLOAD) || (s->peer == 0)) { put_apacket(p); } else { p->len = MAX_PAYLOAD - avail; r = s->peer->enqueue(s->peer, p); - D("LS(%d): fd=%d post peer->enqueue(). r=%d\n", s->id, s->fd, r); + D("LS(%d): fd=%d post peer->enqueue(). r=%d\n", s->id, s->fd, + r); - if(r < 0) { + if (r < 0) { /* error return means they closed us as a side-effect ** and we must return immediately. ** @@ -387,7 +390,7 @@ static void local_socket_event_func(int fd, unsigned ev, void *_s) return; } - if(r > 0) { + if (r > 0) { /* if the remote cannot accept further events, ** we disable notification of READs. They'll ** be enabled again when we get a call to ready() @@ -396,13 +399,14 @@ static void local_socket_event_func(int fd, unsigned ev, void *_s) } } /* Don't allow a forced eof if data is still there */ - if((s->fde.force_eof && !r) || is_eof) { - D(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n", is_eof, r, s->fde.force_eof); + if ((s->fde.force_eof && !r) || is_eof) { + D(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n", + is_eof, r, s->fde.force_eof); s->close(s); } } - if(ev & FDE_ERROR){ + if (ev & FDE_ERROR){ /* this should be caught be the next read or write ** catching it here means we may skip the last few ** bytes of readable data. @@ -415,7 +419,7 @@ static void local_socket_event_func(int fd, unsigned ev, void *_s) asocket *create_local_socket(int fd) { - asocket *s = calloc(1, sizeof(asocket)); + asocket *s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket))); if (s == NULL) fatal("cannot allocate socket"); s->fd = fd; s->enqueue = local_socket_enqueue; @@ -539,8 +543,8 @@ static void remote_socket_close(asocket *s) static void remote_socket_disconnect(void* _s, atransport* t) { - asocket* s = _s; - asocket* peer = s->peer; + asocket* s = reinterpret_cast<asocket*>(_s); + asocket* peer = s->peer; D("remote_socket_disconnect RS(%d)\n", s->id); if (peer) { @@ -557,12 +561,9 @@ static void remote_socket_disconnect(void* _s, atransport* t) Returns a new non-NULL asocket handle. */ asocket *create_remote_socket(unsigned id, atransport *t) { - asocket* s; - adisconnect* dis; - if (id == 0) fatal("invalid remote socket id (0)"); - s = calloc(1, sizeof(aremotesocket)); - dis = &((aremotesocket*)s)->disconnect; + asocket* s = reinterpret_cast<asocket*>(calloc(1, sizeof(aremotesocket))); + adisconnect* dis = &reinterpret_cast<aremotesocket*>(s)->disconnect; if (s == NULL) fatal("cannot allocate socket"); s->id = id; @@ -824,7 +825,7 @@ static int smart_socket_enqueue(asocket *s, apacket *p) } #else /* !ADB_HOST */ if (s->transport == NULL) { - char* error_string = "unknown failure"; + const char* error_string = "unknown failure"; s->transport = acquire_one_transport (CS_ANY, kTransportAny, NULL, &error_string); @@ -892,7 +893,7 @@ static void smart_socket_close(asocket *s) static asocket *create_smart_socket(void) { D("Creating smart socket \n"); - asocket *s = calloc(1, sizeof(asocket)); + asocket *s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket))); if (s == NULL) fatal("cannot allocate socket"); s->enqueue = smart_socket_enqueue; s->ready = smart_socket_ready; diff --git a/adb/test_track_devices.c b/adb/test_track_devices.cpp index 77b3ad9..77b3ad9 100644 --- a/adb/test_track_devices.c +++ b/adb/test_track_devices.cpp diff --git a/adb/test_track_jdwp.c b/adb/test_track_jdwp.cpp index 8ecc6b8..8ecc6b8 100644 --- a/adb/test_track_jdwp.c +++ b/adb/test_track_jdwp.cpp diff --git a/adb/tests/test_adb.py b/adb/tests/test_adb.py index 49ead73..f111b04 100755 --- a/adb/tests/test_adb.py +++ b/adb/tests/test_adb.py @@ -237,16 +237,36 @@ class AdbBasic(unittest.TestCase): version_num = True self.assertTrue(version_num) - def test_root_unroot(self): - """Make sure that adb root and adb unroot work, using id(1).""" + def _test_root(self): adb = AdbWrapper() adb.root() adb.wait() self.assertEqual("root", adb.shell("id -un").strip()) + + def _test_unroot(self): + adb = AdbWrapper() adb.unroot() adb.wait() self.assertEqual("shell", adb.shell("id -un").strip()) + def test_root_unroot(self): + """Make sure that adb root and adb unroot work, using id(1).""" + adb = AdbWrapper() + original_user = adb.shell("id -un").strip() + try: + if original_user == "root": + self._test_unroot() + self._test_root() + elif original_user == "shell": + self._test_root() + self._test_unroot() + finally: + if original_user == "root": + adb.root() + else: + adb.unroot() + adb.wait() + class AdbFile(unittest.TestCase): SCRATCH_DIR = "/data/local/tmp" diff --git a/adb/transport.c b/adb/transport.cpp index e2c204e..1f8ac03 100644 --- a/adb/transport.c +++ b/adb/transport.cpp @@ -221,7 +221,7 @@ write_packet(int fd, const char* name, apacket** ppacket) static void transport_socket_events(int fd, unsigned events, void *_t) { - atransport *t = _t; + atransport *t = reinterpret_cast<atransport*>(_t); D("transport_socket_events(fd=%d, events=%04x,...)\n", fd, events); if(events & FDE_READ){ apacket *p = 0; @@ -278,7 +278,7 @@ void send_packet(apacket *p, atransport *t) static void *output_thread(void *_t) { - atransport *t = _t; + atransport *t = reinterpret_cast<atransport*>(_t); apacket *p; D("%s: starting transport output thread on fd %d, SYNC online (%d)\n", @@ -333,7 +333,7 @@ oops: static void *input_thread(void *_t) { - atransport *t = _t; + atransport *t = reinterpret_cast<atransport*>(_t); apacket *p; int active = 0; @@ -494,7 +494,8 @@ device_tracker_ready( asocket* socket ) asocket* create_device_tracker(void) { - device_tracker* tracker = calloc(1,sizeof(*tracker)); + device_tracker* tracker = reinterpret_cast<device_tracker*>( + calloc(1, sizeof(*tracker))); if(tracker == 0) fatal("cannot allocate device tracker"); @@ -799,7 +800,8 @@ static int qual_match(const char *to_test, return !*to_test; } -atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char** error_out) +atransport *acquire_one_transport(int state, transport_type ttype, + const char* serial, const char** error_out) { atransport *t; atransport *result = NULL; @@ -1007,7 +1009,8 @@ void close_usb_devices() int register_socket_transport(int s, const char *serial, int port, int local) { - atransport *t = calloc(1, sizeof(atransport)); + atransport *t = reinterpret_cast<atransport*>( + calloc(1, sizeof(atransport))); atransport *n; char buff[32]; @@ -1106,7 +1109,8 @@ void unregister_all_tcp_transports() void register_usb_transport(usb_handle *usb, const char *serial, const char *devpath, unsigned writeable) { - atransport *t = calloc(1, sizeof(atransport)); + atransport *t = reinterpret_cast<atransport*>( + calloc(1, sizeof(atransport))); D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb, serial ? serial : ""); init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM)); diff --git a/adb/transport.h b/adb/transport.h index 352bbe4..36a0e40 100644 --- a/adb/transport.h +++ b/adb/transport.h @@ -37,7 +37,7 @@ void dump_hex(const unsigned char* ptr, size_t len); * If no suitable transport is found, error is set. */ atransport* acquire_one_transport(int state, transport_type ttype, - const char* serial, char** error_out); + const char* serial, const char** error_out); void add_transport_disconnect(atransport* t, adisconnect* dis); void remove_transport_disconnect(atransport* t, adisconnect* dis); void kick_transport(atransport* t); diff --git a/adb/transport_local.c b/adb/transport_local.cpp index 440d4c5..440d4c5 100644 --- a/adb/transport_local.c +++ b/adb/transport_local.cpp diff --git a/adb/transport_usb.c b/adb/transport_usb.cpp index 37a8219..37a8219 100644 --- a/adb/transport_usb.c +++ b/adb/transport_usb.cpp diff --git a/adb/usb_linux.c b/adb/usb_linux.cpp index d03f8be..c01ec8c 100644 --- a/adb/usb_linux.c +++ b/adb/usb_linux.cpp @@ -574,7 +574,6 @@ static void register_device(const char *dev_name, const char *devpath, unsigned char ep_in, unsigned char ep_out, int interface, int serial_index, unsigned zero_mask) { - usb_handle* usb = 0; int n = 0; char serial[256]; @@ -587,8 +586,9 @@ static void register_device(const char *dev_name, const char *devpath, ** name, we have no further work to do. */ adb_mutex_lock(&usb_lock); - for(usb = handle_list.next; usb != &handle_list; usb = usb->next){ - if(!strcmp(usb->fname, dev_name)) { + for (usb_handle* usb = handle_list.next; usb != &handle_list; + usb = usb->next) { + if (!strcmp(usb->fname, dev_name)) { adb_mutex_unlock(&usb_lock); return; } @@ -597,7 +597,8 @@ static void register_device(const char *dev_name, const char *devpath, D("[ usb located new device %s (%d/%d/%d) ]\n", dev_name, ep_in, ep_out, interface); - usb = calloc(1, sizeof(usb_handle)); + usb_handle* usb = reinterpret_cast<usb_handle*>( + calloc(1, sizeof(usb_handle))); strcpy(usb->fname, dev_name); usb->ep_in = ep_in; usb->ep_out = ep_out; diff --git a/adb/usb_windows.c b/adb/usb_windows.cpp index 3c5533b..3c5533b 100644 --- a/adb/usb_windows.c +++ b/adb/usb_windows.cpp diff --git a/adf/libadf/Android.mk b/adf/libadf/Android.mk index 908aa6c..7df354b 100644 --- a/adf/libadf/Android.mk +++ b/adf/libadf/Android.mk @@ -18,6 +18,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := adf.c LOCAL_MODULE := libadf LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS += -Werror LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include LOCAL_C_INCLUDES += $(LOCAL_EXPORT_C_INCLUDE_DIRS) include $(BUILD_STATIC_LIBRARY) diff --git a/adf/libadf/tests/Android.mk b/adf/libadf/tests/Android.mk index 93efafa..68e5817 100644 --- a/adf/libadf/tests/Android.mk +++ b/adf/libadf/tests/Android.mk @@ -19,4 +19,5 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := adf_test.cpp LOCAL_MODULE := adf-unit-tests LOCAL_STATIC_LIBRARIES := libadf +LOCAL_CFLAGS += -Werror include $(BUILD_NATIVE_TEST) diff --git a/adf/libadf/tests/adf_test.cpp b/adf/libadf/tests/adf_test.cpp index d95330d..01b2785 100644 --- a/adf/libadf/tests/adf_test.cpp +++ b/adf/libadf/tests/adf_test.cpp @@ -182,9 +182,9 @@ TEST_F(AdfTest, device_data) { ASSERT_GE(err, 0) << "getting ADF device data failed: " << strerror(-err); EXPECT_LT(data.n_attachments, ADF_MAX_ATTACHMENTS); - EXPECT_GT(data.n_allowed_attachments, 0); + EXPECT_GT(data.n_allowed_attachments, 0U); EXPECT_LT(data.n_allowed_attachments, ADF_MAX_ATTACHMENTS); - EXPECT_LT(data.custom_data_size, ADF_MAX_CUSTOM_DATA_SIZE); + EXPECT_LT(data.custom_data_size, (size_t)ADF_MAX_CUSTOM_DATA_SIZE); adf_free_device_data(&data); } @@ -195,8 +195,8 @@ TEST_F(AdfTest, interface_data) { EXPECT_LT(data.type, ADF_INTF_TYPE_MAX); EXPECT_LE(data.dpms_state, DRM_MODE_DPMS_OFF); EXPECT_EQ(1, data.hotplug_detect); - EXPECT_GT(data.n_available_modes, 0); - EXPECT_LT(data.custom_data_size, ADF_MAX_CUSTOM_DATA_SIZE); + EXPECT_GT(data.n_available_modes, 0U); + EXPECT_LT(data.custom_data_size, (size_t)ADF_MAX_CUSTOM_DATA_SIZE); adf_free_interface_data(&data); } @@ -206,9 +206,9 @@ TEST_F(AdfTest, overlay_engine_data) { ASSERT_GE(err, 0) << "getting ADF overlay engine failed: " << strerror(-err); - EXPECT_GT(data.n_supported_formats, 0); + EXPECT_GT(data.n_supported_formats, 0U); EXPECT_LT(data.n_supported_formats, ADF_MAX_SUPPORTED_FORMATS); - EXPECT_LT(data.custom_data_size, ADF_MAX_CUSTOM_DATA_SIZE); + EXPECT_LT(data.custom_data_size, (size_t)ADF_MAX_CUSTOM_DATA_SIZE); adf_free_overlay_engine_data(&data); } diff --git a/adf/libadfhwc/Android.mk b/adf/libadfhwc/Android.mk index acea322..898f9c9 100644 --- a/adf/libadfhwc/Android.mk +++ b/adf/libadfhwc/Android.mk @@ -19,7 +19,7 @@ LOCAL_SRC_FILES := adfhwc.cpp LOCAL_MODULE := libadfhwc LOCAL_MODULE_TAGS := optional LOCAL_STATIC_LIBRARIES := libadf liblog libutils -LOCAL_CFLAGS += -DLOG_TAG=\"adfhwc\" +LOCAL_CFLAGS += -DLOG_TAG=\"adfhwc\" -Werror LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include LOCAL_C_INCLUDES += $(LOCAL_EXPORT_C_INCLUDE_DIRS) include $(BUILD_STATIC_LIBRARY) diff --git a/base/.clang-format b/base/.clang-format new file mode 100644 index 0000000..2b83a1f --- /dev/null +++ b/base/.clang-format @@ -0,0 +1,11 @@ +BasedOnStyle: Google +AllowShortBlocksOnASingleLine: false +AllowShortFunctionsOnASingleLine: false + +CommentPragmas: NOLINT:.* +DerivePointerAlignment: false +IndentWidth: 2 +PointerAlignment: Left +TabWidth: 2 +UseTab: Never +PenaltyExcessCharacter: 32 diff --git a/base/Android.mk b/base/Android.mk new file mode 100644 index 0000000..0e1a9b6 --- /dev/null +++ b/base/Android.mk @@ -0,0 +1,98 @@ +# +# 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) + +libbase_src_files := \ + file.cpp \ + stringprintf.cpp \ + strings.cpp \ + +libbase_test_src_files := \ + file_test.cpp \ + stringprintf_test.cpp \ + strings_test.cpp \ + +libbase_cppflags := \ + -Wall \ + -Wextra \ + -Werror \ + +# Device +# ------------------------------------------------------------------------------ +include $(CLEAR_VARS) +LOCAL_MODULE := libbase +LOCAL_CLANG := true +LOCAL_SRC_FILES := $(libbase_src_files) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +LOCAL_CPPFLAGS := $(libbase_cppflags) +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include +LOCAL_MULTILIB := both +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := libbase +LOCAL_CLANG := true +LOCAL_WHOLE_STATIC_LIBRARIES := libbase +LOCAL_SHARED_LIBRARIES := liblog +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include +LOCAL_MULTILIB := both +include $(BUILD_SHARED_LIBRARY) + +# Host +# ------------------------------------------------------------------------------ +include $(CLEAR_VARS) +LOCAL_MODULE := libbase +LOCAL_CLANG := true +LOCAL_SRC_FILES := $(libbase_src_files) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +LOCAL_CPPFLAGS := $(libbase_cppflags) +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include +LOCAL_MULTILIB := both +include $(BUILD_HOST_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := libbase +LOCAL_CLANG := true +LOCAL_WHOLE_STATIC_LIBRARIES := libbase +LOCAL_SHARED_LIBRARIES := liblog +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include +LOCAL_MULTILIB := both +include $(BUILD_HOST_SHARED_LIBRARY) + +# Tests +# ------------------------------------------------------------------------------ +include $(CLEAR_VARS) +LOCAL_MODULE := libbase_test +LOCAL_CLANG := true +LOCAL_SRC_FILES := $(libbase_test_src_files) +LOCAL_CPPFLAGS := $(libbase_cppflags) +LOCAL_SHARED_LIBRARIES := libbase +LOCAL_MULTILIB := both +LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32 +LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64 +include $(BUILD_NATIVE_TEST) + +include $(CLEAR_VARS) +LOCAL_MODULE := libbase_test +LOCAL_CLANG := true +LOCAL_SRC_FILES := $(libbase_test_src_files) +LOCAL_CPPFLAGS := $(libbase_cppflags) +LOCAL_SHARED_LIBRARIES := libbase +LOCAL_MULTILIB := both +LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32 +LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64 +include $(BUILD_HOST_NATIVE_TEST) diff --git a/base/CPPLINT.cfg b/base/CPPLINT.cfg new file mode 100644 index 0000000..5ee068e --- /dev/null +++ b/base/CPPLINT.cfg @@ -0,0 +1,2 @@ +set noparent +filter=-build/header_guard diff --git a/libutils/file.cpp b/base/file.cpp index 0690bc2..118071e 100644 --- a/libutils/file.cpp +++ b/base/file.cpp @@ -14,19 +14,23 @@ * limitations under the License. */ -#define LOG_TAG "utils.file" -#include <cutils/log.h> - -#include "utils/file.h" +#include "base/file.h" #include <errno.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> -#include <utils/Compat.h> // For TEMP_FAILURE_RETRY on Darwin. +#include <string> + +#include "base/macros.h" // For TEMP_FAILURE_RETRY on Darwin. +#define LOG_TAG "base.file" +#include "cutils/log.h" -bool android::ReadFdToString(int fd, std::string* content) { +namespace android { +namespace base { + +bool ReadFdToString(int fd, std::string* content) { content->clear(); char buf[BUFSIZ]; @@ -37,10 +41,11 @@ bool android::ReadFdToString(int fd, std::string* content) { return (n == 0) ? true : false; } -bool android::ReadFileToString(const std::string& path, std::string* content) { +bool ReadFileToString(const std::string& path, std::string* content) { content->clear(); - int fd = TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW)); + int fd = + TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW)); if (fd == -1) { return false; } @@ -49,7 +54,7 @@ bool android::ReadFileToString(const std::string& path, std::string* content) { return result; } -bool android::WriteStringToFd(const std::string& content, int fd) { +bool WriteStringToFd(const std::string& content, int fd) { const char* p = content.data(); size_t left = content.size(); while (left > 0) { @@ -72,18 +77,18 @@ static bool CleanUpAfterFailedWrite(const std::string& path) { } #if !defined(_WIN32) -bool android::WriteStringToFile(const std::string& content, const std::string& path, - mode_t mode, uid_t owner, gid_t group) { - int fd = TEMP_FAILURE_RETRY(open(path.c_str(), - O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, - mode)); +bool WriteStringToFile(const std::string& content, const std::string& path, + mode_t mode, uid_t owner, gid_t group) { + int fd = TEMP_FAILURE_RETRY( + open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, + mode)); if (fd == -1) { ALOGE("android::WriteStringToFile open failed: %s", strerror(errno)); return false; } - // We do an explicit fchmod here because we assume that the caller really meant what they - // said and doesn't want the umask-influenced mode. + // We do an explicit fchmod here because we assume that the caller really + // meant what they said and doesn't want the umask-influenced mode. if (fchmod(fd, mode) == -1) { ALOGE("android::WriteStringToFile fchmod failed: %s", strerror(errno)); return CleanUpAfterFailedWrite(path); @@ -101,10 +106,10 @@ bool android::WriteStringToFile(const std::string& content, const std::string& p } #endif -bool android::WriteStringToFile(const std::string& content, const std::string& path) { - int fd = TEMP_FAILURE_RETRY(open(path.c_str(), - O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, - DEFFILEMODE)); +bool WriteStringToFile(const std::string& content, const std::string& path) { + int fd = TEMP_FAILURE_RETRY( + open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, + DEFFILEMODE)); if (fd == -1) { return false; } @@ -113,3 +118,6 @@ bool android::WriteStringToFile(const std::string& content, const std::string& p TEMP_FAILURE_RETRY(close(fd)); return result || CleanUpAfterFailedWrite(path); } + +} // namespace base +} // namespace android diff --git a/libutils/tests/file_test.cpp b/base/file_test.cpp index cea18b6..34b8755 100644 --- a/libutils/tests/file_test.cpp +++ b/base/file_test.cpp @@ -14,12 +14,15 @@ * limitations under the License. */ -#include "utils/file.h" +#include "base/file.h" + +#include <gtest/gtest.h> #include <errno.h> #include <fcntl.h> #include <unistd.h> -#include <gtest/gtest.h> + +#include <string> class TemporaryFile { public: @@ -48,14 +51,14 @@ class TemporaryFile { TEST(file, ReadFileToString_ENOENT) { std::string s("hello"); errno = 0; - ASSERT_FALSE(android::ReadFileToString("/proc/does-not-exist", &s)); + ASSERT_FALSE(android::base::ReadFileToString("/proc/does-not-exist", &s)); EXPECT_EQ(ENOENT, errno); - EXPECT_EQ("", s); // s was cleared. + EXPECT_EQ("", s); // s was cleared. } TEST(file, ReadFileToString_success) { std::string s("hello"); - ASSERT_TRUE(android::ReadFileToString("/proc/version", &s)) << errno; + ASSERT_TRUE(android::base::ReadFileToString("/proc/version", &s)) << errno; EXPECT_GT(s.length(), 6U); EXPECT_EQ('\n', s[s.length() - 1]); s[5] = 0; @@ -65,34 +68,36 @@ TEST(file, ReadFileToString_success) { TEST(file, WriteStringToFile) { TemporaryFile tf; ASSERT_TRUE(tf.fd != -1); - ASSERT_TRUE(android::WriteStringToFile("abc", tf.filename)) << errno; + ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.filename)) << errno; std::string s; - ASSERT_TRUE(android::ReadFileToString(tf.filename, &s)) << errno; + ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s)) << errno; EXPECT_EQ("abc", s); } TEST(file, WriteStringToFile2) { TemporaryFile tf; ASSERT_TRUE(tf.fd != -1); - ASSERT_TRUE(android::WriteStringToFile("abc", tf.filename, 0660, getuid(), getgid())) << errno; + ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.filename, 0660, + getuid(), getgid())) + << errno; struct stat sb; ASSERT_EQ(0, stat(tf.filename, &sb)); ASSERT_EQ(0660U, (sb.st_mode & ~S_IFMT)); ASSERT_EQ(getuid(), sb.st_uid); ASSERT_EQ(getgid(), sb.st_gid); std::string s; - ASSERT_TRUE(android::ReadFileToString(tf.filename, &s)) << errno; + ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s)) << errno; EXPECT_EQ("abc", s); } TEST(file, WriteStringToFd) { TemporaryFile tf; ASSERT_TRUE(tf.fd != -1); - ASSERT_TRUE(android::WriteStringToFd("abc", tf.fd)); + ASSERT_TRUE(android::base::WriteStringToFd("abc", tf.fd)); ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << errno; std::string s; - ASSERT_TRUE(android::ReadFdToString(tf.fd, &s)) << errno; + ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s)) << errno; EXPECT_EQ("abc", s); } diff --git a/include/utils/file.h b/base/include/base/file.h index a80afb1..ef97742 100644 --- a/include/utils/file.h +++ b/base/include/base/file.h @@ -14,13 +14,14 @@ * limitations under the License. */ -#ifndef UTILS_FILE_H -#define UTILS_FILE_H +#ifndef BASE_FILE_H +#define BASE_FILE_H -#include <string> #include <sys/stat.h> +#include <string> namespace android { +namespace base { bool ReadFdToString(int fd, std::string* content); bool ReadFileToString(const std::string& path, std::string* content); @@ -33,6 +34,7 @@ bool WriteStringToFile(const std::string& content, const std::string& path, mode_t mode, uid_t owner, gid_t group); #endif -} // namespace android +} // namespace base +} // namespace android -#endif +#endif // BASE_FILE_H diff --git a/base/include/base/macros.h b/base/include/base/macros.h new file mode 100644 index 0000000..b1ce7c6 --- /dev/null +++ b/base/include/base/macros.h @@ -0,0 +1,188 @@ +/* + * 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. + */ + +#ifndef UTILS_MACROS_H +#define UTILS_MACROS_H + +#include <stddef.h> // for size_t +#include <unistd.h> // for TEMP_FAILURE_RETRY + +// bionic and glibc both have TEMP_FAILURE_RETRY, but eg Mac OS' libc doesn't. +#ifndef TEMP_FAILURE_RETRY +#define TEMP_FAILURE_RETRY(exp) \ + ({ \ + decltype(exp) _rc; \ + do { \ + _rc = (exp); \ + } while (_rc == -1 && errno == EINTR); \ + _rc; \ + }) +#endif + +// A macro to disallow the copy constructor and operator= functions +// This must be placed in the private: declarations for a class. +// +// For disallowing only assign or copy, delete the relevant operator or +// constructor, for example: +// void operator=(const TypeName&) = delete; +// Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken +// semantically, one should either use disallow both or neither. Try to +// avoid these in new code. +// +// When building with C++11 toolchains, just use the language support +// for explicitly deleted methods. +#if __cplusplus >= 201103L +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&) = delete; \ + void operator=(const TypeName&) = delete +#else +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) +#endif + +// A macro to disallow all the implicit constructors, namely the +// default constructor, copy constructor and operator= functions. +// +// This should be used in the private: declarations for a class +// that wants to prevent anyone from instantiating it. This is +// especially useful for classes containing only static methods. +#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ + TypeName(); \ + DISALLOW_COPY_AND_ASSIGN(TypeName) + +// The arraysize(arr) macro returns the # of elements in an array arr. +// The expression is a compile-time constant, and therefore can be +// used in defining new arrays, for example. If you use arraysize on +// a pointer by mistake, you will get a compile-time error. +// +// One caveat is that arraysize() doesn't accept any array of an +// anonymous type or a type defined inside a function. In these rare +// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below. This is +// due to a limitation in C++'s template system. The limitation might +// eventually be removed, but it hasn't happened yet. + +// This template function declaration is used in defining arraysize. +// Note that the function doesn't need an implementation, as we only +// use its type. +template <typename T, size_t N> +char(&ArraySizeHelper(T(&array)[N]))[N]; // NOLINT(readability/casting) + +#define arraysize(array) (sizeof(ArraySizeHelper(array))) + +// ARRAYSIZE_UNSAFE performs essentially the same calculation as arraysize, +// but can be used on anonymous types or types defined inside +// functions. It's less safe than arraysize as it accepts some +// (although not all) pointers. Therefore, you should use arraysize +// whenever possible. +// +// The expression ARRAYSIZE_UNSAFE(a) is a compile-time constant of type +// size_t. +// +// ARRAYSIZE_UNSAFE catches a few type errors. If you see a compiler error +// +// "warning: division by zero in ..." +// +// when using ARRAYSIZE_UNSAFE, you are (wrongfully) giving it a pointer. +// You should only use ARRAYSIZE_UNSAFE on statically allocated arrays. +// +// The following comments are on the implementation details, and can +// be ignored by the users. +// +// ARRAYSIZE_UNSAFE(arr) works by inspecting sizeof(arr) (the # of bytes in +// the array) and sizeof(*(arr)) (the # of bytes in one array +// element). If the former is divisible by the latter, perhaps arr is +// indeed an array, in which case the division result is the # of +// elements in the array. Otherwise, arr cannot possibly be an array, +// and we generate a compiler error to prevent the code from +// compiling. +// +// Since the size of bool is implementation-defined, we need to cast +// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final +// result has type size_t. +// +// This macro is not perfect as it wrongfully accepts certain +// pointers, namely where the pointer size is divisible by the pointee +// size. Since all our code has to go through a 32-bit compiler, +// where a pointer is 4 bytes, this means all pointers to a type whose +// size is 3 or greater than 4 will be (righteously) rejected. +#define ARRAYSIZE_UNSAFE(a) \ + ((sizeof(a) / sizeof(*(a))) / \ + static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) + +#define LIKELY(x) __builtin_expect((x), true) +#define UNLIKELY(x) __builtin_expect((x), false) + +#define WARN_UNUSED __attribute__((warn_unused_result)) + +// A deprecated function to call to create a false use of the parameter, for +// example: +// int foo(int x) { UNUSED(x); return 10; } +// to avoid compiler warnings. Going forward we prefer ATTRIBUTE_UNUSED. +template <typename... T> +void UNUSED(const T&...) { +} + +// An attribute to place on a parameter to a function, for example: +// int foo(int x ATTRIBUTE_UNUSED) { return 10; } +// to avoid compiler warnings. +#define ATTRIBUTE_UNUSED __attribute__((__unused__)) + +// The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through +// between switch labels: +// switch (x) { +// case 40: +// case 41: +// if (truth_is_out_there) { +// ++x; +// FALLTHROUGH_INTENDED; // Use instead of/along with annotations in +// // comments. +// } else { +// return x; +// } +// case 42: +// ... +// +// As shown in the example above, the FALLTHROUGH_INTENDED macro should be +// followed by a semicolon. It is designed to mimic control-flow statements +// like 'break;', so it can be placed in most places where 'break;' can, but +// only if there are no statements on the execution path between it and the +// next switch label. +// +// When compiled with clang in C++11 mode, the FALLTHROUGH_INTENDED macro is +// expanded to [[clang::fallthrough]] attribute, which is analysed when +// performing switch labels fall-through diagnostic ('-Wimplicit-fallthrough'). +// See clang documentation on language extensions for details: +// http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough +// +// When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no +// effect on diagnostics. +// +// In either case this macro has no effect on runtime behavior and performance +// of code. +#if defined(__clang__) && __cplusplus >= 201103L && defined(__has_warning) +#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough") +#define FALLTHROUGH_INTENDED [[clang::fallthrough]] // NOLINT +#endif +#endif + +#ifndef FALLTHROUGH_INTENDED +#define FALLTHROUGH_INTENDED \ + do { \ + } while (0) +#endif + +#endif // UTILS_MACROS_H diff --git a/include/utils/stringprintf.h b/base/include/base/stringprintf.h index e7dbac7..195c1de 100644 --- a/include/utils/stringprintf.h +++ b/base/include/base/stringprintf.h @@ -14,25 +14,27 @@ * limitations under the License. */ -#ifndef UTILS_STRINGPRINTF_H_ -#define UTILS_STRINGPRINTF_H_ +#ifndef BASE_STRINGPRINTF_H +#define BASE_STRINGPRINTF_H #include <stdarg.h> #include <string> namespace android { +namespace base { // Returns a string corresponding to printf-like formatting of the arguments. std::string StringPrintf(const char* fmt, ...) - __attribute__((__format__(__printf__, 1, 2))); + __attribute__((__format__(__printf__, 1, 2))); // Appends a printf-like formatting of the arguments to 'dst'. void StringAppendF(std::string* dst, const char* fmt, ...) - __attribute__((__format__(__printf__, 2, 3))); + __attribute__((__format__(__printf__, 2, 3))); // Appends a printf-like formatting of the arguments to 'dst'. void StringAppendV(std::string* dst, const char* format, va_list ap); +} // namespace base } // namespace android -#endif +#endif // BASE_STRINGPRINTF_H diff --git a/base/include/base/strings.h b/base/include/base/strings.h new file mode 100644 index 0000000..5ddfbbd --- /dev/null +++ b/base/include/base/strings.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#ifndef BASE_STRINGS_H +#define BASE_STRINGS_H + +#include <string> +#include <vector> + +namespace android { +namespace base { + +// Splits a string using the given separator character into a vector of strings. +// Empty strings will be omitted. +void Split(const std::string& s, char separator, + std::vector<std::string>* result); + +// Trims whitespace off both ends of the given string. +std::string Trim(const std::string& s); + +// Joins a vector of strings into a single string, using the given separator. +template <typename StringT> +std::string Join(const std::vector<StringT>& strings, char separator); + +// Tests whether 's' starts with 'prefix'. +bool StartsWith(const std::string& s, const char* prefix); + +// Tests whether 's' ends with 'suffix'. +bool EndsWith(const std::string& s, const char* suffix); + +} // namespace base +} // namespace android + +#endif // BASE_STRINGS_H diff --git a/libutils/stringprintf.cpp b/base/stringprintf.cpp index 5eaa293..d55ff52 100644 --- a/libutils/stringprintf.cpp +++ b/base/stringprintf.cpp @@ -14,11 +14,16 @@ * limitations under the License. */ -#include <utils/stringprintf.h> +#include "base/stringprintf.h" #include <stdio.h> -void android::StringAppendV(std::string* dst, const char* format, va_list ap) { +#include <string> + +namespace android { +namespace base { + +void StringAppendV(std::string* dst, const char* format, va_list ap) { // First try with a small fixed size buffer char space[1024]; @@ -45,7 +50,7 @@ void android::StringAppendV(std::string* dst, const char* format, va_list ap) { // Increase the buffer size to the size requested by vsnprintf, // plus one for the closing \0. - int length = result+1; + int length = result + 1; char* buf = new char[length]; // Restore the va_list before we use it again @@ -60,7 +65,7 @@ void android::StringAppendV(std::string* dst, const char* format, va_list ap) { delete[] buf; } -std::string android::StringPrintf(const char* fmt, ...) { +std::string StringPrintf(const char* fmt, ...) { va_list ap; va_start(ap, fmt); std::string result; @@ -69,9 +74,12 @@ std::string android::StringPrintf(const char* fmt, ...) { return result; } -void android::StringAppendF(std::string* dst, const char* format, ...) { +void StringAppendF(std::string* dst, const char* format, ...) { va_list ap; va_start(ap, format); StringAppendV(dst, format, ap); va_end(ap); } + +} // namespace base +} // namespace android diff --git a/libutils/tests/stringprintf_test.cpp b/base/stringprintf_test.cpp index f995452..5cc2086 100644 --- a/libutils/tests/stringprintf_test.cpp +++ b/base/stringprintf_test.cpp @@ -14,25 +14,27 @@ * limitations under the License. */ -#include <utils/stringprintf.h> +#include "base/stringprintf.h" #include <gtest/gtest.h> +#include <string> + TEST(StringPrintfTest, HexSizeT) { size_t size = 0x00107e59; - EXPECT_EQ("00107e59", android::StringPrintf("%08zx", size)); - EXPECT_EQ("0x00107e59", android::StringPrintf("0x%08zx", size)); + EXPECT_EQ("00107e59", android::base::StringPrintf("%08zx", size)); + EXPECT_EQ("0x00107e59", android::base::StringPrintf("0x%08zx", size)); } TEST(StringPrintfTest, StringAppendF) { std::string s("a"); - android::StringAppendF(&s, "b"); + android::base::StringAppendF(&s, "b"); EXPECT_EQ("ab", s); } TEST(StringPrintfTest, Errno) { errno = 123; - android::StringPrintf("hello %s", "world"); + android::base::StringPrintf("hello %s", "world"); EXPECT_EQ(123, errno); } @@ -40,7 +42,7 @@ void TestN(size_t n) { char* buf = new char[n + 1]; memset(buf, 'x', n); buf[n] = '\0'; - std::string s(android::StringPrintf("%s", buf)); + std::string s(android::base::StringPrintf("%s", buf)); EXPECT_EQ(buf, s); delete[] buf; } diff --git a/base/strings.cpp b/base/strings.cpp new file mode 100644 index 0000000..224a46f --- /dev/null +++ b/base/strings.cpp @@ -0,0 +1,111 @@ +/* + * 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. + */ + +#include "base/strings.h" + +#include <string> +#include <vector> + +namespace android { +namespace base { + +void Split(const std::string& s, char separator, + std::vector<std::string>* result) { + const char* p = s.data(); + const char* end = p + s.size(); + while (p != end) { + if (*p == separator) { + ++p; + } else { + const char* start = p; + while (++p != end && *p != separator) { + // Skip to the next occurrence of the separator. + } + result->push_back(std::string(start, p - start)); + } + } +} + +std::string Trim(const std::string& s) { + std::string result; + + if (s.size() == 0) { + return result; + } + + size_t start_index = 0; + size_t end_index = s.size() - 1; + + // Skip initial whitespace. + while (start_index < s.size()) { + if (!isspace(s[start_index])) { + break; + } + start_index++; + } + + // Skip terminating whitespace. + while (end_index >= start_index) { + if (!isspace(s[end_index])) { + break; + } + end_index--; + } + + // All spaces, no beef. + if (end_index < start_index) { + return ""; + } + // Start_index is the first non-space, end_index is the last one. + return s.substr(start_index, end_index - start_index + 1); +} + +template <typename StringT> +std::string Join(const std::vector<StringT>& strings, char separator) { + if (strings.empty()) { + return ""; + } + + std::string result(strings[0]); + for (size_t i = 1; i < strings.size(); ++i) { + result += separator; + result += strings[i]; + } + return result; +} + +// Explicit instantiations. +template std::string Join<std::string>(const std::vector<std::string>& strings, + char separator); +template std::string Join<const char*>(const std::vector<const char*>& strings, + char separator); + +bool StartsWith(const std::string& s, const char* prefix) { + return s.compare(0, strlen(prefix), prefix) == 0; +} + +bool EndsWith(const std::string& s, const char* suffix) { + size_t suffix_length = strlen(suffix); + size_t string_length = s.size(); + if (suffix_length > string_length) { + return false; + } + size_t offset = string_length - suffix_length; + return s.compare(offset, suffix_length, suffix) == 0; +} + +} // namespace base +} // namespace android diff --git a/base/strings_test.cpp b/base/strings_test.cpp new file mode 100644 index 0000000..824598d --- /dev/null +++ b/base/strings_test.cpp @@ -0,0 +1,142 @@ +/* + * 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. + */ + +#include "base/strings.h" + +#include <gtest/gtest.h> + +#include <string> +#include <vector> + +TEST(strings, split_empty) { + std::vector<std::string> parts; + android::base::Split("", '\0', &parts); + ASSERT_EQ(0U, parts.size()); +} + +TEST(strings, split_single) { + std::vector<std::string> parts; + android::base::Split("foo", ',', &parts); + ASSERT_EQ(1U, parts.size()); + ASSERT_EQ("foo", parts[0]); +} + +TEST(strings, split_simple) { + std::vector<std::string> parts; + android::base::Split("foo,bar,baz", ',', &parts); + ASSERT_EQ(3U, parts.size()); + ASSERT_EQ("foo", parts[0]); + ASSERT_EQ("bar", parts[1]); + ASSERT_EQ("baz", parts[2]); +} + +TEST(strings, split_with_empty_part) { + std::vector<std::string> parts; + android::base::Split("foo,,bar", ',', &parts); + ASSERT_EQ(2U, parts.size()); + ASSERT_EQ("foo", parts[0]); + ASSERT_EQ("bar", parts[1]); +} + +TEST(strings, trim_empty) { + ASSERT_EQ("", android::base::Trim("")); +} + +TEST(strings, trim_already_trimmed) { + ASSERT_EQ("foo", android::base::Trim("foo")); +} + +TEST(strings, trim_left) { + ASSERT_EQ("foo", android::base::Trim(" foo")); +} + +TEST(strings, trim_right) { + ASSERT_EQ("foo", android::base::Trim("foo ")); +} + +TEST(strings, trim_both) { + ASSERT_EQ("foo", android::base::Trim(" foo ")); +} + +TEST(strings, trim_no_trim_middle) { + ASSERT_EQ("foo bar", android::base::Trim("foo bar")); +} + +TEST(strings, trim_other_whitespace) { + ASSERT_EQ("foo", android::base::Trim("\v\tfoo\n\f")); +} + +TEST(strings, join_nothing) { + std::vector<std::string> list = {}; + ASSERT_EQ("", android::base::Join(list, ',')); +} + +TEST(strings, join_single) { + std::vector<std::string> list = {"foo"}; + ASSERT_EQ("foo", android::base::Join(list, ',')); +} + +TEST(strings, join_simple) { + std::vector<std::string> list = {"foo", "bar", "baz"}; + ASSERT_EQ("foo,bar,baz", android::base::Join(list, ',')); +} + +TEST(strings, join_separator_in_vector) { + std::vector<std::string> list = {",", ","}; + ASSERT_EQ(",,,", android::base::Join(list, ',')); +} + +TEST(strings, startswith_empty) { + ASSERT_FALSE(android::base::StartsWith("", "foo")); + ASSERT_TRUE(android::base::StartsWith("", "")); +} + +TEST(strings, startswith_simple) { + ASSERT_TRUE(android::base::StartsWith("foo", "")); + ASSERT_TRUE(android::base::StartsWith("foo", "f")); + ASSERT_TRUE(android::base::StartsWith("foo", "fo")); + ASSERT_TRUE(android::base::StartsWith("foo", "foo")); +} + +TEST(strings, startswith_prefix_too_long) { + ASSERT_FALSE(android::base::StartsWith("foo", "foobar")); +} + +TEST(strings, startswith_contains_prefix) { + ASSERT_FALSE(android::base::StartsWith("foobar", "oba")); + ASSERT_FALSE(android::base::StartsWith("foobar", "bar")); +} + +TEST(strings, endswith_empty) { + ASSERT_FALSE(android::base::EndsWith("", "foo")); + ASSERT_TRUE(android::base::EndsWith("", "")); +} + +TEST(strings, endswith_simple) { + ASSERT_TRUE(android::base::EndsWith("foo", "")); + ASSERT_TRUE(android::base::EndsWith("foo", "o")); + ASSERT_TRUE(android::base::EndsWith("foo", "oo")); + ASSERT_TRUE(android::base::EndsWith("foo", "foo")); +} + +TEST(strings, endswith_prefix_too_long) { + ASSERT_FALSE(android::base::EndsWith("foo", "foobar")); +} + +TEST(strings, endswith_contains_prefix) { + ASSERT_FALSE(android::base::EndsWith("foobar", "oba")); + ASSERT_FALSE(android::base::EndsWith("foobar", "foo")); +} diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk index fbaac39..dd53296 100644 --- a/debuggerd/Android.mk +++ b/debuggerd/Android.mk @@ -5,6 +5,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ backtrace.cpp \ debuggerd.cpp \ + elf_utils.cpp \ getevent.cpp \ tombstone.cpp \ utility.cpp \ @@ -12,7 +13,7 @@ LOCAL_SRC_FILES:= \ LOCAL_SRC_FILES_arm := arm/machine.cpp LOCAL_SRC_FILES_arm64 := arm64/machine.cpp LOCAL_SRC_FILES_mips := mips/machine.cpp -LOCAL_SRC_FILES_mips64 := mips/machine.cpp +LOCAL_SRC_FILES_mips64 := mips64/machine.cpp LOCAL_SRC_FILES_x86 := x86/machine.cpp LOCAL_SRC_FILES_x86_64 := x86_64/machine.cpp @@ -28,6 +29,7 @@ endif LOCAL_SHARED_LIBRARIES := \ libbacktrace \ + libbase \ libcutils \ liblog \ libselinux \ @@ -38,7 +40,6 @@ LOCAL_MODULE := debuggerd LOCAL_MODULE_STEM_32 := debuggerd LOCAL_MODULE_STEM_64 := debuggerd64 LOCAL_MULTILIB := both -LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk include $(BUILD_EXECUTABLE) @@ -49,7 +50,7 @@ LOCAL_SRC_FILES := crasher.c LOCAL_SRC_FILES_arm := arm/crashglue.S LOCAL_SRC_FILES_arm64 := arm64/crashglue.S LOCAL_SRC_FILES_mips := mips/crashglue.S -LOCAL_SRC_FILES_mips64 := mips/crashglue.S +LOCAL_SRC_FILES_mips64 := mips64/crashglue.S LOCAL_SRC_FILES_x86 := x86/crashglue.S LOCAL_SRC_FILES_x86_64 := x86_64/crashglue.S LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) diff --git a/debuggerd/elf_utils.cpp b/debuggerd/elf_utils.cpp new file mode 100644 index 0000000..764b9db --- /dev/null +++ b/debuggerd/elf_utils.cpp @@ -0,0 +1,119 @@ +/* + * 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. + */ + +#define LOG_TAG "DEBUG" + +#include <elf.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include <string> + +#include <backtrace/Backtrace.h> +#include <base/stringprintf.h> +#include <log/log.h> + +#include "elf_utils.h" + +template <typename HdrType, typename PhdrType, typename NhdrType> +static bool get_build_id( + Backtrace* backtrace, uintptr_t base_addr, uint8_t* e_ident, std::string* build_id) { + HdrType hdr; + + memcpy(&hdr.e_ident[0], e_ident, EI_NIDENT); + + // First read the rest of the header. + if (backtrace->Read(base_addr + EI_NIDENT, reinterpret_cast<uint8_t*>(&hdr) + EI_NIDENT, + sizeof(HdrType) - EI_NIDENT) != sizeof(HdrType) - EI_NIDENT) { + return false; + } + + for (size_t i = 0; i < hdr.e_phnum; i++) { + PhdrType phdr; + if (backtrace->Read(base_addr + hdr.e_phoff + i * hdr.e_phentsize, + reinterpret_cast<uint8_t*>(&phdr), sizeof(phdr)) != sizeof(phdr)) { + return false; + } + // Looking for the .note.gnu.build-id note. + if (phdr.p_type == PT_NOTE) { + size_t hdr_size = phdr.p_filesz; + uintptr_t addr = base_addr + phdr.p_offset; + while (hdr_size >= sizeof(NhdrType)) { + NhdrType nhdr; + if (backtrace->Read(addr, reinterpret_cast<uint8_t*>(&nhdr), sizeof(nhdr)) != sizeof(nhdr)) { + return false; + } + addr += sizeof(nhdr); + if (nhdr.n_type == NT_GNU_BUILD_ID) { + // Skip the name (which is the owner and should be "GNU"). + addr += nhdr.n_namesz; + uint8_t build_id_data[128]; + if (nhdr.n_namesz > sizeof(build_id_data)) { + ALOGE("Possible corrupted note, name size value is too large: %u", + nhdr.n_namesz); + return false; + } + if (backtrace->Read(addr, build_id_data, nhdr.n_descsz) != nhdr.n_descsz) { + return false; + } + + build_id->clear(); + for (size_t bytes = 0; bytes < nhdr.n_descsz; bytes++) { + *build_id += android::base::StringPrintf("%02x", build_id_data[bytes]); + } + + return true; + } else { + // Move past the extra note data. + hdr_size -= sizeof(nhdr); + size_t skip_bytes = nhdr.n_namesz + nhdr.n_descsz; + addr += skip_bytes; + if (hdr_size < skip_bytes) { + break; + } + hdr_size -= skip_bytes; + } + } + } + } + return false; +} + +bool elf_get_build_id(Backtrace* backtrace, uintptr_t addr, std::string* build_id) { + // Read and verify the elf magic number first. + uint8_t e_ident[EI_NIDENT]; + if (backtrace->Read(addr, e_ident, SELFMAG) != SELFMAG) { + return false; + } + + if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) { + return false; + } + + // Read the rest of EI_NIDENT. + if (backtrace->Read(addr + SELFMAG, e_ident + SELFMAG, EI_NIDENT - SELFMAG) != EI_NIDENT - SELFMAG) { + return false; + } + + if (e_ident[EI_CLASS] == ELFCLASS32) { + return get_build_id<Elf32_Ehdr, Elf32_Phdr, Elf32_Nhdr>(backtrace, addr, e_ident, build_id); + } else if (e_ident[EI_CLASS] == ELFCLASS64) { + return get_build_id<Elf64_Ehdr, Elf64_Phdr, Elf64_Nhdr>(backtrace, addr, e_ident, build_id); + } + + return false; +} diff --git a/debuggerd/elf_utils.h b/debuggerd/elf_utils.h new file mode 100644 index 0000000..11d0a43 --- /dev/null +++ b/debuggerd/elf_utils.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef _DEBUGGERD_ELF_UTILS_H +#define _DEBUGGERD_ELF_UTILS_H + +#include <stdint.h> +#include <string> + +class Backtrace; + +bool elf_get_build_id(Backtrace*, uintptr_t, std::string*); + +#endif // _DEBUGGERD_ELF_UTILS_H diff --git a/debuggerd/mips64/crashglue.S b/debuggerd/mips64/crashglue.S new file mode 100644 index 0000000..70a6641 --- /dev/null +++ b/debuggerd/mips64/crashglue.S @@ -0,0 +1,48 @@ + .set noat + + .globl crash1 + .globl crashnostack + +crash1: + li $0,0xdead0000+0 + li $1,0xdead0000+1 + li $2,0xdead0000+2 + li $3,0xdead0000+3 + li $4,0xdead0000+4 + li $5,0xdead0000+5 + li $6,0xdead0000+6 + li $7,0xdead0000+7 + li $8,0xdead0000+8 + li $9,0xdead0000+9 + li $10,0xdead0000+10 + li $11,0xdead0000+11 + li $12,0xdead0000+12 + li $13,0xdead0000+13 + li $14,0xdead0000+14 + li $15,0xdead0000+15 + li $16,0xdead0000+16 + li $17,0xdead0000+17 + li $18,0xdead0000+18 + li $19,0xdead0000+19 + li $20,0xdead0000+20 + li $21,0xdead0000+21 + li $22,0xdead0000+22 + li $23,0xdead0000+23 + li $24,0xdead0000+24 + li $25,0xdead0000+25 + li $26,0xdead0000+26 + li $27,0xdead0000+27 + li $28,0xdead0000+28 + # don't trash the stack otherwise the signal handler won't run + #li $29,0xdead0000+29 + li $30,0xdead0000+30 + li $31,0xdead0000+31 + + lw $zero,($0) + b . + + +crashnostack: + li $sp, 0 + lw $zero,($0) + b . diff --git a/debuggerd/mips64/machine.cpp b/debuggerd/mips64/machine.cpp new file mode 100644 index 0000000..ef9092f --- /dev/null +++ b/debuggerd/mips64/machine.cpp @@ -0,0 +1,100 @@ +/* + * Copyright 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. + */ + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/ptrace.h> + +#include <sys/user.h> + +#include "../utility.h" +#include "../machine.h" + +#define R(x) (static_cast<unsigned long>(x)) + +// If configured to do so, dump memory around *all* registers +// for the crashing thread. +void dump_memory_and_code(log_t* log, pid_t tid) { + pt_regs r; + if (ptrace(PTRACE_GETREGS, tid, 0, &r)) { + return; + } + + static const char REG_NAMES[] = "$0atv0v1a0a1a2a3a4a5a6a7t0t1t2t3s0s1s2s3s4s5s6s7t8t9k0k1gpsps8ra"; + + for (int reg = 0; reg < 32; reg++) { + // skip uninteresting registers + if (reg == 0 // $0 + || reg == 26 // $k0 + || reg == 27 // $k1 + || reg == 31 // $ra (done below) + ) + continue; + + uintptr_t addr = R(r.regs[reg]); + + // Don't bother if it looks like a small int or ~= null, or if + // it's in the kernel area. + if (addr < 4096 || addr >= 0x4000000000000000) { + continue; + } + + _LOG(log, logtype::MEMORY, "\nmemory near %.2s:\n", ®_NAMES[reg * 2]); + dump_memory(log, tid, addr); + } + + unsigned long pc = R(r.cp0_epc); + unsigned long ra = R(r.regs[31]); + + _LOG(log, logtype::MEMORY, "\ncode around pc:\n"); + dump_memory(log, tid, (uintptr_t)pc); + + if (pc != ra) { + _LOG(log, logtype::MEMORY, "\ncode around ra:\n"); + dump_memory(log, tid, (uintptr_t)ra); + } +} + +void dump_registers(log_t* log, pid_t tid) { + pt_regs r; + if(ptrace(PTRACE_GETREGS, tid, 0, &r)) { + _LOG(log, logtype::ERROR, "cannot get registers: %s\n", strerror(errno)); + return; + } + + _LOG(log, logtype::REGISTERS, " zr %016lx at %016lx v0 %016lx v1 %016lx\n", + R(r.regs[0]), R(r.regs[1]), R(r.regs[2]), R(r.regs[3])); + _LOG(log, logtype::REGISTERS, " a0 %016lx a1 %016lx a2 %016lx a3 %016lx\n", + R(r.regs[4]), R(r.regs[5]), R(r.regs[6]), R(r.regs[7])); + _LOG(log, logtype::REGISTERS, " a4 %016lx a5 %016lx a6 %016lx a7 %016lx\n", + R(r.regs[8]), R(r.regs[9]), R(r.regs[10]), R(r.regs[11])); + _LOG(log, logtype::REGISTERS, " t0 %016lx t1 %016lx t2 %016lx t3 %016lx\n", + R(r.regs[12]), R(r.regs[13]), R(r.regs[14]), R(r.regs[15])); + _LOG(log, logtype::REGISTERS, " s0 %016lx s1 %016lx s2 %016lx s3 %016lx\n", + R(r.regs[16]), R(r.regs[17]), R(r.regs[18]), R(r.regs[19])); + _LOG(log, logtype::REGISTERS, " s4 %016lx s5 %016lx s6 %016lx s7 %016lx\n", + R(r.regs[20]), R(r.regs[21]), R(r.regs[22]), R(r.regs[23])); + _LOG(log, logtype::REGISTERS, " t8 %016lx t9 %016lx k0 %016lx k1 %016lx\n", + R(r.regs[24]), R(r.regs[25]), R(r.regs[26]), R(r.regs[27])); + _LOG(log, logtype::REGISTERS, " gp %016lx sp %016lx s8 %016lx ra %016lx\n", + R(r.regs[28]), R(r.regs[29]), R(r.regs[30]), R(r.regs[31])); + _LOG(log, logtype::REGISTERS, " hi %016lx lo %016lx bva %016lx epc %016lx\n", + R(r.hi), R(r.lo), R(r.cp0_badvaddr), R(r.cp0_epc)); +} diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp index e927ea3..094ab48 100644 --- a/debuggerd/tombstone.cpp +++ b/debuggerd/tombstone.cpp @@ -34,6 +34,7 @@ #include <private/android_filesystem_config.h> +#include <base/stringprintf.h> #include <cutils/properties.h> #include <log/log.h> #include <log/logger.h> @@ -46,9 +47,12 @@ #include <UniquePtr.h> +#include <string> + +#include "backtrace.h" +#include "elf_utils.h" #include "machine.h" #include "tombstone.h" -#include "backtrace.h" #define STACK_WORDS 16 @@ -234,47 +238,36 @@ static void dump_thread_info(log_t* log, pid_t pid, pid_t tid) { static void dump_stack_segment( Backtrace* backtrace, log_t* log, uintptr_t* sp, size_t words, int label) { + // Read the data all at once. + word_t stack_data[words]; + size_t bytes_read = backtrace->Read(*sp, reinterpret_cast<uint8_t*>(&stack_data[0]), sizeof(word_t) * words); + words = bytes_read / sizeof(word_t); + std::string line; for (size_t i = 0; i < words; i++) { - word_t stack_content; - if (!backtrace->ReadWord(*sp, &stack_content)) { - break; + line = " "; + if (i == 0 && label >= 0) { + // Print the label once. + line += android::base::StringPrintf("#%02d ", label); + } else { + line += " "; } + line += android::base::StringPrintf("%" PRIPTR " %" PRIPTR, *sp, stack_data[i]); backtrace_map_t map; - backtrace->FillInMap(stack_content, &map); - std::string map_name; - if (BacktraceMap::IsValid(map) && map.name.length() > 0) { - map_name = " " + map.name; - } - uintptr_t offset = 0; - std::string func_name(backtrace->GetFunctionName(stack_content, &offset)); - if (!func_name.empty()) { - if (!i && label >= 0) { + backtrace->FillInMap(stack_data[i], &map); + if (BacktraceMap::IsValid(map) && !map.name.empty()) { + line += " " + map.name; + uintptr_t offset = 0; + std::string func_name(backtrace->GetFunctionName(stack_data[i], &offset)); + if (!func_name.empty()) { + line += " (" + func_name; if (offset) { - _LOG(log, logtype::STACK, " #%02d %" PRIPTR " %" PRIPTR "%s (%s+%" PRIuPTR ")\n", - label, *sp, stack_content, map_name.c_str(), func_name.c_str(), offset); - } else { - _LOG(log, logtype::STACK, " #%02d %" PRIPTR " %" PRIPTR "%s (%s)\n", - label, *sp, stack_content, map_name.c_str(), func_name.c_str()); + line += android::base::StringPrintf("+%" PRIuPTR, offset); } - } else { - if (offset) { - _LOG(log, logtype::STACK, " %" PRIPTR " %" PRIPTR "%s (%s+%" PRIuPTR ")\n", - *sp, stack_content, map_name.c_str(), func_name.c_str(), offset); - } else { - _LOG(log, logtype::STACK, " %" PRIPTR " %" PRIPTR "%s (%s)\n", - *sp, stack_content, map_name.c_str(), func_name.c_str()); - } - } - } else { - if (!i && label >= 0) { - _LOG(log, logtype::STACK, " #%02d %" PRIPTR " %" PRIPTR "%s\n", - label, *sp, stack_content, map_name.c_str()); - } else { - _LOG(log, logtype::STACK, " %" PRIPTR " %" PRIPTR "%s\n", - *sp, stack_content, map_name.c_str()); + line += ')'; } } + _LOG(log, logtype::STACK, "%s\n", line.c_str()); *sp += sizeof(word_t); } @@ -325,44 +318,72 @@ static void dump_stack(Backtrace* backtrace, log_t* log) { } } -static void dump_map(log_t* log, const backtrace_map_t* map, bool fault_addr) { - _LOG(log, logtype::MAPS, "%s%" PRIPTR "-%" PRIPTR " %c%c%c %7" PRIdPTR "%s\n", - (fault_addr? "--->" : " "), map->start, map->end - 1, - (map->flags & PROT_READ) ? 'r' : '-', (map->flags & PROT_WRITE) ? 'w' : '-', - (map->flags & PROT_EXEC) ? 'x' : '-', - (map->end - map->start), - (map->name.length() > 0) ? (" " + map->name).c_str() : ""); -} - -static void dump_all_maps(BacktraceMap* map, log_t* log, pid_t tid) { - bool has_fault_address = false; +static void dump_all_maps(Backtrace* backtrace, BacktraceMap* map, log_t* log, pid_t tid) { + bool print_fault_address_marker = false; uintptr_t addr = 0; siginfo_t si; memset(&si, 0, sizeof(si)); if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) { - _LOG(log, logtype::MAPS, "cannot get siginfo for %d: %s\n", tid, strerror(errno)); + _LOG(log, logtype::ERROR, "cannot get siginfo for %d: %s\n", tid, strerror(errno)); } else { - has_fault_address = signal_has_si_addr(si.si_signo); + print_fault_address_marker = signal_has_si_addr(si.si_signo); addr = reinterpret_cast<uintptr_t>(si.si_addr); } - _LOG(log, logtype::MAPS, "\nmemory map:%s\n", has_fault_address ? " (fault address prefixed with --->)" : ""); - - if (has_fault_address && (addr < map->begin()->start)) { - _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " before any mapped regions\n", addr); + _LOG(log, logtype::MAPS, "\n"); + if (!print_fault_address_marker) { + _LOG(log, logtype::MAPS, "memory map:\n"); + } else { + _LOG(log, logtype::MAPS, "memory map: (fault address prefixed with --->)\n"); + if (map->begin() != map->end() && addr < map->begin()->start) { + _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " before any mapped regions\n", + addr); + print_fault_address_marker = false; + } } - BacktraceMap::const_iterator prev = map->begin(); + std::string line; for (BacktraceMap::const_iterator it = map->begin(); it != map->end(); ++it) { - if (addr >= (*prev).end && addr < (*it).start) { - _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " between mapped regions\n", addr); + line = " "; + if (print_fault_address_marker) { + if (addr < it->start) { + _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " between mapped regions\n", + addr); + print_fault_address_marker = false; + } else if (addr >= it->start && addr < it->end) { + line = "--->"; + print_fault_address_marker = false; + } + } + line += android::base::StringPrintf("%" PRIPTR "-%" PRIPTR " ", it->start, it->end - 1); + if (it->flags & PROT_READ) { + line += 'r'; + } else { + line += '-'; + } + if (it->flags & PROT_WRITE) { + line += 'w'; + } else { + line += '-'; + } + if (it->flags & PROT_EXEC) { + line += 'x'; + } else { + line += '-'; + } + line += android::base::StringPrintf(" %8" PRIxPTR, it->end - it->start); + if (it->name.length() > 0) { + line += " " + it->name; + std::string build_id; + if ((it->flags & PROT_READ) && elf_get_build_id(backtrace, it->start, &build_id)) { + line += " (BuildId: " + build_id + ")"; + } } - prev = it; - bool in_map = has_fault_address && (addr >= (*it).start) && (addr < (*it).end); - dump_map(log, &*it, in_map); + _LOG(log, logtype::MAPS, "%s\n", line.c_str()); } - if (has_fault_address && (addr >= (*prev).end)) { - _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " after any mapped regions\n", addr); + if (print_fault_address_marker) { + _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " after any mapped regions\n", + addr); } } @@ -627,7 +648,7 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, int si_code dump_backtrace_and_stack(backtrace.get(), log); } dump_memory_and_code(log, tid); - dump_all_maps(map.get(), log, tid); + dump_all_maps(backtrace.get(), map.get(), log, tid); if (want_logs) { dump_logs(log, pid, 5); diff --git a/debuggerd/utility.h b/debuggerd/utility.h index 58a882c..49b46e8 100644 --- a/debuggerd/utility.h +++ b/debuggerd/utility.h @@ -26,8 +26,10 @@ #define ABI_STRING "arm" #elif defined(__aarch64__) #define ABI_STRING "arm64" -#elif defined(__mips__) +#elif defined(__mips__) && !defined(__LP64__) #define ABI_STRING "mips" +#elif defined(__mips__) && defined(__LP64__) +#define ABI_STRING "mips64" #elif defined(__i386__) #define ABI_STRING "x86" #elif defined(__x86_64__) diff --git a/fastboot/Android.mk b/fastboot/Android.mk index aa5b14a..9cb002f 100644 --- a/fastboot/Android.mk +++ b/fastboot/Android.mk @@ -19,10 +19,11 @@ include $(CLEAR_VARS) LOCAL_C_INCLUDES := $(LOCAL_PATH)/../mkbootimg \ $(LOCAL_PATH)/../../extras/ext4_utils \ $(LOCAL_PATH)/../../extras/f2fs_utils -LOCAL_SRC_FILES := protocol.c engine.c bootimg.c fastboot.c util.c fs.c +LOCAL_SRC_FILES := protocol.c engine.c bootimg_utils.cpp fastboot.cpp util.c fs.c LOCAL_MODULE := fastboot LOCAL_MODULE_TAGS := debug -LOCAL_CFLAGS += -std=gnu99 -Werror +LOCAL_CONLYFLAGS += -std=gnu99 +LOCAL_CFLAGS += -Wall -Werror ifeq ($(HOST_OS),linux) LOCAL_SRC_FILES += usb_linux.c util_linux.c diff --git a/fastboot/bootimg.c b/fastboot/bootimg_utils.cpp index 240784f..d8905a6 100644 --- a/fastboot/bootimg.c +++ b/fastboot/bootimg_utils.cpp @@ -26,12 +26,12 @@ * SUCH DAMAGE. */ +#include "bootimg_utils.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <bootimg.h> - void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline) { strcpy((char*) h->cmdline, cmdline); @@ -47,7 +47,6 @@ boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offs unsigned ramdisk_actual; unsigned second_actual; unsigned page_mask; - boot_img_hdr *hdr; page_mask = page_size - 1; @@ -57,9 +56,8 @@ boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offs *bootimg_size = page_size + kernel_actual + ramdisk_actual + second_actual; - hdr = calloc(*bootimg_size, 1); - - if(hdr == 0) { + boot_img_hdr* hdr = reinterpret_cast<boot_img_hdr*>(calloc(*bootimg_size, 1)); + if (hdr == 0) { return hdr; } diff --git a/fastboot/bootimg_utils.h b/fastboot/bootimg_utils.h new file mode 100644 index 0000000..b1a86cd --- /dev/null +++ b/fastboot/bootimg_utils.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _FASTBOOT_BOOTIMG_UTILS_H_ +#define _FASTBOOT_BOOTIMG_UTILS_H_ + +#include <bootimg.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline); +boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offset, + void *ramdisk, unsigned ramdisk_size, unsigned ramdisk_offset, + void *second, unsigned second_size, unsigned second_offset, + unsigned page_size, unsigned base, unsigned tags_offset, + unsigned *bootimg_size); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/fastboot/fastboot.c b/fastboot/fastboot.cpp index fc544a6..04f3166 100644 --- a/fastboot/fastboot.c +++ b/fastboot/fastboot.cpp @@ -44,10 +44,10 @@ #include <sys/types.h> #include <unistd.h> -#include <bootimg.h> #include <sparse/sparse.h> #include <zipfile/zipfile.h> +#include "bootimg_utils.h" #include "fastboot.h" #include "fs.h" @@ -59,14 +59,6 @@ char cur_product[FB_RESPONSE_SZ + 1]; -void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline); - -boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, unsigned kernel_offset, - void *ramdisk, unsigned ramdisk_size, unsigned ramdisk_offset, - void *second, unsigned second_size, unsigned second_offset, - unsigned page_size, unsigned base, unsigned tags_offset, - unsigned *bootimg_size); - static usb_handle *usb = 0; static const char *serial = 0; static const char *product = 0; @@ -106,12 +98,10 @@ static struct { {"vendor.img", "vendor.sig", "vendor", true}, }; -void get_my_path(char *path); - char *find_item(const char *item, const char *product) { char *dir; - char *fn; + const char *fn; char path[PATH_MAX + 128]; if(!strcmp(item,"boot")) { @@ -234,7 +224,7 @@ int match_fastboot(usb_ifc_info *info) int list_devices_callback(usb_ifc_info *info) { if (match_fastboot_with_serial(info, NULL) == 0) { - char* serial = info->serial_number; + const char* serial = info->serial_number; if (!info->writable) { serial = "no permissions"; // like "adb devices" } @@ -389,7 +379,7 @@ void *load_bootable_image(const char *kernel, const char *ramdisk, return bdata; } -void *unzip_file(zipfile_t zip, const char *name, unsigned *sz) +static void *unzip_file(zipfile_t zip, const char *name, unsigned *sz) { void *data; zipentry_t entry; @@ -422,16 +412,13 @@ void *unzip_file(zipfile_t zip, const char *name, unsigned *sz) static int unzip_to_file(zipfile_t zip, char *name) { - int fd; - char *data; - unsigned sz; - - fd = fileno(tmpfile()); + int fd = fileno(tmpfile()); if (fd < 0) { return -1; } - data = unzip_file(zip, name, &sz); + unsigned sz; + void* data = unzip_file(zip, name, &sz); if (data == 0) { return -1; } @@ -461,7 +448,6 @@ static char *strip(char *s) static int setup_requirement_line(char *name) { char *val[MAX_OPTIONS]; - const char **out; char *prod = NULL; unsigned n, count; char *x; @@ -501,10 +487,11 @@ static int setup_requirement_line(char *name) name = strip(name); if (name == 0) return -1; - /* work around an unfortunate name mismatch */ - if (!strcmp(name,"board")) name = "product"; + const char* var = name; + // Work around an unfortunate name mismatch. + if (!strcmp(name,"board")) var = "product"; - out = malloc(sizeof(char*) * count); + const char** out = reinterpret_cast<const char**>(malloc(sizeof(char*) * count)); if (out == 0) return -1; for(n = 0; n < count; n++) { @@ -518,7 +505,7 @@ static int setup_requirement_line(char *name) } } - fb_queue_require(prod, name, invert, n, out); + fb_queue_require(prod, var, invert, n, out); return 0; } @@ -551,21 +538,17 @@ void queue_info_dump(void) static struct sparse_file **load_sparse_files(int fd, int max_size) { - struct sparse_file *s; - int files; - struct sparse_file **out_s; - - s = sparse_file_import_auto(fd, false); + struct sparse_file* s = sparse_file_import_auto(fd, false); if (!s) { die("cannot sparse read file\n"); } - files = sparse_file_resparse(s, max_size, NULL, 0); + int files = sparse_file_resparse(s, max_size, NULL, 0); if (files < 0) { die("Failed to resparse\n"); } - out_s = calloc(sizeof(struct sparse_file *), files + 1); + sparse_file** out_s = reinterpret_cast<sparse_file**>(calloc(sizeof(struct sparse_file *), files + 1)); if (!out_s) { die("Failed to allocate sparse file array\n"); } @@ -682,11 +665,11 @@ static int load_buf(usb_handle *usb, const char *fname, static void flash_buf(const char *pname, struct fastboot_buffer *buf) { - struct sparse_file **s; + sparse_file** s; switch (buf->type) { case FB_BUFFER_SPARSE: - s = buf->data; + s = reinterpret_cast<sparse_file**>(buf->data); while (*s) { int64_t sz64 = sparse_file_len(*s, true, false); fb_queue_flash_sparse(pname, *s++, sz64); @@ -720,53 +703,42 @@ void do_update_signature(zipfile_t zip, char *fn) fb_queue_command("signature", "installing signature"); } -void do_update(usb_handle *usb, char *fn, int erase_first) +void do_update(usb_handle *usb, const char *filename, int erase_first) { - void *zdata; - unsigned zsize; - void *data; - unsigned sz; - zipfile_t zip; - int fd; - int rc; - struct fastboot_buffer buf; - size_t i; - queue_info_dump(); fb_queue_query_save("product", cur_product, sizeof(cur_product)); - zdata = load_file(fn, &zsize); - if (zdata == 0) die("failed to load '%s': %s", fn, strerror(errno)); + unsigned zsize; + void* zdata = load_file(filename, &zsize); + if (zdata == 0) die("failed to load '%s': %s", filename, strerror(errno)); - zip = init_zipfile(zdata, zsize); - if(zip == 0) die("failed to access zipdata in '%s'"); + zipfile_t zip = init_zipfile(zdata, zsize); + if (zip == 0) die("failed to access zipdata in '%s'"); - data = unzip_file(zip, "android-info.txt", &sz); + unsigned sz; + void* data = unzip_file(zip, "android-info.txt", &sz); if (data == 0) { - char *tmp; /* fallback for older zipfiles */ data = unzip_file(zip, "android-product.txt", &sz); if ((data == 0) || (sz < 1)) { die("update package has no android-info.txt or android-product.txt"); } - tmp = malloc(sz + 128); - if (tmp == 0) die("out of memory"); - sprintf(tmp,"board=%sversion-baseband=0.66.04.19\n",(char*)data); - data = tmp; - sz = strlen(tmp); + data = mkmsg("board=%sversion-baseband=0.66.04.19\n", reinterpret_cast<char*>(data)); + sz = strlen(reinterpret_cast<char*>(data)); } - setup_requirements(data, sz); + setup_requirements(reinterpret_cast<char*>(data), sz); - for (i = 0; i < ARRAY_SIZE(images); i++) { - fd = unzip_to_file(zip, images[i].img_name); + for (size_t i = 0; i < ARRAY_SIZE(images); i++) { + int fd = unzip_to_file(zip, images[i].img_name); if (fd < 0) { if (images[i].is_optional) continue; die("update package missing %s", images[i].img_name); } - rc = load_buf_fd(usb, fd, &buf); + fastboot_buffer buf; + int rc = load_buf_fd(usb, fd, &buf); if (rc) die("cannot load %s from flash", images[i].img_name); do_update_signature(zip, images[i].sig_name); if (erase_first && needs_erase(images[i].part_name)) { @@ -800,24 +772,22 @@ void do_send_signature(char *fn) void do_flashall(usb_handle *usb, int erase_first) { - char *fname; - void *data; - unsigned sz; - struct fastboot_buffer buf; - size_t i; - queue_info_dump(); fb_queue_query_save("product", cur_product, sizeof(cur_product)); - fname = find_item("info", product); + char* fname = find_item("info", product); if (fname == 0) die("cannot find android-info.txt"); - data = load_file(fname, &sz); + + unsigned sz; + void* data = load_file(fname, &sz); if (data == 0) die("could not load android-info.txt: %s", strerror(errno)); - setup_requirements(data, sz); - for (i = 0; i < ARRAY_SIZE(images); i++) { + setup_requirements(reinterpret_cast<char*>(data), sz); + + for (size_t i = 0; i < ARRAY_SIZE(images); i++) { fname = find_item(images[i].part_name, product); + fastboot_buffer buf; if (load_buf(usb, fname, &buf)) { if (images[i].is_optional) continue; diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h index fc5d4f4..1786e49 100644 --- a/fastboot/fastboot.h +++ b/fastboot/fastboot.h @@ -31,6 +31,10 @@ #include "usb.h" +#if defined(__cplusplus) +extern "C" { +#endif + struct sparse_file; /* protocol.c - fastboot protocol */ @@ -67,7 +71,13 @@ double now(); char *mkmsg(const char *fmt, ...); void die(const char *fmt, ...); +void get_my_path(char *path); + /* Current product */ extern char cur_product[FB_RESPONSE_SZ + 1]; +#if defined(__cplusplus) +} +#endif + #endif diff --git a/fastboot/fs.h b/fastboot/fs.h index 8444081..307772b 100644 --- a/fastboot/fs.h +++ b/fastboot/fs.h @@ -3,10 +3,18 @@ #include <stdint.h> +#if defined(__cplusplus) +extern "C" { +#endif + struct fs_generator; const struct fs_generator* fs_get_generator(const char *fs_type); int fs_generator_generate(const struct fs_generator* gen, int tmpFileNo, long long partSize); +#if defined(__cplusplus) +} +#endif + #endif diff --git a/fastboot/usb.h b/fastboot/usb.h index 17cf0a9..c7b748e 100644 --- a/fastboot/usb.h +++ b/fastboot/usb.h @@ -29,6 +29,10 @@ #ifndef _USB_H_ #define _USB_H_ +#if defined(__cplusplus) +extern "C" { +#endif + typedef struct usb_handle usb_handle; typedef struct usb_ifc_info usb_ifc_info; @@ -64,4 +68,8 @@ int usb_read(usb_handle *h, void *_data, int len); int usb_write(usb_handle *h, const void *_data, int len); int usb_wait_for_disconnect(usb_handle *h); +#if defined(__cplusplus) +} +#endif + #endif diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c index f9a6ba2..d4daed6 100644 --- a/fs_mgr/fs_mgr.c +++ b/fs_mgr/fs_mgr.c @@ -154,9 +154,10 @@ static void check_fs(char *blk_device, char *fs_type, char *target) } else if (!strcmp(fs_type, "f2fs")) { char *f2fs_fsck_argv[] = { F2FS_FSCK_BIN, + "-f", blk_device }; - INFO("Running %s on %s\n", F2FS_FSCK_BIN, blk_device); + INFO("Running %s -f %s\n", F2FS_FSCK_BIN, blk_device); ret = android_fork_execvp_ext(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv, &status, true, LOG_KLOG | LOG_FILE, @@ -490,7 +491,9 @@ int fs_mgr_mount_all(struct fstab *fstab) /* Deal with encryptability. */ if (!mret) { /* If this is encryptable, need to trigger encryption */ - if (fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) { + if ( (fstab->recs[attempted_idx].fs_mgr_flags & MF_FORCECRYPT) + || (device_is_force_encrypted() + && fs_mgr_is_encryptable(&fstab->recs[attempted_idx]))) { if (umount(fstab->recs[attempted_idx].mount_point) == 0) { if (encryptable == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { ERROR("Will try to encrypt %s %s\n", fstab->recs[attempted_idx].mount_point, diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c index 9d536bd..ab8f128 100644 --- a/fs_mgr/fs_mgr_fstab.c +++ b/fs_mgr/fs_mgr_fstab.c @@ -428,11 +428,6 @@ int fs_mgr_is_encryptable(struct fstab_rec *fstab) return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT); } -int fs_mgr_is_force_encrypted(struct fstab_rec *fstab) -{ - return fstab->fs_mgr_flags & MF_FORCECRYPT; -} - int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab) { return fstab->fs_mgr_flags & MF_NOEMULATEDSD; diff --git a/fs_mgr/fs_mgr_verity.c b/fs_mgr/fs_mgr_verity.c index db63bcc..feb3c19 100644 --- a/fs_mgr/fs_mgr_verity.c +++ b/fs_mgr/fs_mgr_verity.c @@ -42,9 +42,24 @@ #include "fs_mgr_priv.h" #include "fs_mgr_priv_verity.h" +#define FSTAB_PREFIX "/fstab." + #define VERITY_METADATA_SIZE 32768 #define VERITY_TABLE_RSA_KEY "/verity_key" +#define VERITY_STATE_HEADER 0x83c0ae9d +#define VERITY_STATE_VERSION 1 + +#define VERITY_KMSG_RESTART "dm-verity device corrupted" +#define VERITY_KMSG_BUFSIZE 1024 + +struct verity_state { + uint32_t header; + uint32_t version; + uint32_t size; + int32_t mode; +}; + extern struct fs_info info; static RSAPublicKey *load_key(char *path) @@ -86,11 +101,11 @@ static RSAPublicKey *load_key(char *path) static int verify_table(char *signature, char *table, int table_length) { RSAPublicKey *key; - uint8_t hash_buf[SHA_DIGEST_SIZE]; + uint8_t hash_buf[SHA256_DIGEST_SIZE]; int retval = -1; // Hash the table - SHA_hash((uint8_t*)table, table_length, hash_buf); + SHA256_hash((uint8_t*)table, table_length, hash_buf); // Now get the public key from the keyfile key = load_key(VERITY_TABLE_RSA_KEY); @@ -104,7 +119,7 @@ static int verify_table(char *signature, char *table, int table_length) (uint8_t*) signature, RSANUMBYTES, (uint8_t*) hash_buf, - SHA_DIGEST_SIZE)) { + SHA256_DIGEST_SIZE)) { ERROR("Couldn't verify table."); goto out; } @@ -294,10 +309,12 @@ static int get_verity_device_name(struct dm_ioctl *io, char *name, int fd, char return 0; } -static int load_verity_table(struct dm_ioctl *io, char *name, char *blockdev, int fd, char *table) +static int load_verity_table(struct dm_ioctl *io, char *name, char *blockdev, int fd, char *table, + int mode) { char *verity_params; char *buffer = (char*) io; + size_t bufsize; uint64_t device_size = 0; if (get_target_device_size(blockdev, &device_size) < 0) { @@ -317,7 +334,17 @@ static int load_verity_table(struct dm_ioctl *io, char *name, char *blockdev, in // build the verity params here verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); - strcpy(verity_params, table); + bufsize = DM_BUF_SIZE - (verity_params - buffer); + + if (mode == VERITY_MODE_EIO) { + // allow operation with older dm-verity drivers that are unaware + // of the mode parameter by omitting it; this also means that we + // cannot use logging mode with these drivers, they always cause + // an I/O error for corrupted blocks + strcpy(verity_params, table); + } else if (snprintf(verity_params, bufsize, "%s %d", table, mode) < 0) { + return -1; + } // set next target boundary verity_params += strlen(verity_params) + 1; @@ -354,36 +381,300 @@ static int test_access(char *device) { return -1; } -static int set_verified_property(char *name) { - int ret; - char *key; - ret = asprintf(&key, "partition.%s.verified", name); - if (ret < 0) { - ERROR("Error formatting verified property"); - return ret; - } - ret = PROP_NAME_MAX - strlen(key); - if (ret < 0) { - ERROR("Verified property name is too long"); +static int check_verity_restart(const char *fname) +{ + char buffer[VERITY_KMSG_BUFSIZE + 1]; + int fd; + int rc = 0; + ssize_t size; + struct stat s; + + fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC)); + + if (fd == -1) { + if (errno != ENOENT) { + ERROR("Failed to open %s (%s)\n", fname, strerror(errno)); + } + goto out; + } + + if (fstat(fd, &s) == -1) { + ERROR("Failed to fstat %s (%s)\n", fname, strerror(errno)); + goto out; + } + + size = VERITY_KMSG_BUFSIZE; + + if (size > s.st_size) { + size = s.st_size; + } + + if (lseek(fd, s.st_size - size, SEEK_SET) == -1) { + ERROR("Failed to lseek %jd %s (%s)\n", (intmax_t)(s.st_size - size), fname, + strerror(errno)); + goto out; + } + + if (TEMP_FAILURE_RETRY(read(fd, buffer, size)) != size) { + ERROR("Failed to read %zd bytes from %s (%s)\n", size, fname, + strerror(errno)); + goto out; + } + + buffer[size] = '\0'; + + if (strstr(buffer, VERITY_KMSG_RESTART) != NULL) { + rc = 1; + } + +out: + if (fd != -1) { + TEMP_FAILURE_RETRY(close(fd)); + } + + return rc; +} + +static int was_verity_restart() +{ + static const char *files[] = { + "/sys/fs/pstore/console-ramoops", + "/proc/last_kmsg", + NULL + }; + int i; + + for (i = 0; files[i]; ++i) { + if (check_verity_restart(files[i])) { + return 1; + } + } + + return 0; +} + +static int write_verity_state(const char *fname, off64_t offset, int32_t mode) +{ + int fd; + int rc = -1; + + struct verity_state s = { + VERITY_STATE_HEADER, + VERITY_STATE_VERSION, + sizeof(struct verity_state), + mode + }; + + fd = TEMP_FAILURE_RETRY(open(fname, O_WRONLY | O_SYNC | O_CLOEXEC)); + + if (fd == -1) { + ERROR("Failed to open %s (%s)\n", fname, strerror(errno)); + goto out; + } + + if (TEMP_FAILURE_RETRY(lseek64(fd, offset, SEEK_SET)) < 0) { + ERROR("Failed to seek %s to %" PRIu64 " (%s)\n", fname, offset, strerror(errno)); + goto out; + } + + if (TEMP_FAILURE_RETRY(write(fd, &s, sizeof(s))) != sizeof(s)) { + ERROR("Failed to write %zu bytes to %s (%s)\n", sizeof(s), fname, strerror(errno)); + goto out; + } + + rc = 0; + +out: + if (fd != -1) { + TEMP_FAILURE_RETRY(close(fd)); + } + + return rc; +} + +static int get_verity_state_location(char *location, off64_t *offset) +{ + char state_off[PROPERTY_VALUE_MAX]; + + if (property_get("ro.verity.state.location", location, NULL) <= 0) { return -1; } - ret = property_set(key, "1"); - if (ret < 0) - ERROR("Error setting verified property %s: %d", key, ret); - free(key); - return ret; + + if (*location != '/' || access(location, R_OK | W_OK) == -1) { + ERROR("Failed to access verity state %s (%s)\n", location, strerror(errno)); + return -1; + } + + *offset = 0; + + if (property_get("ro.verity.state.offset", state_off, NULL) > 0) { + *offset = strtoll(state_off, NULL, 0); + + if (errno == ERANGE || errno == EINVAL) { + ERROR("Invalid value in ro.verity.state.offset (%s)\n", state_off); + return -1; + } + } + + return 0; +} + +int fs_mgr_load_verity_state(int *mode) +{ + char fname[PROPERTY_VALUE_MAX]; + int fd = -1; + int rc = -1; + off64_t offset = 0; + struct verity_state s; + + if (get_verity_state_location(fname, &offset) < 0) { + /* location for dm-verity state is not specified, fall back to + * default behavior: return -EIO for corrupted blocks */ + *mode = VERITY_MODE_EIO; + rc = 0; + goto out; + } + + if (was_verity_restart()) { + /* device was restarted after dm-verity detected a corrupted + * block, so switch to logging mode */ + *mode = VERITY_MODE_LOGGING; + rc = write_verity_state(fname, offset, *mode); + goto out; + } + + fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC)); + + if (fd == -1) { + ERROR("Failed to open %s (%s)\n", fname, strerror(errno)); + goto out; + } + + if (TEMP_FAILURE_RETRY(lseek64(fd, offset, SEEK_SET)) < 0) { + ERROR("Failed to seek %s to %" PRIu64 " (%s)\n", fname, offset, strerror(errno)); + goto out; + } + + if (TEMP_FAILURE_RETRY(read(fd, &s, sizeof(s))) != sizeof(s)) { + ERROR("Failed to read %zu bytes from %s (%s)\n", sizeof(s), fname, strerror(errno)); + goto out; + } + + if (s.header != VERITY_STATE_HEADER) { + goto out; + } + + if (s.version != VERITY_STATE_VERSION) { + ERROR("Unsupported verity state version (%u)\n", s.version); + goto out; + } + + if (s.size != sizeof(s)) { + ERROR("Unexpected verity state size (%u)\n", s.size); + goto out; + } + + if (s.mode < VERITY_MODE_EIO || + s.mode > VERITY_MODE_LAST) { + ERROR("Unsupported verity mode (%u)\n", s.mode); + goto out; + } + + *mode = s.mode; + rc = 0; + +out: + if (fd != -1) { + TEMP_FAILURE_RETRY(close(fd)); + } + + return rc; +} + +int fs_mgr_update_verity_state() +{ + _Alignas(struct dm_ioctl) char buffer[DM_BUF_SIZE]; + char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; + char *mount_point; + char propbuf[PROPERTY_VALUE_MAX]; + char state_loc[PROPERTY_VALUE_MAX]; + char *status; + int fd = -1; + int i; + int rc = -1; + off64_t offset = 0; + struct dm_ioctl *io = (struct dm_ioctl *) buffer; + struct fstab *fstab = NULL; + + if (get_verity_state_location(state_loc, &offset) < 0) { + goto out; + } + + fd = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC)); + + if (fd == -1) { + ERROR("Error opening device mapper (%s)\n", strerror(errno)); + goto out; + } + + property_get("ro.hardware", propbuf, ""); + snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf); + + fstab = fs_mgr_read_fstab(fstab_filename); + + if (!fstab) { + ERROR("Failed to read %s\n", fstab_filename); + goto out; + } + + for (i = 0; i < fstab->num_entries; i++) { + if (!fs_mgr_is_verified(&fstab->recs[i])) { + continue; + } + + mount_point = basename(fstab->recs[i].mount_point); + verity_ioctl_init(io, mount_point, 0); + + if (ioctl(fd, DM_TABLE_STATUS, io)) { + ERROR("Failed to query DM_TABLE_STATUS for %s (%s)\n", mount_point, + strerror(errno)); + goto out; + } + + status = &buffer[io->data_start + sizeof(struct dm_target_spec)]; + + if (*status == 'C') { + rc = write_verity_state(state_loc, offset, VERITY_MODE_LOGGING); + goto out; + } + } + + /* Don't overwrite possible previous state if there's no corruption. */ + rc = 0; + +out: + if (fstab) { + fs_mgr_free_fstab(fstab); + } + + if (fd) { + TEMP_FAILURE_RETRY(close(fd)); + } + + return rc; } int fs_mgr_setup_verity(struct fstab_rec *fstab) { - int retval = -1; + int retval = FS_MGR_SETUP_VERITY_FAIL; int fd = -1; + int mode; char *verity_blk_name = 0; char *verity_table = 0; char *verity_table_signature = 0; - char buffer[DM_BUF_SIZE]; + _Alignas(struct dm_ioctl) char buffer[DM_BUF_SIZE]; struct dm_ioctl *io = (struct dm_ioctl *) buffer; char *mount_point = basename(fstab->mount_point); @@ -407,6 +698,8 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab) { goto out; } + retval = FS_MGR_SETUP_VERITY_FAIL; + // get the device mapper fd if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) { ERROR("Error opening device mapper (%s)", strerror(errno)); @@ -432,8 +725,13 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab) { goto out; } + if (fs_mgr_load_verity_state(&mode) < 0) { + mode = VERITY_MODE_RESTART; /* default dm-verity mode */ + } + // load the verity mapping table - if (load_verity_table(io, mount_point, fstab->blk_device, fd, verity_table) < 0) { + if (load_verity_table(io, mount_point, fstab->blk_device, fd, verity_table, + mode) < 0) { goto out; } @@ -455,8 +753,7 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab) { goto out; } - // set the property indicating that the partition is verified - retval = set_verified_property(mount_point); + retval = FS_MGR_SETUP_VERITY_SUCCESS; out: if (fd != -1) { diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h index 5ec3b99..0437d45 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -27,6 +27,14 @@ // turn verity off in userdebug builds. #define VERITY_METADATA_MAGIC_DISABLE 0x46464f56 // "VOFF" +// Verity modes +enum verity_mode { + VERITY_MODE_EIO = 0, + VERITY_MODE_LOGGING = 1, + VERITY_MODE_RESTART = 2, + VERITY_MODE_LAST = VERITY_MODE_RESTART +}; + #ifdef __cplusplus extern "C" { #endif @@ -75,6 +83,8 @@ int fs_mgr_do_tmpfs_mount(char *n_name); int fs_mgr_unmount_all(struct fstab *fstab); int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_device, int size); +int fs_mgr_load_verity_state(int *mode); +int fs_mgr_update_verity_state(); int fs_mgr_add_entry(struct fstab *fstab, const char *mount_point, const char *fs_type, const char *blk_device); @@ -83,7 +93,6 @@ int fs_mgr_is_voldmanaged(struct fstab_rec *fstab); int fs_mgr_is_nonremovable(struct fstab_rec *fstab); int fs_mgr_is_verified(struct fstab_rec *fstab); int fs_mgr_is_encryptable(struct fstab_rec *fstab); -int fs_mgr_is_force_encrypted(struct fstab_rec *fstab); int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab); int fs_mgr_swapon_all(struct fstab *fstab); #ifdef __cplusplus diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp index 06497c2..7ea8250 100644 --- a/healthd/BatteryMonitor.cpp +++ b/healthd/BatteryMonitor.cpp @@ -265,10 +265,10 @@ bool BatteryMonitor::update(void) { "battery none"); } - KLOG_INFO(LOG_TAG, "%s chg=%s%s%s\n", dmesgline, - props.chargerAcOnline ? "a" : "", - props.chargerUsbOnline ? "u" : "", - props.chargerWirelessOnline ? "w" : ""); + KLOG_WARNING(LOG_TAG, "%s chg=%s%s%s\n", dmesgline, + props.chargerAcOnline ? "a" : "", + props.chargerUsbOnline ? "u" : "", + props.chargerWirelessOnline ? "w" : ""); } healthd_mode_ops->battery_update(&props); @@ -511,7 +511,7 @@ void BatteryMonitor::init(struct healthd_config *hc) { if (!mChargerNames.size()) KLOG_ERROR(LOG_TAG, "No charger supplies found\n"); if (!mBatteryDevicePresent) { - KLOG_INFO(LOG_TAG, "No battery devices found\n"); + KLOG_WARNING(LOG_TAG, "No battery devices found\n"); hc->periodic_chores_interval_fast = -1; hc->periodic_chores_interval_slow = -1; } else { diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp index b34583d..1fee855 100644 --- a/healthd/healthd.cpp +++ b/healthd/healthd.cpp @@ -53,6 +53,7 @@ static struct healthd_config healthd_config = { .batteryCurrentAvgPath = String8(String8::kEmptyString), .batteryChargeCounterPath = String8(String8::kEmptyString), .energyCounter = NULL, + .screen_on = NULL, }; static int eventct; @@ -313,8 +314,8 @@ static int healthd_init() { return -1; } - healthd_mode_ops->init(&healthd_config); healthd_board_init(&healthd_config); + healthd_mode_ops->init(&healthd_config); wakealarm_init(); uevent_init(); gBatteryMonitor = new BatteryMonitor(); diff --git a/healthd/healthd.h b/healthd/healthd.h index 972e728..4704f0b 100644 --- a/healthd/healthd.h +++ b/healthd/healthd.h @@ -67,6 +67,7 @@ struct healthd_config { android::String8 batteryChargeCounterPath; int (*energyCounter)(int64_t *); + bool (*screen_on)(android::BatteryProperties *props); }; // Global helper functions diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp index 291cb6c..9ed5944 100644 --- a/healthd/healthd_mode_charger.cpp +++ b/healthd/healthd_mode_charger.cpp @@ -68,14 +68,13 @@ char *locale; #define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC) #define BATTERY_FULL_THRESH 95 -#define SCREEN_ON_BATTERY_THRESH 0 #define LAST_KMSG_PATH "/proc/last_kmsg" #define LAST_KMSG_PSTORE_PATH "/sys/fs/pstore/console-ramoops" #define LAST_KMSG_MAX_SZ (32 * 1024) #define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0) -#define LOGI(x...) do { KLOG_INFO("charger", x); } while (0) +#define LOGW(x...) do { KLOG_WARNING("charger", x); } while (0) #define LOGV(x...) do { KLOG_DEBUG("charger", x); } while (0) struct key_state { @@ -109,7 +108,6 @@ struct animation { struct charger { bool have_battery_state; bool charger_connected; - int capacity; int64_t next_screen_transition; int64_t next_key_check; int64_t next_pwr_check; @@ -170,7 +168,8 @@ static struct animation battery_animation = { }; static struct charger charger_state; - +static struct healthd_config *healthd_config; +static struct android::BatteryProperties *batt_prop; static int char_width; static int char_height; static bool minui_inited; @@ -198,15 +197,15 @@ static void dump_last_kmsg(void) unsigned sz = 0; int len; - LOGI("\n"); - LOGI("*************** LAST KMSG ***************\n"); - LOGI("\n"); + LOGW("\n"); + LOGW("*************** LAST KMSG ***************\n"); + LOGW("\n"); buf = (char *)load_file(LAST_KMSG_PSTORE_PATH, &sz); if (!buf || !sz) { buf = (char *)load_file(LAST_KMSG_PATH, &sz); if (!buf || !sz) { - LOGI("last_kmsg not found. Cold reset?\n"); + LOGW("last_kmsg not found. Cold reset?\n"); goto out; } } @@ -225,7 +224,7 @@ static void dump_last_kmsg(void) yoink = ptr[cnt]; ptr[cnt] = '\0'; - klog_write(6, "<6>%s", ptr); + klog_write(6, "<4>%s", ptr); ptr[cnt] = yoink; len -= cnt; @@ -235,14 +234,9 @@ static void dump_last_kmsg(void) free(buf); out: - LOGI("\n"); - LOGI("************* END LAST KMSG *************\n"); - LOGI("\n"); -} - -static int get_battery_capacity() -{ - return charger_state.capacity; + LOGW("\n"); + LOGW("************* END LAST KMSG *************\n"); + LOGW("\n"); } #ifdef CHARGER_ENABLE_SUSPEND @@ -356,15 +350,16 @@ static void update_screen_state(struct charger *charger, int64_t now) return; if (!minui_inited) { - int batt_cap = get_battery_capacity(); - - if (batt_cap < SCREEN_ON_BATTERY_THRESH) { - LOGV("[%" PRId64 "] level %d, leave screen off\n", now, batt_cap); - batt_anim->run = false; - charger->next_screen_transition = -1; - if (charger->charger_connected) - request_suspend(true); - return; + + if (healthd_config && healthd_config->screen_on) { + if (!healthd_config->screen_on(batt_prop)) { + LOGV("[%" PRId64 "] leave screen off\n", now); + batt_anim->run = false; + charger->next_screen_transition = -1; + if (charger->charger_connected) + request_suspend(true); + return; + } } gr_init(); @@ -391,16 +386,14 @@ static void update_screen_state(struct charger *charger, int64_t now) /* animation starting, set up the animation */ if (batt_anim->cur_frame == 0) { - int batt_cap; LOGV("[%" PRId64 "] animation starting\n", now); - batt_cap = get_battery_capacity(); - if (batt_cap >= 0 && batt_anim->num_frames != 0) { + if (batt_prop && batt_prop->batteryLevel >= 0 && batt_anim->num_frames != 0) { int i; /* find first frame given current capacity */ for (i = 1; i < batt_anim->num_frames; i++) { - if (batt_cap < batt_anim->frames[i].min_capacity) + if (batt_prop->batteryLevel < batt_anim->frames[i].min_capacity) break; } batt_anim->cur_frame = i - 1; @@ -408,8 +401,8 @@ static void update_screen_state(struct charger *charger, int64_t now) /* show the first frame for twice as long */ disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time * 2; } - - batt_anim->capacity = batt_cap; + if (batt_prop) + batt_anim->capacity = batt_prop->batteryLevel; } /* unblank the screen on first cycle */ @@ -524,10 +517,10 @@ static void process_key(struct charger *charger, int code, int64_t now) all devices. Check the property and continue booting or reboot accordingly. */ if (property_get_bool("ro.enable_boot_charger_mode", false)) { - LOGI("[%" PRId64 "] booting from charger mode\n", now); + LOGW("[%" PRId64 "] booting from charger mode\n", now); property_set("sys.boot_from_charger_mode", "1"); } else { - LOGI("[%" PRId64 "] rebooting\n", now); + LOGW("[%" PRId64 "] rebooting\n", now); android_reboot(ANDROID_RB_RESTART, 0, 0); } } else { @@ -565,10 +558,10 @@ static void handle_power_supply_state(struct charger *charger, int64_t now) request_suspend(false); if (charger->next_pwr_check == -1) { charger->next_pwr_check = now + UNPLUGGED_SHUTDOWN_TIME; - LOGI("[%" PRId64 "] device unplugged: shutting down in %" PRId64 " (@ %" PRId64 ")\n", + LOGW("[%" PRId64 "] device unplugged: shutting down in %" PRId64 " (@ %" PRId64 ")\n", now, (int64_t)UNPLUGGED_SHUTDOWN_TIME, charger->next_pwr_check); } else if (now >= charger->next_pwr_check) { - LOGI("[%" PRId64 "] shutting down\n", now); + LOGW("[%" PRId64 "] shutting down\n", now); android_reboot(ANDROID_RB_POWEROFF, 0, 0); } else { /* otherwise we already have a shutdown timer scheduled */ @@ -576,7 +569,7 @@ static void handle_power_supply_state(struct charger *charger, int64_t now) } else { /* online supply present, reset shutdown timer if set */ if (charger->next_pwr_check != -1) { - LOGI("[%" PRId64 "] device plugged in: shutdown cancelled\n", now); + LOGW("[%" PRId64 "] device plugged in: shutdown cancelled\n", now); kick_animation(charger->batt_anim); } charger->next_pwr_check = -1; @@ -605,7 +598,6 @@ void healthd_mode_charger_battery_update( charger->charger_connected = props->chargerAcOnline || props->chargerUsbOnline || props->chargerWirelessOnline; - charger->capacity = props->batteryLevel; if (!charger->have_battery_state) { charger->have_battery_state = true; @@ -613,6 +605,7 @@ void healthd_mode_charger_battery_update( reset_animation(charger->batt_anim); kick_animation(charger->batt_anim); } + batt_prop = props; } int healthd_mode_charger_preparetowait(void) @@ -663,7 +656,7 @@ static void charger_event_handler(uint32_t /*epevents*/) ev_dispatch(); } -void healthd_mode_charger_init(struct healthd_config* /*config*/) +void healthd_mode_charger_init(struct healthd_config* config) { int ret; struct charger *charger = &charger_state; @@ -672,7 +665,7 @@ void healthd_mode_charger_init(struct healthd_config* /*config*/) dump_last_kmsg(); - LOGI("--------------- STARTING CHARGER MODE ---------------\n"); + LOGW("--------------- STARTING CHARGER MODE ---------------\n"); ret = ev_init(input_callback, charger); if (!ret) { @@ -711,4 +704,5 @@ void healthd_mode_charger_init(struct healthd_config* /*config*/) charger->next_screen_transition = -1; charger->next_key_check = -1; charger->next_pwr_check = -1; + healthd_config = config; } diff --git a/include/backtrace/Backtrace.h b/include/backtrace/Backtrace.h index e2d718b..8c39acb 100644 --- a/include/backtrace/Backtrace.h +++ b/include/backtrace/Backtrace.h @@ -84,6 +84,12 @@ public: // Read the data at a specific address. virtual bool ReadWord(uintptr_t ptr, word_t* out_value) = 0; + // Read arbitrary data from a specific address. If a read request would + // span from one map to another, this call only reads up until the end + // of the current map. + // Returns the total number of bytes actually read. + virtual size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes) = 0; + // Create a string representing the formatted line of backtrace information // for a single frame. virtual std::string FormatFrameData(size_t frame_num); diff --git a/include/ctest/ctest.h b/include/ctest/ctest.h deleted file mode 100644 index 1a83b20..0000000 --- a/include/ctest/ctest.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -/** - * Very simple unit testing framework. - */ - -#ifndef __CUTILS_TEST_H -#define __CUTILS_TEST_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Adds a test to the test suite. - */ -#define addTest(test) addNamedTest(#test, &test) - -/** - * Asserts that a condition is true. The test fails if it isn't. - */ -#define assertTrue(value, message) assertTrueWithSource(value, __FILE__, __LINE__, message); - -/** - * Asserts that a condition is false. The test fails if the value is true. - */ -#define assertFalse(value, message) assertTrueWithSource(!value, __FILE__, __LINE__, message); - -/** Fails a test with the given message. */ -#define fail(message) assertTrueWithSource(0, __FILE__, __LINE__, message); - -/** - * Asserts that two values are ==. - */ -#define assertSame(a, b) assertTrueWithSource(a == b, __FILE__, __LINE__, "Expected same value."); - -/** - * Asserts that two values are !=. - */ -#define assertNotSame(a, b) assertTrueWithSource(a != b, __FILE__, __LINE__,\ - "Expected different values"); - -/** - * Runs a test suite. - */ -void runTests(void); - -// Do not call these functions directly. Use macros above instead. -void addNamedTest(const char* name, void (*test)(void)); -void assertTrueWithSource(int value, const char* file, int line, char* message); - -#ifdef __cplusplus -} -#endif - -#endif /* __CUTILS_TEST_H */ diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h index 5efe2e1..a3d11a7 100644 --- a/include/private/android_filesystem_config.h +++ b/include/private/android_filesystem_config.h @@ -230,21 +230,14 @@ static const struct fs_path_config android_dirs[] = { static const struct fs_path_config android_files[] = { { 00440, AID_ROOT, AID_SHELL, 0, "system/etc/init.goldfish.rc" }, { 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.goldfish.sh" }, - { 00440, AID_ROOT, AID_SHELL, 0, "system/etc/init.trout.rc" }, { 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.ril" }, { 00550, AID_DHCP, AID_SHELL, 0, "system/etc/dhcpcd/dhcpcd-run-hooks" }, - { 00444, AID_RADIO, AID_AUDIO, 0, "system/etc/AudioPara4.csv" }, { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/ppp/*" }, { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/rc.*" }, { 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app/*" }, { 00644, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/*" }, { 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private/*" }, { 00644, AID_APP, AID_APP, 0, "data/data/*" }, - { 00755, AID_ROOT, AID_ROOT, 0, "system/bin/ping" }, - - /* the following file is INTENTIONALLY set-gid and not set-uid. - * Do not change. */ - { 02750, AID_ROOT, AID_INET, 0, "system/bin/netcfg" }, /* the following five files are INTENTIONALLY set-uid, but they * are NOT included on user builds. */ @@ -252,7 +245,6 @@ static const struct fs_path_config android_files[] = { { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/librank" }, { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/procrank" }, { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/procmem" }, - { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/tcpdump" }, { 04770, AID_ROOT, AID_RADIO, 0, "system/bin/pppd-ril" }, /* the following files have enhanced capabilities and ARE included in user builds. */ diff --git a/include/private/android_logger.h b/include/private/android_logger.h index cc7ba30..724ca51 100644 --- a/include/private/android_logger.h +++ b/include/private/android_logger.h @@ -41,4 +41,46 @@ typedef struct __attribute__((__packed__)) { log_time realtime; } android_log_header_t; +/* Event Header Structure to logd */ +typedef struct __attribute__((__packed__)) { + int32_t tag; // Little Endian Order +} android_event_header_t; + +/* Event payload EVENT_TYPE_INT */ +typedef struct __attribute__((__packed__)) { + int8_t type; // EVENT_TYPE_INT + int32_t data; // Little Endian Order +} android_event_int_t; + +/* Event with single EVENT_TYPE_INT */ +typedef struct __attribute__((__packed__)) { + android_event_header_t header; + android_event_int_t payload; +} android_log_event_int_t; + +/* Event payload EVENT_TYPE_LONG */ +typedef struct __attribute__((__packed__)) { + int8_t type; // EVENT_TYPE_LONG + int64_t data; // Little Endian Order +} android_event_long_t; + +/* Event with single EVENT_TYPE_LONG */ +typedef struct __attribute__((__packed__)) { + android_event_header_t header; + android_event_long_t payload; +} android_log_event_long_t; + +/* Event payload EVENT_TYPE_STRING */ +typedef struct __attribute__((__packed__)) { + int8_t type; // EVENT_TYPE_STRING; + int32_t length; // Little Endian Order + char data[]; +} android_event_string_t; + +/* Event with single EVENT_TYPE_STRING */ +typedef struct __attribute__((__packed__)) { + android_event_header_t header; + android_event_string_t payload; +} android_log_event_string_t; + #endif diff --git a/include/system/audio.h b/include/system/audio.h index 9a25cfb..181a171 100644 --- a/include/system/audio.h +++ b/include/system/audio.h @@ -57,10 +57,14 @@ typedef enum { * and must be routed to speaker */ AUDIO_STREAM_DTMF = 8, - AUDIO_STREAM_TTS = 9, - - AUDIO_STREAM_CNT, - AUDIO_STREAM_MAX = AUDIO_STREAM_CNT - 1, + AUDIO_STREAM_TTS = 9, /* Transmitted Through Speaker. + * Plays over speaker only, silent on other devices. + */ + AUDIO_STREAM_ACCESSIBILITY = 10, /* For accessibility talk back prompts */ + AUDIO_STREAM_REROUTING = 11, /* For dynamic policy output mixes */ + AUDIO_STREAM_PATCH = 12, /* For internal audio flinger tracks. Fixed volume */ + AUDIO_STREAM_PUBLIC_CNT = AUDIO_STREAM_TTS + 1, + AUDIO_STREAM_CNT = AUDIO_STREAM_PATCH + 1, } audio_stream_type_t; /* Do not change these values without updating their counterparts @@ -96,6 +100,7 @@ typedef enum { AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12, AUDIO_USAGE_ASSISTANCE_SONIFICATION = 13, AUDIO_USAGE_GAME = 14, + AUDIO_USAGE_VIRTUAL_SOURCE = 15, AUDIO_USAGE_CNT, AUDIO_USAGE_MAX = AUDIO_USAGE_CNT - 1, @@ -135,6 +140,7 @@ typedef enum { /* play the mix captured by this audio source. */ AUDIO_SOURCE_CNT, AUDIO_SOURCE_MAX = AUDIO_SOURCE_CNT - 1, + AUDIO_SOURCE_FM_TUNER = 1998, AUDIO_SOURCE_HOTWORD = 1999, /* A low-priority, preemptible audio source for for background software hotword detection. Same tuning as AUDIO_SOURCE_VOICE_RECOGNITION. diff --git a/init/Android.mk b/init/Android.mk index a3b01e1..5b8094f 100644 --- a/init/Android.mk +++ b/init/Android.mk @@ -27,6 +27,7 @@ LOCAL_SRC_FILES:= \ parser.cpp \ util.cpp \ +LOCAL_STATIC_LIBRARIES := libbase LOCAL_MODULE := libinit include $(BUILD_STATIC_LIBRARY) @@ -55,7 +56,7 @@ LOCAL_STATIC_LIBRARIES := \ libfs_mgr \ liblogwrap \ libcutils \ - libutils \ + libbase \ liblog \ libc \ libselinux \ @@ -75,11 +76,12 @@ include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) LOCAL_MODULE := init_tests LOCAL_SRC_FILES := \ + init_parser_test.cpp \ util_test.cpp \ LOCAL_SHARED_LIBRARIES += \ libcutils \ - libutils \ + libbase \ LOCAL_STATIC_LIBRARIES := libinit include $(BUILD_NATIVE_TEST) diff --git a/init/bootchart.cpp b/init/bootchart.cpp index cc31920..530eba8 100644 --- a/init/bootchart.cpp +++ b/init/bootchart.cpp @@ -32,7 +32,7 @@ #include <string> -#include <utils/file.h> +#include <base/file.h> #define LOG_ROOT "/data/bootchart" #define LOG_STAT LOG_ROOT"/proc_stat.log" @@ -59,7 +59,7 @@ static FILE* log_disks; static long long get_uptime_jiffies() { std::string uptime; - if (!android::ReadFileToString("/proc/uptime", &uptime)) { + if (!android::base::ReadFileToString("/proc/uptime", &uptime)) { return 0; } return 100LL * strtod(uptime.c_str(), NULL); @@ -82,7 +82,7 @@ static void log_header() { } std::string kernel_cmdline; - android::ReadFileToString("/proc/cmdline", &kernel_cmdline); + android::base::ReadFileToString("/proc/cmdline", &kernel_cmdline); FILE* out = fopen(LOG_HEADER, "we"); if (out == NULL) { @@ -106,7 +106,7 @@ static void do_log_file(FILE* log, const char* procfile) { do_log_uptime(log); std::string content; - if (android::ReadFileToString(procfile, &content)) { + if (android::base::ReadFileToString(procfile, &content)) { fprintf(log, "%s\n", content.c_str()); } } @@ -127,13 +127,13 @@ static void do_log_procs(FILE* log) { // name from /proc/<pid>/cmdline. snprintf(filename, sizeof(filename), "/proc/%d/cmdline", pid); std::string cmdline; - android::ReadFileToString(filename, &cmdline); + android::base::ReadFileToString(filename, &cmdline); const char* full_name = cmdline.c_str(); // So we stop at the first NUL. // Read process stat line. snprintf(filename, sizeof(filename), "/proc/%d/stat", pid); std::string stat; - if (android::ReadFileToString(filename, &stat)) { + if (android::base::ReadFileToString(filename, &stat)) { if (!cmdline.empty()) { // Substitute the process name with its real name. size_t open = stat.find('('); @@ -155,7 +155,7 @@ static int bootchart_init() { int timeout = 0; std::string start; - android::ReadFileToString(LOG_STARTFILE, &start); + android::base::ReadFileToString(LOG_STARTFILE, &start); if (!start.empty()) { timeout = atoi(start.c_str()); } else { @@ -164,7 +164,7 @@ static int bootchart_init() { // timeout. this is useful when using -wipe-data since the /data // partition is fresh. std::string cmdline; - android::ReadFileToString("/proc/cmdline", &cmdline); + android::base::ReadFileToString("/proc/cmdline", &cmdline); #define KERNEL_OPTION "androidboot.bootchart=" if (strstr(cmdline.c_str(), KERNEL_OPTION) != NULL) { timeout = atoi(cmdline.c_str() + sizeof(KERNEL_OPTION) - 1); @@ -226,7 +226,7 @@ static int bootchart_step() { // Stop if /data/bootchart/stop contains 1. std::string stop; - if (android::ReadFileToString(LOG_STOPFILE, &stop) && stop == "1") { + if (android::base::ReadFileToString(LOG_STOPFILE, &stop) && stop == "1") { return -1; } diff --git a/init/builtins.cpp b/init/builtins.cpp index 9f3dcc1..fb1aa7c 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -67,20 +67,6 @@ static int insmod(const char *filename, char *options) return init_module(&module[0], module.size(), options); } -static int setkey(struct kbentry *kbe) -{ - int fd, ret; - - fd = open("/dev/tty0", O_RDWR | O_SYNC | O_CLOEXEC); - if (fd < 0) - return -1; - - ret = ioctl(fd, KDSKBENT, kbe); - - close(fd); - return ret; -} - static int __ifupdown(const char *interface, int up) { struct ifreq ifr; @@ -118,18 +104,6 @@ static void service_start_if_not_disabled(struct service *svc) } } -int do_chdir(int nargs, char **args) -{ - chdir(args[1]); - return 0; -} - -int do_chroot(int nargs, char **args) -{ - chroot(args[1]); - return 0; -} - int do_class_start(int nargs, char **args) { /* Starting a class does not start services @@ -172,11 +146,16 @@ int do_enable(int nargs, char **args) return 0; } -int do_exec(int nargs, char **args) -{ - return -1; +int do_exec(int nargs, char** args) { + service* svc = make_exec_oneshot_service(nargs, args); + if (svc == NULL) { + return -1; + } + service_start(svc, NULL); + return 0; } +// TODO: remove execonce when exec is available. int do_execonce(int nargs, char **args) { pid_t child; @@ -566,24 +545,6 @@ int do_setcon(int nargs, char **args) { return 0; } -int do_setenforce(int nargs, char **args) { - if (is_selinux_enabled() <= 0) - return 0; - if (security_setenforce(atoi(args[1])) < 0) { - return -errno; - } - return 0; -} - -int do_setkey(int nargs, char **args) -{ - struct kbentry kbe; - kbe.kb_table = strtoul(args[1], 0, 0); - kbe.kb_index = strtoul(args[2], 0, 0); - kbe.kb_value = strtoul(args[3], 0, 0); - return setkey(&kbe); -} - int do_setprop(int nargs, char **args) { const char *name = args[1]; @@ -712,6 +673,20 @@ int do_sysclktz(int nargs, char **args) return 0; } +int do_verity_load_state(int nargs, char **args) { + if (nargs == 1) { + int mode = -1; + int rc = fs_mgr_load_verity_state(&mode); + + if (rc == 0 && mode == VERITY_MODE_LOGGING) { + action_for_each_trigger("verity-logging", action_add_queue_tail); + } + + return rc; + } + return -1; +} + int do_write(int nargs, char **args) { const char *path = args[1]; @@ -844,34 +819,6 @@ int do_restorecon_recursive(int nargs, char **args) { return ret; } -int do_setsebool(int nargs, char **args) { - const char *name = args[1]; - const char *value = args[2]; - SELboolean b; - int ret; - - if (is_selinux_enabled() <= 0) - return 0; - - b.name = name; - if (!strcmp(value, "1") || !strcasecmp(value, "true") || !strcasecmp(value, "on")) - b.value = 1; - else if (!strcmp(value, "0") || !strcasecmp(value, "false") || !strcasecmp(value, "off")) - b.value = 0; - else { - ERROR("setsebool: invalid value %s\n", value); - return -EINVAL; - } - - if (security_set_boolean_list(1, &b, 0) < 0) { - ret = -errno; - ERROR("setsebool: could not set %s to %s\n", name, value); - return ret; - } - - return 0; -} - int do_loglevel(int nargs, char **args) { int log_level; char log_level_str[PROP_VALUE_MAX] = ""; diff --git a/init/grab-bootchart.sh b/init/grab-bootchart.sh index 5715862..d6082aa 100755 --- a/init/grab-bootchart.sh +++ b/init/grab-bootchart.sh @@ -1,12 +1,9 @@ #!/bin/sh # -# this script is used to retrieve the bootchart log generated -# by init when compiled with INIT_BOOTCHART=true. -# +# This script is used to retrieve a bootchart log generated by init. # All options are passed to adb, for better or for worse. -# -# for all details, see //device/system/init/README.BOOTCHART -# +# See the readme in this directory for more on bootcharting. + TMPDIR=/tmp/android-bootchart rm -rf $TMPDIR mkdir -p $TMPDIR @@ -22,4 +19,4 @@ done (cd $TMPDIR && tar -czf $TARBALL $FILES) bootchart ${TMPDIR}/${TARBALL} gnome-open ${TARBALL%.tgz}.png -echo "Clean up ${TMPDIR}/ & ./${TARBALL%.tgz}.png when done" +echo "Clean up ${TMPDIR}/ and ./${TARBALL%.tgz}.png when done" diff --git a/init/init.cpp b/init/init.cpp index 41ceb0a..e1c82a4 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -14,37 +14,38 @@ * limitations under the License. */ +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <libgen.h> +#include <paths.h> +#include <signal.h> +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <ctype.h> -#include <signal.h> -#include <sys/wait.h> #include <sys/mount.h> -#include <sys/stat.h> #include <sys/poll.h> -#include <errno.h> -#include <stdarg.h> -#include <mtd/mtd-user.h> -#include <sys/types.h> #include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> #include <sys/un.h> +#include <sys/wait.h> +#include <termios.h> +#include <unistd.h> + +#include <mtd/mtd-user.h> #include <selinux/selinux.h> #include <selinux/label.h> #include <selinux/android.h> -#include <libgen.h> - -#include <cutils/list.h> #include <cutils/android_reboot.h> -#include <cutils/sockets.h> -#include <cutils/iosched_policy.h> #include <cutils/fs.h> +#include <cutils/iosched_policy.h> +#include <cutils/list.h> +#include <cutils/sockets.h> #include <private/android_filesystem_config.h> -#include <termios.h> #include "devices.h" #include "init.h" @@ -72,22 +73,35 @@ static char qemu[32]; static struct action *cur_action = NULL; static struct command *cur_command = NULL; -void notify_service_state(const char *name, const char *state) -{ - char pname[PROP_NAME_MAX]; - int len = strlen(name); - if ((len + 10) > PROP_NAME_MAX) - return; - snprintf(pname, sizeof(pname), "init.svc.%s", name); - property_set(pname, state); -} - static int have_console; static char console_name[PROP_VALUE_MAX] = "/dev/console"; static time_t process_needs_restart; static const char *ENV[32]; +bool waiting_for_exec = false; + +void service::NotifyStateChange(const char* new_state) { + if (!properties_inited()) { + // If properties aren't available yet, we can't set them. + return; + } + + if ((flags & SVC_EXEC) != 0) { + // 'exec' commands don't have properties tracking their state. + return; + } + + char prop_name[PROP_NAME_MAX]; + if (snprintf(prop_name, sizeof(prop_name), "init.svc.%s", name) >= PROP_NAME_MAX) { + // If the property name would be too long, we can't set it. + ERROR("Property name \"init.svc.%s\" too long; not setting to %s\n", name, new_state); + return; + } + + property_set(prop_name, new_state); +} + /* add_environment - add "key=value" to the current environment */ int add_environment(const char *key, const char *val) { @@ -160,35 +174,26 @@ static void publish_socket(const char *name, int fd) void service_start(struct service *svc, const char *dynamic_args) { - struct stat s; - pid_t pid; - int needs_console; - char *scon = NULL; - int rc; - - /* starting a service removes it from the disabled or reset - * state and immediately takes it out of the restarting - * state if it was in there - */ + // Starting a service removes it from the disabled or reset state and + // immediately takes it out of the restarting state if it was in there. svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START)); svc->time_started = 0; - /* running processes require no additional work -- if - * they're in the process of exiting, we've ensured - * that they will immediately restart on exit, unless - * they are ONESHOT - */ + // Running processes require no additional work --- if they're in the + // process of exiting, we've ensured that they will immediately restart + // on exit, unless they are ONESHOT. if (svc->flags & SVC_RUNNING) { return; } - needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0; - if (needs_console && (!have_console)) { + bool needs_console = (svc->flags & SVC_CONSOLE); + if (needs_console && !have_console) { ERROR("service '%s' requires console\n", svc->name); svc->flags |= SVC_DISABLED; return; } + struct stat s; if (stat(svc->args[0], &s) != 0) { ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name); svc->flags |= SVC_DISABLED; @@ -202,6 +207,7 @@ void service_start(struct service *svc, const char *dynamic_args) return; } + char* scon = NULL; if (is_selinux_enabled() > 0) { if (svc->seclabel) { scon = strdup(svc->seclabel); @@ -213,7 +219,7 @@ void service_start(struct service *svc, const char *dynamic_args) char *mycon = NULL, *fcon = NULL; INFO("computing context for service '%s'\n", svc->args[0]); - rc = getcon(&mycon); + int rc = getcon(&mycon); if (rc < 0) { ERROR("could not get context while starting '%s'\n", svc->name); return; @@ -241,8 +247,7 @@ void service_start(struct service *svc, const char *dynamic_args) NOTICE("starting '%s'\n", svc->name); - pid = fork(); - + pid_t pid = fork(); if (pid == 0) { struct socketinfo *si; struct svcenvinfo *ei; @@ -298,7 +303,7 @@ void service_start(struct service *svc, const char *dynamic_args) setpgid(0, getpid()); - /* as requested, set our gid, supplemental gids, and uid */ + // As requested, set our gid, supplemental gids, and uid. if (svc->gid) { if (setgid(svc->gid) != 0) { ERROR("setgid failed: %s\n", strerror(errno)); @@ -361,8 +366,13 @@ void service_start(struct service *svc, const char *dynamic_args) svc->pid = pid; svc->flags |= SVC_RUNNING; - if (properties_inited()) - notify_service_state(svc->name, "running"); + if ((svc->flags & SVC_EXEC) != 0) { + INFO("SVC_EXEC pid %d (uid %d gid %d+%zu context %s) started; waiting...\n", + svc->pid, svc->uid, svc->gid, svc->nr_supp_gids, svc->seclabel); + waiting_for_exec = true; + } + + svc->NotifyStateChange("running"); } /* The how field should be either SVC_DISABLED, SVC_RESET, or SVC_RESTART */ @@ -388,9 +398,9 @@ static void service_stop_or_reset(struct service *svc, int how) if (svc->pid) { NOTICE("service '%s' is being killed\n", svc->name); kill(-svc->pid, SIGKILL); - notify_service_state(svc->name, "stopping"); + svc->NotifyStateChange("stopping"); } else { - notify_service_state(svc->name, "stopped"); + svc->NotifyStateChange("stopped"); } } @@ -669,7 +679,6 @@ ret: if (urandom_fd != -1) { close(urandom_fd); } - memset(buf, 0, sizeof(buf)); return result; } @@ -969,28 +978,20 @@ static void selinux_initialize(void) security_setenforce(is_enforcing); } -int main(int argc, char **argv) -{ - size_t fd_count = 0; - struct pollfd ufds[4]; - int property_set_fd_init = 0; - int signal_fd_init = 0; - int keychord_fd_init = 0; - bool is_charger = false; - +int main(int argc, char** argv) { if (!strcmp(basename(argv[0]), "ueventd")) return ueventd_main(argc, argv); if (!strcmp(basename(argv[0]), "watchdogd")) return watchdogd_main(argc, argv); - /* clear the umask */ + // Clear the umask. umask(0); - /* 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. - */ + add_environment("PATH", _PATH_DEFPATH); + + // 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. mkdir("/dev", 0755); mkdir("/proc", 0755); mkdir("/sys", 0755); @@ -1002,15 +1003,13 @@ int main(int argc, char **argv) mount("proc", "/proc", "proc", 0, NULL); mount("sysfs", "/sys", "sysfs", 0, NULL); - /* indicate that booting is in progress to background fw loaders, etc */ + // Indicate that booting is in progress to background fw loaders, etc. close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000)); - /* We must have some place other than / to create the - * device nodes for kmsg and null, otherwise we won't - * be able to remount / read-only later on. - * Now that tmpfs is mounted on /dev, we can actually - * talk to the outside world. - */ + // We must have some place other than / to create the device nodes for + // kmsg and null, otherwise we won't be able to remount / read-only + // later on. Now that tmpfs is mounted on /dev, we can actually talk + // to the outside world. open_devnull_stdio(); klog_init(); property_init(); @@ -1019,25 +1018,22 @@ int main(int argc, char **argv) process_kernel_cmdline(); - union selinux_callback cb; + selinux_callback cb; cb.func_log = log_callback; selinux_set_callback(SELINUX_CB_LOG, cb); - cb.func_audit = audit_callback; selinux_set_callback(SELINUX_CB_AUDIT, cb); selinux_initialize(); - /* These directories were necessarily created before initial policy load - * and therefore need their security context restored to the proper value. - * This must happen before /dev is populated by ueventd. - */ + + // These directories were necessarily created before initial policy load + // and therefore need their security context restored to the proper value. + // This must happen before /dev is populated by ueventd. restorecon("/dev"); restorecon("/dev/socket"); restorecon("/dev/__properties__"); restorecon_recursive("/sys"); - is_charger = !strcmp(bootmode, "charger"); - INFO("property init\n"); property_load_boot_defaults(); @@ -1050,50 +1046,58 @@ int main(int argc, char **argv) queue_builtin_action(keychord_init_action, "keychord_init"); queue_builtin_action(console_init_action, "console_init"); - /* execute all the boot actions to get us started */ + // Execute all the boot actions to get us started. action_for_each_trigger("init", action_add_queue_tail); - /* Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random - * wasn't ready immediately after wait_for_coldboot_done - */ + // Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random + // wasn't ready immediately after wait_for_coldboot_done queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng"); queue_builtin_action(property_service_init_action, "property_service_init"); queue_builtin_action(signal_init_action, "signal_init"); - /* Don't mount filesystems or start core system services if in charger mode. */ - if (is_charger) { + // Don't mount filesystems or start core system services in charger mode. + if (strcmp(bootmode, "charger") == 0) { action_for_each_trigger("charger", action_add_queue_tail); } else { action_for_each_trigger("late-init", action_add_queue_tail); } - /* run all property triggers based on current state of the properties */ + // Run all property triggers based on current state of the properties. queue_builtin_action(queue_property_triggers_action, "queue_property_triggers"); + // TODO: why do we only initialize ufds after execute_one_command and restart_processes? + size_t fd_count = 0; + struct pollfd ufds[3]; + bool property_set_fd_init = false; + bool signal_fd_init = false; + bool keychord_fd_init = false; + for (;;) { - execute_one_command(); - restart_processes(); + if (!waiting_for_exec) { + execute_one_command(); + restart_processes(); + } if (!property_set_fd_init && get_property_set_fd() > 0) { ufds[fd_count].fd = get_property_set_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; - property_set_fd_init = 1; + property_set_fd_init = true; } if (!signal_fd_init && get_signal_fd() > 0) { ufds[fd_count].fd = get_signal_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; - signal_fd_init = 1; + signal_fd_init = true; } if (!keychord_fd_init && get_keychord_fd() > 0) { ufds[fd_count].fd = get_keychord_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; - keychord_fd_init = 1; + keychord_fd_init = true; } int timeout = -1; diff --git a/init/init.h b/init/init.h index eedec27..a104af6 100644 --- a/init/init.h +++ b/init/init.h @@ -17,13 +17,11 @@ #ifndef _INIT_INIT_H #define _INIT_INIT_H +#include <sys/types.h> + #include <cutils/list.h> #include <cutils/iosched_policy.h> -#include <sys/stat.h> - -void handle_control_message(const char *msg, const char *arg); - struct command { /* list of commands in an action */ @@ -59,8 +57,6 @@ struct action { struct command *current; }; -void build_triggers_string(char *name_str, int length, struct action *cur_action); - struct socketinfo { struct socketinfo *next; const char *name; @@ -77,27 +73,29 @@ struct svcenvinfo { const char *value; }; -#define SVC_DISABLED 0x01 /* do not autostart with class */ -#define SVC_ONESHOT 0x02 /* do not restart on exit */ -#define SVC_RUNNING 0x04 /* currently active */ -#define SVC_RESTARTING 0x08 /* waiting to restart */ -#define SVC_CONSOLE 0x10 /* requires console */ -#define SVC_CRITICAL 0x20 /* will reboot into recovery if keeps crashing */ -#define SVC_RESET 0x40 /* Use when stopping a process, but not disabling - so it can be restarted with its class */ -#define SVC_RC_DISABLED 0x80 /* Remember if the disabled flag was set in the rc script */ -#define SVC_RESTART 0x100 /* Use to safely restart (stop, wait, start) a service */ -#define SVC_DISABLED_START 0x200 /* a start was requested but it was disabled at the time */ +#define SVC_DISABLED 0x001 // do not autostart with class +#define SVC_ONESHOT 0x002 // do not restart on exit +#define SVC_RUNNING 0x004 // currently active +#define SVC_RESTARTING 0x008 // waiting to restart +#define SVC_CONSOLE 0x010 // requires console +#define SVC_CRITICAL 0x020 // will reboot into recovery if keeps crashing +#define SVC_RESET 0x040 // Use when stopping a process, but not disabling so it can be restarted with its class. +#define SVC_RC_DISABLED 0x080 // Remember if the disabled flag was set in the rc script. +#define SVC_RESTART 0x100 // Use to safely restart (stop, wait, start) a service. +#define SVC_DISABLED_START 0x200 // A start was requested but it was disabled at the time. +#define SVC_EXEC 0x400 // This synthetic service corresponds to an 'exec'. #define NR_SVC_SUPP_GIDS 12 /* twelve supplementary groups */ #define COMMAND_RETRY_TIMEOUT 5 struct service { + void NotifyStateChange(const char* new_state); + /* list of all services */ struct listnode slist; - const char *name; + char *name; const char *classname; unsigned flags; @@ -105,19 +103,19 @@ struct service { time_t time_started; /* time of last start */ time_t time_crashed; /* first crash within inspection window */ int nr_crashed; /* number of times crashed within window */ - + uid_t uid; gid_t gid; gid_t supp_gids[NR_SVC_SUPP_GIDS]; size_t nr_supp_gids; - char *seclabel; + const char* seclabel; struct socketinfo *sockets; struct svcenvinfo *envvars; struct action onrestart; /* Actions to execute on restart. */ - + /* keycodes for triggering this service via /dev/keychord */ int *keycodes; int nkeycodes; @@ -131,7 +129,13 @@ struct service { char *args[1]; }; /* ^-------'args' MUST be at the end of this struct! */ -void notify_service_state(const char *name, const char *state); +extern bool waiting_for_exec; +extern struct selabel_handle *sehandle; +extern struct selabel_handle *sehandle_prop; + +void build_triggers_string(char *name_str, int length, struct action *cur_action); + +void handle_control_message(const char *msg, const char *arg); struct service *service_find_by_name(const char *name); struct service *service_find_by_pid(pid_t pid); @@ -147,9 +151,8 @@ void service_restart(struct service *svc); void service_start(struct service *svc, const char *dynamic_args); void property_changed(const char *name, const char *value); -extern struct selabel_handle *sehandle; -extern struct selabel_handle *sehandle_prop; -extern int selinux_reload_policy(void); +int selinux_reload_policy(void); + void zap_stdio(void); #endif /* _INIT_INIT_H */ diff --git a/init/init_parser.cpp b/init/init_parser.cpp index 61a5e0a..f3d34b2 100644 --- a/init/init_parser.cpp +++ b/init/init_parser.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -120,8 +121,6 @@ static int lookup_keyword(const char *s) case 'c': if (!strcmp(s, "opy")) return K_copy; if (!strcmp(s, "apability")) return K_capability; - if (!strcmp(s, "hdir")) return K_chdir; - if (!strcmp(s, "hroot")) return K_chroot; if (!strcmp(s, "lass")) return K_class; if (!strcmp(s, "lass_start")) return K_class_start; if (!strcmp(s, "lass_stop")) return K_class_stop; @@ -185,12 +184,9 @@ static int lookup_keyword(const char *s) if (!strcmp(s, "eclabel")) return K_seclabel; if (!strcmp(s, "ervice")) return K_service; if (!strcmp(s, "etcon")) return K_setcon; - if (!strcmp(s, "etenforce")) return K_setenforce; if (!strcmp(s, "etenv")) return K_setenv; - if (!strcmp(s, "etkey")) return K_setkey; if (!strcmp(s, "etprop")) return K_setprop; if (!strcmp(s, "etrlimit")) return K_setrlimit; - if (!strcmp(s, "etsebool")) return K_setsebool; if (!strcmp(s, "ocket")) return K_socket; if (!strcmp(s, "tart")) return K_start; if (!strcmp(s, "top")) return K_stop; @@ -204,6 +200,9 @@ static int lookup_keyword(const char *s) case 'u': if (!strcmp(s, "ser")) return K_user; break; + case 'v': + if (!strcmp(s, "erity_load_state")) return K_verity_load_state; + break; case 'w': if (!strcmp(s, "rite")) return K_write; if (!strcmp(s, "ait")) return K_wait; @@ -437,7 +436,7 @@ parser_done: } int init_parse_config_file(const char* path) { - INFO("Parsing %s...", path); + INFO("Parsing %s...\n", path); std::string data; if (!read_file(path, &data)) { return -1; @@ -660,6 +659,65 @@ int action_queue_empty() return list_empty(&action_queue); } +service* make_exec_oneshot_service(int nargs, char** args) { + // Parse the arguments: exec [SECLABEL [UID [GID]*] --] COMMAND ARGS... + int command_arg = 1; + for (int i = 1; i < nargs; ++i) { + if (strcmp(args[i], "--") == 0) { + command_arg = i + 1; + break; + } + } + if (command_arg > 4 + NR_SVC_SUPP_GIDS) { + ERROR("exec called with too many supplementary group ids\n"); + return NULL; + } + + int argc = nargs - command_arg; + char** argv = (args + command_arg); + if (argc < 1) { + ERROR("exec called without command\n"); + return NULL; + } + + service* svc = (service*) calloc(1, sizeof(*svc) + sizeof(char*) * argc); + if (svc == NULL) { + ERROR("Couldn't allocate service for exec of '%s': %s", argv[0], strerror(errno)); + return NULL; + } + + if (command_arg > 2) { + svc->seclabel = args[1]; + } + if (command_arg > 3) { + svc->uid = decode_uid(args[2]); + } + if (command_arg > 4) { + svc->gid = decode_uid(args[3]); + svc->nr_supp_gids = command_arg - 1 /* -- */ - 4 /* exec SECLABEL UID GID */; + for (size_t i = 0; i < svc->nr_supp_gids; ++i) { + svc->supp_gids[i] = decode_uid(args[4 + i]); + } + } + + static int exec_count; // Every service needs a unique name. + char* name = NULL; + asprintf(&name, "exec %d (%s)", exec_count++, argv[0]); + if (name == NULL) { + ERROR("Couldn't allocate name for exec service '%s'\n", argv[0]); + free(svc); + return NULL; + } + svc->name = name; + svc->classname = "default"; + svc->flags = SVC_EXEC | SVC_ONESHOT; + svc->nargs = argc; + memcpy(svc->args, argv, sizeof(char*) * svc->nargs); + svc->args[argc] = NULL; + list_add_tail(&service_list, &svc->slist); + return svc; +} + static void *parse_service(struct parse_state *state, int nargs, char **args) { if (nargs < 3) { @@ -683,7 +741,7 @@ static void *parse_service(struct parse_state *state, int nargs, char **args) parse_error(state, "out of memory\n"); return 0; } - svc->name = args[1]; + svc->name = strdup(args[1]); svc->classname = "default"; memcpy(svc->args, args + 2, sizeof(char*) * nargs); trigger* cur_trigger = (trigger*) calloc(1, sizeof(*cur_trigger)); diff --git a/init/init_parser.h b/init/init_parser.h index 0047da7..6348607 100644 --- a/init/init_parser.h +++ b/init/init_parser.h @@ -20,6 +20,7 @@ #define INIT_PARSER_MAXARGS 64 struct action; +struct service; struct action *action_remove_queue_head(void); void action_add_queue_tail(struct action *act); @@ -33,4 +34,6 @@ void queue_builtin_action(int (*func)(int nargs, char **args), const char *name) int init_parse_config_file(const char *fn); int expand_props(char *dst, const char *src, int len); +service* make_exec_oneshot_service(int argc, char** argv); + #endif diff --git a/init/init_parser_test.cpp b/init/init_parser_test.cpp new file mode 100644 index 0000000..170a73a --- /dev/null +++ b/init/init_parser_test.cpp @@ -0,0 +1,134 @@ +/* + * 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. + */ + +#include "init_parser.h" + +#include "init.h" +#include "util.h" + +#include <errno.h> +#include <gtest/gtest.h> + +TEST(init_parser, make_exec_oneshot_service_invalid_syntax) { + char* argv[10]; + memset(argv, 0, sizeof(argv)); + + // Nothing. + ASSERT_EQ(nullptr, make_exec_oneshot_service(0, argv)); + + // No arguments to 'exec'. + argv[0] = const_cast<char*>("exec"); + ASSERT_EQ(nullptr, make_exec_oneshot_service(1, argv)); + + // No command in "exec --". + argv[1] = const_cast<char*>("--"); + ASSERT_EQ(nullptr, make_exec_oneshot_service(2, argv)); +} + +TEST(init_parser, make_exec_oneshot_service_too_many_supplementary_gids) { + int argc = 0; + char* argv[4 + NR_SVC_SUPP_GIDS + 3]; + argv[argc++] = const_cast<char*>("exec"); + argv[argc++] = const_cast<char*>("seclabel"); + argv[argc++] = const_cast<char*>("root"); // uid. + argv[argc++] = const_cast<char*>("root"); // gid. + for (int i = 0; i < NR_SVC_SUPP_GIDS; ++i) { + argv[argc++] = const_cast<char*>("root"); // Supplementary gid. + } + argv[argc++] = const_cast<char*>("--"); + argv[argc++] = const_cast<char*>("/system/bin/id"); + argv[argc] = nullptr; + ASSERT_EQ(nullptr, make_exec_oneshot_service(argc, argv)); +} + +static void Test_make_exec_oneshot_service(bool dash_dash, bool seclabel, bool uid, bool gid, bool supplementary_gids) { + int argc = 0; + char* argv[10]; + argv[argc++] = const_cast<char*>("exec"); + if (seclabel) { + argv[argc++] = const_cast<char*>("u:r:su:s0"); // seclabel + if (uid) { + argv[argc++] = const_cast<char*>("log"); // uid + if (gid) { + argv[argc++] = const_cast<char*>("shell"); // gid + if (supplementary_gids) { + argv[argc++] = const_cast<char*>("system"); // supplementary gid 0 + argv[argc++] = const_cast<char*>("adb"); // supplementary gid 1 + } + } + } + } + if (dash_dash) { + argv[argc++] = const_cast<char*>("--"); + } + argv[argc++] = const_cast<char*>("/system/bin/toybox"); + argv[argc++] = const_cast<char*>("id"); + argv[argc] = nullptr; + service* svc = make_exec_oneshot_service(argc, argv); + ASSERT_NE(nullptr, svc); + + if (seclabel) { + ASSERT_STREQ("u:r:su:s0", svc->seclabel); + } else { + ASSERT_EQ(nullptr, svc->seclabel); + } + if (uid) { + ASSERT_EQ(decode_uid("log"), svc->uid); + } else { + ASSERT_EQ(0U, svc->uid); + } + if (gid) { + ASSERT_EQ(decode_uid("shell"), svc->gid); + } else { + ASSERT_EQ(0U, svc->gid); + } + if (supplementary_gids) { + ASSERT_EQ(2U, svc->nr_supp_gids); + ASSERT_EQ(decode_uid("system"), svc->supp_gids[0]); + ASSERT_EQ(decode_uid("adb"), svc->supp_gids[1]); + } else { + ASSERT_EQ(0U, svc->nr_supp_gids); + } + + ASSERT_EQ(2, svc->nargs); + ASSERT_EQ("/system/bin/toybox", svc->args[0]); + ASSERT_EQ("id", svc->args[1]); + ASSERT_EQ(nullptr, svc->args[2]); +} + +TEST(init_parser, make_exec_oneshot_service_with_everything) { + Test_make_exec_oneshot_service(true, true, true, true, true); +} + +TEST(init_parser, make_exec_oneshot_service_with_seclabel_uid_gid) { + Test_make_exec_oneshot_service(true, true, true, true, false); +} + +TEST(init_parser, make_exec_oneshot_service_with_seclabel_uid) { + Test_make_exec_oneshot_service(true, true, true, false, false); +} + +TEST(init_parser, make_exec_oneshot_service_with_seclabel) { + Test_make_exec_oneshot_service(true, true, false, false, false); +} + +TEST(init_parser, make_exec_oneshot_service_with_just_command) { + Test_make_exec_oneshot_service(true, false, false, false, false); +} + +TEST(init_parser, make_exec_oneshot_service_with_just_command_no_dash) { + Test_make_exec_oneshot_service(false, false, false, false, false); +} diff --git a/init/keywords.h b/init/keywords.h index a8f29d1..c8327c3 100644 --- a/init/keywords.h +++ b/init/keywords.h @@ -1,7 +1,5 @@ #ifndef KEYWORD int do_bootchart_init(int nargs, char **args); -int do_chroot(int nargs, char **args); -int do_chdir(int nargs, char **args); int do_class_start(int nargs, char **args); int do_class_stop(int nargs, char **args); int do_class_reset(int nargs, char **args); @@ -23,11 +21,8 @@ int do_restorecon_recursive(int nargs, char **args); int do_rm(int nargs, char **args); int do_rmdir(int nargs, char **args); int do_setcon(int nargs, char **args); -int do_setenforce(int nargs, char **args); -int do_setkey(int nargs, char **args); int do_setprop(int nargs, char **args); int do_setrlimit(int nargs, char **args); -int do_setsebool(int nargs, char **args); int do_start(int nargs, char **args); int do_stop(int nargs, char **args); int do_swapon_all(int nargs, char **args); @@ -41,6 +36,7 @@ int do_chmod(int nargs, char **args); int do_loglevel(int nargs, char **args); int do_load_persist_props(int nargs, char **args); int do_load_all_props(int nargs, char **args); +int do_verity_load_state(int nargs, char **args); int do_wait(int nargs, char **args); #define __MAKE_KEYWORD_ENUM__ #define KEYWORD(symbol, flags, nargs, func) K_##symbol, @@ -48,8 +44,6 @@ enum { K_UNKNOWN, #endif KEYWORD(capability, OPTION, 0, 0) - KEYWORD(chdir, COMMAND, 1, do_chdir) - KEYWORD(chroot, COMMAND, 1, do_chroot) KEYWORD(class, OPTION, 0, 0) KEYWORD(class_start, COMMAND, 1, do_class_start) KEYWORD(class_stop, COMMAND, 1, do_class_stop) @@ -83,12 +77,9 @@ enum { KEYWORD(seclabel, OPTION, 0, 0) KEYWORD(service, SECTION, 0, 0) KEYWORD(setcon, COMMAND, 1, do_setcon) - KEYWORD(setenforce, COMMAND, 1, do_setenforce) KEYWORD(setenv, OPTION, 2, 0) - KEYWORD(setkey, COMMAND, 0, do_setkey) KEYWORD(setprop, COMMAND, 2, do_setprop) KEYWORD(setrlimit, COMMAND, 3, do_setrlimit) - KEYWORD(setsebool, COMMAND, 2, do_setsebool) KEYWORD(socket, OPTION, 0, 0) KEYWORD(start, COMMAND, 1, do_start) KEYWORD(stop, COMMAND, 1, do_stop) @@ -97,6 +88,7 @@ enum { KEYWORD(symlink, COMMAND, 1, do_symlink) KEYWORD(sysclktz, COMMAND, 1, do_sysclktz) KEYWORD(user, OPTION, 0, 0) + KEYWORD(verity_load_state, COMMAND, 0, do_verity_load_state) KEYWORD(wait, COMMAND, 1, do_wait) KEYWORD(write, COMMAND, 2, do_write) KEYWORD(copy, COMMAND, 2, do_copy) diff --git a/init/property_service.cpp b/init/property_service.cpp index 05c03d6..ddb8050 100644 --- a/init/property_service.cpp +++ b/init/property_service.cpp @@ -30,8 +30,6 @@ #include <cutils/sockets.h> #include <cutils/multiuser.h> -#include <utils/file.h> - #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include <sys/_system_properties.h> diff --git a/init/readme.txt b/init/readme.txt index 9c24220..7443330 100644 --- a/init/readme.txt +++ b/init/readme.txt @@ -70,11 +70,11 @@ disabled setenv <name> <value> Set the environment variable <name> to <value> in the launched process. -socket <name> <type> <perm> [ <user> [ <group> [ <context> ] ] ] +socket <name> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ] Create a unix domain socket named /dev/socket/<name> and pass its fd to the launched process. <type> must be "dgram", "stream" or "seqpacket". User and group default to 0. - Context is the SELinux security context for the socket. + 'seclabel' is the SELinux security context for the socket. It defaults to the service security context, as specified by seclabel or computed based on the service executable file security context. @@ -91,8 +91,8 @@ group <groupname> [ <groupname> ]* supplemental groups of the process (via setgroups()). Currently defaults to root. (??? probably should default to nobody) -seclabel <securitycontext> - Change to securitycontext before exec'ing this service. +seclabel <seclabel> + Change to 'seclabel' before exec'ing this service. Primarily for use by services run from the rootfs, e.g. ueventd, adbd. Services on the system partition can instead use policy-defined transitions based on their file security context. @@ -137,14 +137,17 @@ boot Commands -------- -exec <path> [ <argument> ]* - This command is not implemented. +exec [ <seclabel> [ <user> [ <group> ]* ] ] -- <command> [ <argument> ]* + Fork and execute command with the given arguments. The command starts + after "--" so that an optional security context, user, and supplementary + groups can be provided. No other commands will be run until this one + finishes. execonce <path> [ <argument> ]* Fork and execute a program (<path>). This will block until the program completes execution. This command can be run at most once during init's lifetime. Subsequent invocations are ignored. - It is best to avoid exec as unlike the builtin commands, it runs + It is best to avoid execonce as unlike the builtin commands, it runs the risk of getting init "stuck". export <name> <value> @@ -161,18 +164,12 @@ import <filename> hostname <name> Set the host name. -chdir <directory> - Change working directory. - chmod <octal-mode> <path> Change file access permissions. chown <owner> <group> <path> Change file owner and group. -chroot <directory> - Change process root directory. - class_start <serviceclass> Start all services of the specified class if they are not already running. @@ -202,13 +199,16 @@ loglevel <level> mkdir <path> [mode] [owner] [group] Create a directory at <path>, optionally with the given mode, owner, and group. If not provided, the directory is created with permissions 755 and - owned by the root user and root group. + owned by the root user and root group. If provided, the mode, owner and group + will be updated if the directory exists already. -mount <type> <device> <dir> [ <mountoption> ]* +mount <type> <device> <dir> [ <flag> ]* [<options>] Attempt to mount the named device at the directory <dir> <device> may be of the form mtd@name to specify a mtd block device by name. - <mountoption>s include "ro", "rw", "remount", "noatime", ... + <flag>s include "ro", "rw", "remount", "noatime", ... + <options> include "barrier=1", "noauto_da_alloc", "discard", ... as + a comma separated string, eg: barrier=1,noauto_da_alloc restorecon <path> [ <path> ]* Restore the file named by <path> to the security context specified @@ -220,18 +220,11 @@ restorecon_recursive <path> [ <path> ]* Recursively restore the directory tree named by <path> to the security contexts specified in the file_contexts configuration. -setcon <securitycontext> +setcon <seclabel> Set the current process security context to the specified string. This is typically only used from early-init to set the init context before any other process is started. -setenforce 0|1 - Set the SELinux system-wide enforcing status. - 0 is permissive (i.e. log but do not deny), 1 is enforcing. - -setkey - TBD - setprop <name> <value> Set system property <name> to <value>. Properties are expanded within <value>. @@ -239,10 +232,6 @@ setprop <name> <value> setrlimit <resource> <cur> <max> Set the rlimit for a resource. -setsebool <name> <value> - Set SELinux boolean <name> to <value>. - <value> may be 1|true|on or 0|false|off - start <service> Start a service running if it is not already running. @@ -275,7 +264,7 @@ Properties Init updates some system properties to provide some insight into what it's doing: -init.action +init.action Equal to the name of the action currently being executed or "" if none init.command diff --git a/init/signal_handler.cpp b/init/signal_handler.cpp index c0898fb..c428b96 100644 --- a/init/signal_handler.cpp +++ b/init/signal_handler.cpp @@ -14,11 +14,11 @@ * limitations under the License. */ -#include <stdio.h> #include <errno.h> +#include <fcntl.h> #include <signal.h> +#include <stdio.h> #include <unistd.h> -#include <fcntl.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/wait.h> @@ -27,34 +27,28 @@ #include <cutils/list.h> #include "init.h" -#include "util.h" #include "log.h" +#include "util.h" static int signal_fd = -1; static int signal_recv_fd = -1; -static void sigchld_handler(int s) -{ +static void sigchld_handler(int s) { write(signal_fd, &s, 1); } #define CRITICAL_CRASH_THRESHOLD 4 /* if we crash >4 times ... */ -#define CRITICAL_CRASH_WINDOW (4*60) /* ... in 4 minutes, goto recovery*/ +#define CRITICAL_CRASH_WINDOW (4*60) /* ... in 4 minutes, goto recovery */ -static int wait_for_one_process(int block) -{ +static int wait_for_one_process() { int status; - struct service *svc; - struct socketinfo *si; - time_t now; - struct listnode *node; - struct command *cmd; - - pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, block ? 0 : WNOHANG)); - if (pid <= 0) return -1; + pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG)); + if (pid <= 0) { + return -1; + } INFO("waitpid returned pid %d, status = %08x\n", pid, status); - svc = service_find_by_pid(pid); + service* svc = service_find_by_pid(pid); if (!svc) { if (WIFEXITED(status)) { ERROR("untracked pid %d exited with status %d\n", pid, WEXITSTATUS(status)); @@ -68,36 +62,47 @@ static int wait_for_one_process(int block) return 0; } + // TODO: all the code from here down should be a member function on service. + NOTICE("process '%s', pid %d exited\n", svc->name, pid); if (!(svc->flags & SVC_ONESHOT) || (svc->flags & SVC_RESTART)) { - kill(-pid, SIGKILL); NOTICE("process '%s' killing any children in process group\n", svc->name); + kill(-pid, SIGKILL); } - /* remove any sockets we may have created */ - for (si = svc->sockets; si; si = si->next) { + // Remove any sockets we may have created. + for (socketinfo* si = svc->sockets; si; si = si->next) { char tmp[128]; snprintf(tmp, sizeof(tmp), ANDROID_SOCKET_DIR"/%s", si->name); unlink(tmp); } + if (svc->flags & SVC_EXEC) { + INFO("SVC_EXEC pid %d finished...\n", svc->pid); + waiting_for_exec = false; + list_remove(&svc->slist); + free(svc->name); + free(svc); + return 0; + } + svc->pid = 0; svc->flags &= (~SVC_RUNNING); - /* oneshot processes go into the disabled state on exit, - * except when manually restarted. */ + // Oneshot processes go into the disabled state on exit, + // except when manually restarted. if ((svc->flags & SVC_ONESHOT) && !(svc->flags & SVC_RESTART)) { svc->flags |= SVC_DISABLED; } - /* disabled and reset processes do not get restarted automatically */ - if (svc->flags & (SVC_DISABLED | SVC_RESET) ) { - notify_service_state(svc->name, "stopped"); + // Disabled and reset processes do not get restarted automatically. + if (svc->flags & (SVC_DISABLED | SVC_RESET)) { + svc->NotifyStateChange("stopped"); return 0; } - now = gettime(); + time_t now = gettime(); if ((svc->flags & SVC_CRITICAL) && !(svc->flags & SVC_RESTART)) { if (svc->time_crashed + CRITICAL_CRASH_WINDOW >= now) { if (++svc->nr_crashed > CRITICAL_CRASH_THRESHOLD) { @@ -116,36 +121,33 @@ static int wait_for_one_process(int block) svc->flags &= (~SVC_RESTART); svc->flags |= SVC_RESTARTING; - /* Execute all onrestart commands for this service. */ + // Execute all onrestart commands for this service. + struct listnode* node; list_for_each(node, &svc->onrestart.commands) { - cmd = node_to_item(node, struct command, clist); + command* cmd = node_to_item(node, struct command, clist); cmd->func(cmd->nargs, cmd->args); } - notify_service_state(svc->name, "restarting"); + svc->NotifyStateChange("restarting"); return 0; } -void handle_signal(void) -{ +void handle_signal() { + // We got a SIGCHLD - reap and restart as needed. char tmp[32]; - - /* we got a SIGCHLD - reap and restart as needed */ read(signal_recv_fd, tmp, sizeof(tmp)); - while (!wait_for_one_process(0)) - ; + while (!wait_for_one_process()) { + } } -void signal_init(void) -{ - int s[2]; - +void signal_init() { struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_handler = sigchld_handler; act.sa_flags = SA_NOCLDSTOP; sigaction(SIGCHLD, &act, 0); - /* create a signalling mechanism for the sigchld handler */ + // Create a signalling mechanism for the sigchld handler. + int s[2]; if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == 0) { signal_fd = s[0]; signal_recv_fd = s[1]; @@ -154,7 +156,6 @@ void signal_init(void) handle_signal(); } -int get_signal_fd() -{ +int get_signal_fd() { return signal_recv_fd; } diff --git a/init/util.cpp b/init/util.cpp index 3dddb15..c805083 100644 --- a/init/util.cpp +++ b/init/util.cpp @@ -32,11 +32,11 @@ #include <sys/socket.h> #include <sys/un.h> +#include <base/file.h> + /* for ANDROID_SOCKET_* */ #include <cutils/sockets.h> -#include <utils/file.h> - #include <private/android_filesystem_config.h> #include "init.h" @@ -168,7 +168,7 @@ bool read_file(const char* path, std::string* content) { return false; } - bool okay = android::ReadFdToString(fd, content); + bool okay = android::base::ReadFdToString(fd, content); TEMP_FAILURE_RETRY(close(fd)); if (okay) { content->append("\n", 1); @@ -181,7 +181,7 @@ int write_file(const char* path, const char* content) { if (fd == -1) { return -errno; } - int result = android::WriteStringToFd(content, fd) ? 0 : -errno; + int result = android::base::WriteStringToFd(content, fd) ? 0 : -errno; TEMP_FAILURE_RETRY(close(fd)); return result; } diff --git a/init/util_test.cpp b/init/util_test.cpp index e9a1581..5b3ab50 100644 --- a/init/util_test.cpp +++ b/init/util_test.cpp @@ -35,3 +35,9 @@ TEST(util, read_file_success) { s[5] = 0; EXPECT_STREQ("Linux", s.c_str()); } + +TEST(util, decode_uid) { + EXPECT_EQ(0U, decode_uid("root")); + EXPECT_EQ(-1U, decode_uid("toot")); + EXPECT_EQ(123U, decode_uid("123")); +} diff --git a/libbacktrace/BacktraceImpl.cpp b/libbacktrace/BacktraceImpl.cpp index fb8a725..4650b6a 100644 --- a/libbacktrace/BacktraceImpl.cpp +++ b/libbacktrace/BacktraceImpl.cpp @@ -17,6 +17,7 @@ #include <errno.h> #include <stdlib.h> #include <string.h> +#include <sys/param.h> #include <sys/ptrace.h> #include <sys/types.h> #include <ucontext.h> @@ -159,6 +160,17 @@ bool BacktraceCurrent::ReadWord(uintptr_t ptr, word_t* out_value) { } } +size_t BacktraceCurrent::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) { + backtrace_map_t map; + FillInMap(addr, &map); + if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) { + return 0; + } + bytes = MIN(map.end - addr, bytes); + memcpy(buffer, reinterpret_cast<uint8_t*>(addr), bytes); + return bytes; +} + //------------------------------------------------------------------------- // BacktracePtrace functions. //------------------------------------------------------------------------- @@ -171,25 +183,88 @@ BacktracePtrace::BacktracePtrace( BacktracePtrace::~BacktracePtrace() { } -bool BacktracePtrace::ReadWord(uintptr_t ptr, word_t* out_value) { - if (!VerifyReadWordArgs(ptr, out_value)) { +#if !defined(__APPLE__) +static bool PtraceRead(pid_t tid, uintptr_t addr, word_t* out_value) { + // ptrace() returns -1 and sets errno when the operation fails. + // To disambiguate -1 from a valid result, we clear errno beforehand. + errno = 0; + *out_value = ptrace(PTRACE_PEEKTEXT, tid, reinterpret_cast<void*>(addr), NULL); + if (*out_value == static_cast<word_t>(-1) && errno) { + BACK_LOGW("invalid pointer %p reading from tid %d, ptrace() strerror(errno)=%s", + reinterpret_cast<void*>(addr), tid, strerror(errno)); return false; } + return true; +} +#endif +bool BacktracePtrace::ReadWord(uintptr_t ptr, word_t* out_value) { #if defined(__APPLE__) BACK_LOGW("MacOS does not support reading from another pid."); return false; #else - // ptrace() returns -1 and sets errno when the operation fails. - // To disambiguate -1 from a valid result, we clear errno beforehand. - errno = 0; - *out_value = ptrace(PTRACE_PEEKTEXT, Tid(), reinterpret_cast<void*>(ptr), NULL); - if (*out_value == static_cast<word_t>(-1) && errno) { - BACK_LOGW("invalid pointer %p reading from tid %d, ptrace() strerror(errno)=%s", - reinterpret_cast<void*>(ptr), Tid(), strerror(errno)); + if (!VerifyReadWordArgs(ptr, out_value)) { return false; } - return true; + + backtrace_map_t map; + FillInMap(ptr, &map); + if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) { + return false; + } + + return PtraceRead(Tid(), ptr, out_value); +#endif +} + +size_t BacktracePtrace::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) { +#if defined(__APPLE__) + BACK_LOGW("MacOS does not support reading from another pid."); + return 0; +#else + backtrace_map_t map; + FillInMap(addr, &map); + if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) { + return 0; + } + + bytes = MIN(map.end - addr, bytes); + size_t bytes_read = 0; + word_t data_word; + size_t align_bytes = addr & (sizeof(word_t) - 1); + if (align_bytes != 0) { + if (!PtraceRead(Tid(), addr & ~(sizeof(word_t) - 1), &data_word)) { + return 0; + } + align_bytes = sizeof(word_t) - align_bytes; + memcpy(buffer, reinterpret_cast<uint8_t*>(&data_word) + sizeof(word_t) - align_bytes, + align_bytes); + addr += align_bytes; + buffer += align_bytes; + bytes -= align_bytes; + bytes_read += align_bytes; + } + + size_t num_words = bytes / sizeof(word_t); + for (size_t i = 0; i < num_words; i++) { + if (!PtraceRead(Tid(), addr, &data_word)) { + return bytes_read; + } + memcpy(buffer, &data_word, sizeof(word_t)); + buffer += sizeof(word_t); + addr += sizeof(word_t); + bytes_read += sizeof(word_t); + } + + size_t left_over = bytes & (sizeof(word_t) - 1); + if (left_over) { + if (!PtraceRead(Tid(), addr, &data_word)) { + return bytes_read; + } + memcpy(buffer, &data_word, left_over); + bytes_read += left_over; + } + return bytes_read; #endif } diff --git a/libbacktrace/BacktraceImpl.h b/libbacktrace/BacktraceImpl.h index cd61bdf..18c3cb5 100755 --- a/libbacktrace/BacktraceImpl.h +++ b/libbacktrace/BacktraceImpl.h @@ -56,6 +56,8 @@ public: BacktraceCurrent(BacktraceImpl* impl, BacktraceMap* map); virtual ~BacktraceCurrent(); + size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes); + bool ReadWord(uintptr_t ptr, word_t* out_value); }; @@ -64,6 +66,8 @@ public: BacktracePtrace(BacktraceImpl* impl, pid_t pid, pid_t tid, BacktraceMap* map); virtual ~BacktracePtrace(); + size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes); + bool ReadWord(uintptr_t ptr, word_t* out_value); }; diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp index 76aabd1..b1e34bd 100644 --- a/libbacktrace/backtrace_test.cpp +++ b/libbacktrace/backtrace_test.cpp @@ -31,7 +31,6 @@ #include <backtrace/Backtrace.h> #include <backtrace/BacktraceMap.h> -#include <UniquePtr.h> // For the THREAD_SIGNAL definition. #include "BacktraceThread.h" @@ -40,6 +39,7 @@ #include <gtest/gtest.h> #include <algorithm> +#include <memory> #include <vector> #include "thread_utils.h" @@ -60,6 +60,7 @@ struct thread_t { pid_t tid; int32_t state; pthread_t threadId; + void* data; }; struct dump_thread_t { @@ -142,9 +143,9 @@ void VerifyLevelDump(Backtrace* backtrace) { } void VerifyLevelBacktrace(void*) { - UniquePtr<Backtrace> backtrace( + std::unique_ptr<Backtrace> backtrace( Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(backtrace.get() != NULL); + ASSERT_TRUE(backtrace.get() != nullptr); ASSERT_TRUE(backtrace->Unwind(0)); VerifyLevelDump(backtrace.get()); @@ -162,9 +163,9 @@ void VerifyMaxDump(Backtrace* backtrace) { } void VerifyMaxBacktrace(void*) { - UniquePtr<Backtrace> backtrace( + std::unique_ptr<Backtrace> backtrace( Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(backtrace.get() != NULL); + ASSERT_TRUE(backtrace.get() != nullptr); ASSERT_TRUE(backtrace->Unwind(0)); VerifyMaxDump(backtrace.get()); @@ -180,8 +181,8 @@ void ThreadSetState(void* data) { } void VerifyThreadTest(pid_t tid, void (*VerifyFunc)(Backtrace*)) { - UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), tid)); - ASSERT_TRUE(backtrace.get() != NULL); + std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), tid)); + ASSERT_TRUE(backtrace.get() != nullptr); ASSERT_TRUE(backtrace->Unwind(0)); VerifyFunc(backtrace.get()); @@ -198,7 +199,7 @@ bool WaitForNonZero(int32_t* value, uint64_t seconds) { } TEST(libbacktrace, local_trace) { - ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelBacktrace, NULL), 0); + ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelBacktrace, nullptr), 0); } void VerifyIgnoreFrames( @@ -208,7 +209,7 @@ void VerifyIgnoreFrames( EXPECT_EQ(bt_all->NumFrames(), bt_ign2->NumFrames() + 2); // Check all of the frames are the same > the current frame. - bool check = (cur_proc == NULL); + bool check = (cur_proc == nullptr); for (size_t i = 0; i < bt_ign2->NumFrames(); i++) { if (check) { EXPECT_EQ(bt_ign2->GetFrame(i)->pc, bt_ign1->GetFrame(i+1)->pc); @@ -226,30 +227,30 @@ void VerifyIgnoreFrames( } void VerifyLevelIgnoreFrames(void*) { - UniquePtr<Backtrace> all( + std::unique_ptr<Backtrace> all( Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(all.get() != NULL); + ASSERT_TRUE(all.get() != nullptr); ASSERT_TRUE(all->Unwind(0)); - UniquePtr<Backtrace> ign1( + std::unique_ptr<Backtrace> ign1( Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(ign1.get() != NULL); + ASSERT_TRUE(ign1.get() != nullptr); ASSERT_TRUE(ign1->Unwind(1)); - UniquePtr<Backtrace> ign2( + std::unique_ptr<Backtrace> ign2( Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(ign2.get() != NULL); + ASSERT_TRUE(ign2.get() != nullptr); ASSERT_TRUE(ign2->Unwind(2)); VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), "VerifyLevelIgnoreFrames"); } TEST(libbacktrace, local_trace_ignore_frames) { - ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelIgnoreFrames, NULL), 0); + ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelIgnoreFrames, nullptr), 0); } TEST(libbacktrace, local_max_trace) { - ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxBacktrace, NULL), 0); + ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxBacktrace, nullptr), 0); } void VerifyProcTest(pid_t pid, pid_t tid, bool share_map, @@ -269,13 +270,13 @@ void VerifyProcTest(pid_t pid, pid_t tid, bool share_map, // Wait for the process to get to a stopping point. WaitForStop(ptrace_tid); - UniquePtr<BacktraceMap> map; + std::unique_ptr<BacktraceMap> map; if (share_map) { map.reset(BacktraceMap::Create(pid)); } - UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get())); + std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get())); ASSERT_TRUE(backtrace->Unwind(0)); - ASSERT_TRUE(backtrace.get() != NULL); + ASSERT_TRUE(backtrace.get() != nullptr); if (ReadyFunc(backtrace.get())) { VerifyFunc(backtrace.get()); verified = true; @@ -291,7 +292,7 @@ void VerifyProcTest(pid_t pid, pid_t tid, bool share_map, TEST(libbacktrace, ptrace_trace) { pid_t pid; if ((pid = fork()) == 0) { - ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0); + ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0); _exit(1); } VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, false, ReadyLevelBacktrace, VerifyLevelDump); @@ -304,7 +305,7 @@ TEST(libbacktrace, ptrace_trace) { TEST(libbacktrace, ptrace_trace_shared_map) { pid_t pid; if ((pid = fork()) == 0) { - ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0); + ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0); _exit(1); } @@ -318,7 +319,7 @@ TEST(libbacktrace, ptrace_trace_shared_map) { TEST(libbacktrace, ptrace_max_trace) { pid_t pid; if ((pid = fork()) == 0) { - ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, NULL, NULL), 0); + ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, nullptr, nullptr), 0); _exit(1); } VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, false, ReadyMaxBacktrace, VerifyMaxDump); @@ -329,21 +330,21 @@ TEST(libbacktrace, ptrace_max_trace) { } void VerifyProcessIgnoreFrames(Backtrace* bt_all) { - UniquePtr<Backtrace> ign1(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(ign1.get() != NULL); + std::unique_ptr<Backtrace> ign1(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD)); + ASSERT_TRUE(ign1.get() != nullptr); ASSERT_TRUE(ign1->Unwind(1)); - UniquePtr<Backtrace> ign2(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(ign2.get() != NULL); + std::unique_ptr<Backtrace> ign2(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD)); + ASSERT_TRUE(ign2.get() != nullptr); ASSERT_TRUE(ign2->Unwind(2)); - VerifyIgnoreFrames(bt_all, ign1.get(), ign2.get(), NULL); + VerifyIgnoreFrames(bt_all, ign1.get(), ign2.get(), nullptr); } TEST(libbacktrace, ptrace_ignore_frames) { pid_t pid; if ((pid = fork()) == 0) { - ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0); + ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0); _exit(1); } VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, false, ReadyLevelBacktrace, VerifyProcessIgnoreFrames); @@ -355,8 +356,8 @@ TEST(libbacktrace, ptrace_ignore_frames) { // Create a process with multiple threads and dump all of the threads. void* PtraceThreadLevelRun(void*) { - EXPECT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0); - return NULL; + EXPECT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0); + return nullptr; } void GetThreads(pid_t pid, std::vector<pid_t>* threads) { @@ -365,9 +366,9 @@ void GetThreads(pid_t pid, std::vector<pid_t>* threads) { snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid); DIR* tasks_dir = opendir(task_path); - ASSERT_TRUE(tasks_dir != NULL); + ASSERT_TRUE(tasks_dir != nullptr); struct dirent* entry; - while ((entry = readdir(tasks_dir)) != NULL) { + while ((entry = readdir(tasks_dir)) != nullptr) { char* end; pid_t tid = strtoul(entry->d_name, &end, 10); if (*end == '\0') { @@ -386,9 +387,9 @@ TEST(libbacktrace, ptrace_threads) { pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_t thread; - ASSERT_TRUE(pthread_create(&thread, &attr, PtraceThreadLevelRun, NULL) == 0); + ASSERT_TRUE(pthread_create(&thread, &attr, PtraceThreadLevelRun, nullptr) == 0); } - ASSERT_NE(test_level_one(1, 2, 3, 4, NULL, NULL), 0); + ASSERT_NE(test_level_one(1, 2, 3, 4, nullptr, nullptr), 0); _exit(1); } @@ -420,27 +421,27 @@ TEST(libbacktrace, ptrace_threads) { } void VerifyLevelThread(void*) { - UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), gettid())); - ASSERT_TRUE(backtrace.get() != NULL); + std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), gettid())); + ASSERT_TRUE(backtrace.get() != nullptr); ASSERT_TRUE(backtrace->Unwind(0)); VerifyLevelDump(backtrace.get()); } TEST(libbacktrace, thread_current_level) { - ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelThread, NULL), 0); + ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelThread, nullptr), 0); } void VerifyMaxThread(void*) { - UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), gettid())); - ASSERT_TRUE(backtrace.get() != NULL); + std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), gettid())); + ASSERT_TRUE(backtrace.get() != nullptr); ASSERT_TRUE(backtrace->Unwind(0)); VerifyMaxDump(backtrace.get()); } TEST(libbacktrace, thread_current_max) { - ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxThread, NULL), 0); + ASSERT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, VerifyMaxThread, nullptr), 0); } void* ThreadLevelRun(void* data) { @@ -448,7 +449,7 @@ void* ThreadLevelRun(void* data) { thread->tid = gettid(); EXPECT_NE(test_level_one(1, 2, 3, 4, ThreadSetState, data), 0); - return NULL; + return nullptr; } TEST(libbacktrace, thread_level_trace) { @@ -456,7 +457,7 @@ TEST(libbacktrace, thread_level_trace) { pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - thread_t thread_data = { 0, 0, 0 }; + thread_t thread_data = { 0, 0, 0, nullptr }; pthread_t thread; ASSERT_TRUE(pthread_create(&thread, &attr, ThreadLevelRun, &thread_data) == 0); @@ -471,10 +472,10 @@ TEST(libbacktrace, thread_level_trace) { // Save the current signal action and make sure it is restored afterwards. struct sigaction cur_action; - ASSERT_TRUE(sigaction(THREAD_SIGNAL, NULL, &cur_action) == 0); + ASSERT_TRUE(sigaction(THREAD_SIGNAL, nullptr, &cur_action) == 0); - UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid)); - ASSERT_TRUE(backtrace.get() != NULL); + std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid)); + ASSERT_TRUE(backtrace.get() != nullptr); ASSERT_TRUE(backtrace->Unwind(0)); VerifyLevelDump(backtrace.get()); @@ -484,7 +485,7 @@ TEST(libbacktrace, thread_level_trace) { // Verify that the old action was restored. struct sigaction new_action; - ASSERT_TRUE(sigaction(THREAD_SIGNAL, NULL, &new_action) == 0); + ASSERT_TRUE(sigaction(THREAD_SIGNAL, nullptr, &new_action) == 0); EXPECT_EQ(cur_action.sa_sigaction, new_action.sa_sigaction); // The SA_RESTORER flag gets set behind our back, so a direct comparison // doesn't work unless we mask the value off. Mips doesn't have this @@ -501,26 +502,26 @@ TEST(libbacktrace, thread_ignore_frames) { pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - thread_t thread_data = { 0, 0, 0 }; + thread_t thread_data = { 0, 0, 0, nullptr }; pthread_t thread; ASSERT_TRUE(pthread_create(&thread, &attr, ThreadLevelRun, &thread_data) == 0); // Wait up to 2 seconds for the tid to be set. ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2)); - UniquePtr<Backtrace> all(Backtrace::Create(getpid(), thread_data.tid)); - ASSERT_TRUE(all.get() != NULL); + std::unique_ptr<Backtrace> all(Backtrace::Create(getpid(), thread_data.tid)); + ASSERT_TRUE(all.get() != nullptr); ASSERT_TRUE(all->Unwind(0)); - UniquePtr<Backtrace> ign1(Backtrace::Create(getpid(), thread_data.tid)); - ASSERT_TRUE(ign1.get() != NULL); + std::unique_ptr<Backtrace> ign1(Backtrace::Create(getpid(), thread_data.tid)); + ASSERT_TRUE(ign1.get() != nullptr); ASSERT_TRUE(ign1->Unwind(1)); - UniquePtr<Backtrace> ign2(Backtrace::Create(getpid(), thread_data.tid)); - ASSERT_TRUE(ign2.get() != NULL); + std::unique_ptr<Backtrace> ign2(Backtrace::Create(getpid(), thread_data.tid)); + ASSERT_TRUE(ign2.get() != nullptr); ASSERT_TRUE(ign2->Unwind(2)); - VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), NULL); + VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), nullptr); // Tell the thread to exit its infinite loop. android_atomic_acquire_store(0, &thread_data.state); @@ -531,7 +532,7 @@ void* ThreadMaxRun(void* data) { thread->tid = gettid(); EXPECT_NE(test_recursive_call(MAX_BACKTRACE_FRAMES+10, ThreadSetState, data), 0); - return NULL; + return nullptr; } TEST(libbacktrace, thread_max_trace) { @@ -539,15 +540,15 @@ TEST(libbacktrace, thread_max_trace) { pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - thread_t thread_data = { 0, 0, 0 }; + thread_t thread_data = { 0, 0, 0, nullptr }; pthread_t thread; ASSERT_TRUE(pthread_create(&thread, &attr, ThreadMaxRun, &thread_data) == 0); // Wait for the tid to be set. ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2)); - UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid)); - ASSERT_TRUE(backtrace.get() != NULL); + std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid)); + ASSERT_TRUE(backtrace.get() != nullptr); ASSERT_TRUE(backtrace->Unwind(0)); VerifyMaxDump(backtrace.get()); @@ -570,7 +571,7 @@ void* ThreadDump(void* data) { android_atomic_acquire_store(1, &dump->done); - return NULL; + return nullptr; } TEST(libbacktrace, thread_multiple_dump) { @@ -614,11 +615,11 @@ TEST(libbacktrace, thread_multiple_dump) { // Tell the runner thread to exit its infinite loop. android_atomic_acquire_store(0, &runners[i].state); - ASSERT_TRUE(dumpers[i].backtrace != NULL); + ASSERT_TRUE(dumpers[i].backtrace != nullptr); VerifyMaxDump(dumpers[i].backtrace); delete dumpers[i].backtrace; - dumpers[i].backtrace = NULL; + dumpers[i].backtrace = nullptr; } } @@ -654,11 +655,11 @@ TEST(libbacktrace, thread_multiple_dump_same_thread) { for (size_t i = 0; i < NUM_THREADS; i++) { ASSERT_TRUE(WaitForNonZero(&dumpers[i].done, 30)); - ASSERT_TRUE(dumpers[i].backtrace != NULL); + ASSERT_TRUE(dumpers[i].backtrace != nullptr); VerifyMaxDump(dumpers[i].backtrace); delete dumpers[i].backtrace; - dumpers[i].backtrace = NULL; + dumpers[i].backtrace = nullptr; } // Tell the runner thread to exit its infinite loop. @@ -708,8 +709,8 @@ TEST(libbacktrace, fillin_erases) { } TEST(libbacktrace, format_test) { - UniquePtr<Backtrace> backtrace(Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(backtrace.get() != NULL); + std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD)); + ASSERT_TRUE(backtrace.get() != nullptr); backtrace_frame_data_t frame; frame.num = 1; @@ -778,12 +779,12 @@ bool map_sort(map_test_t i, map_test_t j) { return i.start < j.start; } -static void VerifyMap(pid_t pid) { +void VerifyMap(pid_t pid) { char buffer[4096]; snprintf(buffer, sizeof(buffer), "/proc/%d/maps", pid); FILE* map_file = fopen(buffer, "r"); - ASSERT_TRUE(map_file != NULL); + ASSERT_TRUE(map_file != nullptr); std::vector<map_test_t> test_maps; while (fgets(buffer, sizeof(buffer), map_file)) { map_test_t map; @@ -793,7 +794,7 @@ static void VerifyMap(pid_t pid) { fclose(map_file); std::sort(test_maps.begin(), test_maps.end(), map_sort); - UniquePtr<BacktraceMap> map(BacktraceMap::Create(pid)); + std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(pid)); // Basic test that verifies that the map is in the expected order. std::vector<map_test_t>::const_iterator test_it = test_maps.begin(); @@ -827,7 +828,167 @@ TEST(libbacktrace, verify_map_remote) { ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0); kill(pid, SIGKILL); - ASSERT_EQ(waitpid(pid, NULL, 0), pid); + ASSERT_EQ(waitpid(pid, nullptr, 0), pid); +} + +void* ThreadReadTest(void* data) { + thread_t* thread_data = reinterpret_cast<thread_t*>(data); + + thread_data->tid = gettid(); + + // Create two map pages. + // Mark the second page as not-readable. + size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE)); + uint8_t* memory; + if (posix_memalign(reinterpret_cast<void**>(&memory), pagesize, 2 * pagesize) != 0) { + return reinterpret_cast<void*>(-1); + } + + if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) { + return reinterpret_cast<void*>(-1); + } + + // Set up a simple pattern in memory. + for (size_t i = 0; i < pagesize; i++) { + memory[i] = i; + } + + thread_data->data = memory; + + // Tell the caller it's okay to start reading memory. + android_atomic_acquire_store(1, &thread_data->state); + + // Loop waiting for everything + while (thread_data->state) { + } + + free(memory); + + android_atomic_acquire_store(1, &thread_data->state); + + return nullptr; +} + +void RunReadTest(Backtrace* backtrace, uintptr_t read_addr) { + size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE)); + + // Create a page of data to use to do quick compares. + uint8_t* expected = new uint8_t[pagesize]; + for (size_t i = 0; i < pagesize; i++) { + expected[i] = i; + } + uint8_t* data = new uint8_t[2*pagesize]; + // Verify that we can only read one page worth of data. + size_t bytes_read = backtrace->Read(read_addr, data, 2 * pagesize); + ASSERT_EQ(pagesize, bytes_read); + ASSERT_TRUE(memcmp(data, expected, pagesize) == 0); + + // Verify unaligned reads. + for (size_t i = 1; i < sizeof(word_t); i++) { + bytes_read = backtrace->Read(read_addr + i, data, 2 * sizeof(word_t)); + ASSERT_EQ(2 * sizeof(word_t), bytes_read); + ASSERT_TRUE(memcmp(data, &expected[i], 2 * sizeof(word_t)) == 0) + << "Offset at " << i << " failed"; + } + delete data; + delete expected; +} + +TEST(libbacktrace, thread_read) { + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_t thread; + thread_t thread_data = { 0, 0, 0, nullptr }; + ASSERT_TRUE(pthread_create(&thread, &attr, ThreadReadTest, &thread_data) == 0); + + ASSERT_TRUE(WaitForNonZero(&thread_data.state, 10)); + + std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid)); + ASSERT_TRUE(backtrace.get() != nullptr); + + RunReadTest(backtrace.get(), reinterpret_cast<uintptr_t>(thread_data.data)); + + android_atomic_acquire_store(0, &thread_data.state); + + ASSERT_TRUE(WaitForNonZero(&thread_data.state, 10)); +} + +volatile uintptr_t g_ready = 0; +volatile uintptr_t g_addr = 0; + +void ForkedReadTest() { + // Create two map pages. + size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE)); + uint8_t* memory; + if (posix_memalign(reinterpret_cast<void**>(&memory), pagesize, 2 * pagesize) != 0) { + perror("Failed to allocate memory\n"); + exit(1); + } + + // Mark the second page as not-readable. + if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) { + perror("Failed to mprotect memory\n"); + exit(1); + } + + // Set up a simple pattern in memory. + for (size_t i = 0; i < pagesize; i++) { + memory[i] = i; + } + + g_addr = reinterpret_cast<uintptr_t>(memory); + g_ready = 1; + + while (1) { + usleep(US_PER_MSEC); + } +} + +TEST(libbacktrace, process_read) { + pid_t pid; + if ((pid = fork()) == 0) { + ForkedReadTest(); + exit(0); + } + ASSERT_NE(-1, pid); + + bool test_executed = false; + uint64_t start = NanoTime(); + while (1) { + if (ptrace(PTRACE_ATTACH, pid, 0, 0) == 0) { + WaitForStop(pid); + + std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, pid)); + + uintptr_t read_addr; + size_t bytes_read = backtrace->Read(reinterpret_cast<uintptr_t>(&g_ready), + reinterpret_cast<uint8_t*>(&read_addr), + sizeof(uintptr_t)); + ASSERT_EQ(sizeof(uintptr_t), bytes_read); + if (read_addr) { + // The forked process is ready to be read. + bytes_read = backtrace->Read(reinterpret_cast<uintptr_t>(&g_addr), + reinterpret_cast<uint8_t*>(&read_addr), + sizeof(uintptr_t)); + ASSERT_EQ(sizeof(uintptr_t), bytes_read); + + RunReadTest(backtrace.get(), read_addr); + + test_executed = true; + break; + } + ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0); + } + if ((NanoTime() - start) > 5 * NS_PER_SEC) { + break; + } + usleep(US_PER_MSEC); + } + kill(pid, SIGKILL); + ASSERT_EQ(waitpid(pid, nullptr, 0), pid); + + ASSERT_TRUE(test_executed); } #if defined(ENABLE_PSS_TESTS) @@ -835,11 +996,11 @@ TEST(libbacktrace, verify_map_remote) { #define MAX_LEAK_BYTES 32*1024UL -static void CheckForLeak(pid_t pid, pid_t tid) { +void CheckForLeak(pid_t pid, pid_t tid) { // Do a few runs to get the PSS stable. for (size_t i = 0; i < 100; i++) { Backtrace* backtrace = Backtrace::Create(pid, tid); - ASSERT_TRUE(backtrace != NULL); + ASSERT_TRUE(backtrace != nullptr); ASSERT_TRUE(backtrace->Unwind(0)); delete backtrace; } @@ -848,7 +1009,7 @@ static void CheckForLeak(pid_t pid, pid_t tid) { // Loop enough that even a small leak should be detectable. for (size_t i = 0; i < 4096; i++) { Backtrace* backtrace = Backtrace::Create(pid, tid); - ASSERT_TRUE(backtrace != NULL); + ASSERT_TRUE(backtrace != nullptr); ASSERT_TRUE(backtrace->Unwind(0)); delete backtrace; } @@ -863,9 +1024,9 @@ TEST(libbacktrace, check_for_leak_local) { } TEST(libbacktrace, check_for_leak_local_thread) { - thread_t thread_data = { 0, 0, 0 }; + thread_t thread_data = { 0, 0, 0, nullptr }; pthread_t thread; - ASSERT_TRUE(pthread_create(&thread, NULL, ThreadLevelRun, &thread_data) == 0); + ASSERT_TRUE(pthread_create(&thread, nullptr, ThreadLevelRun, &thread_data) == 0); // Wait up to 2 seconds for the tid to be set. ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2)); @@ -875,7 +1036,7 @@ TEST(libbacktrace, check_for_leak_local_thread) { // Tell the thread to exit its infinite loop. android_atomic_acquire_store(0, &thread_data.state); - ASSERT_TRUE(pthread_join(thread, NULL) == 0); + ASSERT_TRUE(pthread_join(thread, nullptr) == 0); } TEST(libbacktrace, check_for_leak_remote) { @@ -898,6 +1059,6 @@ TEST(libbacktrace, check_for_leak_remote) { ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0); kill(pid, SIGKILL); - ASSERT_EQ(waitpid(pid, NULL, 0), pid); + ASSERT_EQ(waitpid(pid, nullptr, 0), pid); } #endif diff --git a/libcutils/native_handle.c b/libcutils/native_handle.c index 4089968..9a4a5bb 100644 --- a/libcutils/native_handle.c +++ b/libcutils/native_handle.c @@ -30,9 +30,11 @@ native_handle_t* native_handle_create(int numFds, int numInts) native_handle_t* h = malloc( sizeof(native_handle_t) + sizeof(int)*(numFds+numInts)); - h->version = sizeof(native_handle_t); - h->numFds = numFds; - h->numInts = numInts; + if (h) { + h->version = sizeof(native_handle_t); + h->numFds = numFds; + h->numInts = numInts; + } return h; } diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c index 2a9d96b..dfc8777 100644 --- a/libcutils/sched_policy.c +++ b/libcutils/sched_policy.c @@ -45,8 +45,6 @@ static inline SchedPolicy _policy(SchedPolicy p) #define POLICY_DEBUG 0 -#define CAN_SET_SP_SYSTEM 0 // non-zero means to implement set_sched_policy(tid, SP_SYSTEM) - // This prctl is only available in Android kernels. #define PR_SET_TIMERSLACK_PID 41 @@ -60,9 +58,6 @@ static int __sys_supports_schedgroups = -1; // File descriptors open to /dev/cpuctl/../tasks, setup by initialize, or -1 on error. static int bg_cgroup_fd = -1; static int fg_cgroup_fd = -1; -#if CAN_SET_SP_SYSTEM -static int system_cgroup_fd = -1; -#endif /* Add tid to the scheduling group defined by the policy */ static int add_tid_to_cgroup(int tid, SchedPolicy policy) @@ -78,11 +73,6 @@ static int add_tid_to_cgroup(int tid, SchedPolicy policy) case SP_AUDIO_SYS: fd = fg_cgroup_fd; break; -#if CAN_SET_SP_SYSTEM - case SP_SYSTEM: - fd = system_cgroup_fd; - break; -#endif default: fd = -1; break; @@ -123,21 +113,13 @@ static void __initialize(void) { if (!access("/dev/cpuctl/tasks", F_OK)) { __sys_supports_schedgroups = 1; -#if CAN_SET_SP_SYSTEM filename = "/dev/cpuctl/tasks"; - system_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC); - if (system_cgroup_fd < 0) { - SLOGV("open of %s failed: %s\n", filename, strerror(errno)); - } -#endif - - filename = "/dev/cpuctl/apps/tasks"; fg_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC); if (fg_cgroup_fd < 0) { SLOGE("open of %s failed: %s\n", filename, strerror(errno)); } - filename = "/dev/cpuctl/apps/bg_non_interactive/tasks"; + filename = "/dev/cpuctl/bg_non_interactive/tasks"; bg_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC); if (bg_cgroup_fd < 0) { SLOGE("open of %s failed: %s\n", filename, strerror(errno)); @@ -231,11 +213,9 @@ int get_sched_policy(int tid, SchedPolicy *policy) if (getSchedulerGroup(tid, grpBuf, sizeof(grpBuf)) < 0) return -1; if (grpBuf[0] == '\0') { - *policy = SP_SYSTEM; - } else if (!strcmp(grpBuf, "apps/bg_non_interactive")) { - *policy = SP_BACKGROUND; - } else if (!strcmp(grpBuf, "apps")) { *policy = SP_FOREGROUND; + } else if (!strcmp(grpBuf, "bg_non_interactive")) { + *policy = SP_BACKGROUND; } else { errno = ERANGE; return -1; diff --git a/liblog/Android.mk b/liblog/Android.mk index 5756c54..70aff83 100644 --- a/liblog/Android.mk +++ b/liblog/Android.mk @@ -16,6 +16,14 @@ LOCAL_PATH := $(my-dir) include $(CLEAR_VARS) +# This is what we want to do: +# liblog_cflags := $(shell \ +# sed -n \ +# 's/^\([0-9]*\)[ \t]*liblog[ \t].*/-DLIBLOG_LOG_TAG=\1/p' \ +# $(LOCAL_PATH)/event.logtags) +# so make sure we do not regret hard-coding it as follows: +liblog_cflags := -DLIBLOG_LOG_TAG=1005 + ifneq ($(TARGET_USES_LOGD),false) liblog_sources := logd_write.c else @@ -25,28 +33,20 @@ endif # some files must not be compiled when building against Mingw # they correspond to features not used by our host development tools # which are also hard or even impossible to port to native Win32 -WITH_MINGW := -ifeq ($(HOST_OS),windows) - ifeq ($(strip $(USE_CYGWIN)),) - WITH_MINGW := true - endif -endif -# USE_MINGW is defined when we build against Mingw on Linux -ifneq ($(strip $(USE_MINGW)),) - WITH_MINGW := true -endif -ifndef WITH_MINGW +ifeq ($(strip $(USE_MINGW)),) liblog_sources += \ - logprint.c \ event_tag_map.c else liblog_sources += \ uio.c endif -liblog_host_sources := $(liblog_sources) fake_log_device.c +liblog_host_sources := $(liblog_sources) fake_log_device.c event.logtags liblog_target_sources := $(liblog_sources) log_time.cpp log_is_loggable.c +ifeq ($(strip $(USE_MINGW)),) +liblog_target_sources += logprint.c +endif ifneq ($(TARGET_USES_LOGD),false) liblog_target_sources += log_read.c else @@ -57,7 +57,7 @@ endif # ======================================================== LOCAL_MODULE := liblog LOCAL_SRC_FILES := $(liblog_host_sources) -LOCAL_CFLAGS := -DFAKE_LOG_DEVICE=1 -Werror +LOCAL_CFLAGS := -DFAKE_LOG_DEVICE=1 -Werror $(liblog_cflags) LOCAL_MULTILIB := both include $(BUILD_HOST_STATIC_LIBRARY) @@ -76,13 +76,17 @@ include $(BUILD_HOST_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := liblog LOCAL_SRC_FILES := $(liblog_target_sources) -LOCAL_CFLAGS := -Werror +LOCAL_CFLAGS := -Werror $(liblog_cflags) include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := liblog LOCAL_WHOLE_STATIC_LIBRARIES := liblog -LOCAL_CFLAGS := -Werror +LOCAL_CFLAGS := -Werror $(liblog_cflags) + +# TODO: This is to work around b/19059885. Remove after root cause is fixed +LOCAL_LDFLAGS_arm := -Wl,--hash-style=sysv + include $(BUILD_SHARED_LIBRARY) include $(call first-makefiles-under,$(LOCAL_PATH)) diff --git a/liblog/README b/liblog/README index 461dfbe..f29ac04 100644 --- a/liblog/README +++ b/liblog/README @@ -131,6 +131,33 @@ DESCRIPTION when opening the sub-log. It is recommended to open the log ANDROID_LOG_RDONLY in these cases. +ERRORS + If messages fail, a negative error code will be returned to the caller. + + The -ENOTCONN return code indicates that the logger daemon is stopped. + + The -EBADF return code indicates that the log access point can not be + opened, or the log buffer id is out of range. + + For the -EAGAIN return code, this means that the logging message was + temporarily backed-up either because of Denial Of Service (DOS) logging + pressure from some chatty application or service in the Android system, + or if too small of a value is set in /proc/sys/net/unix/max_dgram_qlen. + To aid in diagnosing the occurence of this, a binary event from liblog + will be sent to the log daemon once a new message can get through + indicating how many messages were dropped as a result. Please take + action to resolve the structural problems at the source. + + It is generally not advised for the caller to retry the -EAGAIN return + code as this will only make the problem(s) worse and cause your + application to temporarily drop to the logger daemon priority, BATCH + scheduling policy and background task cgroup. If you require a group of + messages to be passed atomically, merge them into one message with + embedded newlines to the maximum length LOGGER_ENTRY_MAX_PAYLOAD. + + Other return codes from writing operation can be returned. Since the + library retries on EINTR, -EINTR should never be returned. + SEE ALSO syslogd(8) diff --git a/liblog/event.logtags b/liblog/event.logtags new file mode 100644 index 0000000..72ecab1 --- /dev/null +++ b/liblog/event.logtags @@ -0,0 +1,36 @@ +# The entries in this file map a sparse set of log tag numbers to tag names. +# This is installed on the device, in /system/etc, and parsed by logcat. +# +# Tag numbers are decimal integers, from 0 to 2^31. (Let's leave the +# negative values alone for now.) +# +# Tag names are one or more ASCII letters and numbers or underscores, i.e. +# "[A-Z][a-z][0-9]_". Do not include spaces or punctuation (the former +# impacts log readability, the latter makes regex searches more annoying). +# +# Tag numbers and names are separated by whitespace. Blank lines and lines +# starting with '#' are ignored. +# +# Optionally, after the tag names can be put a description for the value(s) +# of the tag. Description are in the format +# (<name>|data type[|data unit]) +# Multiple values are separated by commas. +# +# The data type is a number from the following values: +# 1: int +# 2: long +# 3: string +# 4: list +# +# The data unit is a number taken from the following list: +# 1: Number of objects +# 2: Number of bytes +# 3: Number of milliseconds +# 4: Number of allocations +# 5: Id +# 6: Percent +# Default value for data of type int/long is 2 (bytes). +# +# TODO: generate ".java" and ".h" files with integer constants from this file. + +1005 liblog (dropped|1) diff --git a/liblog/logd_write.c b/liblog/logd_write.c index 0208c73..8f8cc3f 100644 --- a/liblog/logd_write.c +++ b/liblog/logd_write.c @@ -13,12 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#if (FAKE_LOG_DEVICE == 0) +#include <endian.h> +#endif #include <errno.h> #include <fcntl.h> #if !defined(_WIN32) #include <pthread.h> #endif #include <stdarg.h> +#include <stdatomic.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -172,6 +176,11 @@ static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr) size_t i, payload_size; static uid_t last_uid = AID_ROOT; /* logd *always* starts up as AID_ROOT */ static pid_t last_pid = (pid_t) -1; + static atomic_int_fast32_t dropped; + + if (!nr) { + return -EINVAL; + } if (last_uid == AID_ROOT) { /* have we called to get the UID yet? */ last_uid = getuid(); @@ -206,7 +215,6 @@ static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr) pmsg_header.uid = last_uid; pmsg_header.pid = last_pid; - header.id = log_id; header.tid = gettid(); header.realtime.tv_sec = ts.tv_sec; header.realtime.tv_nsec = ts.tv_nsec; @@ -216,6 +224,28 @@ static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr) newVec[1].iov_base = (unsigned char *) &header; newVec[1].iov_len = sizeof(header); + if (logd_fd > 0) { + int32_t snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed); + if (snapshot) { + android_log_event_int_t buffer; + + header.id = LOG_ID_EVENTS; + buffer.header.tag = htole32(LIBLOG_LOG_TAG); + buffer.payload.type = EVENT_TYPE_INT; + buffer.payload.data = htole32(snapshot); + + newVec[2].iov_base = &buffer; + newVec[2].iov_len = sizeof(buffer); + + ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, 2)); + if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) { + atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed); + } + } + } + + header.id = log_id; + for (payload_size = 0, i = header_length; i < nr + header_length; i++) { newVec[i].iov_base = vec[i - header_length].iov_base; payload_size += newVec[i].iov_len = vec[i - header_length].iov_len; @@ -281,6 +311,8 @@ static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr) if (ret > (ssize_t)sizeof(header)) { ret -= sizeof(header); + } else if (ret == -EAGAIN) { + atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed); } #endif @@ -463,7 +495,7 @@ void __android_log_assert(const char *cond, const char *tag, } __android_log_write(ANDROID_LOG_FATAL, tag, buf); - __builtin_trap(); /* trap so we have a chance to debug the situation */ + abort(); /* abort so we have a chance to debug the situation */ /* NOTREACHED */ } diff --git a/liblog/logd_write_kern.c b/liblog/logd_write_kern.c index 2ca3c94..ca63067 100644 --- a/liblog/logd_write_kern.c +++ b/liblog/logd_write_kern.c @@ -266,7 +266,7 @@ void __android_log_assert(const char *cond, const char *tag, } __android_log_write(ANDROID_LOG_FATAL, tag, buf); - __builtin_trap(); /* trap so we have a chance to debug the situation */ + abort(); /* abort so we have a chance to debug the situation */ /* NOTREACHED */ } diff --git a/libnativebridge/tests/CompleteFlow_test.cpp b/libnativebridge/tests/CompleteFlow_test.cpp index cf06d2c..b033792 100644 --- a/libnativebridge/tests/CompleteFlow_test.cpp +++ b/libnativebridge/tests/CompleteFlow_test.cpp @@ -36,6 +36,7 @@ TEST_F(NativeBridgeTest, CompleteFlow) { // Unload UnloadNativeBridge(); + ASSERT_FALSE(NativeBridgeAvailable()); ASSERT_FALSE(NativeBridgeError()); diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c index 0f7c384..70e37c6 100644 --- a/libnetutils/dhcp_utils.c +++ b/libnetutils/dhcp_utils.c @@ -72,14 +72,16 @@ static int wait_for_property(const char *name, const char *desired_value, int ma maxnaps = 1; } - while (maxnaps-- > 0) { - usleep(NAP_TIME * 1000); + while (maxnaps-- >= 0) { if (property_get(name, value, NULL)) { if (desired_value == NULL || strcmp(value, desired_value) == 0) { return 0; } } + if (maxnaps >= 0) { + usleep(NAP_TIME * 1000); + } } return -1; /* failure */ } diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk index acd18b0..aa614bc 100644 --- a/libpixelflinger/Android.mk +++ b/libpixelflinger/Android.mk @@ -74,22 +74,4 @@ LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as include $(BUILD_SHARED_LIBRARY) -# -# Static library version -# - -include $(CLEAR_VARS) -LOCAL_MODULE:= libpixelflinger_static -LOCAL_SRC_FILES := $(PIXELFLINGER_SRC_FILES) -LOCAL_SRC_FILES_arm := $(PIXELFLINGER_SRC_FILES_arm) -LOCAL_SRC_FILES_arm64 := $(PIXELFLINGER_SRC_FILES_arm64) -LOCAL_SRC_FILES_mips := $(PIXELFLINGER_SRC_FILES_mips) -LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS) -# t32cb16blend.S does not compile with Clang. -LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as -# arch-arm64/col32cb16blend.S does not compile with Clang. -LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as -include $(BUILD_STATIC_LIBRARY) - - include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/libutils/Android.mk b/libutils/Android.mk index 7bff14e..e9c5f89 100644 --- a/libutils/Android.mk +++ b/libutils/Android.mk @@ -39,9 +39,7 @@ commonSources:= \ Tokenizer.cpp \ Unicode.cpp \ VectorImpl.cpp \ - file.cpp \ misc.cpp \ - stringprintf.cpp \ host_commonCflags := -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS) -Werror diff --git a/libutils/tests/Android.mk b/libutils/tests/Android.mk index ce288ca..634f44f 100644 --- a/libutils/tests/Android.mk +++ b/libutils/tests/Android.mk @@ -26,11 +26,9 @@ LOCAL_SRC_FILES := \ BasicHashtable_test.cpp \ BlobCache_test.cpp \ BitSet_test.cpp \ - file_test.cpp \ Looper_test.cpp \ LruCache_test.cpp \ String8_test.cpp \ - stringprintf_test.cpp \ Unicode_test.cpp \ Vector_test.cpp \ diff --git a/libziparchive/Android.mk b/libziparchive/Android.mk index ba7b74d..3937449 100644 --- a/libziparchive/Android.mk +++ b/libziparchive/Android.mk @@ -24,7 +24,8 @@ LOCAL_SRC_FILES := ${source_files} LOCAL_STATIC_LIBRARIES := libz LOCAL_SHARED_LIBRARIES := libutils LOCAL_MODULE:= libziparchive -LOCAL_CFLAGS := -Werror +LOCAL_CFLAGS := -Werror -Wall +LOCAL_CPPFLAGS := -Wold-style-cast include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) diff --git a/libziparchive/testdata/declaredlength.zip b/libziparchive/testdata/declaredlength.zip Binary files differnew file mode 100644 index 0000000..773380c --- /dev/null +++ b/libziparchive/testdata/declaredlength.zip diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc index ebbab9f..6475649 100644 --- a/libziparchive/zip_archive.cc +++ b/libziparchive/zip_archive.cc @@ -18,6 +18,9 @@ * Read-only access to Zip archives, with minimal heap allocation. */ +#include <memory> +#include <vector> + #include <assert.h> #include <errno.h> #include <fcntl.h> @@ -293,7 +296,7 @@ struct ZipArchive { /* mapped central directory area */ off64_t directory_offset; - android::FileMap* directory_map; + android::FileMap directory_map; /* number of entries in the Zip archive */ uint16_t num_entries; @@ -311,7 +314,6 @@ struct ZipArchive { fd(fd), close_file(assume_ownership), directory_offset(0), - directory_map(NULL), num_entries(0), hash_table_size(0), hash_table(NULL) {} @@ -321,25 +323,10 @@ struct ZipArchive { close(fd); } - delete directory_map; free(hash_table); } }; -// Returns 0 on success and negative values on failure. -static android::FileMap* MapFileSegment(const int fd, const off64_t start, - const size_t length, const bool read_only, - const char* debug_file_name) { - android::FileMap* file_map = new android::FileMap; - const bool success = file_map->create(debug_file_name, fd, start, length, read_only); - if (!success) { - delete file_map; - return NULL; - } - - return file_map; -} - static int32_t CopyFileToFile(int fd, uint8_t* begin, const uint32_t length, uint64_t *crc_out) { static const uint32_t kBufSize = 32768; uint8_t buf[kBufSize]; @@ -521,16 +508,12 @@ static int32_t MapCentralDirectory0(int fd, const char* debug_file_name, * It all looks good. Create a mapping for the CD, and set the fields * in archive. */ - android::FileMap* map = MapFileSegment(fd, - static_cast<off64_t>(eocd->cd_start_offset), - static_cast<size_t>(eocd->cd_size), - true /* read only */, debug_file_name); - if (map == NULL) { - archive->directory_map = NULL; + if (!archive->directory_map.create(debug_file_name, fd, + static_cast<off64_t>(eocd->cd_start_offset), + static_cast<size_t>(eocd->cd_size), true /* read only */) ) { return kMmapFailed; } - archive->directory_map = map; archive->num_entries = eocd->num_records; archive->directory_offset = eocd->cd_start_offset; @@ -557,7 +540,7 @@ static int32_t MapCentralDirectory(int fd, const char* debug_file_name, return kInvalidFile; } - if (file_length > (off64_t) 0xffffffff) { + if (file_length > static_cast<off64_t>(0xffffffff)) { ALOGV("Zip: zip file too long %" PRId64, static_cast<int64_t>(file_length)); return kInvalidFile; } @@ -599,9 +582,9 @@ static int32_t MapCentralDirectory(int fd, const char* debug_file_name, * Returns 0 on success. */ static int32_t ParseZipArchive(ZipArchive* archive) { - int32_t result = -1; - const uint8_t* const cd_ptr = (const uint8_t*) archive->directory_map->getDataPtr(); - const size_t cd_length = archive->directory_map->getDataLength(); + const uint8_t* const cd_ptr = + reinterpret_cast<const uint8_t*>(archive->directory_map.getDataPtr()); + const size_t cd_length = archive->directory_map.getDataLength(); const uint16_t num_entries = archive->num_entries; /* @@ -610,8 +593,8 @@ static int32_t ParseZipArchive(ZipArchive* archive) { * least one unused entry to avoid an infinite loop during creation. */ archive->hash_table_size = RoundUpPower2(1 + (num_entries * 4) / 3); - archive->hash_table = (ZipEntryName*) calloc(archive->hash_table_size, - sizeof(ZipEntryName)); + archive->hash_table = reinterpret_cast<ZipEntryName*>(calloc(archive->hash_table_size, + sizeof(ZipEntryName))); /* * Walk through the central directory, adding entries to the hash @@ -624,18 +607,19 @@ static int32_t ParseZipArchive(ZipArchive* archive) { reinterpret_cast<const CentralDirectoryRecord*>(ptr); if (cdr->record_signature != CentralDirectoryRecord::kSignature) { ALOGW("Zip: missed a central dir sig (at %" PRIu16 ")", i); - goto bail; + return -1; } if (ptr + sizeof(CentralDirectoryRecord) > cd_end) { ALOGW("Zip: ran off the end (at %" PRIu16 ")", i); - goto bail; + return -1; } const off64_t local_header_offset = cdr->local_file_header_offset; if (local_header_offset >= archive->directory_offset) { - ALOGW("Zip: bad LFH offset %" PRId64 " at entry %" PRIu16, (int64_t)local_header_offset, i); - goto bail; + ALOGW("Zip: bad LFH offset %" PRId64 " at entry %" PRIu16, + static_cast<int64_t>(local_header_offset), i); + return -1; } const uint16_t file_name_length = cdr->file_name_length; @@ -645,7 +629,7 @@ static int32_t ParseZipArchive(ZipArchive* archive) { /* check that file name is valid UTF-8 and doesn't contain NUL (U+0000) characters */ if (!IsValidEntryName(file_name, file_name_length)) { - goto bail; + return -1; } /* add the CDE filename to the hash table */ @@ -654,25 +638,21 @@ static int32_t ParseZipArchive(ZipArchive* archive) { entry_name.name_length = file_name_length; const int add_result = AddToHash(archive->hash_table, archive->hash_table_size, entry_name); - if (add_result) { + if (add_result != 0) { ALOGW("Zip: Error adding entry to hash table %d", add_result); - result = add_result; - goto bail; + return add_result; } ptr += sizeof(CentralDirectoryRecord) + file_name_length + extra_length + comment_length; if ((ptr - cd_ptr) > static_cast<int64_t>(cd_length)) { ALOGW("Zip: bad CD advance (%tu vs %zu) at entry %" PRIu16, ptr - cd_ptr, cd_length, i); - goto bail; + return -1; } } ALOGV("+++ zip good scan %" PRIu16 " entries", num_entries); - result = 0; - -bail: - return result; + return 0; } static int32_t OpenArchiveInternal(ZipArchive* archive, @@ -713,7 +693,7 @@ int32_t OpenArchive(const char* fileName, ZipArchiveHandle* handle) { * Close a ZipArchive, closing the file and freeing the contents. */ void CloseArchive(ZipArchiveHandle handle) { - ZipArchive* archive = (ZipArchive*) handle; + ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle); ALOGV("Closing archive %p", archive); delete archive; } @@ -774,8 +754,8 @@ static int32_t FindEntry(const ZipArchive* archive, const int ent, // the name that's in the hash table is a pointer to a location within // this mapped region. const uint8_t* base_ptr = reinterpret_cast<const uint8_t*>( - archive->directory_map->getDataPtr()); - if (ptr < base_ptr || ptr > base_ptr + archive->directory_map->getDataLength()) { + archive->directory_map.getDataPtr()); + if (ptr < base_ptr || ptr > base_ptr + archive->directory_map.getDataLength()) { ALOGW("Zip: Invalid entry pointer"); return kInvalidOffset; } @@ -810,7 +790,8 @@ static int32_t FindEntry(const ZipArchive* archive, const int ent, ssize_t actual = ReadAtOffset(archive->fd, lfh_buf, sizeof(lfh_buf), local_header_offset); if (actual != sizeof(lfh_buf)) { - ALOGW("Zip: failed reading lfh name from offset %" PRId64, (int64_t)local_header_offset); + ALOGW("Zip: failed reading lfh name from offset %" PRId64, + static_cast<int64_t>(local_header_offset)); return kIoError; } @@ -843,17 +824,17 @@ static int32_t FindEntry(const ZipArchive* archive, const int ent, // name in the central directory. if (lfh->file_name_length == nameLen) { const off64_t name_offset = local_header_offset + sizeof(LocalFileHeader); - if (name_offset + lfh->file_name_length >= cd_offset) { + if (name_offset + lfh->file_name_length > cd_offset) { ALOGW("Zip: Invalid declared length"); return kInvalidOffset; } - uint8_t* name_buf = (uint8_t*) malloc(nameLen); + uint8_t* name_buf = reinterpret_cast<uint8_t*>(malloc(nameLen)); ssize_t actual = ReadAtOffset(archive->fd, name_buf, nameLen, name_offset); if (actual != nameLen) { - ALOGW("Zip: failed reading lfh name from offset %" PRId64, (int64_t)name_offset); + ALOGW("Zip: failed reading lfh name from offset %" PRId64, static_cast<int64_t>(name_offset)); free(name_buf); return kIoError; } @@ -872,20 +853,21 @@ static int32_t FindEntry(const ZipArchive* archive, const int ent, const off64_t data_offset = local_header_offset + sizeof(LocalFileHeader) + lfh->file_name_length + lfh->extra_field_length; if (data_offset > cd_offset) { - ALOGW("Zip: bad data offset %" PRId64 " in zip", (int64_t)data_offset); + ALOGW("Zip: bad data offset %" PRId64 " in zip", static_cast<int64_t>(data_offset)); return kInvalidOffset; } - if ((off64_t)(data_offset + data->compressed_length) > cd_offset) { + if (static_cast<off64_t>(data_offset + data->compressed_length) > cd_offset) { ALOGW("Zip: bad compressed length in zip (%" PRId64 " + %" PRIu32 " > %" PRId64 ")", - (int64_t)data_offset, data->compressed_length, (int64_t)cd_offset); + static_cast<int64_t>(data_offset), data->compressed_length, static_cast<int64_t>(cd_offset)); return kInvalidOffset; } if (data->method == kCompressStored && - (off64_t)(data_offset + data->uncompressed_length) > cd_offset) { + static_cast<off64_t>(data_offset + data->uncompressed_length) > cd_offset) { ALOGW("Zip: bad uncompressed length in zip (%" PRId64 " + %" PRIu32 " > %" PRId64 ")", - (int64_t)data_offset, data->uncompressed_length, (int64_t)cd_offset); + static_cast<int64_t>(data_offset), data->uncompressed_length, + static_cast<int64_t>(cd_offset)); return kInvalidOffset; } @@ -917,7 +899,7 @@ struct IterationHandle { int32_t StartIteration(ZipArchiveHandle handle, void** cookie_ptr, const ZipEntryName* optional_prefix) { - ZipArchive* archive = (ZipArchive *) handle; + ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle); if (archive == NULL || archive->hash_table == NULL) { ALOGW("Zip: Invalid ZipArchiveHandle"); @@ -939,7 +921,7 @@ void EndIteration(void* cookie) { int32_t FindEntry(const ZipArchiveHandle handle, const ZipEntryName& entryName, ZipEntry* data) { - const ZipArchive* archive = (ZipArchive*) handle; + const ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle); if (entryName.name_length == 0) { ALOGW("Zip: Invalid filename %.*s", entryName.name_length, entryName.name); return kInvalidEntryName; @@ -957,7 +939,7 @@ int32_t FindEntry(const ZipArchiveHandle handle, const ZipEntryName& entryName, } int32_t Next(void* cookie, ZipEntry* data, ZipEntryName* name) { - IterationHandle* handle = (IterationHandle *) cookie; + IterationHandle* handle = reinterpret_cast<IterationHandle*>(cookie); if (handle == NULL) { return kInvalidHandle; } @@ -991,13 +973,20 @@ int32_t Next(void* cookie, ZipEntry* data, ZipEntryName* name) { return kIterationEnd; } +// This method is using libz macros with old-style-casts +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +static inline int zlib_inflateInit2(z_stream* stream, int window_bits) { + return inflateInit2(stream, window_bits); +} +#pragma GCC diagnostic pop + static int32_t InflateToFile(int fd, const ZipEntry* entry, uint8_t* begin, uint32_t length, uint64_t* crc_out) { - int32_t result = -1; - const uint32_t kBufSize = 32768; - uint8_t read_buf[kBufSize]; - uint8_t write_buf[kBufSize]; + const size_t kBufSize = 32768; + std::vector<uint8_t> read_buf(kBufSize); + std::vector<uint8_t> write_buf(kBufSize); z_stream zstream; int zerr; @@ -1010,7 +999,7 @@ static int32_t InflateToFile(int fd, const ZipEntry* entry, zstream.opaque = Z_NULL; zstream.next_in = NULL; zstream.avail_in = 0; - zstream.next_out = (Bytef*) write_buf; + zstream.next_out = &write_buf[0]; zstream.avail_out = kBufSize; zstream.data_type = Z_UNKNOWN; @@ -1018,7 +1007,7 @@ static int32_t InflateToFile(int fd, const ZipEntry* entry, * Use the undocumented "negative window bits" feature to tell zlib * that there's no zlib header waiting for it. */ - zerr = inflateInit2(&zstream, -MAX_WBITS); + zerr = zlib_inflateInit2(&zstream, -MAX_WBITS); if (zerr != Z_OK) { if (zerr == Z_VERSION_ERROR) { ALOGE("Installed zlib is not compatible with linked version (%s)", @@ -1030,6 +1019,12 @@ static int32_t InflateToFile(int fd, const ZipEntry* entry, return kZlibError; } + auto zstream_deleter = [](z_stream* stream) { + inflateEnd(stream); /* free up any allocated structures */ + }; + + std::unique_ptr<z_stream, decltype(zstream_deleter)> zstream_guard(&zstream, zstream_deleter); + const uint32_t uncompressed_length = entry->uncompressed_length; uint32_t compressed_length = entry->compressed_length; @@ -1038,16 +1033,15 @@ static int32_t InflateToFile(int fd, const ZipEntry* entry, /* read as much as we can */ if (zstream.avail_in == 0) { const ZD_TYPE getSize = (compressed_length > kBufSize) ? kBufSize : compressed_length; - const ZD_TYPE actual = TEMP_FAILURE_RETRY(read(fd, read_buf, getSize)); + const ZD_TYPE actual = TEMP_FAILURE_RETRY(read(fd, &read_buf[0], getSize)); if (actual != getSize) { ALOGW("Zip: inflate read failed (" ZD " vs " ZD ")", actual, getSize); - result = kIoError; - goto z_bail; + return kIoError; } compressed_length -= getSize; - zstream.next_in = read_buf; + zstream.next_in = &read_buf[0]; zstream.avail_in = getSize; } @@ -1057,22 +1051,21 @@ static int32_t InflateToFile(int fd, const ZipEntry* entry, ALOGW("Zip: inflate zerr=%d (nIn=%p aIn=%u nOut=%p aOut=%u)", zerr, zstream.next_in, zstream.avail_in, zstream.next_out, zstream.avail_out); - result = kZlibError; - goto z_bail; + return kZlibError; } /* write when we're full or when we're done */ if (zstream.avail_out == 0 || (zerr == Z_STREAM_END && zstream.avail_out != kBufSize)) { - const size_t write_size = zstream.next_out - write_buf; + const size_t write_size = zstream.next_out - &write_buf[0]; // The file might have declared a bogus length. if (write_size + write_count > length) { - goto z_bail; + return -1; } - memcpy(begin + write_count, write_buf, write_size); + memcpy(begin + write_count, &write_buf[0], write_size); write_count += write_size; - zstream.next_out = write_buf; + zstream.next_out = &write_buf[0]; zstream.avail_out = kBufSize; } } while (zerr == Z_OK); @@ -1085,26 +1078,20 @@ static int32_t InflateToFile(int fd, const ZipEntry* entry, if (zstream.total_out != uncompressed_length || compressed_length != 0) { ALOGW("Zip: size mismatch on inflated file (%lu vs %" PRIu32 ")", zstream.total_out, uncompressed_length); - result = kInconsistentInformation; - goto z_bail; + return kInconsistentInformation; } - result = 0; - -z_bail: - inflateEnd(&zstream); /* free up any allocated structures */ - - return result; + return 0; } int32_t ExtractToMemory(ZipArchiveHandle handle, ZipEntry* entry, uint8_t* begin, uint32_t size) { - ZipArchive* archive = (ZipArchive*) handle; + ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle); const uint16_t method = entry->method; off64_t data_offset = entry->offset; if (lseek64(archive->fd, data_offset, SEEK_SET) != data_offset) { - ALOGW("Zip: lseek to data at %" PRId64 " failed", (int64_t)data_offset); + ALOGW("Zip: lseek to data at %" PRId64 " failed", static_cast<int64_t>(data_offset)); return kIoError; } @@ -1148,7 +1135,7 @@ int32_t ExtractEntryToFile(ZipArchiveHandle handle, int result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset)); if (result == -1) { ALOGW("Zip: unable to truncate file to %" PRId64 ": %s", - (int64_t)(declared_length + current_offset), strerror(errno)); + static_cast<int64_t>(declared_length + current_offset), strerror(errno)); return kIoError; } @@ -1159,16 +1146,14 @@ int32_t ExtractEntryToFile(ZipArchiveHandle handle, return 0; } - android::FileMap* map = MapFileSegment(fd, current_offset, declared_length, - false, kTempMappingFileName); - if (map == NULL) { + android::FileMap map; + if (!map.create(kTempMappingFileName, fd, current_offset, declared_length, false)) { return kMmapFailed; } const int32_t error = ExtractToMemory(handle, entry, - reinterpret_cast<uint8_t*>(map->getDataPtr()), - map->getDataLength()); - delete map; + reinterpret_cast<uint8_t*>(map.getDataPtr()), + map.getDataLength()); return error; } @@ -1181,6 +1166,6 @@ const char* ErrorCodeString(int32_t error_code) { } int GetFileDescriptor(const ZipArchiveHandle handle) { - return ((ZipArchive*) handle)->fd; + return reinterpret_cast<ZipArchive*>(handle)->fd; } diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc index c8dafa9..64faa6d 100644 --- a/libziparchive/zip_archive_test.cc +++ b/libziparchive/zip_archive_test.cc @@ -171,6 +171,22 @@ TEST(ziparchive, FindEntry) { CloseArchive(handle); } +TEST(ziparchive, TestInvalidDeclaredLength) { + ZipArchiveHandle handle; + ASSERT_EQ(0, OpenArchiveWrapper("declaredlength.zip", &handle)); + + void* iteration_cookie; + ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, NULL)); + + ZipEntryName name; + ZipEntry data; + + ASSERT_EQ(Next(iteration_cookie, &data, &name), 0); + ASSERT_EQ(Next(iteration_cookie, &data, &name), 0); + + CloseArchive(handle); +} + TEST(ziparchive, ExtractToMemory) { ZipArchiveHandle handle; ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle)); diff --git a/libzipfile/zipfile.c b/libzipfile/zipfile.c index b903fcf..1032ecc 100644 --- a/libzipfile/zipfile.c +++ b/libzipfile/zipfile.c @@ -76,7 +76,7 @@ enum { }; static int -uninflate(unsigned char* out, int unlen, const unsigned char* in, int clen) +inflate_wrapper(unsigned char* out, int unlen, const unsigned char* in, int clen) { z_stream zstream; int err = 0; @@ -121,7 +121,7 @@ decompress_zipentry(zipentry_t e, void* buf, int bufsize) memcpy(buf, entry->data, entry->uncompressedSize); return 0; case DEFLATED: - return uninflate(buf, bufsize, entry->data, entry->compressedSize); + return inflate_wrapper(buf, bufsize, entry->data, entry->compressedSize); default: return -1; } diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp index cd5003e..be96fc4 100644 --- a/logcat/logcat.cpp +++ b/logcat/logcat.cpp @@ -38,14 +38,12 @@ struct log_device_t { struct logger *logger; struct logger_list *logger_list; bool printed; - char label; log_device_t* next; - log_device_t(const char* d, bool b, char l) { + log_device_t(const char* d, bool b) { device = d; binary = b; - label = l; next = NULL; printed = false; } @@ -61,9 +59,7 @@ static int g_maxRotatedLogs = DEFAULT_MAX_ROTATED_LOGS; // 0 means "unbounded" static int g_outFD = -1; static off_t g_outByteCount = 0; static int g_printBinary = 0; -static int g_devCount = 0; - -static EventTagMap* g_eventTagMap = NULL; +static int g_devCount = 0; // >1 means multiple static int openLogFile (const char *pathname) { @@ -133,8 +129,15 @@ static void processBuffer(log_device_t* dev, struct log_msg *buf) char binaryMsgBuf[1024]; if (dev->binary) { + static bool hasOpenedEventTagMap = false; + static EventTagMap *eventTagMap = NULL; + + if (!eventTagMap && !hasOpenedEventTagMap) { + eventTagMap = android_openEventTagMap(EVENT_TAG_MAP_FILE); + hasOpenedEventTagMap = true; + } err = android_log_processBinaryLogBuffer(&buf->entry_v1, &entry, - g_eventTagMap, + eventTagMap, binaryMsgBuf, sizeof(binaryMsgBuf)); //printf(">>> pri=%d len=%d msg='%s'\n", @@ -147,16 +150,6 @@ static void processBuffer(log_device_t* dev, struct log_msg *buf) } if (android_log_shouldPrintLine(g_logformat, entry.tag, entry.priority)) { - if (false && g_devCount > 1) { - binaryMsgBuf[0] = dev->label; - binaryMsgBuf[1] = ' '; - bytesWritten = write(g_outFD, binaryMsgBuf, 2); - if (bytesWritten < 0) { - perror("output error"); - exit(-1); - } - } - bytesWritten = android_log_printLogLine(g_logformat, g_outFD, &entry); if (bytesWritten < 0) { @@ -222,7 +215,7 @@ static void show_help(const char *cmd) fprintf(stderr, "options include:\n" " -s Set default filter to silent.\n" - " Like specifying filterspec '*:s'\n" + " Like specifying filterspec '*:S'\n" " -f <filename> Log to file. Default to stdout\n" " -r [<kbytes>] Rotate log every kbytes. (16 if unspecified). Requires -f\n" " -n <count> Sets max number of rotated logs to <count>, default 4\n" @@ -257,21 +250,19 @@ static void show_help(const char *cmd) fprintf(stderr,"\nfilterspecs are a series of \n" " <tag>[:priority]\n\n" "where <tag> is a log component tag (or * for all) and priority is:\n" - " V Verbose\n" - " D Debug\n" + " V Verbose (default for <tag>)\n" + " D Debug (default for '*')\n" " I Info\n" " W Warn\n" " E Error\n" " F Fatal\n" - " S Silent (supress all output)\n" - "\n'*' means '*:d' and <tag> by itself means <tag>:v\n" - "\nIf not specified on the commandline, filterspec is set from ANDROID_LOG_TAGS.\n" - "If no filterspec is found, filter defaults to '*:I'\n" - "\nIf not specified with -v, format is set from ANDROID_PRINTF_LOG\n" + " S Silent (suppress all output)\n" + "\n'*' by itself means '*:D' and <tag> by itself means <tag>:V.\n" + "If no '*' filterspec or -s on command line, all filter defaults to '*:V'.\n" + "eg: '*:S <tag>' prints only <tag>, '<tag>:S' suppresses all <tag> log messages.\n" + "\nIf not specified on the command line, filterspec is set from ANDROID_LOG_TAGS.\n" + "\nIf not specified with -v on command line, format is set from ANDROID_PRINTF_LOG\n" "or defaults to \"threadtime\"\n\n"); - - - } @@ -331,7 +322,6 @@ int main(int argc, char **argv) const char *forceFilters = NULL; log_device_t* devices = NULL; log_device_t* dev; - bool needBinary = false; bool printDividers = false; struct logger_list *logger_list; unsigned int tail_lines = 0; @@ -469,7 +459,6 @@ int main(int argc, char **argv) devices = dev = NULL; android::g_devCount = 0; - needBinary = false; for(int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) { const char *name = android_log_id_to_name((log_id_t)i); log_id_t log_id = android_name_to_log_id(name); @@ -479,7 +468,7 @@ int main(int argc, char **argv) } bool binary = strcmp(name, "events") == 0; - log_device_t* d = new log_device_t(name, binary, *name); + log_device_t* d = new log_device_t(name, binary); if (dev) { dev->next = d; @@ -488,26 +477,20 @@ int main(int argc, char **argv) devices = dev = d; } android::g_devCount++; - if (binary) { - needBinary = true; - } } break; } bool binary = strcmp(optarg, "events") == 0; - if (binary) { - needBinary = true; - } if (devices) { dev = devices; while (dev->next) { dev = dev->next; } - dev->next = new log_device_t(optarg, binary, optarg[0]); + dev->next = new log_device_t(optarg, binary); } else { - devices = new log_device_t(optarg, binary, optarg[0]); + devices = new log_device_t(optarg, binary); } android::g_devCount++; } @@ -641,14 +624,14 @@ int main(int argc, char **argv) } if (!devices) { - dev = devices = new log_device_t("main", false, 'm'); + dev = devices = new log_device_t("main", false); android::g_devCount = 1; if (android_name_to_log_id("system") == LOG_ID_SYSTEM) { - dev = dev->next = new log_device_t("system", false, 's'); + dev = dev->next = new log_device_t("system", false); android::g_devCount++; } if (android_name_to_log_id("crash") == LOG_ID_CRASH) { - dev = dev->next = new log_device_t("crash", false, 'c'); + dev = dev->next = new log_device_t("crash", false); android::g_devCount++; } } @@ -848,17 +831,15 @@ int main(int argc, char **argv) //LOG_EVENT_LONG(11, 0x1122334455667788LL); //LOG_EVENT_STRING(0, "whassup, doc?"); - if (needBinary) - android::g_eventTagMap = android_openEventTagMap(EVENT_TAG_MAP_FILE); - dev = NULL; + log_device_t unexpected("unexpected", false); while (1) { struct log_msg log_msg; log_device_t* d; int ret = android_logger_list_read(logger_list, &log_msg); if (ret == 0) { - fprintf(stderr, "read: Unexpected EOF!\n"); + fprintf(stderr, "read: unexpected EOF!\n"); exit(EXIT_FAILURE); } @@ -868,7 +849,7 @@ int main(int argc, char **argv) } if (ret == -EIO) { - fprintf(stderr, "read: Unexpected EOF!\n"); + fprintf(stderr, "read: unexpected EOF!\n"); exit(EXIT_FAILURE); } if (ret == -EINVAL) { @@ -885,8 +866,9 @@ int main(int argc, char **argv) } } if (!d) { - fprintf(stderr, "read: Unexpected log ID!\n"); - exit(EXIT_FAILURE); + android::g_devCount = 2; // set to Multiple + d = &unexpected; + d->binary = log_msg.id() == LOG_ID_EVENTS; } if (dev != d) { diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp index b358485..de2db67 100644 --- a/logcat/tests/logcat_test.cpp +++ b/logcat/tests/logcat_test.cpp @@ -505,12 +505,14 @@ TEST(logcat, logrotate) { while (fgets(buffer, sizeof(buffer), fp)) { static const char match_1[] = "4 log.txt"; static const char match_2[] = "8 log.txt"; - static const char match_3[] = "16 log.txt"; + static const char match_3[] = "12 log.txt"; + static const char match_4[] = "16 log.txt"; static const char total[] = "total "; if (!strncmp(buffer, match_1, sizeof(match_1) - 1) || !strncmp(buffer, match_2, sizeof(match_2) - 1) - || !strncmp(buffer, match_3, sizeof(match_3) - 1)) { + || !strncmp(buffer, match_3, sizeof(match_3) - 1) + || !strncmp(buffer, match_4, sizeof(match_4) - 1)) { ++count; } else if (strncmp(buffer, total, sizeof(total) - 1)) { fprintf(stderr, "WARNING: Parse error: %s", buffer); diff --git a/logd/Android.mk b/logd/Android.mk index 188511f..127a66b 100644 --- a/logd/Android.mk +++ b/logd/Android.mk @@ -26,7 +26,16 @@ LOCAL_SHARED_LIBRARIES := \ libcutils \ libutils -LOCAL_CFLAGS := -Werror $(shell sed -n 's/^\([0-9]*\)[ \t]*auditd[ \t].*/-DAUDITD_LOG_TAG=\1/p' $(LOCAL_PATH)/event.logtags) +# This is what we want to do: +# event_logtags = $(shell \ +# sed -n \ +# "s/^\([0-9]*\)[ \t]*$1[ \t].*/-D`echo $1 | tr a-z A-Z`_LOG_TAG=\1/p" \ +# $(LOCAL_PATH)/$2/event.logtags) +# event_flag := $(call event_logtags,auditd) +# so make sure we do not regret hard-coding it as follows: +event_flag := -DAUDITD_LOG_TAG=1003 + +LOCAL_CFLAGS := -Werror $(event_flag) include $(BUILD_EXECUTABLE) diff --git a/logd/CommandListener.cpp b/logd/CommandListener.cpp index d7088b4..561ea3e 100644 --- a/logd/CommandListener.cpp +++ b/logd/CommandListener.cpp @@ -44,6 +44,7 @@ CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/, registerCmd(new GetStatisticsCmd(buf)); registerCmd(new SetPruneListCmd(buf)); registerCmd(new GetPruneListCmd(buf)); + registerCmd(new ReinitCmd()); } CommandListener::ShutdownCmd::ShutdownCmd(LogBuffer *buf, LogReader *reader, @@ -296,6 +297,21 @@ int CommandListener::SetPruneListCmd::runCommand(SocketClient *cli, return 0; } +CommandListener::ReinitCmd::ReinitCmd() + : LogCommand("reinit") +{ } + +int CommandListener::ReinitCmd::runCommand(SocketClient *cli, + int /*argc*/, char ** /*argv*/) { + setname(); + + reinit_signal_handler(SIGHUP); + + cli->sendMsg("success"); + + return 0; +} + int CommandListener::getLogSocket() { static const char socketName[] = "logd"; int sock = android_get_control_socket(socketName); diff --git a/logd/CommandListener.h b/logd/CommandListener.h index cd1c306..83e06b4 100644 --- a/logd/CommandListener.h +++ b/logd/CommandListener.h @@ -23,6 +23,9 @@ #include "LogReader.h" #include "LogListener.h" +// See main.cpp for implementation +void reinit_signal_handler(int /*signal*/); + class CommandListener : public FrameworkListener { LogBuffer &mBuf; @@ -60,6 +63,14 @@ private: LogBufferCmd(GetStatistics) LogBufferCmd(GetPruneList) LogBufferCmd(SetPruneList) + + class ReinitCmd : public LogCommand { + public: + ReinitCmd(); + virtual ~ReinitCmd() {} + int runCommand(SocketClient *c, int argc, char ** argv); + }; + }; #endif diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp index 3be07c0..26a1861 100644 --- a/logd/FlushCommand.cpp +++ b/logd/FlushCommand.cpp @@ -27,7 +27,7 @@ FlushCommand::FlushCommand(LogReader &reader, unsigned long tail, unsigned int logMask, pid_t pid, - log_time start) + uint64_t start) : mReader(reader) , mNonBlock(nonBlock) , mTail(tail) diff --git a/logd/FlushCommand.h b/logd/FlushCommand.h index f34c06a..61c6858 100644 --- a/logd/FlushCommand.h +++ b/logd/FlushCommand.h @@ -31,7 +31,7 @@ class FlushCommand : public SocketClientCommand { unsigned long mTail; unsigned int mLogMask; pid_t mPid; - log_time mStart; + uint64_t mStart; public: FlushCommand(LogReader &mReader, @@ -39,7 +39,7 @@ public: unsigned long tail = -1, unsigned int logMask = -1, pid_t pid = 0, - log_time start = LogTimeEntry::EPOCH); + uint64_t start = 1); virtual void runSocketCommand(SocketClient *client); static bool hasReadLogs(SocketClient *client); diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp index c7c0249..6b3e637 100644 --- a/logd/LogAudit.cpp +++ b/logd/LogAudit.cpp @@ -15,6 +15,7 @@ */ #include <ctype.h> +#include <endian.h> #include <errno.h> #include <limits.h> #include <stdarg.h> @@ -23,13 +24,15 @@ #include <sys/uio.h> #include <syslog.h> +#include <private/android_logger.h> + #include "libaudit.h" #include "LogAudit.h" -#define KMSG_PRIORITY(PRI) \ - '<', \ - '0' + (LOG_AUTH | (PRI)) / 10, \ - '0' + (LOG_AUTH | (PRI)) % 10, \ +#define KMSG_PRIORITY(PRI) \ + '<', \ + '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) / 10, \ + '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) % 10, \ '>' LogAudit::LogAudit(LogBuffer *buf, LogReader *reader, int fdDmesg) @@ -138,29 +141,23 @@ int LogAudit::logPrint(const char *fmt, ...) { // log to events size_t l = strlen(str); - size_t n = l + sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t); + size_t n = l + sizeof(android_log_event_string_t); bool notify = false; - char *newstr = reinterpret_cast<char *>(malloc(n)); - if (!newstr) { + android_log_event_string_t *event = static_cast<android_log_event_string_t *>(malloc(n)); + if (!event) { rc = -ENOMEM; } else { - cp = newstr; - *cp++ = AUDITD_LOG_TAG & 0xFF; - *cp++ = (AUDITD_LOG_TAG >> 8) & 0xFF; - *cp++ = (AUDITD_LOG_TAG >> 16) & 0xFF; - *cp++ = (AUDITD_LOG_TAG >> 24) & 0xFF; - *cp++ = EVENT_TYPE_STRING; - *cp++ = l & 0xFF; - *cp++ = (l >> 8) & 0xFF; - *cp++ = (l >> 16) & 0xFF; - *cp++ = (l >> 24) & 0xFF; - memcpy(cp, str, l); - - logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid, newstr, + event->header.tag = htole32(AUDITD_LOG_TAG); + event->payload.type = EVENT_TYPE_STRING; + event->payload.length = htole32(l); + memcpy(event->payload.data, str, l); + + logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid, + reinterpret_cast<char *>(event), (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX); - free(newstr); + free(event); notify = true; } @@ -190,7 +187,7 @@ int LogAudit::logPrint(const char *fmt, ...) { } n = (estr - str) + strlen(ecomm) + l + 2; - newstr = reinterpret_cast<char *>(malloc(n)); + char *newstr = static_cast<char *>(malloc(n)); if (!newstr) { rc = -ENOMEM; } else { diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp index 3d0b38f..2693583 100644 --- a/logd/LogBuffer.cpp +++ b/logd/LogBuffer.cpp @@ -92,11 +92,7 @@ static unsigned long property_get_size(const char *key) { return value; } -LogBuffer::LogBuffer(LastLogTimes *times) - : dgramQlenStatistics(false) - , mTimes(*times) { - pthread_mutex_init(&mLogElementsLock, NULL); - +void LogBuffer::init() { static const char global_tuneable[] = "persist.logd.size"; // Settings App static const char global_default[] = "ro.logd.size"; // BoardConfig.mk @@ -132,6 +128,13 @@ LogBuffer::LogBuffer(LastLogTimes *times) } } +LogBuffer::LogBuffer(LastLogTimes *times) + : mTimes(*times) { + pthread_mutex_init(&mLogElementsLock, NULL); + + init(); +} + void LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid, const char *msg, unsigned short len) { @@ -150,23 +153,6 @@ void LogBuffer::log(log_id_t log_id, log_time realtime, while (last != mLogElements.begin()) { --it; if ((*it)->getRealTime() <= realtime) { - // halves the peak performance, use with caution - if (dgramQlenStatistics) { - LogBufferElementCollection::iterator ib = it; - unsigned short buckets, num = 1; - for (unsigned short i = 0; (buckets = stats.dgramQlen(i)); ++i) { - buckets -= num; - num += buckets; - while (buckets && (--ib != mLogElements.begin())) { - --buckets; - } - if (buckets) { - break; - } - stats.recordDiff( - elem->getRealTime() - (*ib)->getRealTime(), i); - } - } break; } last = it; @@ -175,7 +161,7 @@ void LogBuffer::log(log_id_t log_id, log_time realtime, if (last == mLogElements.end()) { mLogElements.push_back(elem); } else { - log_time end = log_time::EPOCH; + uint64_t end = 1; bool end_set = false; bool end_always = false; @@ -198,7 +184,7 @@ void LogBuffer::log(log_id_t log_id, log_time realtime, } if (end_always - || (end_set && (end >= (*last)->getMonotonicTime()))) { + || (end_set && (end >= (*last)->getSequence()))) { mLogElements.push_back(elem); } else { mLogElements.insert(last,elem); @@ -255,7 +241,7 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) { for(it = mLogElements.begin(); it != mLogElements.end();) { LogBufferElement *e = *it; - if (oldest && (oldest->mStart <= e->getMonotonicTime())) { + if (oldest && (oldest->mStart <= e->getSequence())) { break; } @@ -307,7 +293,7 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) { for(it = mLogElements.begin(); it != mLogElements.end();) { LogBufferElement *e = *it; - if (oldest && (oldest->mStart <= e->getMonotonicTime())) { + if (oldest && (oldest->mStart <= e->getSequence())) { break; } @@ -348,7 +334,7 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) { while((pruneRows > 0) && (it != mLogElements.end())) { LogBufferElement *e = *it; if (e->getLogId() == id) { - if (oldest && (oldest->mStart <= e->getMonotonicTime())) { + if (oldest && (oldest->mStart <= e->getSequence())) { if (!whitelist) { if (stats.sizes(id) > (2 * log_buffer_size(id))) { // kick a misbehaving log reader client off the island @@ -380,7 +366,7 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) { while((it != mLogElements.end()) && (pruneRows > 0)) { LogBufferElement *e = *it; if (e->getLogId() == id) { - if (oldest && (oldest->mStart <= e->getMonotonicTime())) { + if (oldest && (oldest->mStart <= e->getSequence())) { if (stats.sizes(id) > (2 * log_buffer_size(id))) { // kick a misbehaving log reader client off the island oldest->release_Locked(); @@ -437,16 +423,16 @@ unsigned long LogBuffer::getSize(log_id_t id) { return retval; } -log_time LogBuffer::flushTo( - SocketClient *reader, const log_time start, bool privileged, - bool (*filter)(const LogBufferElement *element, void *arg), void *arg) { +uint64_t LogBuffer::flushTo( + SocketClient *reader, const uint64_t start, bool privileged, + int (*filter)(const LogBufferElement *element, void *arg), void *arg) { LogBufferElementCollection::iterator it; - log_time max = start; + uint64_t max = start; uid_t uid = reader->getUid(); pthread_mutex_lock(&mLogElementsLock); - if (start == LogTimeEntry::EPOCH) { + if (start <= 1) { // client wants to start from the beginning it = mLogElements.begin(); } else { @@ -455,7 +441,7 @@ log_time LogBuffer::flushTo( for (it = mLogElements.end(); it != mLogElements.begin(); /* do nothing */) { --it; LogBufferElement *element = *it; - if (element->getMonotonicTime() <= start) { + if (element->getSequence() <= start) { it++; break; } @@ -469,13 +455,19 @@ log_time LogBuffer::flushTo( continue; } - if (element->getMonotonicTime() <= start) { + if (element->getSequence() <= start) { continue; } // NB: calling out to another object with mLogElementsLock held (safe) - if (filter && !(*filter)(element, arg)) { - continue; + if (filter) { + int ret = (*filter)(element, arg); + if (ret == false) { + continue; + } + if (ret != true) { + break; + } } pthread_mutex_unlock(&mLogElementsLock); @@ -495,7 +487,7 @@ log_time LogBuffer::flushTo( } void LogBuffer::formatStatistics(char **strp, uid_t uid, unsigned int logMask) { - log_time oldest(CLOCK_MONOTONIC); + uint64_t oldest = UINT64_MAX; pthread_mutex_lock(&mLogElementsLock); @@ -505,7 +497,7 @@ void LogBuffer::formatStatistics(char **strp, uid_t uid, unsigned int logMask) { LogBufferElement *element = *it; if ((logMask & (1 << element->getLogId()))) { - oldest = element->getMonotonicTime(); + oldest = element->getSequence(); break; } } diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h index 879baea..13e6aa8 100644 --- a/logd/LogBuffer.h +++ b/logd/LogBuffer.h @@ -37,7 +37,6 @@ class LogBuffer { pthread_mutex_t mLogElementsLock; LogStatistics stats; - bool dgramQlenStatistics; PruneList mPrune; @@ -47,13 +46,14 @@ public: LastLogTimes &mTimes; LogBuffer(LastLogTimes *times); + void init(); void log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid, const char *msg, unsigned short len); - log_time flushTo(SocketClient *writer, const log_time start, + uint64_t flushTo(SocketClient *writer, const uint64_t start, bool privileged, - bool (*filter)(const LogBufferElement *element, void *arg) = NULL, + int (*filter)(const LogBufferElement *element, void *arg) = NULL, void *arg = NULL); void clear(log_id_t id, uid_t uid = AID_ROOT); @@ -63,11 +63,6 @@ public: // *strp uses malloc, use free to release. void formatStatistics(char **strp, uid_t uid, unsigned int logMask); - void enableDgramQlenStatistics() { - stats.enableDgramQlenStatistics(); - dgramQlenStatistics = true; - } - void enableStatistics() { stats.enableStatistics(); } diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp index d959ceb..5e780b5 100644 --- a/logd/LogBufferElement.cpp +++ b/logd/LogBufferElement.cpp @@ -24,7 +24,8 @@ #include "LogBufferElement.h" #include "LogReader.h" -const log_time LogBufferElement::FLUSH_ERROR((uint32_t)0, (uint32_t)0); +const uint64_t LogBufferElement::FLUSH_ERROR(0); +atomic_int_fast64_t LogBufferElement::sequence; LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid, @@ -34,7 +35,7 @@ LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime, , mPid(pid) , mTid(tid) , mMsgLen(len) - , mMonotonicTime(CLOCK_MONOTONIC) + , mSequence(sequence.fetch_add(1, memory_order_relaxed)) , mRealTime(realtime) { mMsg = new char[len]; memcpy(mMsg, msg, len); @@ -44,7 +45,7 @@ LogBufferElement::~LogBufferElement() { delete [] mMsg; } -log_time LogBufferElement::flushTo(SocketClient *reader) { +uint64_t LogBufferElement::flushTo(SocketClient *reader) { struct logger_entry_v3 entry; memset(&entry, 0, sizeof(struct logger_entry_v3)); entry.hdr_size = sizeof(struct logger_entry_v3); @@ -64,5 +65,5 @@ log_time LogBufferElement::flushTo(SocketClient *reader) { return FLUSH_ERROR; } - return mMonotonicTime; + return mSequence; } diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h index fdca973..25f1450 100644 --- a/logd/LogBufferElement.h +++ b/logd/LogBufferElement.h @@ -18,6 +18,7 @@ #define _LOGD_LOG_BUFFER_ELEMENT_H__ #include <sys/types.h> +#include <stdatomic.h> #include <sysutils/SocketClient.h> #include <log/log.h> #include <log/log_read.h> @@ -29,8 +30,9 @@ class LogBufferElement { const pid_t mTid; char *mMsg; const unsigned short mMsgLen; - const log_time mMonotonicTime; + const uint64_t mSequence; const log_time mRealTime; + static atomic_int_fast64_t sequence; public: LogBufferElement(log_id_t log_id, log_time realtime, @@ -43,11 +45,12 @@ public: pid_t getPid(void) const { return mPid; } pid_t getTid(void) const { return mTid; } unsigned short getMsgLen() const { return mMsgLen; } - log_time getMonotonicTime(void) const { return mMonotonicTime; } + uint64_t getSequence(void) const { return mSequence; } + static uint64_t getCurrentSequence(void) { return sequence.load(memory_order_relaxed); } log_time getRealTime(void) const { return mRealTime; } - static const log_time FLUSH_ERROR; - log_time flushTo(SocketClient *writer); + static const uint64_t FLUSH_ERROR; + uint64_t flushTo(SocketClient *writer); }; #endif diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp index 26df087..f7df275 100644 --- a/logd/LogReader.cpp +++ b/logd/LogReader.cpp @@ -100,50 +100,51 @@ bool LogReader::onDataAvailable(SocketClient *cli) { nonBlock = true; } - // Convert realtime to monotonic time - if (start == log_time::EPOCH) { - start = LogTimeEntry::EPOCH; - } else { + uint64_t sequence = 1; + // Convert realtime to sequence number + if (start != log_time::EPOCH) { class LogFindStart { const pid_t mPid; const unsigned mLogMask; bool startTimeSet; log_time &start; - log_time last; + uint64_t &sequence; + uint64_t last; public: - LogFindStart(unsigned logMask, pid_t pid, log_time &start) + LogFindStart(unsigned logMask, pid_t pid, log_time &start, uint64_t &sequence) : mPid(pid) , mLogMask(logMask) , startTimeSet(false) , start(start) - , last(LogTimeEntry::EPOCH) + , sequence(sequence) + , last(sequence) { } - static bool callback(const LogBufferElement *element, void *obj) { + static int callback(const LogBufferElement *element, void *obj) { LogFindStart *me = reinterpret_cast<LogFindStart *>(obj); - if (!me->startTimeSet - && (!me->mPid || (me->mPid == element->getPid())) + if ((!me->mPid || (me->mPid == element->getPid())) && (me->mLogMask & (1 << element->getLogId()))) { if (me->start == element->getRealTime()) { - me->start = element->getMonotonicTime(); + me->sequence = element->getSequence(); me->startTimeSet = true; + return -1; } else { if (me->start < element->getRealTime()) { - me->start = me->last; + me->sequence = me->last; me->startTimeSet = true; + return -1; } - me->last = element->getMonotonicTime(); + me->last = element->getSequence(); } } return false; } bool found() { return startTimeSet; } - } logFindStart(logMask, pid, start); + } logFindStart(logMask, pid, start, sequence); - logbuf().flushTo(cli, LogTimeEntry::EPOCH, - FlushCommand::hasReadLogs(cli), + logbuf().flushTo(cli, sequence, FlushCommand::hasReadLogs(cli), logFindStart.callback, &logFindStart); if (!logFindStart.found()) { @@ -151,12 +152,11 @@ bool LogReader::onDataAvailable(SocketClient *cli) { doSocketDelete(cli); return false; } - log_time now(CLOCK_MONOTONIC); - start = now; + sequence = LogBufferElement::getCurrentSequence(); } } - FlushCommand command(*this, nonBlock, tail, logMask, pid, start); + FlushCommand command(*this, nonBlock, tail, logMask, pid, sequence); command.runSocketCommand(cli); return true; } diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp index 53036e6..5a70689 100644 --- a/logd/LogStatistics.cpp +++ b/logd/LogStatistics.cpp @@ -395,71 +395,11 @@ size_t LidStatistics::elementsTotal(uid_t uid, pid_t pid) { LogStatistics::LogStatistics() : mStatistics(false) - , dgramQlenStatistics(false) , start(CLOCK_MONOTONIC) { log_id_for_each(i) { mSizes[i] = 0; mElements[i] = 0; } - - for(unsigned short bucket = 0; dgramQlen(bucket); ++bucket) { - mMinimum[bucket].tv_sec = mMinimum[bucket].tv_sec_max; - mMinimum[bucket].tv_nsec = mMinimum[bucket].tv_nsec_max; - } -} - -// Each bucket below represents a dgramQlen of log messages. By -// finding the minimum period of time from start to finish -// of each dgramQlen, we can get a performance expectation for -// the user space logger. The net result is that the period -// of time divided by the dgramQlen will give us the average time -// between log messages; at the point where the average time -// is greater than the throughput capability of the logger -// we will not longer require the benefits of the FIFO formed -// by max_dgram_qlen. We will also expect to see a very visible -// knee in the average time between log messages at this point, -// so we do not necessarily have to compare the rate against the -// measured performance (BM_log_maximum_retry) of the logger. -// -// for example (reformatted): -// -// Minimum time between log events per dgramQlen: -// 1 2 3 5 10 20 30 50 100 200 300 400 500 600 -// 5u2 12u 13u 15u 16u 27u 30u 36u 407u 3m1 3m3 3m9 3m9 5m5 -// -// demonstrates a clear knee rising at 100, so this means that for this -// case max_dgram_qlen = 100 would be more than sufficient to handle the -// worst that the system could stuff into the logger. The -// BM_log_maximum_retry performance (derated by the log collection) on the -// same system was 33.2us so we would almost be fine with max_dgram_qlen = 50. -// BM_log_maxumum_retry with statistics off is roughly 20us, so -// max_dgram_qlen = 20 would work. We will be more than willing to have -// a large engineering margin so the rule of thumb that lead us to 100 is -// fine. -// -// bucket dgramQlen are tuned for /proc/sys/net/unix/max_dgram_qlen = 300 -const unsigned short LogStatistics::mBuckets[] = { - 1, 2, 3, 5, 10, 20, 30, 50, 100, 200, 300, 400, 500, 600 -}; - -unsigned short LogStatistics::dgramQlen(unsigned short bucket) { - if (bucket >= sizeof(mBuckets) / sizeof(mBuckets[0])) { - return 0; - } - return mBuckets[bucket]; -} - -unsigned long long LogStatistics::minimum(unsigned short bucket) { - if (mMinimum[bucket].tv_sec == mMinimum[bucket].tv_sec_max) { - return 0; - } - return mMinimum[bucket].nsec(); -} - -void LogStatistics::recordDiff(log_time diff, unsigned short bucket) { - if ((diff.tv_sec || diff.tv_nsec) && (mMinimum[bucket] > diff)) { - mMinimum[bucket] = diff; - } } void LogStatistics::add(unsigned short size, @@ -709,55 +649,6 @@ void LogStatistics::format(char **buf, pids.clear(); } - if (dgramQlenStatistics) { - const unsigned short spaces_time = 6; - const unsigned long long max_seconds = 100000; - spaces = 0; - string.append("\n\nMinimum time between log events per max_dgram_qlen:\n"); - for(unsigned short i = 0; dgramQlen(i); ++i) { - oldLength = string.length(); - if (spaces < 0) { - spaces = 0; - } - string.appendFormat("%*s%u", spaces, "", dgramQlen(i)); - spaces += spaces_time + oldLength - string.length(); - } - string.append("\n"); - spaces = 0; - unsigned short n; - for(unsigned short i = 0; (n = dgramQlen(i)); ++i) { - unsigned long long duration = minimum(i); - if (duration) { - duration /= n; - if (duration >= (NS_PER_SEC * max_seconds)) { - duration = NS_PER_SEC * (max_seconds - 1); - } - oldLength = string.length(); - if (spaces < 0) { - spaces = 0; - } - string.appendFormat("%*s", spaces, ""); - if (duration >= (NS_PER_SEC * 10)) { - string.appendFormat("%llu", - (duration + (NS_PER_SEC / 2)) - / NS_PER_SEC); - } else if (duration >= (NS_PER_SEC / (1000 / 10))) { - string.appendFormat("%llum", - (duration + (NS_PER_SEC / 2 / 1000)) - / (NS_PER_SEC / 1000)); - } else if (duration >= (NS_PER_SEC / (1000000 / 10))) { - string.appendFormat("%lluu", - (duration + (NS_PER_SEC / 2 / 1000000)) - / (NS_PER_SEC / 1000000)); - } else { - string.appendFormat("%llun", duration); - } - spaces -= string.length() - oldLength; - } - spaces += spaces_time; - } - } - log_id_for_each(i) { if (!(logMask & (1 << i))) { continue; diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h index f6c4329..f892cd0 100644 --- a/logd/LogStatistics.h +++ b/logd/LogStatistics.h @@ -145,7 +145,6 @@ class LogStatistics { size_t mElements[LOG_ID_MAX]; bool mStatistics; - bool dgramQlenStatistics; static const unsigned short mBuckets[14]; log_time mMinimum[sizeof(mBuckets) / sizeof(mBuckets[0])]; @@ -157,11 +156,7 @@ public: LidStatistics &id(log_id_t log_id) { return LogIds[log_id]; } - void enableDgramQlenStatistics() { dgramQlenStatistics = true; } void enableStatistics() { mStatistics = true; } - static unsigned short dgramQlen(unsigned short bucket); - unsigned long long minimum(unsigned short bucket); - void recordDiff(log_time diff, unsigned short bucket); void add(unsigned short size, log_id_t log_id, uid_t uid, pid_t pid); void subtract(unsigned short size, log_id_t log_id, uid_t uid, pid_t pid); diff --git a/logd/LogTimes.cpp b/logd/LogTimes.cpp index 5f9db8d..1b60b7e 100644 --- a/logd/LogTimes.cpp +++ b/logd/LogTimes.cpp @@ -23,12 +23,10 @@ pthread_mutex_t LogTimeEntry::timesLock = PTHREAD_MUTEX_INITIALIZER; -const struct timespec LogTimeEntry::EPOCH = { 0, 1 }; - LogTimeEntry::LogTimeEntry(LogReader &reader, SocketClient *client, bool nonBlock, unsigned long tail, unsigned int logMask, pid_t pid, - log_time start) + uint64_t start) : mRefCount(1) , mRelease(false) , mError(false) @@ -42,7 +40,7 @@ LogTimeEntry::LogTimeEntry(LogReader &reader, SocketClient *client, , mClient(client) , mStart(start) , mNonBlock(nonBlock) - , mEnd(CLOCK_MONOTONIC) + , mEnd(LogBufferElement::getCurrentSequence()) { pthread_cond_init(&threadTriggeredCondition, NULL); cleanSkip_Locked(); @@ -129,7 +127,7 @@ void *LogTimeEntry::threadStart(void *obj) { lock(); while (me->threadRunning && !me->isError_Locked()) { - log_time start = me->mStart; + uint64_t start = me->mStart; unlock(); @@ -161,13 +159,13 @@ void *LogTimeEntry::threadStart(void *obj) { } // A first pass to count the number of elements -bool LogTimeEntry::FilterFirstPass(const LogBufferElement *element, void *obj) { +int LogTimeEntry::FilterFirstPass(const LogBufferElement *element, void *obj) { LogTimeEntry *me = reinterpret_cast<LogTimeEntry *>(obj); LogTimeEntry::lock(); if (me->mCount == 0) { - me->mStart = element->getMonotonicTime(); + me->mStart = element->getSequence(); } if ((!me->mPid || (me->mPid == element->getPid())) @@ -181,12 +179,12 @@ bool LogTimeEntry::FilterFirstPass(const LogBufferElement *element, void *obj) { } // A second pass to send the selected elements -bool LogTimeEntry::FilterSecondPass(const LogBufferElement *element, void *obj) { +int LogTimeEntry::FilterSecondPass(const LogBufferElement *element, void *obj) { LogTimeEntry *me = reinterpret_cast<LogTimeEntry *>(obj); LogTimeEntry::lock(); - me->mStart = element->getMonotonicTime(); + me->mStart = element->getSequence(); if (me->skipAhead[element->getLogId()]) { me->skipAhead[element->getLogId()]--; @@ -195,7 +193,7 @@ bool LogTimeEntry::FilterSecondPass(const LogBufferElement *element, void *obj) // Truncate to close race between first and second pass if (me->mNonBlock && me->mTail && (me->mIndex >= me->mCount)) { - goto skip; + goto stop; } if (!me->isWatching(element->getLogId())) { @@ -207,7 +205,7 @@ bool LogTimeEntry::FilterSecondPass(const LogBufferElement *element, void *obj) } if (me->isError_Locked()) { - goto skip; + goto stop; } if (!me->mTail) { @@ -234,6 +232,10 @@ ok: skip: LogTimeEntry::unlock(); return false; + +stop: + LogTimeEntry::unlock(); + return -1; } void LogTimeEntry::cleanSkip_Locked(void) { diff --git a/logd/LogTimes.h b/logd/LogTimes.h index 81aedfb..ae2f92b 100644 --- a/logd/LogTimes.h +++ b/logd/LogTimes.h @@ -47,13 +47,12 @@ class LogTimeEntry { public: LogTimeEntry(LogReader &reader, SocketClient *client, bool nonBlock, unsigned long tail, unsigned int logMask, pid_t pid, - log_time start); + uint64_t start); SocketClient *mClient; - static const struct timespec EPOCH; - log_time mStart; + uint64_t mStart; const bool mNonBlock; - const log_time mEnd; // only relevant if mNonBlock + const uint64_t mEnd; // only relevant if mNonBlock // Protect List manipulations static void lock(void) { pthread_mutex_lock(×Lock); } @@ -103,8 +102,8 @@ public: } bool isWatching(log_id_t id) { return (mLogMask & (1<<id)) != 0; } // flushTo filter callbacks - static bool FilterFirstPass(const LogBufferElement *element, void *me); - static bool FilterSecondPass(const LogBufferElement *element, void *me); + static int FilterFirstPass(const LogBufferElement *element, void *me); + static int FilterSecondPass(const LogBufferElement *element, void *me); }; typedef android::List<LogTimeEntry *> LastLogTimes; diff --git a/logd/README.property b/logd/README.property index b7fcece..60542b2 100644 --- a/logd/README.property +++ b/logd/README.property @@ -7,12 +7,6 @@ logd.auditd.dmesg bool true selinux audit messages duplicated and logd.statistics bool depends Enable logcat -S statistics. ro.config.low_ram bool false if true, logd.statistics default false ro.build.type string if user, logd.statistics default false -logd.statistics.dgram_qlen bool false Record dgram_qlen statistics. This - represents a performance impact and - is used to determine the platform's - minimum domain socket network FIFO - size (see source for details) based - on typical load (logcat -S to view) persist.logd.size number 256K default size of the buffer for all log ids at initial startup, at runtime use: logcat -b all -G <value> diff --git a/logd/main.cpp b/logd/main.cpp index 7a1ae54..a61beff 100644 --- a/logd/main.cpp +++ b/logd/main.cpp @@ -17,7 +17,10 @@ #include <dirent.h> #include <errno.h> #include <fcntl.h> +#include <poll.h> #include <sched.h> +#include <semaphore.h> +#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -26,10 +29,12 @@ #include <sys/prctl.h> #include <sys/stat.h> #include <sys/types.h> +#include <syslog.h> #include <unistd.h> #include <cutils/properties.h> #include <cutils/sched_policy.h> +#include <cutils/sockets.h> #include "private/android_filesystem_config.h" #include "CommandListener.h" @@ -37,6 +42,12 @@ #include "LogListener.h" #include "LogAudit.h" +#define KMSG_PRIORITY(PRI) \ + '<', \ + '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) / 10, \ + '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) % 10, \ + '>' + // // The service is designed to be run by init, it does not respond well // to starting up manually. When starting up manually the sockets will @@ -127,17 +138,107 @@ static bool property_get_bool(const char *key, bool def) { return def; } -// Foreground waits for exit of the three main persistent threads that -// are started here. The three threads are created to manage UNIX -// domain client sockets for writing, reading and controlling the user -// space logger. Additional transitory per-client threads are created -// for each reader once they register. -int main() { - bool auditd = property_get_bool("logd.auditd", true); +// Remove the static, and use this variable +// globally for debugging if necessary. eg: +// write(fdDmesg, "I am here\n", 10); +static int fdDmesg = -1; + +static sem_t reinit; +static bool reinit_running = false; +static LogBuffer *logBuf = NULL; + +static void *reinit_thread_start(void * /*obj*/) { + prctl(PR_SET_NAME, "logd.daemon"); + set_sched_policy(0, SP_BACKGROUND); + + setgid(AID_LOGD); + setuid(AID_LOGD); + + while (reinit_running && !sem_wait(&reinit) && reinit_running) { + if (fdDmesg >= 0) { + static const char reinit_message[] = { KMSG_PRIORITY(LOG_INFO), + 'l', 'o', 'g', 'd', '.', 'd', 'a', 'e', 'm', 'o', 'n', ':', + ' ', 'r', 'e', 'i', 'n', 'i', 't', '\n' }; + write(fdDmesg, reinit_message, sizeof(reinit_message)); + } + + // Anything that reads persist.<property> + if (logBuf) { + logBuf->init(); + } + } + + return NULL; +} + +// Serves as a global method to trigger reinitialization +// and as a function that can be provided to signal(). +void reinit_signal_handler(int /*signal*/) { + sem_post(&reinit); +} + +// Foreground waits for exit of the main persistent threads +// that are started here. The threads are created to manage +// UNIX domain client sockets for writing, reading and +// controlling the user space logger, and for any additional +// logging plugins like auditd and restart control. Additional +// transitory per-client threads are created for each reader. +int main(int argc, char *argv[]) { + fdDmesg = open("/dev/kmsg", O_WRONLY); + + // issue reinit command. KISS argument parsing. + if ((argc > 1) && argv[1] && !strcmp(argv[1], "--reinit")) { + int sock = TEMP_FAILURE_RETRY( + socket_local_client("logd", + ANDROID_SOCKET_NAMESPACE_RESERVED, + SOCK_STREAM)); + if (sock < 0) { + return -errno; + } + static const char reinit[] = "reinit"; + ssize_t ret = TEMP_FAILURE_RETRY(write(sock, reinit, sizeof(reinit))); + if (ret < 0) { + return -errno; + } + struct pollfd p; + memset(&p, 0, sizeof(p)); + p.fd = sock; + p.events = POLLIN; + ret = TEMP_FAILURE_RETRY(poll(&p, 1, 100)); + if (ret < 0) { + return -errno; + } + if ((ret == 0) || !(p.revents & POLLIN)) { + return -ETIME; + } + static const char success[] = "success"; + char buffer[sizeof(success) - 1]; + memset(buffer, 0, sizeof(buffer)); + ret = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer))); + if (ret < 0) { + return -errno; + } + return strncmp(buffer, success, sizeof(success) - 1) != 0; + } - int fdDmesg = -1; - if (auditd && property_get_bool("logd.auditd.dmesg", true)) { - fdDmesg = open("/dev/kmsg", O_WRONLY); + // Reinit Thread + sem_init(&reinit, 0, 0); + pthread_attr_t attr; + if (!pthread_attr_init(&attr)) { + struct sched_param param; + + memset(¶m, 0, sizeof(param)); + pthread_attr_setschedparam(&attr, ¶m); + pthread_attr_setschedpolicy(&attr, SCHED_BATCH); + if (!pthread_attr_setdetachstate(&attr, + PTHREAD_CREATE_DETACHED)) { + pthread_t thread; + reinit_running = true; + if (pthread_create(&thread, &attr, reinit_thread_start, NULL)) { + reinit_running = false; + } + } + pthread_attr_destroy(&attr); } if (drop_privs() != 0) { @@ -153,11 +254,10 @@ int main() { // LogBuffer is the object which is responsible for holding all // log entries. - LogBuffer *logBuf = new LogBuffer(times); + logBuf = new LogBuffer(times); + + signal(SIGHUP, reinit_signal_handler); - if (property_get_bool("logd.statistics.dgram_qlen", false)) { - logBuf->enableDgramQlenStatistics(); - } { char property[PROPERTY_VALUE_MAX]; property_get("ro.build.type", property, ""); @@ -198,9 +298,13 @@ int main() { // initiated log messages. New log entries are added to LogBuffer // and LogReader is notified to send updates to connected clients. + bool auditd = property_get_bool("logd.auditd", true); + if (auditd) { + bool dmesg = property_get_bool("logd.auditd.dmesg", true); + // failure is an option ... messages are in dmesg (required by standard) - LogAudit *al = new LogAudit(logBuf, reader, fdDmesg); + LogAudit *al = new LogAudit(logBuf, reader, dmesg ? fdDmesg : -1); int len = klogctl(KLOG_SIZE_BUFFER, NULL, 0); if (len > 0) { @@ -220,11 +324,10 @@ int main() { if (al->startListener()) { delete al; - close(fdDmesg); } } - pause(); + TEMP_FAILURE_RETRY(pause()); + exit(0); } - diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp index 96877a9..46bd9c0 100644 --- a/logd/tests/logd_test.cpp +++ b/logd/tests/logd_test.cpp @@ -192,164 +192,6 @@ TEST(logd, statistics) { EXPECT_TRUE(NULL != events_logs); #endif - // Parse timing stats - - cp = strstr(cp, "Minimum time between log events per dgram_qlen:"); - - if (cp) { - while (*cp && (*cp != '\n')) { - ++cp; - } - if (*cp == '\n') { - ++cp; - } - - char *list_of_spans = cp; - EXPECT_NE('\0', *list_of_spans); - - unsigned short number_of_buckets = 0; - unsigned short *dgram_qlen = NULL; - unsigned short bucket = 0; - while (*cp && (*cp != '\n')) { - bucket = 0; - while (isdigit(*cp)) { - bucket = bucket * 10 + *cp - '0'; - ++cp; - } - while (*cp == ' ') { - ++cp; - } - if (!bucket) { - break; - } - unsigned short *new_dgram_qlen = new unsigned short[number_of_buckets + 1]; - EXPECT_TRUE(new_dgram_qlen != NULL); - if (dgram_qlen) { - memcpy(new_dgram_qlen, dgram_qlen, sizeof(*dgram_qlen) * number_of_buckets); - delete [] dgram_qlen; - } - - dgram_qlen = new_dgram_qlen; - dgram_qlen[number_of_buckets++] = bucket; - } - - char *end_of_spans = cp; - EXPECT_NE('\0', *end_of_spans); - - EXPECT_LT(5, number_of_buckets); - - unsigned long long *times = new unsigned long long [number_of_buckets]; - ASSERT_TRUE(times != NULL); - - memset(times, 0, sizeof(*times) * number_of_buckets); - - while (*cp == '\n') { - ++cp; - } - - unsigned short number_of_values = 0; - unsigned long long value; - while (*cp && (*cp != '\n')) { - EXPECT_GE(number_of_buckets, number_of_values); - - value = 0; - while (isdigit(*cp)) { - value = value * 10ULL + *cp - '0'; - ++cp; - } - - switch(*cp) { - case ' ': - case '\n': - value *= 1000ULL; - /* FALLTHRU */ - case 'm': - value *= 1000ULL; - /* FALLTHRU */ - case 'u': - value *= 1000ULL; - /* FALLTHRU */ - case 'n': - default: - break; - } - while (*++cp == ' '); - - if (!value) { - break; - } - - times[number_of_values] = value; - ++number_of_values; - } - -#ifdef TARGET_USES_LOGD - EXPECT_EQ(number_of_values, number_of_buckets); -#endif - - FILE *fp; - ASSERT_TRUE(NULL != (fp = fopen("/proc/sys/net/unix/max_dgram_qlen", "r"))); - - unsigned max_dgram_qlen = 0; - fscanf(fp, "%u", &max_dgram_qlen); - - fclose(fp); - - // Find launch point - unsigned short launch = 0; - unsigned long long total = 0; - do { - total += times[launch]; - } while (((++launch < number_of_buckets) - && ((total / launch) >= (times[launch] / 8ULL))) - || (launch == 1)); // too soon - - bool failure = number_of_buckets <= launch; - if (!failure) { - unsigned short l = launch; - if (l >= number_of_buckets) { - l = number_of_buckets - 1; - } - failure = max_dgram_qlen < dgram_qlen[l]; - } - - // We can get failure if at any time liblog_benchmarks has been run - // because designed to overload /proc/sys/net/unix/max_dgram_qlen even - // at excessive values like 20000. It does so to measure the raw processing - // performance of logd. - if (failure) { - cp = find_benchmark_spam(cp); - } - - if (cp) { - // Fake a failure, but without the failure code - if (number_of_buckets <= launch) { - printf ("Expected: number_of_buckets > launch, actual: %u vs %u\n", - number_of_buckets, launch); - } - if (launch >= number_of_buckets) { - launch = number_of_buckets - 1; - } - if (max_dgram_qlen < dgram_qlen[launch]) { - printf ("Expected: max_dgram_qlen >= dgram_qlen[%d]," - " actual: %u vs %u\n", - launch, max_dgram_qlen, dgram_qlen[launch]); - } - } else -#ifndef TARGET_USES_LOGD - if (total) -#endif - { - EXPECT_GT(number_of_buckets, launch); - if (launch >= number_of_buckets) { - launch = number_of_buckets - 1; - } - EXPECT_GE(max_dgram_qlen, dgram_qlen[launch]); - } - - delete [] dgram_qlen; - delete [] times; - } delete [] buf; } diff --git a/netcfg/Android.mk b/netcfg/Android.mk deleted file mode 100644 index 4796c11..0000000 --- a/netcfg/Android.mk +++ /dev/null @@ -1,8 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_SRC_FILES:= netcfg.c -LOCAL_MODULE:= netcfg -LOCAL_SHARED_LIBRARIES := libnetutils -LOCAL_CFLAGS := -Werror -include $(BUILD_EXECUTABLE) diff --git a/netcfg/MODULE_LICENSE_APACHE2 b/netcfg/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 --- a/netcfg/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/netcfg/NOTICE b/netcfg/NOTICE deleted file mode 100644 index c5b1efa..0000000 --- a/netcfg/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/netcfg/netcfg.c b/netcfg/netcfg.c deleted file mode 100644 index eec1b2f..0000000 --- a/netcfg/netcfg.c +++ /dev/null @@ -1,114 +0,0 @@ -/* -** Copyright 2006, 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 <errno.h> -#include <dirent.h> -#include <netinet/ether.h> -#include <netinet/if_ether.h> -#include <netutils/dhcp.h> -#include <netutils/ifc.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -static const char *ipaddr(in_addr_t addr) -{ - struct in_addr in_addr; - - in_addr.s_addr = addr; - return inet_ntoa(in_addr); -} - -static void usage(void) -{ - fprintf(stderr,"usage: netcfg [<interface> dhcp]\n"); - exit(1); -} - -static int dump_interface(const char *name) -{ - unsigned addr, flags; - unsigned char hwbuf[ETH_ALEN]; - int prefixLength; - - if(ifc_get_info(name, &addr, &prefixLength, &flags)) { - return 0; - } - - printf("%-8s %s ", name, flags & 1 ? "UP " : "DOWN"); - printf("%40s", ipaddr(addr)); - printf("/%-4d", prefixLength); - printf("0x%08x ", flags); - if (!ifc_get_hwaddr(name, hwbuf)) { - int i; - for(i=0; i < (ETH_ALEN-1); i++) - printf("%02x:", hwbuf[i]); - printf("%02x\n", hwbuf[i]); - } else { - printf("\n"); - } - return 0; -} - -static int dump_interfaces(void) -{ - DIR *d; - struct dirent *de; - - d = opendir("/sys/class/net"); - if(d == 0) return -1; - - while((de = readdir(d))) { - if(de->d_name[0] == '.') continue; - dump_interface(de->d_name); - } - closedir(d); - return 0; -} - -int main(int argc, char **argv) -{ - if(ifc_init()) { - perror("Cannot perform requested operation"); - exit(1); - } - - if(argc == 1) { - int result = dump_interfaces(); - ifc_close(); - return result; - } - - if(argc != 3) usage(); - - char* iname = argv[1]; - char* action = argv[2]; - if(strlen(iname) > 16) usage(); - - if (!strcmp(action, "dhcp")) { - if (do_dhcp(iname)) { - fprintf(stderr, "dhcp failed: %s\n", strerror(errno)); - ifc_close(); - exit(1); - } - } else { - fprintf(stderr,"no such action '%s'\n", action); - usage(); - } - - ifc_close(); - return 0; -} diff --git a/rootdir/init.environ.rc.in b/rootdir/init.environ.rc.in index 30bef46..0064790 100644 --- a/rootdir/init.environ.rc.in +++ b/rootdir/init.environ.rc.in @@ -1,6 +1,5 @@ # set up the global environment on init - export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin export ANDROID_BOOTLOGO 1 export ANDROID_ROOT /system export ANDROID_ASSETS /system/app diff --git a/rootdir/init.rc b/rootdir/init.rc index 2a599ac..bc36c3e 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -118,25 +118,18 @@ on init mount cgroup none /dev/cpuctl cpu chown system system /dev/cpuctl chown system system /dev/cpuctl/tasks - chmod 0660 /dev/cpuctl/tasks + chmod 0666 /dev/cpuctl/tasks write /dev/cpuctl/cpu.shares 1024 - write /dev/cpuctl/cpu.rt_runtime_us 950000 + write /dev/cpuctl/cpu.rt_runtime_us 800000 write /dev/cpuctl/cpu.rt_period_us 1000000 - mkdir /dev/cpuctl/apps - chown system system /dev/cpuctl/apps/tasks - chmod 0666 /dev/cpuctl/apps/tasks - write /dev/cpuctl/apps/cpu.shares 1024 - write /dev/cpuctl/apps/cpu.rt_runtime_us 800000 - write /dev/cpuctl/apps/cpu.rt_period_us 1000000 - - mkdir /dev/cpuctl/apps/bg_non_interactive - chown system system /dev/cpuctl/apps/bg_non_interactive/tasks - chmod 0666 /dev/cpuctl/apps/bg_non_interactive/tasks + mkdir /dev/cpuctl/bg_non_interactive + chown system system /dev/cpuctl/bg_non_interactive/tasks + chmod 0666 /dev/cpuctl/bg_non_interactive/tasks # 5.0 % - write /dev/cpuctl/apps/bg_non_interactive/cpu.shares 52 - write /dev/cpuctl/apps/bg_non_interactive/cpu.rt_runtime_us 700000 - write /dev/cpuctl/apps/bg_non_interactive/cpu.rt_period_us 1000000 + write /dev/cpuctl/bg_non_interactive/cpu.shares 52 + write /dev/cpuctl/bg_non_interactive/cpu.rt_runtime_us 700000 + write /dev/cpuctl/bg_non_interactive/cpu.rt_period_us 1000000 # qtaguid will limit access to specific data based on group memberships. # net_bw_acct grants impersonation of socket owners. @@ -171,6 +164,7 @@ on property:sys.boot_from_charger_mode=1 # Load properties from /system/ + /factory after fs mount. on load_all_props_action load_all_props + start logd-reinit # Indicate to fw loaders that the relevant mounts are up. on firmware_mounts_complete @@ -437,6 +431,7 @@ on property:vold.decrypt=trigger_reset_main on property:vold.decrypt=trigger_load_persist_props load_persist_props + start logd-reinit on property:vold.decrypt=trigger_post_fs_data trigger post-fs-data @@ -479,6 +474,10 @@ service logd /system/bin/logd socket logdr seqpacket 0666 logd logd socket logdw dgram 0222 logd logd +service logd-reinit /system/bin/logd --reinit + oneshot + disabled + service healthd /sbin/healthd class core critical @@ -572,7 +571,7 @@ service defaultcrypto /system/bin/vdc --wait cryptfs mountdefaultencrypted # encryption) or trigger_restart_min_framework (other encryption) # One shot invocation to encrypt unencrypted volumes -service encrypt /system/bin/vdc --wait cryptfs maybeenabledefaultcrypto +service encrypt /system/bin/vdc --wait cryptfs enablecrypto inplace default disabled oneshot # vold will set vold.decrypt to trigger_restart_framework (default diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc index 43d7bc9..9cf9ed9 100644 --- a/rootdir/ueventd.rc +++ b/rootdir/ueventd.rc @@ -89,6 +89,7 @@ subsystem adf /dev/ppp 0660 radio vpn # sysfs properties +/sys/devices/platform/trusty.* trusty_version 0440 root log /sys/devices/virtual/input/input* enable 0660 root input /sys/devices/virtual/input/input* poll_delay 0660 root input /sys/devices/virtual/usb_composite/* enable 0664 root system diff --git a/sdcard/Android.mk b/sdcard/Android.mk index 63b0f41..cb3a8fb 100644 --- a/sdcard/Android.mk +++ b/sdcard/Android.mk @@ -6,6 +6,6 @@ LOCAL_SRC_FILES := sdcard.c LOCAL_MODULE := sdcard LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror -LOCAL_SHARED_LIBRARIES := libc libcutils +LOCAL_SHARED_LIBRARIES := libcutils include $(BUILD_EXECUTABLE) diff --git a/toolbox/Android.mk b/toolbox/Android.mk index 05b83a2..b822ea0 100644 --- a/toolbox/Android.mk +++ b/toolbox/Android.mk @@ -44,7 +44,6 @@ OUR_TOOLS := \ df \ getevent \ getprop \ - getsebool \ iftop \ ioctl \ ionice \ @@ -56,6 +55,7 @@ OUR_TOOLS := \ nandread \ newfs_msdos \ ps \ + prlimit \ renice \ restorecon \ route \ @@ -63,15 +63,12 @@ OUR_TOOLS := \ schedtop \ sendevent \ setprop \ - setsebool \ - smd \ start \ stop \ top \ umount \ uptime \ watchprops \ - wipe \ ALL_TOOLS = $(BSD_TOOLS) $(OUR_TOOLS) diff --git a/toolbox/getsebool.c b/toolbox/getsebool.c deleted file mode 100644 index aab5200..0000000 --- a/toolbox/getsebool.c +++ /dev/null @@ -1,104 +0,0 @@ -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <getopt.h> -#include <errno.h> -#include <string.h> -#include <selinux/selinux.h> - -static void usage(const char *progname) -{ - fprintf(stderr, "usage: %s -a or %s boolean...\n", progname, progname); - exit(1); -} - -int getsebool_main(int argc, char **argv) -{ - int i, get_all = 0, rc = 0, active, pending, len = 0, opt; - char **names; - - while ((opt = getopt(argc, argv, "a")) > 0) { - switch (opt) { - case 'a': - if (argc > 2) - usage(argv[0]); - if (is_selinux_enabled() <= 0) { - fprintf(stderr, "%s: SELinux is disabled\n", - argv[0]); - return 1; - } - errno = 0; - rc = security_get_boolean_names(&names, &len); - if (rc) { - fprintf(stderr, - "%s: Unable to get boolean names: %s\n", - argv[0], strerror(errno)); - return 1; - } - if (!len) { - printf("No booleans\n"); - return 0; - } - get_all = 1; - break; - default: - usage(argv[0]); - } - } - - if (is_selinux_enabled() <= 0) { - fprintf(stderr, "%s: SELinux is disabled\n", argv[0]); - return 1; - } - if (!len) { - if (argc < 2) - usage(argv[0]); - len = argc - 1; - names = malloc(sizeof(char *) * len); - if (!names) { - fprintf(stderr, "%s: out of memory\n", argv[0]); - return 2; - } - for (i = 0; i < len; i++) { - names[i] = strdup(argv[i + 1]); - if (!names[i]) { - fprintf(stderr, "%s: out of memory\n", - argv[0]); - return 2; - } - } - } - - for (i = 0; i < len; i++) { - active = security_get_boolean_active(names[i]); - if (active < 0) { - if (get_all && errno == EACCES) - continue; - fprintf(stderr, "Error getting active value for %s\n", - names[i]); - rc = -1; - goto out; - } - pending = security_get_boolean_pending(names[i]); - if (pending < 0) { - fprintf(stderr, "Error getting pending value for %s\n", - names[i]); - rc = -1; - goto out; - } - if (pending != active) { - printf("%s --> %s pending: %s\n", names[i], - (active ? "on" : "off"), - (pending ? "on" : "off")); - } else { - printf("%s --> %s\n", names[i], - (active ? "on" : "off")); - } - } - -out: - for (i = 0; i < len; i++) - free(names[i]); - free(names); - return rc; -} diff --git a/toolbox/prlimit.c b/toolbox/prlimit.c new file mode 100644 index 0000000..8cf202a --- /dev/null +++ b/toolbox/prlimit.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014, The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google, Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/time.h> +#include <sys/resource.h> + +static void +usage(const char *s) +{ + fprintf(stderr, "usage: %s pid resource cur max\n", s); + exit(EXIT_FAILURE); +} + +int prlimit_main(int argc, char *argv[]) +{ + pid_t pid; + struct rlimit64 rl; + int resource; + int rc; + + if (argc != 5) + usage(*argv); + + if (sscanf(argv[1], "%d", &pid) != 1) + usage(*argv); + + if (sscanf(argv[2], "%d", &resource) != 1) + usage(*argv); + + if (sscanf(argv[3], "%llu", &rl.rlim_cur) != 1) + usage(*argv); + + if (sscanf(argv[4], "%llu", &rl.rlim_max) != 1) + usage(*argv); + + printf("setting resource %d of pid %d to [%llu,%llu]\n", resource, pid, + rl.rlim_cur, rl.rlim_max); + rc = prlimit64(pid, resource, &rl, NULL); + if (rc < 0) { + perror("prlimit"); + exit(EXIT_FAILURE); + } + + return 0; +} diff --git a/toolbox/ps.c b/toolbox/ps.c index d0a8db3..cf3f05a 100644 --- a/toolbox/ps.c +++ b/toolbox/ps.c @@ -1,6 +1,7 @@ #include <ctype.h> #include <dirent.h> #include <fcntl.h> +#include <inttypes.h> #include <pwd.h> #include <stdio.h> #include <stdlib.h> @@ -29,6 +30,12 @@ static char *nexttok(char **strp) #define SHOW_NUMERIC_UID 32 #define SHOW_ABI 64 +#if __LP64__ +#define PC_WIDTH 10 /* Realistically, the top bits will be 0, so don't waste space. */ +#else +#define PC_WIDTH (2*sizeof(uintptr_t)) +#endif + static int display_flags = 0; static int ppid_filter = 0; @@ -44,7 +51,8 @@ static int ps_line(int pid, int tid, char *namefilter) int fd, r; char *ptr, *name, *state; int ppid; - unsigned wchan, rss, vss, eip; + unsigned rss, vss; + uintptr_t eip; unsigned utime, stime; int prio, nice, rtprio, sched, psr; struct passwd *pw; @@ -124,7 +132,7 @@ static int ps_line(int pid, int tid, char *namefilter) nexttok(&ptr); // blocked nexttok(&ptr); // sigignore nexttok(&ptr); // sigcatch - wchan = strtoul(nexttok(&ptr), 0, 10); // wchan + nexttok(&ptr); // wchan nexttok(&ptr); // nswap nexttok(&ptr); // cnswap nexttok(&ptr); // exit signal @@ -176,7 +184,16 @@ static int ps_line(int pid, int tid, char *namefilter) else printf(" %.2s ", get_sched_policy_name(p)); } - printf(" %08x %08x %s ", wchan, eip, state); + char path[PATH_MAX]; + snprintf(path, sizeof(path), "/proc/%d/wchan", pid); + char wchan[10]; + int fd = open(path, O_RDONLY); + ssize_t wchan_len = read(fd, wchan, sizeof(wchan)); + if (wchan_len == -1) { + wchan[wchan_len = 0] = '\0'; + } + close(fd); + printf(" %10.*s %0*" PRIxPTR " %s ", (int) wchan_len, wchan, (int) PC_WIDTH, eip, state); if (display_flags & SHOW_ABI) { print_exe_abi(pid); } @@ -285,12 +302,13 @@ int ps_main(int argc, char **argv) } if (display_flags & SHOW_MACLABEL) { - printf("LABEL USER PID PPID NAME\n"); + printf("LABEL USER PID PPID NAME\n"); } else { - printf("USER PID PPID VSIZE RSS %s%s %s WCHAN PC %sNAME\n", + printf("USER PID PPID VSIZE RSS %s%s %sWCHAN %*s %sNAME\n", (display_flags&SHOW_CPU)?"CPU ":"", (display_flags&SHOW_PRIO)?"PRIO NICE RTPRI SCHED ":"", (display_flags&SHOW_POLICY)?"PCY " : "", + (int) PC_WIDTH, "PC", (display_flags&SHOW_ABI)?"ABI " : ""); } while((de = readdir(d)) != 0){ diff --git a/toolbox/setsebool.c b/toolbox/setsebool.c deleted file mode 100644 index f79a612..0000000 --- a/toolbox/setsebool.c +++ /dev/null @@ -1,46 +0,0 @@ -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> -#include <selinux/selinux.h> -#include <errno.h> - -static int do_setsebool(int nargs, char **args) { - const char *name = args[1]; - const char *value = args[2]; - SELboolean b; - - if (is_selinux_enabled() <= 0) - return 0; - - b.name = name; - if (!strcmp(value, "1") || !strcasecmp(value, "true") || !strcasecmp(value, "on")) - b.value = 1; - else if (!strcmp(value, "0") || !strcasecmp(value, "false") || !strcasecmp(value, "off")) - b.value = 0; - else { - fprintf(stderr, "setsebool: invalid value %s\n", value); - return -1; - } - - if (security_set_boolean_list(1, &b, 0) < 0) - { - fprintf(stderr, "setsebool: could not set %s to %s: %s", name, value, strerror(errno)); - return -1; - } - - return 0; -} - -int setsebool_main(int argc, char **argv) -{ - if (argc != 3) { - fprintf(stderr, "Usage: %s name value\n", argv[0]); - exit(1); - } - - return do_setsebool(argc, argv); -} diff --git a/toolbox/smd.c b/toolbox/smd.c deleted file mode 100644 index 343dea7..0000000 --- a/toolbox/smd.c +++ /dev/null @@ -1,42 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <unistd.h> - -int smd_main(int argc, char **argv) -{ - int fd, len, r, port = 0; - char devname[32]; - argc--; - argv++; - - if((argc > 0) && (argv[0][0] == '-')) { - port = atoi(argv[0] + 1); - argc--; - argv++; - } - - sprintf(devname,"/dev/smd%d",port); - fd = open(devname, O_WRONLY); - if(fd < 0) { - fprintf(stderr,"failed to open smd0 - %s\n", - strerror(errno)); - return -1; - } - while(argc > 0) { - len = strlen(argv[0]); - r = write(fd, argv[0], len); - if(r != len) { - fprintf(stderr,"failed to write smd0 (%d) %s\n", - r, strerror(errno)); - return -1; - } - argc--; - argv++; - write(fd, argc ? " " : "\r", 1); - } - close(fd); - return 0; -} diff --git a/toolbox/wipe.c b/toolbox/wipe.c deleted file mode 100644 index 650a0d6..0000000 --- a/toolbox/wipe.c +++ /dev/null @@ -1,176 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <dirent.h> -#include <string.h> -#include <errno.h> -#include <sys/types.h> -#include <cutils/android_reboot.h> -#include <sys/stat.h> - -#ifndef PATH_MAX -#define PATH_MAX 4096 -#endif - - -/* Directories created by init defined in system/rootdir/init.rc */ -static char *INIT_DIRS[] = { - "/system/etc/ppp", - "/data/misc", - "/data/local", - "/data/local/tmp", - "/data/data", - "/data/app_private", - "/data/app", - NULL -}; - -static void wipe (const char *path); - -static int usage() -{ - fprintf(stderr, "wipe <system|data|all>\n\n" - "system means '/system'\n" - "data means '/data'\n"); - - return -1; -} - -int wipe_main (int argc, char *argv[]) -{ - char *whatToWipe; - - if (argc != 2) return usage(); - - whatToWipe = argv[1]; - - if (0 == strcmp (whatToWipe, "system")) { - fprintf(stdout, "Wiping /system\n"); - wipe ("/system"); - fprintf(stdout, "Done wiping /android\n"); - } else if (0 == strcmp (whatToWipe, "data")) { - fprintf(stdout, "Wiping /data\n"); - wipe ("/data"); - fprintf(stdout, "Done wiping /data\n"); - } else if (0 == strcmp (whatToWipe, "all")) { - fprintf(stdout, "Wiping /system and /data\n"); - wipe ("/system"); - wipe ("/data"); - fprintf(stdout, "Done wiping /system and /data\n"); - } else if (0 == strcmp(whatToWipe, "nuke")) { - int ret; - fprintf(stdout, "Nuking the device...\n"); - wipe ("/system"); - wipe ("/data"); - fprintf(stdout, "Device nuked! Rebooting...\n"); - ret = android_reboot(ANDROID_RB_RESTART, 0, 0); - if (ret < 0) { - fprintf(stderr, "Reboot failed, %s\n", strerror(errno)); - return 1; - } - } else { - return usage(); - } - - return 0; -} - -static char nameBuffer[PATH_MAX]; -static struct stat statBuffer; - -static void wipe (const char *path) -{ - DIR *dir; - struct dirent *de; - int ret; - - dir = opendir(path); - - if (dir == NULL) { - fprintf (stderr, "Error opendir'ing %s '%s'\n", - path, strerror(errno)); - return; - } - - char *filenameOffset; - - strcpy(nameBuffer, path); - strcat(nameBuffer, "/"); - - filenameOffset = nameBuffer + strlen(nameBuffer); - - for (;;) { - de = readdir(dir); - - if (de == NULL) { - break; - } - - if (0 == strcmp(de->d_name, ".") - || 0 == strcmp(de->d_name, "..") - || 0 == strcmp(de->d_name, "lost+found") - ) { - continue; - } - - strcpy(filenameOffset, de->d_name); - - ret = lstat (nameBuffer, &statBuffer); - - if (ret != 0) { - fprintf(stderr, "stat() error on '%s' '%s'\n", - nameBuffer, strerror(errno)); - } - - if(S_ISDIR(statBuffer.st_mode)) { - int i; - char *newpath; - -#if 0 - closedir(dir); -#endif - - newpath = strdup(nameBuffer); - wipe(newpath); - - /* Leave directories created by init, they have special permissions. */ - for (i = 0; INIT_DIRS[i]; i++) { - if (strcmp(INIT_DIRS[i], newpath) == 0) { - break; - } - } - if (INIT_DIRS[i] == NULL) { - ret = rmdir(newpath); - if (ret != 0) { - fprintf(stderr, "rmdir() error on '%s' '%s'\n", - newpath, strerror(errno)); - } - } - - free(newpath); - -#if 0 - dir = opendir(path); - if (dir == NULL) { - fprintf (stderr, "Error opendir'ing %s '%s'\n", - path, strerror(errno)); - return; - } -#endif - - strcpy(nameBuffer, path); - strcat(nameBuffer, "/"); - - } else { - ret = unlink(nameBuffer); - - if (ret != 0) { - fprintf(stderr, "unlink() error on '%s' '%s'\n", - nameBuffer, strerror(errno)); - } - } - } - - closedir(dir); - -} |