diff options
304 files changed, 9534 insertions, 3581 deletions
diff --git a/adb/Android.mk b/adb/Android.mk index 6ed01fac4..5913d940a 100644 --- a/adb/Android.mk +++ b/adb/Android.mk | |||
@@ -350,11 +350,11 @@ LOCAL_CFLAGS := \ | |||
350 | -D_GNU_SOURCE \ | 350 | -D_GNU_SOURCE \ |
351 | -Wno-deprecated-declarations \ | 351 | -Wno-deprecated-declarations \ |
352 | 352 | ||
353 | LOCAL_CFLAGS += -DALLOW_ADBD_ROOT=$(if $(filter userdebug eng,$(TARGET_BUILD_VARIANT)),1,0) | ||
353 | LOCAL_CFLAGS += -DALLOW_ADBD_NO_AUTH=$(if $(filter userdebug eng,$(TARGET_BUILD_VARIANT)),1,0) | 354 | LOCAL_CFLAGS += -DALLOW_ADBD_NO_AUTH=$(if $(filter userdebug eng,$(TARGET_BUILD_VARIANT)),1,0) |
354 | 355 | ||
355 | ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT))) | 356 | ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT))) |
356 | LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1 | 357 | LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1 |
357 | LOCAL_CFLAGS += -DALLOW_ADBD_ROOT=1 | ||
358 | endif | 358 | endif |
359 | 359 | ||
360 | LOCAL_MODULE := adbd | 360 | LOCAL_MODULE := adbd |
diff --git a/adb/adb.cpp b/adb/adb.cpp index bfb1144d4..ff7b71f81 100644 --- a/adb/adb.cpp +++ b/adb/adb.cpp | |||
@@ -49,6 +49,7 @@ | |||
49 | #include "adb_auth.h" | 49 | #include "adb_auth.h" |
50 | #include "adb_io.h" | 50 | #include "adb_io.h" |
51 | #include "adb_listeners.h" | 51 | #include "adb_listeners.h" |
52 | #include "adb_unique_fd.h" | ||
52 | #include "adb_utils.h" | 53 | #include "adb_utils.h" |
53 | #include "sysdeps/chrono.h" | 54 | #include "sysdeps/chrono.h" |
54 | #include "transport.h" | 55 | #include "transport.h" |
@@ -656,6 +657,26 @@ static unsigned __stdcall _redirect_stderr_thread(HANDLE h) { | |||
656 | 657 | ||
657 | #endif | 658 | #endif |
658 | 659 | ||
660 | static void ReportServerStartupFailure(pid_t pid) { | ||
661 | fprintf(stderr, "ADB server didn't ACK\n"); | ||
662 | fprintf(stderr, "Full server startup log: %s\n", GetLogFilePath().c_str()); | ||
663 | fprintf(stderr, "Server had pid: %d\n", pid); | ||
664 | |||
665 | unique_fd fd(adb_open(GetLogFilePath().c_str(), O_RDONLY)); | ||
666 | if (fd == -1) return; | ||
667 | |||
668 | // Let's not show more than 128KiB of log... | ||
669 | adb_lseek(fd, -128 * 1024, SEEK_END); | ||
670 | std::string content; | ||
671 | if (!android::base::ReadFdToString(fd, &content)) return; | ||
672 | |||
673 | std::string header = android::base::StringPrintf("--- adb starting (pid %d) ---", pid); | ||
674 | std::vector<std::string> lines = android::base::Split(content, "\n"); | ||
675 | int i = lines.size() - 1; | ||
676 | while (i >= 0 && lines[i] != header) --i; | ||
677 | while (static_cast<size_t>(i) < lines.size()) fprintf(stderr, "%s\n", lines[i++].c_str()); | ||
678 | } | ||
679 | |||
659 | int launch_server(const std::string& socket_spec) { | 680 | int launch_server(const std::string& socket_spec) { |
660 | #if defined(_WIN32) | 681 | #if defined(_WIN32) |
661 | /* we need to start the server in the background */ | 682 | /* we need to start the server in the background */ |
@@ -835,7 +856,8 @@ int launch_server(const std::string& socket_spec) { | |||
835 | memcmp(temp, expected, expected_length) == 0) { | 856 | memcmp(temp, expected, expected_length) == 0) { |
836 | got_ack = true; | 857 | got_ack = true; |
837 | } else { | 858 | } else { |
838 | fprintf(stderr, "ADB server didn't ACK\n"); | 859 | ReportServerStartupFailure(GetProcessId(process_handle.get())); |
860 | return -1; | ||
839 | } | 861 | } |
840 | } else { | 862 | } else { |
841 | const DWORD err = GetLastError(); | 863 | const DWORD err = GetLastError(); |
@@ -909,12 +931,9 @@ int launch_server(const std::string& socket_spec) { | |||
909 | "--reply-fd", reply_fd, NULL); | 931 | "--reply-fd", reply_fd, NULL); |
910 | // this should not return | 932 | // this should not return |
911 | fprintf(stderr, "adb: execl returned %d: %s\n", result, strerror(errno)); | 933 | fprintf(stderr, "adb: execl returned %d: %s\n", result, strerror(errno)); |
912 | } else { | 934 | } else { |
913 | // parent side of the fork | 935 | // parent side of the fork |
914 | 936 | char temp[3] = {}; | |
915 | char temp[3]; | ||
916 | |||
917 | temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C'; | ||
918 | // wait for the "OK\n" message | 937 | // wait for the "OK\n" message |
919 | adb_close(fd[1]); | 938 | adb_close(fd[1]); |
920 | int ret = adb_read(fd[0], temp, 3); | 939 | int ret = adb_read(fd[0], temp, 3); |
@@ -925,7 +944,7 @@ int launch_server(const std::string& socket_spec) { | |||
925 | return -1; | 944 | return -1; |
926 | } | 945 | } |
927 | if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { | 946 | if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { |
928 | fprintf(stderr, "ADB server didn't ACK\n" ); | 947 | ReportServerStartupFailure(pid); |
929 | return -1; | 948 | return -1; |
930 | } | 949 | } |
931 | } | 950 | } |
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp index 6f2403d03..b236fb39f 100644 --- a/adb/adb_utils.cpp +++ b/adb/adb_utils.cpp | |||
@@ -157,7 +157,12 @@ bool mkdirs(const std::string& path) { | |||
157 | } | 157 | } |
158 | 158 | ||
159 | std::string dump_hex(const void* data, size_t byte_count) { | 159 | std::string dump_hex(const void* data, size_t byte_count) { |
160 | byte_count = std::min(byte_count, size_t(16)); | 160 | size_t truncate_len = 16; |
161 | bool truncated = false; | ||
162 | if (byte_count > truncate_len) { | ||
163 | byte_count = truncate_len; | ||
164 | truncated = true; | ||
165 | } | ||
161 | 166 | ||
162 | const uint8_t* p = reinterpret_cast<const uint8_t*>(data); | 167 | const uint8_t* p = reinterpret_cast<const uint8_t*>(data); |
163 | 168 | ||
@@ -172,6 +177,10 @@ std::string dump_hex(const void* data, size_t byte_count) { | |||
172 | line.push_back(isprint(ch) ? ch : '.'); | 177 | line.push_back(isprint(ch) ? ch : '.'); |
173 | } | 178 | } |
174 | 179 | ||
180 | if (truncated) { | ||
181 | line += " [truncated]"; | ||
182 | } | ||
183 | |||
175 | return line; | 184 | return line; |
176 | } | 185 | } |
177 | 186 | ||
@@ -278,3 +287,29 @@ int syntax_error(const char* fmt, ...) { | |||
278 | fprintf(stderr, "\n"); | 287 | fprintf(stderr, "\n"); |
279 | return 1; | 288 | return 1; |
280 | } | 289 | } |
290 | |||
291 | std::string GetLogFilePath() { | ||
292 | #if defined(_WIN32) | ||
293 | const char log_name[] = "adb.log"; | ||
294 | WCHAR temp_path[MAX_PATH]; | ||
295 | |||
296 | // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364992%28v=vs.85%29.aspx | ||
297 | DWORD nchars = GetTempPathW(arraysize(temp_path), temp_path); | ||
298 | if (nchars >= arraysize(temp_path) || nchars == 0) { | ||
299 | // If string truncation or some other error. | ||
300 | fatal("cannot retrieve temporary file path: %s\n", | ||
301 | android::base::SystemErrorCodeToString(GetLastError()).c_str()); | ||
302 | } | ||
303 | |||
304 | std::string temp_path_utf8; | ||
305 | if (!android::base::WideToUTF8(temp_path, &temp_path_utf8)) { | ||
306 | fatal_errno("cannot convert temporary file path from UTF-16 to UTF-8"); | ||
307 | } | ||
308 | |||
309 | return temp_path_utf8 + log_name; | ||
310 | #else | ||
311 | const char* tmp_dir = getenv("TMPDIR"); | ||
312 | if (tmp_dir == nullptr) tmp_dir = "/tmp"; | ||
313 | return android::base::StringPrintf("%s/adb.%u.log", tmp_dir, getuid()); | ||
314 | #endif | ||
315 | } | ||
diff --git a/adb/adb_utils.h b/adb/adb_utils.h index 11c0ec9cc..f764a0eea 100644 --- a/adb/adb_utils.h +++ b/adb/adb_utils.h | |||
@@ -89,4 +89,6 @@ class BlockingQueue { | |||
89 | } | 89 | } |
90 | }; | 90 | }; |
91 | 91 | ||
92 | std::string GetLogFilePath(); | ||
93 | |||
92 | #endif | 94 | #endif |
diff --git a/adb/client/main.cpp b/adb/client/main.cpp index 62798cde7..f0d0ce799 100644 --- a/adb/client/main.cpp +++ b/adb/client/main.cpp | |||
@@ -39,33 +39,7 @@ | |||
39 | #include "sysdeps/chrono.h" | 39 | #include "sysdeps/chrono.h" |
40 | #include "transport.h" | 40 | #include "transport.h" |
41 | 41 | ||
42 | static std::string GetLogFilePath() { | 42 | static void setup_daemon_logging() { |
43 | #if defined(_WIN32) | ||
44 | const char log_name[] = "adb.log"; | ||
45 | WCHAR temp_path[MAX_PATH]; | ||
46 | |||
47 | // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364992%28v=vs.85%29.aspx | ||
48 | DWORD nchars = GetTempPathW(arraysize(temp_path), temp_path); | ||
49 | if (nchars >= arraysize(temp_path) || nchars == 0) { | ||
50 | // If string truncation or some other error. | ||
51 | fatal("cannot retrieve temporary file path: %s\n", | ||
52 | android::base::SystemErrorCodeToString(GetLastError()).c_str()); | ||
53 | } | ||
54 | |||
55 | std::string temp_path_utf8; | ||
56 | if (!android::base::WideToUTF8(temp_path, &temp_path_utf8)) { | ||
57 | fatal_errno("cannot convert temporary file path from UTF-16 to UTF-8"); | ||
58 | } | ||
59 | |||
60 | return temp_path_utf8 + log_name; | ||
61 | #else | ||
62 | const char* tmp_dir = getenv("TMPDIR"); | ||
63 | if (tmp_dir == nullptr) tmp_dir = "/tmp"; | ||
64 | return android::base::StringPrintf("%s/adb.%u.log", tmp_dir, getuid()); | ||
65 | #endif | ||
66 | } | ||
67 | |||
68 | static void setup_daemon_logging(void) { | ||
69 | const std::string log_file_path(GetLogFilePath()); | 43 | const std::string log_file_path(GetLogFilePath()); |
70 | int fd = unix_open(log_file_path.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0640); | 44 | int fd = unix_open(log_file_path.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0640); |
71 | if (fd == -1) { | 45 | if (fd == -1) { |
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp index 1c94298da..e0629abdd 100644 --- a/adb/daemon/main.cpp +++ b/adb/daemon/main.cpp | |||
@@ -49,17 +49,23 @@ | |||
49 | 49 | ||
50 | static const char* root_seclabel = nullptr; | 50 | static const char* root_seclabel = nullptr; |
51 | 51 | ||
52 | static inline bool is_device_unlocked() { | ||
53 | return "orange" == android::base::GetProperty("ro.boot.verifiedbootstate", ""); | ||
54 | } | ||
55 | |||
52 | static void drop_capabilities_bounding_set_if_needed(struct minijail *j) { | 56 | static void drop_capabilities_bounding_set_if_needed(struct minijail *j) { |
53 | #if defined(ALLOW_ADBD_ROOT) | 57 | if (ALLOW_ADBD_ROOT || is_device_unlocked()) { |
54 | if (__android_log_is_debuggable()) { | 58 | if (__android_log_is_debuggable()) { |
55 | return; | 59 | return; |
60 | } | ||
56 | } | 61 | } |
57 | #endif | ||
58 | minijail_capbset_drop(j, CAP_TO_MASK(CAP_SETUID) | CAP_TO_MASK(CAP_SETGID)); | 62 | minijail_capbset_drop(j, CAP_TO_MASK(CAP_SETUID) | CAP_TO_MASK(CAP_SETGID)); |
59 | } | 63 | } |
60 | 64 | ||
61 | static bool should_drop_privileges() { | 65 | static bool should_drop_privileges() { |
62 | #if defined(ALLOW_ADBD_ROOT) | 66 | // "adb root" not allowed, always drop privileges. |
67 | if (!ALLOW_ADBD_ROOT && !is_device_unlocked()) return true; | ||
68 | |||
63 | // The properties that affect `adb root` and `adb unroot` are ro.secure and | 69 | // The properties that affect `adb root` and `adb unroot` are ro.secure and |
64 | // ro.debuggable. In this context the names don't make the expected behavior | 70 | // ro.debuggable. In this context the names don't make the expected behavior |
65 | // particularly obvious. | 71 | // particularly obvious. |
@@ -89,9 +95,6 @@ static bool should_drop_privileges() { | |||
89 | } | 95 | } |
90 | 96 | ||
91 | return drop; | 97 | return drop; |
92 | #else | ||
93 | return true; // "adb root" not allowed, always drop privileges. | ||
94 | #endif // ALLOW_ADBD_ROOT | ||
95 | } | 98 | } |
96 | 99 | ||
97 | static void drop_privileges(int server_port) { | 100 | static void drop_privileges(int server_port) { |
@@ -158,7 +161,10 @@ int adbd_main(int server_port) { | |||
158 | // descriptor will always be open. | 161 | // descriptor will always be open. |
159 | adbd_cloexec_auth_socket(); | 162 | adbd_cloexec_auth_socket(); |
160 | 163 | ||
161 | if (ALLOW_ADBD_NO_AUTH && !android::base::GetBoolProperty("ro.adb.secure", false)) { | 164 | // Respect ro.adb.secure in userdebug/eng builds (ALLOW_ADBD_NO_AUTH), or when the |
165 | // device is unlocked. | ||
166 | if ((ALLOW_ADBD_NO_AUTH || is_device_unlocked()) && | ||
167 | !android::base::GetBoolProperty("ro.adb.secure", false)) { | ||
162 | auth_required = false; | 168 | auth_required = false; |
163 | } | 169 | } |
164 | 170 | ||
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp index 809ed89c5..9cd378cad 100644 --- a/adb/transport_local.cpp +++ b/adb/transport_local.cpp | |||
@@ -388,6 +388,25 @@ static void qemu_socket_thread(int port) { | |||
388 | D("transport: qemu_socket_thread() exiting"); | 388 | D("transport: qemu_socket_thread() exiting"); |
389 | return; | 389 | return; |
390 | } | 390 | } |
391 | |||
392 | // If adbd is running inside the emulator, it will normally use QEMUD pipe (aka | ||
393 | // goldfish) as the transport. This can either be explicitly set by the | ||
394 | // service.adb.transport property, or be inferred from ro.kernel.qemu that is | ||
395 | // set to "1" for ranchu/goldfish. | ||
396 | static bool use_qemu_goldfish() { | ||
397 | // Legacy way to detect if adbd should use the goldfish pipe is to check for | ||
398 | // ro.kernel.qemu, keep that behaviour for backward compatibility. | ||
399 | if (android::base::GetBoolProperty("ro.kernel.qemu", false)) { | ||
400 | return true; | ||
401 | } | ||
402 | // If service.adb.transport is present and is set to "goldfish", use the | ||
403 | // QEMUD pipe. | ||
404 | if (android::base::GetProperty("service.adb.transport", "") == "goldfish") { | ||
405 | return true; | ||
406 | } | ||
407 | return false; | ||
408 | } | ||
409 | |||
391 | #endif // !ADB_HOST | 410 | #endif // !ADB_HOST |
392 | 411 | ||
393 | void local_init(int port) | 412 | void local_init(int port) |
@@ -401,13 +420,7 @@ void local_init(int port) | |||
401 | #else | 420 | #else |
402 | // For the adbd daemon in the system image we need to distinguish | 421 | // For the adbd daemon in the system image we need to distinguish |
403 | // between the device, and the emulator. | 422 | // between the device, and the emulator. |
404 | if (android::base::GetBoolProperty("ro.kernel.qemu", false)) { | 423 | func = use_qemu_goldfish() ? qemu_socket_thread : server_socket_thread; |
405 | // Running inside the emulator: use QEMUD pipe as the transport. | ||
406 | func = qemu_socket_thread; | ||
407 | } else { | ||
408 | // Running inside the device: use TCP socket as the transport. | ||
409 | func = server_socket_thread; | ||
410 | } | ||
411 | debug_name = "server"; | 424 | debug_name = "server"; |
412 | #endif // !ADB_HOST | 425 | #endif // !ADB_HOST |
413 | 426 | ||
diff --git a/base/chrono_utils.cpp b/base/chrono_utils.cpp index 5eedf3bce..b6bf701ea 100644 --- a/base/chrono_utils.cpp +++ b/base/chrono_utils.cpp | |||
@@ -33,5 +33,10 @@ boot_clock::time_point boot_clock::now() { | |||
33 | #endif // __ANDROID__ | 33 | #endif // __ANDROID__ |
34 | } | 34 | } |
35 | 35 | ||
36 | std::ostream& operator<<(std::ostream& os, const Timer& t) { | ||
37 | os << t.duration().count() << "ms"; | ||
38 | return os; | ||
39 | } | ||
40 | |||
36 | } // namespace base | 41 | } // namespace base |
37 | } // namespace android | 42 | } // namespace android |
diff --git a/base/chrono_utils_test.cpp b/base/chrono_utils_test.cpp index 057132d9f..da442f455 100644 --- a/base/chrono_utils_test.cpp +++ b/base/chrono_utils_test.cpp | |||
@@ -19,6 +19,9 @@ | |||
19 | #include <time.h> | 19 | #include <time.h> |
20 | 20 | ||
21 | #include <chrono> | 21 | #include <chrono> |
22 | #include <sstream> | ||
23 | #include <string> | ||
24 | #include <thread> | ||
22 | 25 | ||
23 | #include <gtest/gtest.h> | 26 | #include <gtest/gtest.h> |
24 | 27 | ||
@@ -42,5 +45,36 @@ TEST(ChronoUtilsTest, BootClockNowSeconds) { | |||
42 | EXPECT_EQ(now, boot_seconds); | 45 | EXPECT_EQ(now, boot_seconds); |
43 | } | 46 | } |
44 | 47 | ||
48 | template <typename T> | ||
49 | void ExpectAboutEqual(T expected, T actual) { | ||
50 | auto expected_upper_bound = expected * 1.05f; | ||
51 | auto expected_lower_bound = expected * .95; | ||
52 | EXPECT_GT(expected_upper_bound, actual); | ||
53 | EXPECT_LT(expected_lower_bound, actual); | ||
54 | } | ||
55 | |||
56 | TEST(ChronoUtilsTest, TimerDurationIsSane) { | ||
57 | auto start = boot_clock::now(); | ||
58 | Timer t; | ||
59 | std::this_thread::sleep_for(50ms); | ||
60 | auto stop = boot_clock::now(); | ||
61 | auto stop_timer = t.duration(); | ||
62 | |||
63 | auto expected = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start); | ||
64 | ExpectAboutEqual(expected, stop_timer); | ||
65 | } | ||
66 | |||
67 | TEST(ChronoUtilsTest, TimerOstream) { | ||
68 | Timer t; | ||
69 | std::this_thread::sleep_for(50ms); | ||
70 | auto stop_timer = t.duration().count(); | ||
71 | std::stringstream os; | ||
72 | os << t; | ||
73 | decltype(stop_timer) stop_timer_from_stream; | ||
74 | os >> stop_timer_from_stream; | ||
75 | EXPECT_NE(0, stop_timer); | ||
76 | ExpectAboutEqual(stop_timer, stop_timer_from_stream); | ||
77 | } | ||
78 | |||
45 | } // namespace base | 79 | } // namespace base |
46 | } // namespace android \ No newline at end of file | 80 | } // namespace android |
diff --git a/base/include/android-base/chrono_utils.h b/base/include/android-base/chrono_utils.h index 0086425e5..7679d4c94 100644 --- a/base/include/android-base/chrono_utils.h +++ b/base/include/android-base/chrono_utils.h | |||
@@ -18,6 +18,9 @@ | |||
18 | #define ANDROID_BASE_CHRONO_UTILS_H | 18 | #define ANDROID_BASE_CHRONO_UTILS_H |
19 | 19 | ||
20 | #include <chrono> | 20 | #include <chrono> |
21 | #include <sstream> | ||
22 | |||
23 | using namespace std::chrono_literals; | ||
21 | 24 | ||
22 | namespace android { | 25 | namespace android { |
23 | namespace base { | 26 | namespace base { |
@@ -31,6 +34,20 @@ class boot_clock { | |||
31 | static time_point now(); | 34 | static time_point now(); |
32 | }; | 35 | }; |
33 | 36 | ||
37 | class Timer { | ||
38 | public: | ||
39 | Timer() : start_(boot_clock::now()) {} | ||
40 | |||
41 | std::chrono::milliseconds duration() const { | ||
42 | return std::chrono::duration_cast<std::chrono::milliseconds>(boot_clock::now() - start_); | ||
43 | } | ||
44 | |||
45 | private: | ||
46 | boot_clock::time_point start_; | ||
47 | }; | ||
48 | |||
49 | std::ostream& operator<<(std::ostream& os, const Timer& t); | ||
50 | |||
34 | } // namespace base | 51 | } // namespace base |
35 | } // namespace android | 52 | } // namespace android |
36 | 53 | ||
diff --git a/base/include/android-base/utf8.h b/base/include/android-base/utf8.h index 2d5a6f6d7..c9cc1ab0c 100755 --- a/base/include/android-base/utf8.h +++ b/base/include/android-base/utf8.h | |||
@@ -22,6 +22,8 @@ | |||
22 | #else | 22 | #else |
23 | // Bring in prototypes for standard APIs so that we can import them into the utf8 namespace. | 23 | // Bring in prototypes for standard APIs so that we can import them into the utf8 namespace. |
24 | #include <fcntl.h> // open | 24 | #include <fcntl.h> // open |
25 | #include <stdio.h> // fopen | ||
26 | #include <sys/stat.h> // mkdir | ||
25 | #include <unistd.h> // unlink | 27 | #include <unistd.h> // unlink |
26 | #endif | 28 | #endif |
27 | 29 | ||
@@ -53,6 +55,19 @@ bool UTF8ToWide(const char* utf8, std::wstring* utf16); | |||
53 | // Convert a UTF-8 std::string (including any embedded NULL characters) to | 55 | // Convert a UTF-8 std::string (including any embedded NULL characters) to |
54 | // UTF-16. Returns whether the conversion was done successfully. | 56 | // UTF-16. Returns whether the conversion was done successfully. |
55 | bool UTF8ToWide(const std::string& utf8, std::wstring* utf16); | 57 | bool UTF8ToWide(const std::string& utf8, std::wstring* utf16); |
58 | |||
59 | // Convert a file system path, represented as a NULL-terminated string of | ||
60 | // UTF-8 characters, to a UTF-16 string representing the same file system | ||
61 | // path using the Windows extended-lengh path representation. | ||
62 | // | ||
63 | // See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#MAXPATH: | ||
64 | // ```The Windows API has many functions that also have Unicode versions to | ||
65 | // permit an extended-length path for a maximum total path length of 32,767 | ||
66 | // characters. To specify an extended-length path, use the "\\?\" prefix. | ||
67 | // For example, "\\?\D:\very long path".``` | ||
68 | // | ||
69 | // Returns whether the conversion was done successfully. | ||
70 | bool UTF8PathToWindowsLongPath(const char* utf8, std::wstring* utf16); | ||
56 | #endif | 71 | #endif |
57 | 72 | ||
58 | // The functions in the utf8 namespace take UTF-8 strings. For Windows, these | 73 | // The functions in the utf8 namespace take UTF-8 strings. For Windows, these |
@@ -73,9 +88,13 @@ bool UTF8ToWide(const std::string& utf8, std::wstring* utf16); | |||
73 | namespace utf8 { | 88 | namespace utf8 { |
74 | 89 | ||
75 | #ifdef _WIN32 | 90 | #ifdef _WIN32 |
91 | FILE* fopen(const char* name, const char* mode); | ||
92 | int mkdir(const char* name, mode_t mode); | ||
76 | int open(const char* name, int flags, ...); | 93 | int open(const char* name, int flags, ...); |
77 | int unlink(const char* name); | 94 | int unlink(const char* name); |
78 | #else | 95 | #else |
96 | using ::fopen; | ||
97 | using ::mkdir; | ||
79 | using ::open; | 98 | using ::open; |
80 | using ::unlink; | 99 | using ::unlink; |
81 | #endif | 100 | #endif |
diff --git a/base/utf8.cpp b/base/utf8.cpp index 3cca70026..5984fb06c 100644 --- a/base/utf8.cpp +++ b/base/utf8.cpp | |||
@@ -19,7 +19,9 @@ | |||
19 | #include "android-base/utf8.h" | 19 | #include "android-base/utf8.h" |
20 | 20 | ||
21 | #include <fcntl.h> | 21 | #include <fcntl.h> |
22 | #include <stdio.h> | ||
22 | 23 | ||
24 | #include <algorithm> | ||
23 | #include <string> | 25 | #include <string> |
24 | 26 | ||
25 | #include "android-base/logging.h" | 27 | #include "android-base/logging.h" |
@@ -153,12 +155,58 @@ bool UTF8ToWide(const std::string& utf8, std::wstring* utf16) { | |||
153 | return UTF8ToWide(utf8.c_str(), utf8.length(), utf16); | 155 | return UTF8ToWide(utf8.c_str(), utf8.length(), utf16); |
154 | } | 156 | } |
155 | 157 | ||
158 | static bool isDriveLetter(wchar_t c) { | ||
159 | return (c >= L'a' && c <= L'z') || (c >= L'A' && c <= L'Z'); | ||
160 | } | ||
161 | |||
162 | bool UTF8PathToWindowsLongPath(const char* utf8, std::wstring* utf16) { | ||
163 | if (!UTF8ToWide(utf8, utf16)) { | ||
164 | return false; | ||
165 | } | ||
166 | // Note: Although most Win32 File I/O API are limited to MAX_PATH (260 | ||
167 | // characters), the CreateDirectory API is limited to 248 characters. | ||
168 | if (utf16->length() >= 248) { | ||
169 | // If path is of the form "x:\" or "x:/" | ||
170 | if (isDriveLetter((*utf16)[0]) && (*utf16)[1] == L':' && | ||
171 | ((*utf16)[2] == L'\\' || (*utf16)[2] == L'/')) { | ||
172 | // Append long path prefix, and make sure there are no unix-style | ||
173 | // separators to ensure a fully compliant Win32 long path string. | ||
174 | utf16->insert(0, LR"(\\?\)"); | ||
175 | std::replace(utf16->begin(), utf16->end(), L'/', L'\\'); | ||
176 | } | ||
177 | } | ||
178 | return true; | ||
179 | } | ||
180 | |||
156 | // Versions of standard library APIs that support UTF-8 strings. | 181 | // Versions of standard library APIs that support UTF-8 strings. |
157 | namespace utf8 { | 182 | namespace utf8 { |
158 | 183 | ||
184 | FILE* fopen(const char* name, const char* mode) { | ||
185 | std::wstring name_utf16; | ||
186 | if (!UTF8PathToWindowsLongPath(name, &name_utf16)) { | ||
187 | return nullptr; | ||
188 | } | ||
189 | |||
190 | std::wstring mode_utf16; | ||
191 | if (!UTF8ToWide(mode, &mode_utf16)) { | ||
192 | return nullptr; | ||
193 | } | ||
194 | |||
195 | return _wfopen(name_utf16.c_str(), mode_utf16.c_str()); | ||
196 | } | ||
197 | |||
198 | int mkdir(const char* name, mode_t mode) { | ||
199 | std::wstring name_utf16; | ||
200 | if (!UTF8PathToWindowsLongPath(name, &name_utf16)) { | ||
201 | return -1; | ||
202 | } | ||
203 | |||
204 | return _wmkdir(name_utf16.c_str()); | ||
205 | } | ||
206 | |||
159 | int open(const char* name, int flags, ...) { | 207 | int open(const char* name, int flags, ...) { |
160 | std::wstring name_utf16; | 208 | std::wstring name_utf16; |
161 | if (!UTF8ToWide(name, &name_utf16)) { | 209 | if (!UTF8PathToWindowsLongPath(name, &name_utf16)) { |
162 | return -1; | 210 | return -1; |
163 | } | 211 | } |
164 | 212 | ||
@@ -175,7 +223,7 @@ int open(const char* name, int flags, ...) { | |||
175 | 223 | ||
176 | int unlink(const char* name) { | 224 | int unlink(const char* name) { |
177 | std::wstring name_utf16; | 225 | std::wstring name_utf16; |
178 | if (!UTF8ToWide(name, &name_utf16)) { | 226 | if (!UTF8PathToWindowsLongPath(name, &name_utf16)) { |
179 | return -1; | 227 | return -1; |
180 | } | 228 | } |
181 | 229 | ||
diff --git a/base/utf8_test.cpp b/base/utf8_test.cpp index ae8fc8c79..fcb25c350 100644 --- a/base/utf8_test.cpp +++ b/base/utf8_test.cpp | |||
@@ -18,7 +18,12 @@ | |||
18 | 18 | ||
19 | #include <gtest/gtest.h> | 19 | #include <gtest/gtest.h> |
20 | 20 | ||
21 | #include <fcntl.h> | ||
22 | #include <stdlib.h> | ||
23 | |||
21 | #include "android-base/macros.h" | 24 | #include "android-base/macros.h" |
25 | #include "android-base/test_utils.h" | ||
26 | #include "android-base/unique_fd.h" | ||
22 | 27 | ||
23 | namespace android { | 28 | namespace android { |
24 | namespace base { | 29 | namespace base { |
@@ -408,5 +413,76 @@ TEST(SysStrings, SysUTF8ToWide) { | |||
408 | EXPECT_EQ(expected_null, SysUTF8ToWide(utf8_null)); | 413 | EXPECT_EQ(expected_null, SysUTF8ToWide(utf8_null)); |
409 | } | 414 | } |
410 | 415 | ||
416 | TEST(UTF8PathToWindowsLongPathTest, DontAddPrefixIfShorterThanMaxPath) { | ||
417 | std::string utf8 = "c:\\mypath\\myfile.txt"; | ||
418 | |||
419 | std::wstring wide; | ||
420 | EXPECT_TRUE(UTF8PathToWindowsLongPath(utf8.c_str(), &wide)); | ||
421 | |||
422 | EXPECT_EQ(std::string::npos, wide.find(LR"(\\?\)")); | ||
423 | } | ||
424 | |||
425 | TEST(UTF8PathToWindowsLongPathTest, AddPrefixIfLongerThanMaxPath) { | ||
426 | std::string utf8 = "c:\\mypath"; | ||
427 | while (utf8.length() < 300 /* MAX_PATH is 260 */) { | ||
428 | utf8 += "\\mypathsegment"; | ||
429 | } | ||
430 | |||
431 | std::wstring wide; | ||
432 | EXPECT_TRUE(UTF8PathToWindowsLongPath(utf8.c_str(), &wide)); | ||
433 | |||
434 | EXPECT_EQ(0U, wide.find(LR"(\\?\)")); | ||
435 | EXPECT_EQ(std::string::npos, wide.find(L"/")); | ||
436 | } | ||
437 | |||
438 | TEST(UTF8PathToWindowsLongPathTest, AddPrefixAndFixSeparatorsIfLongerThanMaxPath) { | ||
439 | std::string utf8 = "c:/mypath"; | ||
440 | while (utf8.length() < 300 /* MAX_PATH is 260 */) { | ||
441 | utf8 += "/mypathsegment"; | ||
442 | } | ||
443 | |||
444 | std::wstring wide; | ||
445 | EXPECT_TRUE(UTF8PathToWindowsLongPath(utf8.c_str(), &wide)); | ||
446 | |||
447 | EXPECT_EQ(0U, wide.find(LR"(\\?\)")); | ||
448 | EXPECT_EQ(std::string::npos, wide.find(L"/")); | ||
449 | } | ||
450 | |||
451 | namespace utf8 { | ||
452 | |||
453 | TEST(Utf8FilesTest, CanCreateOpenAndDeleteFileWithLongPath) { | ||
454 | TemporaryDir td; | ||
455 | |||
456 | // Create long directory path | ||
457 | std::string utf8 = td.path; | ||
458 | while (utf8.length() < 300 /* MAX_PATH is 260 */) { | ||
459 | utf8 += "\\mypathsegment"; | ||
460 | EXPECT_EQ(0, mkdir(utf8.c_str(), 0)); | ||
461 | } | ||
462 | |||
463 | // Create file | ||
464 | utf8 += "\\test-file.bin"; | ||
465 | int flags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY; | ||
466 | int mode = 0666; | ||
467 | android::base::unique_fd fd(open(utf8.c_str(), flags, mode)); | ||
468 | EXPECT_NE(-1, fd.get()); | ||
469 | |||
470 | // Close file | ||
471 | fd.reset(); | ||
472 | EXPECT_EQ(-1, fd.get()); | ||
473 | |||
474 | // Open file with fopen | ||
475 | FILE* file = fopen(utf8.c_str(), "rb"); | ||
476 | EXPECT_NE(nullptr, file); | ||
477 | |||
478 | if (file) { | ||
479 | fclose(file); | ||
480 | } | ||
481 | |||
482 | // Delete file | ||
483 | EXPECT_EQ(0, unlink(utf8.c_str())); | ||
484 | } | ||
485 | |||
486 | } // namespace utf8 | ||
411 | } // namespace base | 487 | } // namespace base |
412 | } // namespace android | 488 | } // namespace android |
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp index a4c216033..344fa9aae 100644 --- a/bootstat/bootstat.cpp +++ b/bootstat/bootstat.cpp | |||
@@ -85,12 +85,13 @@ void ShowHelp(const char *cmd) { | |||
85 | fprintf(stderr, "Usage: %s [options]\n", cmd); | 85 | fprintf(stderr, "Usage: %s [options]\n", cmd); |
86 | fprintf(stderr, | 86 | fprintf(stderr, |
87 | "options include:\n" | 87 | "options include:\n" |
88 | " -h, --help Show this help\n" | 88 | " -h, --help Show this help\n" |
89 | " -l, --log Log all metrics to logstorage\n" | 89 | " -l, --log Log all metrics to logstorage\n" |
90 | " -p, --print Dump the boot event records to the console\n" | 90 | " -p, --print Dump the boot event records to the console\n" |
91 | " -r, --record Record the timestamp of a named boot event\n" | 91 | " -r, --record Record the timestamp of a named boot event\n" |
92 | " --value Optional value to associate with the boot event\n" | 92 | " --value Optional value to associate with the boot event\n" |
93 | " --record_boot_reason Record the reason why the device booted\n" | 93 | " --record_boot_complete Record metrics related to the time for the device boot\n" |
94 | " --record_boot_reason Record the reason why the device booted\n" | ||
94 | " --record_time_since_factory_reset Record the time since the device was reset\n"); | 95 | " --record_time_since_factory_reset Record the time since the device was reset\n"); |
95 | } | 96 | } |
96 | 97 | ||
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp index 5565cfdd7..f86aaa014 100644 --- a/debuggerd/Android.bp +++ b/debuggerd/Android.bp | |||
@@ -274,7 +274,7 @@ cc_binary { | |||
274 | "libbase", | 274 | "libbase", |
275 | "libdebuggerd_client", | 275 | "libdebuggerd_client", |
276 | "liblog", | 276 | "liblog", |
277 | "libselinux", | 277 | "libprocinfo", |
278 | ], | 278 | ], |
279 | 279 | ||
280 | local_include_dirs: ["include"], | 280 | local_include_dirs: ["include"], |
diff --git a/debuggerd/client/debuggerd_client_test.cpp b/debuggerd/client/debuggerd_client_test.cpp index 8420f038f..9c2f0d632 100644 --- a/debuggerd/client/debuggerd_client_test.cpp +++ b/debuggerd/client/debuggerd_client_test.cpp | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <gtest/gtest.h> | 27 | #include <gtest/gtest.h> |
28 | 28 | ||
29 | #include <android-base/file.h> | 29 | #include <android-base/file.h> |
30 | #include <android-base/properties.h> | ||
30 | #include <android-base/stringprintf.h> | 31 | #include <android-base/stringprintf.h> |
31 | #include <android-base/strings.h> | 32 | #include <android-base/strings.h> |
32 | #include <android-base/unique_fd.h> | 33 | #include <android-base/unique_fd.h> |
@@ -36,8 +37,20 @@ | |||
36 | using namespace std::chrono_literals; | 37 | using namespace std::chrono_literals; |
37 | using android::base::unique_fd; | 38 | using android::base::unique_fd; |
38 | 39 | ||
40 | static int getThreadCount() { | ||
41 | int threadCount = 1024; | ||
42 | std::vector<std::string> characteristics = | ||
43 | android::base::Split(android::base::GetProperty("ro.build.characteristics", ""), ","); | ||
44 | if (std::find(characteristics.begin(), characteristics.end(), "embedded") | ||
45 | != characteristics.end()) { | ||
46 | // 128 is the realistic number for iot devices. | ||
47 | threadCount = 128; | ||
48 | } | ||
49 | return threadCount; | ||
50 | } | ||
51 | |||
39 | TEST(debuggerd_client, race) { | 52 | TEST(debuggerd_client, race) { |
40 | static constexpr int THREAD_COUNT = 1024; | 53 | static int THREAD_COUNT = getThreadCount(); |
41 | pid_t forkpid = fork(); | 54 | pid_t forkpid = fork(); |
42 | 55 | ||
43 | ASSERT_NE(-1, forkpid); | 56 | ASSERT_NE(-1, forkpid); |
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp index 5db0e5fed..4b1e51dde 100644 --- a/debuggerd/crash_dump.cpp +++ b/debuggerd/crash_dump.cpp | |||
@@ -44,6 +44,9 @@ | |||
44 | #include <private/android_filesystem_config.h> | 44 | #include <private/android_filesystem_config.h> |
45 | #include <procinfo/process.h> | 45 | #include <procinfo/process.h> |
46 | 46 | ||
47 | #define ATRACE_TAG ATRACE_TAG_BIONIC | ||
48 | #include <utils/Trace.h> | ||
49 | |||
47 | #include "backtrace.h" | 50 | #include "backtrace.h" |
48 | #include "tombstone.h" | 51 | #include "tombstone.h" |
49 | #include "utility.h" | 52 | #include "utility.h" |
@@ -101,6 +104,7 @@ static bool ptrace_seize_thread(int pid_proc_fd, pid_t tid, std::string* error) | |||
101 | } | 104 | } |
102 | 105 | ||
103 | static bool activity_manager_notify(pid_t pid, int signal, const std::string& amfd_data) { | 106 | static bool activity_manager_notify(pid_t pid, int signal, const std::string& amfd_data) { |
107 | ATRACE_CALL(); | ||
104 | android::base::unique_fd amfd(socket_local_client( | 108 | android::base::unique_fd amfd(socket_local_client( |
105 | "/data/system/ndebugsocket", ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM)); | 109 | "/data/system/ndebugsocket", ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM)); |
106 | if (amfd.get() == -1) { | 110 | if (amfd.get() == -1) { |
@@ -176,6 +180,7 @@ static void abort_handler(pid_t target, const bool tombstoned_connected, | |||
176 | } | 180 | } |
177 | 181 | ||
178 | static void drop_capabilities() { | 182 | static void drop_capabilities() { |
183 | ATRACE_CALL(); | ||
179 | __user_cap_header_struct capheader; | 184 | __user_cap_header_struct capheader; |
180 | memset(&capheader, 0, sizeof(capheader)); | 185 | memset(&capheader, 0, sizeof(capheader)); |
181 | capheader.version = _LINUX_CAPABILITY_VERSION_3; | 186 | capheader.version = _LINUX_CAPABILITY_VERSION_3; |
@@ -194,6 +199,8 @@ static void drop_capabilities() { | |||
194 | } | 199 | } |
195 | 200 | ||
196 | int main(int argc, char** argv) { | 201 | int main(int argc, char** argv) { |
202 | atrace_begin(ATRACE_TAG, "before reparent"); | ||
203 | |||
197 | pid_t target = getppid(); | 204 | pid_t target = getppid(); |
198 | bool tombstoned_connected = false; | 205 | bool tombstoned_connected = false; |
199 | unique_fd tombstoned_socket; | 206 | unique_fd tombstoned_socket; |
@@ -261,6 +268,8 @@ int main(int argc, char** argv) { | |||
261 | PLOG(FATAL) << "parent died"; | 268 | PLOG(FATAL) << "parent died"; |
262 | } | 269 | } |
263 | 270 | ||
271 | atrace_end(ATRACE_TAG); | ||
272 | |||
264 | // Reparent ourselves to init, so that the signal handler can waitpid on the | 273 | // Reparent ourselves to init, so that the signal handler can waitpid on the |
265 | // original process to avoid leaving a zombie for non-fatal dumps. | 274 | // original process to avoid leaving a zombie for non-fatal dumps. |
266 | pid_t forkpid = fork(); | 275 | pid_t forkpid = fork(); |
@@ -270,6 +279,8 @@ int main(int argc, char** argv) { | |||
270 | exit(0); | 279 | exit(0); |
271 | } | 280 | } |
272 | 281 | ||
282 | ATRACE_NAME("after reparent"); | ||
283 | |||
273 | // Die if we take too long. | 284 | // Die if we take too long. |
274 | // | 285 | // |
275 | // Note: processes with many threads and minidebug-info can take a bit to | 286 | // Note: processes with many threads and minidebug-info can take a bit to |
@@ -278,42 +289,53 @@ int main(int argc, char** argv) { | |||
278 | 289 | ||
279 | std::string attach_error; | 290 | std::string attach_error; |
280 | 291 | ||
281 | // Seize the main thread. | ||
282 | if (!ptrace_seize_thread(target_proc_fd, main_tid, &attach_error)) { | ||
283 | LOG(FATAL) << attach_error; | ||
284 | } | ||
285 | |||
286 | // Seize the siblings. | ||
287 | std::map<pid_t, std::string> threads; | 292 | std::map<pid_t, std::string> threads; |
293 | |||
288 | { | 294 | { |
289 | std::set<pid_t> siblings; | 295 | ATRACE_NAME("ptrace"); |
290 | if (!android::procinfo::GetProcessTids(target, &siblings)) { | 296 | // Seize the main thread. |
291 | PLOG(FATAL) << "failed to get process siblings"; | 297 | if (!ptrace_seize_thread(target_proc_fd, main_tid, &attach_error)) { |
298 | LOG(FATAL) << attach_error; | ||
292 | } | 299 | } |
293 | 300 | ||
294 | // but not the already attached main thread. | 301 | // Seize the siblings. |
295 | siblings.erase(main_tid); | 302 | { |
296 | // or the handler pseudothread. | 303 | std::set<pid_t> siblings; |
297 | siblings.erase(pseudothread_tid); | 304 | if (!android::procinfo::GetProcessTids(target, &siblings)) { |
305 | PLOG(FATAL) << "failed to get process siblings"; | ||
306 | } | ||
298 | 307 | ||
299 | for (pid_t sibling_tid : siblings) { | 308 | // but not the already attached main thread. |
300 | if (!ptrace_seize_thread(target_proc_fd, sibling_tid, &attach_error)) { | 309 | siblings.erase(main_tid); |
301 | LOG(WARNING) << attach_error; | 310 | // or the handler pseudothread. |
302 | } else { | 311 | siblings.erase(pseudothread_tid); |
303 | threads.emplace(sibling_tid, get_thread_name(sibling_tid)); | 312 | |
313 | for (pid_t sibling_tid : siblings) { | ||
314 | if (!ptrace_seize_thread(target_proc_fd, sibling_tid, &attach_error)) { | ||
315 | LOG(WARNING) << attach_error; | ||
316 | } else { | ||
317 | threads.emplace(sibling_tid, get_thread_name(sibling_tid)); | ||
318 | } | ||
304 | } | 319 | } |
305 | } | 320 | } |
306 | } | 321 | } |
307 | 322 | ||
308 | // Collect the backtrace map, open files, and process/thread names, while we still have caps. | 323 | // Collect the backtrace map, open files, and process/thread names, while we still have caps. |
309 | std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(main_tid)); | 324 | std::unique_ptr<BacktraceMap> backtrace_map; |
310 | if (!backtrace_map) { | 325 | { |
311 | LOG(FATAL) << "failed to create backtrace map"; | 326 | ATRACE_NAME("backtrace map"); |
327 | backtrace_map.reset(BacktraceMap::Create(main_tid)); | ||
328 | if (!backtrace_map) { | ||
329 | LOG(FATAL) << "failed to create backtrace map"; | ||
330 | } | ||
312 | } | 331 | } |
313 | 332 | ||
314 | // Collect the list of open files. | 333 | // Collect the list of open files. |
315 | OpenFilesList open_files; | 334 | OpenFilesList open_files; |
316 | populate_open_files_list(target, &open_files); | 335 | { |
336 | ATRACE_NAME("open files"); | ||
337 | populate_open_files_list(target, &open_files); | ||
338 | } | ||
317 | 339 | ||
318 | std::string process_name = get_process_name(main_tid); | 340 | std::string process_name = get_process_name(main_tid); |
319 | threads.emplace(main_tid, get_thread_name(main_tid)); | 341 | threads.emplace(main_tid, get_thread_name(main_tid)); |
@@ -321,9 +343,12 @@ int main(int argc, char** argv) { | |||
321 | // Drop our capabilities now that we've attached to the threads we care about. | 343 | // Drop our capabilities now that we've attached to the threads we care about. |
322 | drop_capabilities(); | 344 | drop_capabilities(); |
323 | 345 | ||
324 | const DebuggerdDumpType dump_type_enum = static_cast<DebuggerdDumpType>(dump_type); | 346 | { |
325 | LOG(INFO) << "obtaining output fd from tombstoned, type: " << dump_type_enum; | 347 | ATRACE_NAME("tombstoned_connect"); |
326 | tombstoned_connected = tombstoned_connect(target, &tombstoned_socket, &output_fd, dump_type_enum); | 348 | const DebuggerdDumpType dump_type_enum = static_cast<DebuggerdDumpType>(dump_type); |
349 | LOG(INFO) << "obtaining output fd from tombstoned, type: " << dump_type_enum; | ||
350 | tombstoned_connected = tombstoned_connect(target, &tombstoned_socket, &output_fd, dump_type_enum); | ||
351 | } | ||
327 | 352 | ||
328 | // Write a '\1' to stdout to tell the crashing process to resume. | 353 | // Write a '\1' to stdout to tell the crashing process to resume. |
329 | // It also restores the value of PR_SET_DUMPABLE at this point. | 354 | // It also restores the value of PR_SET_DUMPABLE at this point. |
@@ -352,9 +377,12 @@ int main(int argc, char** argv) { | |||
352 | } | 377 | } |
353 | 378 | ||
354 | siginfo_t siginfo = {}; | 379 | siginfo_t siginfo = {}; |
355 | if (!wait_for_signal(main_tid, &siginfo)) { | 380 | { |
356 | printf("failed to wait for signal in tid %d: %s\n", main_tid, strerror(errno)); | 381 | ATRACE_NAME("wait_for_signal"); |
357 | exit(1); | 382 | if (!wait_for_signal(main_tid, &siginfo)) { |
383 | printf("failed to wait for signal in tid %d: %s\n", main_tid, strerror(errno)); | ||
384 | exit(1); | ||
385 | } | ||
358 | } | 386 | } |
359 | 387 | ||
360 | int signo = siginfo.si_signo; | 388 | int signo = siginfo.si_signo; |
@@ -376,8 +404,10 @@ int main(int argc, char** argv) { | |||
376 | 404 | ||
377 | std::string amfd_data; | 405 | std::string amfd_data; |
378 | if (backtrace) { | 406 | if (backtrace) { |
407 | ATRACE_NAME("dump_backtrace"); | ||
379 | dump_backtrace(output_fd.get(), backtrace_map.get(), target, main_tid, process_name, threads, 0); | 408 | dump_backtrace(output_fd.get(), backtrace_map.get(), target, main_tid, process_name, threads, 0); |
380 | } else { | 409 | } else { |
410 | ATRACE_NAME("engrave_tombstone"); | ||
381 | engrave_tombstone(output_fd.get(), backtrace_map.get(), &open_files, target, main_tid, | 411 | engrave_tombstone(output_fd.get(), backtrace_map.get(), &open_files, target, main_tid, |
382 | process_name, threads, abort_address, fatal_signal ? &amfd_data : nullptr); | 412 | process_name, threads, abort_address, fatal_signal ? &amfd_data : nullptr); |
383 | } | 413 | } |
diff --git a/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp index 697020171..f57349b16 100644 --- a/debuggerd/crasher/crasher.cpp +++ b/debuggerd/crasher/crasher.cpp | |||
@@ -134,6 +134,14 @@ noinline void abuse_heap() { | |||
134 | free(buf); // GCC is smart enough to warn about this, but we're doing it deliberately. | 134 | free(buf); // GCC is smart enough to warn about this, but we're doing it deliberately. |
135 | } | 135 | } |
136 | 136 | ||
137 | noinline void leak() { | ||
138 | while (true) { | ||
139 | void* mapping = | ||
140 | mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | ||
141 | static_cast<volatile char*>(mapping)[0] = 'a'; | ||
142 | } | ||
143 | } | ||
144 | |||
137 | noinline void sigsegv_non_null() { | 145 | noinline void sigsegv_non_null() { |
138 | int* a = (int *)(&do_action); | 146 | int* a = (int *)(&do_action); |
139 | *a = 42; | 147 | *a = 42; |
@@ -160,8 +168,8 @@ static int usage() { | |||
160 | fprintf(stderr, " stack-overflow recurse until the stack overflows\n"); | 168 | fprintf(stderr, " stack-overflow recurse until the stack overflows\n"); |
161 | fprintf(stderr, " nostack crash with a NULL stack pointer\n"); | 169 | fprintf(stderr, " nostack crash with a NULL stack pointer\n"); |
162 | fprintf(stderr, "\n"); | 170 | fprintf(stderr, "\n"); |
163 | fprintf(stderr, " heap-corruption cause a libc abort by corrupting the heap\n"); | ||
164 | fprintf(stderr, " heap-usage cause a libc abort by abusing a heap function\n"); | 171 | fprintf(stderr, " heap-usage cause a libc abort by abusing a heap function\n"); |
172 | fprintf(stderr, " leak leak memory until we get OOM-killed\n"); | ||
165 | fprintf(stderr, "\n"); | 173 | fprintf(stderr, "\n"); |
166 | fprintf(stderr, " abort call abort()\n"); | 174 | fprintf(stderr, " abort call abort()\n"); |
167 | fprintf(stderr, " assert call assert() without a function\n"); | 175 | fprintf(stderr, " assert call assert() without a function\n"); |
@@ -265,6 +273,8 @@ noinline int do_action(const char* arg) { | |||
265 | return pthread_join(0, nullptr); | 273 | return pthread_join(0, nullptr); |
266 | } else if (!strcasecmp(arg, "heap-usage")) { | 274 | } else if (!strcasecmp(arg, "heap-usage")) { |
267 | abuse_heap(); | 275 | abuse_heap(); |
276 | } else if (!strcasecmp(arg, "leak")) { | ||
277 | leak(); | ||
268 | } else if (!strcasecmp(arg, "SIGSEGV-unmapped")) { | 278 | } else if (!strcasecmp(arg, "SIGSEGV-unmapped")) { |
269 | char* map = reinterpret_cast<char*>(mmap(nullptr, sizeof(int), PROT_READ | PROT_WRITE, | 279 | char* map = reinterpret_cast<char*>(mmap(nullptr, sizeof(int), PROT_READ | PROT_WRITE, |
270 | MAP_SHARED | MAP_ANONYMOUS, -1, 0)); | 280 | MAP_SHARED | MAP_ANONYMOUS, -1, 0)); |
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp index 6298ace9d..b016e23ee 100644 --- a/debuggerd/debuggerd.cpp +++ b/debuggerd/debuggerd.cpp | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <android-base/parseint.h> | 27 | #include <android-base/parseint.h> |
28 | #include <android-base/unique_fd.h> | 28 | #include <android-base/unique_fd.h> |
29 | #include <debuggerd/client.h> | 29 | #include <debuggerd/client.h> |
30 | #include <selinux/selinux.h> | 30 | #include <procinfo/process.h> |
31 | #include "util.h" | 31 | #include "util.h" |
32 | 32 | ||
33 | using android::base::unique_fd; | 33 | using android::base::unique_fd; |
@@ -66,6 +66,24 @@ int main(int argc, char* argv[]) { | |||
66 | usage(1); | 66 | usage(1); |
67 | } | 67 | } |
68 | 68 | ||
69 | if (getuid() != 0) { | ||
70 | errx(1, "root is required"); | ||
71 | } | ||
72 | |||
73 | // Check to see if the process exists and that we can actually send a signal to it. | ||
74 | android::procinfo::ProcessInfo proc_info; | ||
75 | if (!android::procinfo::GetProcessInfo(pid, &proc_info)) { | ||
76 | err(1, "failed to fetch info for process %d", pid); | ||
77 | } | ||
78 | |||
79 | if (proc_info.state == android::procinfo::kProcessStateZombie) { | ||
80 | errx(1, "process %d is a zombie", pid); | ||
81 | } | ||
82 | |||
83 | if (kill(pid, 0) != 0) { | ||
84 | err(1, "cannot send signal to process %d", pid); | ||
85 | } | ||
86 | |||
69 | unique_fd piperead, pipewrite; | 87 | unique_fd piperead, pipewrite; |
70 | if (!Pipe(&piperead, &pipewrite)) { | 88 | if (!Pipe(&piperead, &pipewrite)) { |
71 | err(1, "failed to create pipe"); | 89 | err(1, "failed to create pipe"); |
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp index 201515761..b51fc665e 100644 --- a/debuggerd/debuggerd_test.cpp +++ b/debuggerd/debuggerd_test.cpp | |||
@@ -88,8 +88,12 @@ constexpr char kWaitForGdbKey[] = "debug.debuggerd.wait_for_gdb"; | |||
88 | } \ | 88 | } \ |
89 | } while (0) | 89 | } while (0) |
90 | 90 | ||
91 | #define ASSERT_BACKTRACE_FRAME(result, frame_name) \ | ||
92 | ASSERT_MATCH(result, R"(#\d\d pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX \ | ||
93 | R"(/libc.so \()" frame_name R"(\+)") | ||
94 | |||
91 | static void tombstoned_intercept(pid_t target_pid, unique_fd* intercept_fd, unique_fd* output_fd, | 95 | static void tombstoned_intercept(pid_t target_pid, unique_fd* intercept_fd, unique_fd* output_fd, |
92 | DebuggerdDumpType intercept_type) { | 96 | InterceptStatus* status, DebuggerdDumpType intercept_type) { |
93 | intercept_fd->reset(socket_local_client(kTombstonedInterceptSocketName, | 97 | intercept_fd->reset(socket_local_client(kTombstonedInterceptSocketName, |
94 | ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET)); | 98 | ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET)); |
95 | if (intercept_fd->get() == -1) { | 99 | if (intercept_fd->get() == -1) { |
@@ -136,7 +140,7 @@ static void tombstoned_intercept(pid_t target_pid, unique_fd* intercept_fd, uniq | |||
136 | << ", received " << rc; | 140 | << ", received " << rc; |
137 | } | 141 | } |
138 | 142 | ||
139 | ASSERT_EQ(InterceptStatus::kRegistered, response.status); | 143 | *status = response.status; |
140 | } | 144 | } |
141 | 145 | ||
142 | class CrasherTest : public ::testing::Test { | 146 | class CrasherTest : public ::testing::Test { |
@@ -180,7 +184,9 @@ void CrasherTest::StartIntercept(unique_fd* output_fd, DebuggerdDumpType interce | |||
180 | FAIL() << "crasher hasn't been started"; | 184 | FAIL() << "crasher hasn't been started"; |
181 | } | 185 | } |
182 | 186 | ||
183 | tombstoned_intercept(crasher_pid, &this->intercept_fd, output_fd, intercept_type); | 187 | InterceptStatus status; |
188 | tombstoned_intercept(crasher_pid, &this->intercept_fd, output_fd, &status, intercept_type); | ||
189 | ASSERT_EQ(InterceptStatus::kRegistered, status); | ||
184 | } | 190 | } |
185 | 191 | ||
186 | void CrasherTest::FinishIntercept(int* result) { | 192 | void CrasherTest::FinishIntercept(int* result) { |
@@ -305,7 +311,7 @@ TEST_F(CrasherTest, abort) { | |||
305 | 311 | ||
306 | std::string result; | 312 | std::string result; |
307 | ConsumeFd(std::move(output_fd), &result); | 313 | ConsumeFd(std::move(output_fd), &result); |
308 | ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(abort)"); | 314 | ASSERT_BACKTRACE_FRAME(result, "abort"); |
309 | } | 315 | } |
310 | 316 | ||
311 | TEST_F(CrasherTest, signal) { | 317 | TEST_F(CrasherTest, signal) { |
@@ -441,7 +447,7 @@ TEST_F(CrasherTest, backtrace) { | |||
441 | FinishIntercept(&intercept_result); | 447 | FinishIntercept(&intercept_result); |
442 | ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; | 448 | ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; |
443 | ConsumeFd(std::move(output_fd), &result); | 449 | ConsumeFd(std::move(output_fd), &result); |
444 | ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(read\+)"); | 450 | ASSERT_BACKTRACE_FRAME(result, "read"); |
445 | 451 | ||
446 | int status; | 452 | int status; |
447 | ASSERT_EQ(0, waitpid(crasher_pid, &status, WNOHANG | WUNTRACED)); | 453 | ASSERT_EQ(0, waitpid(crasher_pid, &status, WNOHANG | WUNTRACED)); |
@@ -452,7 +458,7 @@ TEST_F(CrasherTest, backtrace) { | |||
452 | FinishIntercept(&intercept_result); | 458 | FinishIntercept(&intercept_result); |
453 | ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; | 459 | ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; |
454 | ConsumeFd(std::move(output_fd), &result); | 460 | ConsumeFd(std::move(output_fd), &result); |
455 | ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(abort)"); | 461 | ASSERT_BACKTRACE_FRAME(result, "abort"); |
456 | } | 462 | } |
457 | 463 | ||
458 | TEST_F(CrasherTest, PR_SET_DUMPABLE_0_crash) { | 464 | TEST_F(CrasherTest, PR_SET_DUMPABLE_0_crash) { |
@@ -472,7 +478,7 @@ TEST_F(CrasherTest, PR_SET_DUMPABLE_0_crash) { | |||
472 | 478 | ||
473 | std::string result; | 479 | std::string result; |
474 | ConsumeFd(std::move(output_fd), &result); | 480 | ConsumeFd(std::move(output_fd), &result); |
475 | ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(abort)"); | 481 | ASSERT_BACKTRACE_FRAME(result, "abort"); |
476 | } | 482 | } |
477 | 483 | ||
478 | TEST_F(CrasherTest, capabilities) { | 484 | TEST_F(CrasherTest, capabilities) { |
@@ -529,7 +535,7 @@ TEST_F(CrasherTest, capabilities) { | |||
529 | ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; | 535 | ASSERT_EQ(1, intercept_result) << "tombstoned reported failure"; |
530 | ConsumeFd(std::move(output_fd), &result); | 536 | ConsumeFd(std::move(output_fd), &result); |
531 | ASSERT_MATCH(result, R"(name: thread_name\s+>>> .+debuggerd_test(32|64) <<<)"); | 537 | ASSERT_MATCH(result, R"(name: thread_name\s+>>> .+debuggerd_test(32|64) <<<)"); |
532 | ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(tgkill)"); | 538 | ASSERT_BACKTRACE_FRAME(result, "tgkill"); |
533 | } | 539 | } |
534 | 540 | ||
535 | TEST_F(CrasherTest, fake_pid) { | 541 | TEST_F(CrasherTest, fake_pid) { |
@@ -560,7 +566,7 @@ TEST_F(CrasherTest, fake_pid) { | |||
560 | 566 | ||
561 | std::string result; | 567 | std::string result; |
562 | ConsumeFd(std::move(output_fd), &result); | 568 | ConsumeFd(std::move(output_fd), &result); |
563 | ASSERT_MATCH(result, R"(#00 pc [0-9a-f]+\s+ /system/lib)" ARCH_SUFFIX R"(/libc.so \(tgkill)"); | 569 | ASSERT_BACKTRACE_FRAME(result, "tgkill"); |
564 | } | 570 | } |
565 | 571 | ||
566 | TEST(crash_dump, zombie) { | 572 | TEST(crash_dump, zombie) { |
@@ -598,7 +604,9 @@ TEST(tombstoned, no_notify) { | |||
598 | pid_t pid = 123'456'789 + i; | 604 | pid_t pid = 123'456'789 + i; |
599 | 605 | ||
600 | unique_fd intercept_fd, output_fd; | 606 | unique_fd intercept_fd, output_fd; |
601 | tombstoned_intercept(pid, &intercept_fd, &output_fd, kDebuggerdTombstone); | 607 | InterceptStatus status; |
608 | tombstoned_intercept(pid, &intercept_fd, &output_fd, &status, kDebuggerdTombstone); | ||
609 | ASSERT_EQ(InterceptStatus::kRegistered, status); | ||
602 | 610 | ||
603 | { | 611 | { |
604 | unique_fd tombstoned_socket, input_fd; | 612 | unique_fd tombstoned_socket, input_fd; |
@@ -630,7 +638,9 @@ TEST(tombstoned, stress) { | |||
630 | pid_t pid = pid_base + dump; | 638 | pid_t pid = pid_base + dump; |
631 | 639 | ||
632 | unique_fd intercept_fd, output_fd; | 640 | unique_fd intercept_fd, output_fd; |
633 | tombstoned_intercept(pid, &intercept_fd, &output_fd, kDebuggerdTombstone); | 641 | InterceptStatus status; |
642 | tombstoned_intercept(pid, &intercept_fd, &output_fd, &status, kDebuggerdTombstone); | ||
643 | ASSERT_EQ(InterceptStatus::kRegistered, status); | ||
634 | 644 | ||
635 | // Pretend to crash, and then immediately close the socket. | 645 | // Pretend to crash, and then immediately close the socket. |
636 | unique_fd sockfd(socket_local_client(kTombstonedCrashSocketName, | 646 | unique_fd sockfd(socket_local_client(kTombstonedCrashSocketName, |
@@ -661,7 +671,9 @@ TEST(tombstoned, stress) { | |||
661 | pid_t pid = pid_base + dump; | 671 | pid_t pid = pid_base + dump; |
662 | 672 | ||
663 | unique_fd intercept_fd, output_fd; | 673 | unique_fd intercept_fd, output_fd; |
664 | tombstoned_intercept(pid, &intercept_fd, &output_fd, kDebuggerdTombstone); | 674 | InterceptStatus status; |
675 | tombstoned_intercept(pid, &intercept_fd, &output_fd, &status, kDebuggerdTombstone); | ||
676 | ASSERT_EQ(InterceptStatus::kRegistered, status); | ||
665 | 677 | ||
666 | { | 678 | { |
667 | unique_fd tombstoned_socket, input_fd; | 679 | unique_fd tombstoned_socket, input_fd; |
@@ -685,3 +697,65 @@ TEST(tombstoned, stress) { | |||
685 | thread.join(); | 697 | thread.join(); |
686 | } | 698 | } |
687 | } | 699 | } |
700 | |||
701 | TEST(tombstoned, java_trace_intercept_smoke) { | ||
702 | // Using a "real" PID is a little dangerous here - if the test fails | ||
703 | // or crashes, we might end up getting a bogus / unreliable stack | ||
704 | // trace. | ||
705 | const pid_t self = getpid(); | ||
706 | |||
707 | unique_fd intercept_fd, output_fd; | ||
708 | InterceptStatus status; | ||
709 | tombstoned_intercept(self, &intercept_fd, &output_fd, &status, kDebuggerdJavaBacktrace); | ||
710 | ASSERT_EQ(InterceptStatus::kRegistered, status); | ||
711 | |||
712 | // First connect to tombstoned requesting a native backtrace. This | ||
713 | // should result in a "regular" FD and not the installed intercept. | ||
714 | const char native[] = "native"; | ||
715 | unique_fd tombstoned_socket, input_fd; | ||
716 | ASSERT_TRUE(tombstoned_connect(self, &tombstoned_socket, &input_fd, kDebuggerdNativeBacktrace)); | ||
717 | ASSERT_TRUE(android::base::WriteFully(input_fd.get(), native, sizeof(native))); | ||
718 | tombstoned_notify_completion(tombstoned_socket.get()); | ||
719 | |||
720 | // Then, connect to tombstoned asking for a java backtrace. This *should* | ||
721 | // trigger the intercept. | ||
722 | const char java[] = "java"; | ||
723 | ASSERT_TRUE(tombstoned_connect(self, &tombstoned_socket, &input_fd, kDebuggerdJavaBacktrace)); | ||
724 | ASSERT_TRUE(android::base::WriteFully(input_fd.get(), java, sizeof(java))); | ||
725 | tombstoned_notify_completion(tombstoned_socket.get()); | ||
726 | |||
727 | char outbuf[sizeof(java)]; | ||
728 | ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf))); | ||
729 | ASSERT_STREQ("java", outbuf); | ||
730 | } | ||
731 | |||
732 | TEST(tombstoned, multiple_intercepts) { | ||
733 | const pid_t fake_pid = 1'234'567; | ||
734 | unique_fd intercept_fd, output_fd; | ||
735 | InterceptStatus status; | ||
736 | tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &status, kDebuggerdJavaBacktrace); | ||
737 | ASSERT_EQ(InterceptStatus::kRegistered, status); | ||
738 | |||
739 | unique_fd intercept_fd_2, output_fd_2; | ||
740 | tombstoned_intercept(fake_pid, &intercept_fd_2, &output_fd_2, &status, kDebuggerdNativeBacktrace); | ||
741 | ASSERT_EQ(InterceptStatus::kFailedAlreadyRegistered, status); | ||
742 | } | ||
743 | |||
744 | TEST(tombstoned, intercept_any) { | ||
745 | const pid_t fake_pid = 1'234'567; | ||
746 | |||
747 | unique_fd intercept_fd, output_fd; | ||
748 | InterceptStatus status; | ||
749 | tombstoned_intercept(fake_pid, &intercept_fd, &output_fd, &status, kDebuggerdNativeBacktrace); | ||
750 | ASSERT_EQ(InterceptStatus::kRegistered, status); | ||
751 | |||
752 | const char any[] = "any"; | ||
753 | unique_fd tombstoned_socket, input_fd; | ||
754 | ASSERT_TRUE(tombstoned_connect(fake_pid, &tombstoned_socket, &input_fd, kDebuggerdAnyIntercept)); | ||
755 | ASSERT_TRUE(android::base::WriteFully(input_fd.get(), any, sizeof(any))); | ||
756 | tombstoned_notify_completion(tombstoned_socket.get()); | ||
757 | |||
758 | char outbuf[sizeof(any)]; | ||
759 | ASSERT_TRUE(android::base::ReadFully(output_fd.get(), outbuf, sizeof(outbuf))); | ||
760 | ASSERT_STREQ("any", outbuf); | ||
761 | } | ||
diff --git a/debuggerd/libdebuggerd/test/tombstone_test.cpp b/debuggerd/libdebuggerd/test/tombstone_test.cpp index 325210d94..6be59e7ac 100644 --- a/debuggerd/libdebuggerd/test/tombstone_test.cpp +++ b/debuggerd/libdebuggerd/test/tombstone_test.cpp | |||
@@ -220,21 +220,21 @@ TEST_F(TombstoneTest, multiple_maps) { | |||
220 | map.start = 0xa434000; | 220 | map.start = 0xa434000; |
221 | map.end = 0xa435000; | 221 | map.end = 0xa435000; |
222 | map.offset = 0x1000; | 222 | map.offset = 0x1000; |
223 | map.load_base = 0xd000; | 223 | map.load_bias = 0xd000; |
224 | map.flags = PROT_WRITE; | 224 | map.flags = PROT_WRITE; |
225 | map_mock_->AddMap(map); | 225 | map_mock_->AddMap(map); |
226 | 226 | ||
227 | map.start = 0xa534000; | 227 | map.start = 0xa534000; |
228 | map.end = 0xa535000; | 228 | map.end = 0xa535000; |
229 | map.offset = 0x3000; | 229 | map.offset = 0x3000; |
230 | map.load_base = 0x2000; | 230 | map.load_bias = 0x2000; |
231 | map.flags = PROT_EXEC; | 231 | map.flags = PROT_EXEC; |
232 | map_mock_->AddMap(map); | 232 | map_mock_->AddMap(map); |
233 | 233 | ||
234 | map.start = 0xa634000; | 234 | map.start = 0xa634000; |
235 | map.end = 0xa635000; | 235 | map.end = 0xa635000; |
236 | map.offset = 0; | 236 | map.offset = 0; |
237 | map.load_base = 0; | 237 | map.load_bias = 0; |
238 | map.flags = PROT_READ | PROT_WRITE | PROT_EXEC; | 238 | map.flags = PROT_READ | PROT_WRITE | PROT_EXEC; |
239 | map.name = "/system/lib/fake.so"; | 239 | map.name = "/system/lib/fake.so"; |
240 | map_mock_->AddMap(map); | 240 | map_mock_->AddMap(map); |
@@ -244,20 +244,20 @@ TEST_F(TombstoneTest, multiple_maps) { | |||
244 | std::string tombstone_contents; | 244 | std::string tombstone_contents; |
245 | ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); | 245 | ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); |
246 | ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); | 246 | ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); |
247 | const char* expected_dump = \ | 247 | const char* expected_dump = |
248 | "\nmemory map:\n" | 248 | "\nmemory map:\n" |
249 | #if defined(__LP64__) | 249 | #if defined(__LP64__) |
250 | " 00000000'0a234000-00000000'0a234fff --- 0 1000\n" | 250 | " 00000000'0a234000-00000000'0a234fff --- 0 1000\n" |
251 | " 00000000'0a334000-00000000'0a334fff r-- f000 1000\n" | 251 | " 00000000'0a334000-00000000'0a334fff r-- f000 1000\n" |
252 | " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load base 0xd000)\n" | 252 | " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load bias 0xd000)\n" |
253 | " 00000000'0a534000-00000000'0a534fff --x 3000 1000 (load base 0x2000)\n" | 253 | " 00000000'0a534000-00000000'0a534fff --x 3000 1000 (load bias 0x2000)\n" |
254 | " 00000000'0a634000-00000000'0a634fff rwx 0 1000 /system/lib/fake.so\n"; | 254 | " 00000000'0a634000-00000000'0a634fff rwx 0 1000 /system/lib/fake.so\n"; |
255 | #else | 255 | #else |
256 | " 0a234000-0a234fff --- 0 1000\n" | 256 | " 0a234000-0a234fff --- 0 1000\n" |
257 | " 0a334000-0a334fff r-- f000 1000\n" | 257 | " 0a334000-0a334fff r-- f000 1000\n" |
258 | " 0a434000-0a434fff -w- 1000 1000 (load base 0xd000)\n" | 258 | " 0a434000-0a434fff -w- 1000 1000 (load bias 0xd000)\n" |
259 | " 0a534000-0a534fff --x 3000 1000 (load base 0x2000)\n" | 259 | " 0a534000-0a534fff --x 3000 1000 (load bias 0x2000)\n" |
260 | " 0a634000-0a634fff rwx 0 1000 /system/lib/fake.so\n"; | 260 | " 0a634000-0a634fff rwx 0 1000 /system/lib/fake.so\n"; |
261 | #endif | 261 | #endif |
262 | ASSERT_STREQ(expected_dump, tombstone_contents.c_str()); | 262 | ASSERT_STREQ(expected_dump, tombstone_contents.c_str()); |
263 | 263 | ||
@@ -274,21 +274,21 @@ TEST_F(TombstoneTest, multiple_maps_fault_address_before) { | |||
274 | map.start = 0xa434000; | 274 | map.start = 0xa434000; |
275 | map.end = 0xa435000; | 275 | map.end = 0xa435000; |
276 | map.offset = 0x1000; | 276 | map.offset = 0x1000; |
277 | map.load_base = 0xd000; | 277 | map.load_bias = 0xd000; |
278 | map.flags = PROT_WRITE; | 278 | map.flags = PROT_WRITE; |
279 | map_mock_->AddMap(map); | 279 | map_mock_->AddMap(map); |
280 | 280 | ||
281 | map.start = 0xa534000; | 281 | map.start = 0xa534000; |
282 | map.end = 0xa535000; | 282 | map.end = 0xa535000; |
283 | map.offset = 0x3000; | 283 | map.offset = 0x3000; |
284 | map.load_base = 0x2000; | 284 | map.load_bias = 0x2000; |
285 | map.flags = PROT_EXEC; | 285 | map.flags = PROT_EXEC; |
286 | map_mock_->AddMap(map); | 286 | map_mock_->AddMap(map); |
287 | 287 | ||
288 | map.start = 0xa634000; | 288 | map.start = 0xa634000; |
289 | map.end = 0xa635000; | 289 | map.end = 0xa635000; |
290 | map.offset = 0; | 290 | map.offset = 0; |
291 | map.load_base = 0; | 291 | map.load_bias = 0; |
292 | map.flags = PROT_READ | PROT_WRITE | PROT_EXEC; | 292 | map.flags = PROT_READ | PROT_WRITE | PROT_EXEC; |
293 | map.name = "/system/lib/fake.so"; | 293 | map.name = "/system/lib/fake.so"; |
294 | map_mock_->AddMap(map); | 294 | map_mock_->AddMap(map); |
@@ -304,18 +304,18 @@ TEST_F(TombstoneTest, multiple_maps_fault_address_before) { | |||
304 | std::string tombstone_contents; | 304 | std::string tombstone_contents; |
305 | ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); | 305 | ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); |
306 | ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); | 306 | ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); |
307 | const char* expected_dump = \ | 307 | const char* expected_dump = |
308 | "\nmemory map: (fault address prefixed with --->)\n" | 308 | "\nmemory map: (fault address prefixed with --->)\n" |
309 | #if defined(__LP64__) | 309 | #if defined(__LP64__) |
310 | "--->Fault address falls at 00000000'00001000 before any mapped regions\n" | 310 | "--->Fault address falls at 00000000'00001000 before any mapped regions\n" |
311 | " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load base 0xd000)\n" | 311 | " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load bias 0xd000)\n" |
312 | " 00000000'0a534000-00000000'0a534fff --x 3000 1000 (load base 0x2000)\n" | 312 | " 00000000'0a534000-00000000'0a534fff --x 3000 1000 (load bias 0x2000)\n" |
313 | " 00000000'0a634000-00000000'0a634fff rwx 0 1000 /system/lib/fake.so\n"; | 313 | " 00000000'0a634000-00000000'0a634fff rwx 0 1000 /system/lib/fake.so\n"; |
314 | #else | 314 | #else |
315 | "--->Fault address falls at 00001000 before any mapped regions\n" | 315 | "--->Fault address falls at 00001000 before any mapped regions\n" |
316 | " 0a434000-0a434fff -w- 1000 1000 (load base 0xd000)\n" | 316 | " 0a434000-0a434fff -w- 1000 1000 (load bias 0xd000)\n" |
317 | " 0a534000-0a534fff --x 3000 1000 (load base 0x2000)\n" | 317 | " 0a534000-0a534fff --x 3000 1000 (load bias 0x2000)\n" |
318 | " 0a634000-0a634fff rwx 0 1000 /system/lib/fake.so\n"; | 318 | " 0a634000-0a634fff rwx 0 1000 /system/lib/fake.so\n"; |
319 | #endif | 319 | #endif |
320 | ASSERT_STREQ(expected_dump, tombstone_contents.c_str()); | 320 | ASSERT_STREQ(expected_dump, tombstone_contents.c_str()); |
321 | 321 | ||
@@ -332,21 +332,21 @@ TEST_F(TombstoneTest, multiple_maps_fault_address_between) { | |||
332 | map.start = 0xa434000; | 332 | map.start = 0xa434000; |
333 | map.end = 0xa435000; | 333 | map.end = 0xa435000; |
334 | map.offset = 0x1000; | 334 | map.offset = 0x1000; |
335 | map.load_base = 0xd000; | 335 | map.load_bias = 0xd000; |
336 | map.flags = PROT_WRITE; | 336 | map.flags = PROT_WRITE; |
337 | map_mock_->AddMap(map); | 337 | map_mock_->AddMap(map); |
338 | 338 | ||
339 | map.start = 0xa534000; | 339 | map.start = 0xa534000; |
340 | map.end = 0xa535000; | 340 | map.end = 0xa535000; |
341 | map.offset = 0x3000; | 341 | map.offset = 0x3000; |
342 | map.load_base = 0x2000; | 342 | map.load_bias = 0x2000; |
343 | map.flags = PROT_EXEC; | 343 | map.flags = PROT_EXEC; |
344 | map_mock_->AddMap(map); | 344 | map_mock_->AddMap(map); |
345 | 345 | ||
346 | map.start = 0xa634000; | 346 | map.start = 0xa634000; |
347 | map.end = 0xa635000; | 347 | map.end = 0xa635000; |
348 | map.offset = 0; | 348 | map.offset = 0; |
349 | map.load_base = 0; | 349 | map.load_bias = 0; |
350 | map.flags = PROT_READ | PROT_WRITE | PROT_EXEC; | 350 | map.flags = PROT_READ | PROT_WRITE | PROT_EXEC; |
351 | map.name = "/system/lib/fake.so"; | 351 | map.name = "/system/lib/fake.so"; |
352 | map_mock_->AddMap(map); | 352 | map_mock_->AddMap(map); |
@@ -362,18 +362,18 @@ TEST_F(TombstoneTest, multiple_maps_fault_address_between) { | |||
362 | std::string tombstone_contents; | 362 | std::string tombstone_contents; |
363 | ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); | 363 | ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); |
364 | ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); | 364 | ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); |
365 | const char* expected_dump = \ | 365 | const char* expected_dump = |
366 | "\nmemory map: (fault address prefixed with --->)\n" | 366 | "\nmemory map: (fault address prefixed with --->)\n" |
367 | #if defined(__LP64__) | 367 | #if defined(__LP64__) |
368 | " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load base 0xd000)\n" | 368 | " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load bias 0xd000)\n" |
369 | "--->Fault address falls at 00000000'0a533000 between mapped regions\n" | 369 | "--->Fault address falls at 00000000'0a533000 between mapped regions\n" |
370 | " 00000000'0a534000-00000000'0a534fff --x 3000 1000 (load base 0x2000)\n" | 370 | " 00000000'0a534000-00000000'0a534fff --x 3000 1000 (load bias 0x2000)\n" |
371 | " 00000000'0a634000-00000000'0a634fff rwx 0 1000 /system/lib/fake.so\n"; | 371 | " 00000000'0a634000-00000000'0a634fff rwx 0 1000 /system/lib/fake.so\n"; |
372 | #else | 372 | #else |
373 | " 0a434000-0a434fff -w- 1000 1000 (load base 0xd000)\n" | 373 | " 0a434000-0a434fff -w- 1000 1000 (load bias 0xd000)\n" |
374 | "--->Fault address falls at 0a533000 between mapped regions\n" | 374 | "--->Fault address falls at 0a533000 between mapped regions\n" |
375 | " 0a534000-0a534fff --x 3000 1000 (load base 0x2000)\n" | 375 | " 0a534000-0a534fff --x 3000 1000 (load bias 0x2000)\n" |
376 | " 0a634000-0a634fff rwx 0 1000 /system/lib/fake.so\n"; | 376 | " 0a634000-0a634fff rwx 0 1000 /system/lib/fake.so\n"; |
377 | #endif | 377 | #endif |
378 | ASSERT_STREQ(expected_dump, tombstone_contents.c_str()); | 378 | ASSERT_STREQ(expected_dump, tombstone_contents.c_str()); |
379 | 379 | ||
@@ -390,21 +390,21 @@ TEST_F(TombstoneTest, multiple_maps_fault_address_in_map) { | |||
390 | map.start = 0xa434000; | 390 | map.start = 0xa434000; |
391 | map.end = 0xa435000; | 391 | map.end = 0xa435000; |
392 | map.offset = 0x1000; | 392 | map.offset = 0x1000; |
393 | map.load_base = 0xd000; | 393 | map.load_bias = 0xd000; |
394 | map.flags = PROT_WRITE; | 394 | map.flags = PROT_WRITE; |
395 | map_mock_->AddMap(map); | 395 | map_mock_->AddMap(map); |
396 | 396 | ||
397 | map.start = 0xa534000; | 397 | map.start = 0xa534000; |
398 | map.end = 0xa535000; | 398 | map.end = 0xa535000; |
399 | map.offset = 0x3000; | 399 | map.offset = 0x3000; |
400 | map.load_base = 0x2000; | 400 | map.load_bias = 0x2000; |
401 | map.flags = PROT_EXEC; | 401 | map.flags = PROT_EXEC; |
402 | map_mock_->AddMap(map); | 402 | map_mock_->AddMap(map); |
403 | 403 | ||
404 | map.start = 0xa634000; | 404 | map.start = 0xa634000; |
405 | map.end = 0xa635000; | 405 | map.end = 0xa635000; |
406 | map.offset = 0; | 406 | map.offset = 0; |
407 | map.load_base = 0; | 407 | map.load_bias = 0; |
408 | map.flags = PROT_READ | PROT_WRITE | PROT_EXEC; | 408 | map.flags = PROT_READ | PROT_WRITE | PROT_EXEC; |
409 | map.name = "/system/lib/fake.so"; | 409 | map.name = "/system/lib/fake.so"; |
410 | map_mock_->AddMap(map); | 410 | map_mock_->AddMap(map); |
@@ -420,16 +420,16 @@ TEST_F(TombstoneTest, multiple_maps_fault_address_in_map) { | |||
420 | std::string tombstone_contents; | 420 | std::string tombstone_contents; |
421 | ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); | 421 | ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); |
422 | ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); | 422 | ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); |
423 | const char* expected_dump = \ | 423 | const char* expected_dump = |
424 | "\nmemory map: (fault address prefixed with --->)\n" | 424 | "\nmemory map: (fault address prefixed with --->)\n" |
425 | #if defined(__LP64__) | 425 | #if defined(__LP64__) |
426 | " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load base 0xd000)\n" | 426 | " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load bias 0xd000)\n" |
427 | "--->00000000'0a534000-00000000'0a534fff --x 3000 1000 (load base 0x2000)\n" | 427 | "--->00000000'0a534000-00000000'0a534fff --x 3000 1000 (load bias 0x2000)\n" |
428 | " 00000000'0a634000-00000000'0a634fff rwx 0 1000 /system/lib/fake.so\n"; | 428 | " 00000000'0a634000-00000000'0a634fff rwx 0 1000 /system/lib/fake.so\n"; |
429 | #else | 429 | #else |
430 | " 0a434000-0a434fff -w- 1000 1000 (load base 0xd000)\n" | 430 | " 0a434000-0a434fff -w- 1000 1000 (load bias 0xd000)\n" |
431 | "--->0a534000-0a534fff --x 3000 1000 (load base 0x2000)\n" | 431 | "--->0a534000-0a534fff --x 3000 1000 (load bias 0x2000)\n" |
432 | " 0a634000-0a634fff rwx 0 1000 /system/lib/fake.so\n"; | 432 | " 0a634000-0a634fff rwx 0 1000 /system/lib/fake.so\n"; |
433 | #endif | 433 | #endif |
434 | ASSERT_STREQ(expected_dump, tombstone_contents.c_str()); | 434 | ASSERT_STREQ(expected_dump, tombstone_contents.c_str()); |
435 | 435 | ||
@@ -446,21 +446,21 @@ TEST_F(TombstoneTest, multiple_maps_fault_address_after) { | |||
446 | map.start = 0xa434000; | 446 | map.start = 0xa434000; |
447 | map.end = 0xa435000; | 447 | map.end = 0xa435000; |
448 | map.offset = 0x1000; | 448 | map.offset = 0x1000; |
449 | map.load_base = 0xd000; | 449 | map.load_bias = 0xd000; |
450 | map.flags = PROT_WRITE; | 450 | map.flags = PROT_WRITE; |
451 | map_mock_->AddMap(map); | 451 | map_mock_->AddMap(map); |
452 | 452 | ||
453 | map.start = 0xa534000; | 453 | map.start = 0xa534000; |
454 | map.end = 0xa535000; | 454 | map.end = 0xa535000; |
455 | map.offset = 0x3000; | 455 | map.offset = 0x3000; |
456 | map.load_base = 0x2000; | 456 | map.load_bias = 0x2000; |
457 | map.flags = PROT_EXEC; | 457 | map.flags = PROT_EXEC; |
458 | map_mock_->AddMap(map); | 458 | map_mock_->AddMap(map); |
459 | 459 | ||
460 | map.start = 0xa634000; | 460 | map.start = 0xa634000; |
461 | map.end = 0xa635000; | 461 | map.end = 0xa635000; |
462 | map.offset = 0; | 462 | map.offset = 0; |
463 | map.load_base = 0; | 463 | map.load_bias = 0; |
464 | map.flags = PROT_READ | PROT_WRITE | PROT_EXEC; | 464 | map.flags = PROT_READ | PROT_WRITE | PROT_EXEC; |
465 | map.name = "/system/lib/fake.so"; | 465 | map.name = "/system/lib/fake.so"; |
466 | map_mock_->AddMap(map); | 466 | map_mock_->AddMap(map); |
@@ -480,18 +480,18 @@ TEST_F(TombstoneTest, multiple_maps_fault_address_after) { | |||
480 | std::string tombstone_contents; | 480 | std::string tombstone_contents; |
481 | ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); | 481 | ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); |
482 | ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); | 482 | ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); |
483 | const char* expected_dump = \ | 483 | const char* expected_dump = |
484 | "\nmemory map: (fault address prefixed with --->)\n" | 484 | "\nmemory map: (fault address prefixed with --->)\n" |
485 | #if defined(__LP64__) | 485 | #if defined(__LP64__) |
486 | " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load base 0xd000)\n" | 486 | " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load bias 0xd000)\n" |
487 | " 00000000'0a534000-00000000'0a534fff --x 3000 1000 (load base 0x2000)\n" | 487 | " 00000000'0a534000-00000000'0a534fff --x 3000 1000 (load bias 0x2000)\n" |
488 | " 00000000'0a634000-00000000'0a634fff rwx 0 1000 /system/lib/fake.so\n" | 488 | " 00000000'0a634000-00000000'0a634fff rwx 0 1000 /system/lib/fake.so\n" |
489 | "--->Fault address falls at 00001234'5a534040 after any mapped regions\n"; | 489 | "--->Fault address falls at 00001234'5a534040 after any mapped regions\n"; |
490 | #else | 490 | #else |
491 | " 0a434000-0a434fff -w- 1000 1000 (load base 0xd000)\n" | 491 | " 0a434000-0a434fff -w- 1000 1000 (load bias 0xd000)\n" |
492 | " 0a534000-0a534fff --x 3000 1000 (load base 0x2000)\n" | 492 | " 0a534000-0a534fff --x 3000 1000 (load bias 0x2000)\n" |
493 | " 0a634000-0a634fff rwx 0 1000 /system/lib/fake.so\n" | 493 | " 0a634000-0a634fff rwx 0 1000 /system/lib/fake.so\n" |
494 | "--->Fault address falls at 0f534040 after any mapped regions\n"; | 494 | "--->Fault address falls at 0f534040 after any mapped regions\n"; |
495 | #endif | 495 | #endif |
496 | ASSERT_STREQ(expected_dump, tombstone_contents.c_str()); | 496 | ASSERT_STREQ(expected_dump, tombstone_contents.c_str()); |
497 | 497 | ||
@@ -508,7 +508,7 @@ TEST_F(TombstoneTest, multiple_maps_getsiginfo_fail) { | |||
508 | map.start = 0xa434000; | 508 | map.start = 0xa434000; |
509 | map.end = 0xa435000; | 509 | map.end = 0xa435000; |
510 | map.offset = 0x1000; | 510 | map.offset = 0x1000; |
511 | map.load_base = 0xd000; | 511 | map.load_bias = 0xd000; |
512 | map.flags = PROT_WRITE; | 512 | map.flags = PROT_WRITE; |
513 | map_mock_->AddMap(map); | 513 | map_mock_->AddMap(map); |
514 | 514 | ||
@@ -520,12 +520,12 @@ TEST_F(TombstoneTest, multiple_maps_getsiginfo_fail) { | |||
520 | std::string tombstone_contents; | 520 | std::string tombstone_contents; |
521 | ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); | 521 | ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); |
522 | ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); | 522 | ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); |
523 | const char* expected_dump = \ | 523 | const char* expected_dump = |
524 | "\nmemory map:\n" | 524 | "\nmemory map:\n" |
525 | #if defined(__LP64__) | 525 | #if defined(__LP64__) |
526 | " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load base 0xd000)\n"; | 526 | " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load bias 0xd000)\n"; |
527 | #else | 527 | #else |
528 | " 0a434000-0a434fff -w- 1000 1000 (load base 0xd000)\n"; | 528 | " 0a434000-0a434fff -w- 1000 1000 (load bias 0xd000)\n"; |
529 | #endif | 529 | #endif |
530 | ASSERT_STREQ(expected_dump, tombstone_contents.c_str()); | 530 | ASSERT_STREQ(expected_dump, tombstone_contents.c_str()); |
531 | 531 | ||
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp index edc7be5e2..011313149 100644 --- a/debuggerd/libdebuggerd/tombstone.cpp +++ b/debuggerd/libdebuggerd/tombstone.cpp | |||
@@ -168,6 +168,26 @@ static const char* get_sigcode(int signo, int code) { | |||
168 | case TRAP_BRANCH: return "TRAP_BRANCH"; | 168 | case TRAP_BRANCH: return "TRAP_BRANCH"; |
169 | case TRAP_HWBKPT: return "TRAP_HWBKPT"; | 169 | case TRAP_HWBKPT: return "TRAP_HWBKPT"; |
170 | } | 170 | } |
171 | if ((code & 0xff) == SIGTRAP) { | ||
172 | switch ((code >> 8) & 0xff) { | ||
173 | case PTRACE_EVENT_FORK: | ||
174 | return "PTRACE_EVENT_FORK"; | ||
175 | case PTRACE_EVENT_VFORK: | ||
176 | return "PTRACE_EVENT_VFORK"; | ||
177 | case PTRACE_EVENT_CLONE: | ||
178 | return "PTRACE_EVENT_CLONE"; | ||
179 | case PTRACE_EVENT_EXEC: | ||
180 | return "PTRACE_EVENT_EXEC"; | ||
181 | case PTRACE_EVENT_VFORK_DONE: | ||
182 | return "PTRACE_EVENT_VFORK_DONE"; | ||
183 | case PTRACE_EVENT_EXIT: | ||
184 | return "PTRACE_EVENT_EXIT"; | ||
185 | case PTRACE_EVENT_SECCOMP: | ||
186 | return "PTRACE_EVENT_SECCOMP"; | ||
187 | case PTRACE_EVENT_STOP: | ||
188 | return "PTRACE_EVENT_STOP"; | ||
189 | } | ||
190 | } | ||
171 | static_assert(NSIGTRAP == TRAP_HWBKPT, "missing TRAP_* si_code"); | 191 | static_assert(NSIGTRAP == TRAP_HWBKPT, "missing TRAP_* si_code"); |
172 | break; | 192 | break; |
173 | } | 193 | } |
@@ -446,11 +466,11 @@ static void dump_all_maps(Backtrace* backtrace, BacktraceMap* map, log_t* log, p | |||
446 | line += " (BuildId: " + build_id + ")"; | 466 | line += " (BuildId: " + build_id + ")"; |
447 | } | 467 | } |
448 | } | 468 | } |
449 | if (it->load_base != 0) { | 469 | if (it->load_bias != 0) { |
450 | if (space_needed) { | 470 | if (space_needed) { |
451 | line += ' '; | 471 | line += ' '; |
452 | } | 472 | } |
453 | line += StringPrintf(" (load base 0x%" PRIxPTR ")", it->load_base); | 473 | line += StringPrintf(" (load bias 0x%" PRIxPTR ")", it->load_bias); |
454 | } | 474 | } |
455 | _LOG(log, logtype::MAPS, "%s\n", line.c_str()); | 475 | _LOG(log, logtype::MAPS, "%s\n", line.c_str()); |
456 | } | 476 | } |
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp index 09cff4559..93c7fb5b8 100644 --- a/debuggerd/tombstoned/tombstoned.cpp +++ b/debuggerd/tombstoned/tombstoned.cpp | |||
@@ -103,7 +103,7 @@ class CrashQueue { | |||
103 | } | 103 | } |
104 | 104 | ||
105 | static CrashQueue* for_anrs() { | 105 | static CrashQueue* for_anrs() { |
106 | static CrashQueue queue("/data/anr", "anr_" /* file_name_prefix */, | 106 | static CrashQueue queue("/data/anr", "trace_" /* file_name_prefix */, |
107 | GetIntProperty("tombstoned.max_anr_count", 64), | 107 | GetIntProperty("tombstoned.max_anr_count", 64), |
108 | 4 /* max_concurrent_dumps */); | 108 | 4 /* max_concurrent_dumps */); |
109 | return &queue; | 109 | return &queue; |
@@ -194,7 +194,7 @@ class CrashQueue { | |||
194 | }; | 194 | }; |
195 | 195 | ||
196 | // Whether java trace dumps are produced via tombstoned. | 196 | // Whether java trace dumps are produced via tombstoned. |
197 | static constexpr bool kJavaTraceDumpsEnabled = false; | 197 | static constexpr bool kJavaTraceDumpsEnabled = true; |
198 | 198 | ||
199 | // Forward declare the callbacks so they can be placed in a sensible order. | 199 | // Forward declare the callbacks so they can be placed in a sensible order. |
200 | static void crash_accept_cb(evconnlistener* listener, evutil_socket_t sockfd, sockaddr*, int, void*); | 200 | static void crash_accept_cb(evconnlistener* listener, evutil_socket_t sockfd, sockaddr*, int, void*); |
@@ -343,7 +343,14 @@ static void crash_completed_cb(evutil_socket_t sockfd, short ev, void* arg) { | |||
343 | } | 343 | } |
344 | 344 | ||
345 | if (!crash->crash_path.empty()) { | 345 | if (!crash->crash_path.empty()) { |
346 | LOG(ERROR) << "Tombstone written to: " << crash->crash_path; | 346 | if (crash->crash_type == kDebuggerdJavaBacktrace) { |
347 | LOG(ERROR) << "Traces for pid " << crash->crash_pid << " written to: " << crash->crash_path; | ||
348 | } else { | ||
349 | // NOTE: Several tools parse this log message to figure out where the | ||
350 | // tombstone associated with a given native crash was written. Any changes | ||
351 | // to this message must be carefully considered. | ||
352 | LOG(ERROR) << "Tombstone written to: " << crash->crash_path; | ||
353 | } | ||
347 | } | 354 | } |
348 | 355 | ||
349 | fail: | 356 | fail: |
diff --git a/debuggerd/tombstoned/tombstoned.rc b/debuggerd/tombstoned/tombstoned.rc index b8345cacf..53ef01c5f 100644 --- a/debuggerd/tombstoned/tombstoned.rc +++ b/debuggerd/tombstoned/tombstoned.rc | |||
@@ -7,4 +7,5 @@ service tombstoned /system/bin/tombstoned | |||
7 | 7 | ||
8 | socket tombstoned_crash seqpacket 0666 system system | 8 | socket tombstoned_crash seqpacket 0666 system system |
9 | socket tombstoned_intercept seqpacket 0666 system system | 9 | socket tombstoned_intercept seqpacket 0666 system system |
10 | socket tombstoned_java_trace seqpacket 0666 system system | ||
10 | writepid /dev/cpuset/system-background/tasks | 11 | writepid /dev/cpuset/system-background/tasks |
diff --git a/demangle/Android.bp b/demangle/Android.bp index ce617a794..e55c8869f 100644 --- a/demangle/Android.bp +++ b/demangle/Android.bp | |||
@@ -28,10 +28,8 @@ cc_defaults { | |||
28 | 28 | ||
29 | cc_library { | 29 | cc_library { |
30 | name: "libdemangle", | 30 | name: "libdemangle", |
31 | |||
32 | vendor_available: true, | ||
33 | |||
34 | defaults: ["libdemangle_defaults"], | 31 | defaults: ["libdemangle_defaults"], |
32 | vendor_available: true, | ||
35 | 33 | ||
36 | srcs: [ | 34 | srcs: [ |
37 | "Demangler.cpp", | 35 | "Demangler.cpp", |
diff --git a/fastboot/Android.mk b/fastboot/Android.mk index 80def732c..dd8bad9aa 100644 --- a/fastboot/Android.mk +++ b/fastboot/Android.mk | |||
@@ -40,6 +40,7 @@ LOCAL_MODULE := fastboot | |||
40 | LOCAL_MODULE_TAGS := debug | 40 | LOCAL_MODULE_TAGS := debug |
41 | LOCAL_MODULE_HOST_OS := darwin linux windows | 41 | LOCAL_MODULE_HOST_OS := darwin linux windows |
42 | LOCAL_CFLAGS += -Wall -Wextra -Werror -Wunreachable-code | 42 | LOCAL_CFLAGS += -Wall -Wextra -Werror -Wunreachable-code |
43 | LOCAL_REQUIRED_MODULES := mke2fs e2fsdroid | ||
43 | 44 | ||
44 | LOCAL_SRC_FILES_linux := usb_linux.cpp | 45 | LOCAL_SRC_FILES_linux := usb_linux.cpp |
45 | LOCAL_STATIC_LIBRARIES_linux := libselinux | 46 | LOCAL_STATIC_LIBRARIES_linux := libselinux |
@@ -85,6 +86,8 @@ LOCAL_SHARED_LIBRARIES := | |||
85 | include $(BUILD_HOST_EXECUTABLE) | 86 | include $(BUILD_HOST_EXECUTABLE) |
86 | 87 | ||
87 | my_dist_files := $(LOCAL_BUILT_MODULE) | 88 | my_dist_files := $(LOCAL_BUILT_MODULE) |
89 | my_dist_files += $(HOST_OUT_EXECUTABLES)/mke2fs$(HOST_EXECUTABLE_SUFFIX) | ||
90 | my_dist_files += $(HOST_OUT_EXECUTABLES)/e2fsdroid$(HOST_EXECUTABLE_SUFFIX) | ||
88 | ifeq ($(HOST_OS),linux) | 91 | ifeq ($(HOST_OS),linux) |
89 | my_dist_files += $(HOST_LIBRARY_PATH)/libf2fs_fmt_host_dyn$(HOST_SHLIB_SUFFIX) | 92 | my_dist_files += $(HOST_LIBRARY_PATH)/libf2fs_fmt_host_dyn$(HOST_SHLIB_SUFFIX) |
90 | endif | 93 | endif |
diff --git a/fastboot/fs.cpp b/fastboot/fs.cpp index 99ca7dd81..f3c000eb7 100644 --- a/fastboot/fs.cpp +++ b/fastboot/fs.cpp | |||
@@ -10,14 +10,22 @@ | |||
10 | #include <string.h> | 10 | #include <string.h> |
11 | #include <sys/stat.h> | 11 | #include <sys/stat.h> |
12 | #include <sys/types.h> | 12 | #include <sys/types.h> |
13 | #ifndef WIN32 | ||
14 | #include <sys/wait.h> | ||
15 | #endif | ||
13 | #include <unistd.h> | 16 | #include <unistd.h> |
17 | #include <vector> | ||
14 | 18 | ||
19 | #include <android-base/file.h> | ||
20 | #include <android-base/stringprintf.h> | ||
15 | #include <android-base/unique_fd.h> | 21 | #include <android-base/unique_fd.h> |
16 | #include <ext4_utils/make_ext4fs.h> | 22 | #include <ext4_utils/make_ext4fs.h> |
17 | #include <sparse/sparse.h> | 23 | #include <sparse/sparse.h> |
18 | 24 | ||
25 | using android::base::StringPrintf; | ||
19 | using android::base::unique_fd; | 26 | using android::base::unique_fd; |
20 | 27 | ||
28 | #ifdef WIN32 | ||
21 | static int generate_ext4_image(const char* fileName, long long partSize, const std::string& initial_dir, | 29 | static int generate_ext4_image(const char* fileName, long long partSize, const std::string& initial_dir, |
22 | unsigned eraseBlkSize, unsigned logicalBlkSize) | 30 | unsigned eraseBlkSize, unsigned logicalBlkSize) |
23 | { | 31 | { |
@@ -34,6 +42,84 @@ static int generate_ext4_image(const char* fileName, long long partSize, const s | |||
34 | } | 42 | } |
35 | return 0; | 43 | return 0; |
36 | } | 44 | } |
45 | #else | ||
46 | static int exec_e2fs_cmd(const char* path, char* const argv[]) { | ||
47 | int status; | ||
48 | pid_t child; | ||
49 | if ((child = fork()) == 0) { | ||
50 | setenv("MKE2FS_CONFIG", "", 1); | ||
51 | execvp(path, argv); | ||
52 | _exit(EXIT_FAILURE); | ||
53 | } | ||
54 | if (child < 0) { | ||
55 | fprintf(stderr, "%s failed with fork %s\n", path, strerror(errno)); | ||
56 | return -1; | ||
57 | } | ||
58 | if (TEMP_FAILURE_RETRY(waitpid(child, &status, 0)) == -1) { | ||
59 | fprintf(stderr, "%s failed with waitpid %s\n", path, strerror(errno)); | ||
60 | return -1; | ||
61 | } | ||
62 | int ret = -1; | ||
63 | if (WIFEXITED(status)) { | ||
64 | ret = WEXITSTATUS(status); | ||
65 | if (ret != 0) { | ||
66 | fprintf(stderr, "%s failed with status %d\n", path, ret); | ||
67 | } | ||
68 | } | ||
69 | return ret; | ||
70 | } | ||
71 | |||
72 | static int generate_ext4_image(const char* fileName, long long partSize, | ||
73 | const std::string& initial_dir, unsigned eraseBlkSize, | ||
74 | unsigned logicalBlkSize) { | ||
75 | static constexpr int block_size = 4096; | ||
76 | const std::string exec_dir = android::base::GetExecutableDirectory(); | ||
77 | |||
78 | const std::string mke2fs_path = exec_dir + "/mke2fs"; | ||
79 | std::vector<const char*> mke2fs_args = {mke2fs_path.c_str(), "-t", "ext4", "-b"}; | ||
80 | |||
81 | std::string block_size_str = std::to_string(block_size); | ||
82 | mke2fs_args.push_back(block_size_str.c_str()); | ||
83 | |||
84 | std::string ext_attr = "android_sparse"; | ||
85 | if (eraseBlkSize != 0 && logicalBlkSize != 0) { | ||
86 | int raid_stride = logicalBlkSize / block_size; | ||
87 | int raid_stripe_width = eraseBlkSize / block_size; | ||
88 | // stride should be the max of 8kb and logical block size | ||
89 | if (logicalBlkSize != 0 && logicalBlkSize < 8192) raid_stride = 8192 / block_size; | ||
90 | ext_attr += StringPrintf(",stride=%d,stripe-width=%d", raid_stride, raid_stripe_width); | ||
91 | } | ||
92 | mke2fs_args.push_back("-E"); | ||
93 | mke2fs_args.push_back(ext_attr.c_str()); | ||
94 | mke2fs_args.push_back(fileName); | ||
95 | |||
96 | std::string size_str = std::to_string(partSize / block_size); | ||
97 | mke2fs_args.push_back(size_str.c_str()); | ||
98 | mke2fs_args.push_back(nullptr); | ||
99 | |||
100 | int ret = exec_e2fs_cmd(mke2fs_args[0], const_cast<char**>(mke2fs_args.data())); | ||
101 | if (ret != 0) { | ||
102 | fprintf(stderr, "mke2fs failed: %d\n", ret); | ||
103 | return -1; | ||
104 | } | ||
105 | |||
106 | if (initial_dir.empty()) { | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | const std::string e2fsdroid_path = exec_dir + "/e2fsdroid"; | ||
111 | std::vector<const char*> e2fsdroid_args = {e2fsdroid_path.c_str(), "-f", initial_dir.c_str(), | ||
112 | fileName, nullptr}; | ||
113 | |||
114 | ret = exec_e2fs_cmd(e2fsdroid_args[0], const_cast<char**>(e2fsdroid_args.data())); | ||
115 | if (ret != 0) { | ||
116 | fprintf(stderr, "e2fsdroid failed: %d\n", ret); | ||
117 | return -1; | ||
118 | } | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | #endif | ||
37 | 123 | ||
38 | #ifdef USE_F2FS | 124 | #ifdef USE_F2FS |
39 | static int generate_f2fs_image(const char* fileName, long long partSize, const std::string& initial_dir, | 125 | static int generate_f2fs_image(const char* fileName, long long partSize, const std::string& initial_dir, |
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp index 4441ad0c1..7fd67c293 100644 --- a/fs_mgr/Android.bp +++ b/fs_mgr/Android.bp | |||
@@ -21,20 +21,6 @@ cc_defaults { | |||
21 | }, | 21 | }, |
22 | local_include_dirs: ["include/"], | 22 | local_include_dirs: ["include/"], |
23 | cppflags: ["-Werror"], | 23 | cppflags: ["-Werror"], |
24 | static_libs: [ | ||
25 | "libfec", | ||
26 | "libfec_rs", | ||
27 | "libbase", | ||
28 | "libcrypto_utils", | ||
29 | "libcrypto", | ||
30 | "libext4_utils", | ||
31 | "libsquashfs_utils", | ||
32 | "libselinux", | ||
33 | "libavb", | ||
34 | ], | ||
35 | whole_static_libs: [ | ||
36 | "liblogwrap", | ||
37 | ], | ||
38 | } | 24 | } |
39 | 25 | ||
40 | cc_library_static { | 26 | cc_library_static { |
@@ -46,12 +32,28 @@ cc_library_static { | |||
46 | "fs_mgr.cpp", | 32 | "fs_mgr.cpp", |
47 | "fs_mgr_dm_ioctl.cpp", | 33 | "fs_mgr_dm_ioctl.cpp", |
48 | "fs_mgr_format.cpp", | 34 | "fs_mgr_format.cpp", |
49 | "fs_mgr_fstab.cpp", | ||
50 | "fs_mgr_slotselect.cpp", | ||
51 | "fs_mgr_verity.cpp", | 35 | "fs_mgr_verity.cpp", |
52 | "fs_mgr_avb.cpp", | 36 | "fs_mgr_avb.cpp", |
53 | "fs_mgr_avb_ops.cpp", | 37 | "fs_mgr_avb_ops.cpp", |
54 | "fs_mgr_boot_config.cpp", | 38 | ], |
39 | static_libs: [ | ||
40 | "libfec", | ||
41 | "libfec_rs", | ||
42 | "libbase", | ||
43 | "libcrypto_utils", | ||
44 | "libcrypto", | ||
45 | "libext4_utils", | ||
46 | "libsquashfs_utils", | ||
47 | "libselinux", | ||
48 | "libavb", | ||
49 | "libfstab", | ||
50 | ], | ||
51 | export_static_lib_headers: [ | ||
52 | "libfstab", | ||
53 | ], | ||
54 | whole_static_libs: [ | ||
55 | "liblogwrap", | ||
56 | "libfstab", | ||
55 | ], | 57 | ], |
56 | product_variables: { | 58 | product_variables: { |
57 | debuggable: { | 59 | debuggable: { |
@@ -62,3 +64,16 @@ cc_library_static { | |||
62 | }, | 64 | }, |
63 | }, | 65 | }, |
64 | } | 66 | } |
67 | |||
68 | cc_library_static { | ||
69 | name: "libfstab", | ||
70 | vendor_available: true, | ||
71 | defaults: ["fs_mgr_defaults"], | ||
72 | srcs: [ | ||
73 | "fs_mgr_fstab.cpp", | ||
74 | "fs_mgr_boot_config.cpp", | ||
75 | "fs_mgr_slotselect.cpp", | ||
76 | ], | ||
77 | export_include_dirs: ["include_fstab"], | ||
78 | header_libs: ["libbase_headers"], | ||
79 | } | ||
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index e0093834b..91ed49663 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <unistd.h> | 32 | #include <unistd.h> |
33 | 33 | ||
34 | #include <memory> | 34 | #include <memory> |
35 | #include <thread> | ||
35 | 36 | ||
36 | #include <android-base/file.h> | 37 | #include <android-base/file.h> |
37 | #include <android-base/properties.h> | 38 | #include <android-base/properties.h> |
@@ -78,43 +79,33 @@ enum FsStatFlags { | |||
78 | FS_STAT_E2FSCK_F_ALWAYS = 0x0004, | 79 | FS_STAT_E2FSCK_F_ALWAYS = 0x0004, |
79 | FS_STAT_UNCLEAN_SHUTDOWN = 0x0008, | 80 | FS_STAT_UNCLEAN_SHUTDOWN = 0x0008, |
80 | FS_STAT_QUOTA_ENABLED = 0x0010, | 81 | FS_STAT_QUOTA_ENABLED = 0x0010, |
81 | FS_STAT_TUNE2FS_FAILED = 0x0020, | ||
82 | FS_STAT_RO_MOUNT_FAILED = 0x0040, | 82 | FS_STAT_RO_MOUNT_FAILED = 0x0040, |
83 | FS_STAT_RO_UNMOUNT_FAILED = 0x0080, | 83 | FS_STAT_RO_UNMOUNT_FAILED = 0x0080, |
84 | FS_STAT_FULL_MOUNT_FAILED = 0x0100, | 84 | FS_STAT_FULL_MOUNT_FAILED = 0x0100, |
85 | FS_STAT_E2FSCK_FAILED = 0x0200, | 85 | FS_STAT_E2FSCK_FAILED = 0x0200, |
86 | FS_STAT_E2FSCK_FS_FIXED = 0x0400, | 86 | FS_STAT_E2FSCK_FS_FIXED = 0x0400, |
87 | FS_STAT_EXT4_INVALID_MAGIC = 0x0800, | 87 | FS_STAT_EXT4_INVALID_MAGIC = 0x0800, |
88 | FS_STAT_TOGGLE_QUOTAS_FAILED = 0x10000, | ||
89 | FS_STAT_SET_RESERVED_BLOCKS_FAILED = 0x20000, | ||
90 | FS_STAT_ENABLE_ENCRYPTION_FAILED = 0x40000, | ||
88 | }; | 91 | }; |
89 | 92 | ||
90 | /* | 93 | // TODO: switch to inotify() |
91 | * gettime() - returns the time in seconds of the system's monotonic clock or | 94 | bool fs_mgr_wait_for_file(const std::string& filename, |
92 | * zero on error. | 95 | const std::chrono::milliseconds relative_timeout) { |
93 | */ | 96 | auto start_time = std::chrono::steady_clock::now(); |
94 | static time_t gettime(void) | ||
95 | { | ||
96 | struct timespec ts; | ||
97 | int ret; | ||
98 | |||
99 | ret = clock_gettime(CLOCK_MONOTONIC, &ts); | ||
100 | if (ret < 0) { | ||
101 | PERROR << "clock_gettime(CLOCK_MONOTONIC) failed"; | ||
102 | return 0; | ||
103 | } | ||
104 | 97 | ||
105 | return ts.tv_sec; | 98 | while (true) { |
106 | } | 99 | if (!access(filename.c_str(), F_OK) || errno != ENOENT) { |
107 | 100 | return true; | |
108 | static int wait_for_file(const char *filename, int timeout) | 101 | } |
109 | { | ||
110 | struct stat info; | ||
111 | time_t timeout_time = gettime() + timeout; | ||
112 | int ret = -1; | ||
113 | 102 | ||
114 | while (gettime() < timeout_time && ((ret = stat(filename, &info)) < 0)) | 103 | std::this_thread::sleep_for(50ms); |
115 | usleep(10000); | ||
116 | 104 | ||
117 | return ret; | 105 | auto now = std::chrono::steady_clock::now(); |
106 | auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time); | ||
107 | if (time_elapsed > relative_timeout) return false; | ||
108 | } | ||
118 | } | 109 | } |
119 | 110 | ||
120 | static void log_fs_stat(const char* blk_device, int fs_stat) | 111 | static void log_fs_stat(const char* blk_device, int fs_stat) |
@@ -128,10 +119,16 @@ static void log_fs_stat(const char* blk_device, int fs_stat) | |||
128 | } | 119 | } |
129 | } | 120 | } |
130 | 121 | ||
122 | static bool is_extfs(const std::string& fs_type) { | ||
123 | return fs_type == "ext4" || fs_type == "ext3" || fs_type == "ext2"; | ||
124 | } | ||
125 | |||
131 | static bool should_force_check(int fs_stat) { | 126 | static bool should_force_check(int fs_stat) { |
132 | return fs_stat & (FS_STAT_E2FSCK_F_ALWAYS | FS_STAT_UNCLEAN_SHUTDOWN | FS_STAT_QUOTA_ENABLED | | 127 | return fs_stat & |
133 | FS_STAT_TUNE2FS_FAILED | FS_STAT_RO_MOUNT_FAILED | FS_STAT_RO_UNMOUNT_FAILED | | 128 | (FS_STAT_E2FSCK_F_ALWAYS | FS_STAT_UNCLEAN_SHUTDOWN | FS_STAT_QUOTA_ENABLED | |
134 | FS_STAT_FULL_MOUNT_FAILED | FS_STAT_E2FSCK_FAILED); | 129 | FS_STAT_RO_MOUNT_FAILED | FS_STAT_RO_UNMOUNT_FAILED | FS_STAT_FULL_MOUNT_FAILED | |
130 | FS_STAT_E2FSCK_FAILED | FS_STAT_TOGGLE_QUOTAS_FAILED | | ||
131 | FS_STAT_SET_RESERVED_BLOCKS_FAILED | FS_STAT_ENABLE_ENCRYPTION_FAILED); | ||
135 | } | 132 | } |
136 | 133 | ||
137 | static void check_fs(const char *blk_device, char *fs_type, char *target, int *fs_stat) | 134 | static void check_fs(const char *blk_device, char *fs_type, char *target, int *fs_stat) |
@@ -144,7 +141,7 @@ static void check_fs(const char *blk_device, char *fs_type, char *target, int *f | |||
144 | const char* e2fsck_forced_argv[] = {E2FSCK_BIN, "-f", "-y", blk_device}; | 141 | const char* e2fsck_forced_argv[] = {E2FSCK_BIN, "-f", "-y", blk_device}; |
145 | 142 | ||
146 | /* Check for the types of filesystems we know how to check */ | 143 | /* Check for the types of filesystems we know how to check */ |
147 | if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) { | 144 | if (is_extfs(fs_type)) { |
148 | if (*fs_stat & FS_STAT_EXT4_INVALID_MAGIC) { // will fail, so do not try | 145 | if (*fs_stat & FS_STAT_EXT4_INVALID_MAGIC) { // will fail, so do not try |
149 | return; | 146 | return; |
150 | } | 147 | } |
@@ -242,186 +239,208 @@ static void check_fs(const char *blk_device, char *fs_type, char *target, int *f | |||
242 | return; | 239 | return; |
243 | } | 240 | } |
244 | 241 | ||
245 | /* Function to read the primary superblock */ | 242 | static ext4_fsblk_t ext4_blocks_count(const struct ext4_super_block* es) { |
246 | static int read_super_block(int fd, struct ext4_super_block *sb) | 243 | return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) | |
247 | { | 244 | le32_to_cpu(es->s_blocks_count_lo); |
248 | off64_t ret; | 245 | } |
249 | 246 | ||
250 | ret = lseek64(fd, 1024, SEEK_SET); | 247 | static ext4_fsblk_t ext4_r_blocks_count(const struct ext4_super_block* es) { |
251 | if (ret < 0) | 248 | return ((ext4_fsblk_t)le32_to_cpu(es->s_r_blocks_count_hi) << 32) | |
252 | return ret; | 249 | le32_to_cpu(es->s_r_blocks_count_lo); |
250 | } | ||
253 | 251 | ||
254 | ret = read(fd, sb, sizeof(*sb)); | 252 | // Read the primary superblock from an ext4 filesystem. On failure return |
255 | if (ret < 0) | 253 | // false. If it's not an ext4 filesystem, also set FS_STAT_EXT4_INVALID_MAGIC. |
256 | return ret; | 254 | static bool read_ext4_superblock(const char* blk_device, struct ext4_super_block* sb, int* fs_stat) { |
257 | if (ret != sizeof(*sb)) | 255 | android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC))); |
258 | return ret; | ||
259 | 256 | ||
260 | return 0; | 257 | if (fd < 0) { |
258 | PERROR << "Failed to open '" << blk_device << "'"; | ||
259 | return false; | ||
260 | } | ||
261 | |||
262 | if (pread(fd, sb, sizeof(*sb), 1024) != sizeof(*sb)) { | ||
263 | PERROR << "Can't read '" << blk_device << "' superblock"; | ||
264 | return false; | ||
265 | } | ||
266 | |||
267 | if (sb->s_magic != EXT4_SUPER_MAGIC) { | ||
268 | LINFO << "Invalid ext4 magic:0x" << std::hex << sb->s_magic << " " | ||
269 | << "on '" << blk_device << "'"; | ||
270 | // not a valid fs, tune2fs, fsck, and mount will all fail. | ||
271 | *fs_stat |= FS_STAT_EXT4_INVALID_MAGIC; | ||
272 | return false; | ||
273 | } | ||
274 | *fs_stat |= FS_STAT_IS_EXT4; | ||
275 | LINFO << "superblock s_max_mnt_count:" << sb->s_max_mnt_count << "," << blk_device; | ||
276 | if (sb->s_max_mnt_count == 0xffff) { // -1 (int16) in ext2, but uint16 in ext4 | ||
277 | *fs_stat |= FS_STAT_NEW_IMAGE_VERSION; | ||
278 | } | ||
279 | return true; | ||
261 | } | 280 | } |
262 | 281 | ||
263 | static ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es) | 282 | // Some system images do not have tune2fs for licensing reasons. |
264 | { | 283 | // Detect these and skip running it. |
265 | return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) | | 284 | static bool tune2fs_available(void) { |
266 | le32_to_cpu(es->s_blocks_count_lo); | 285 | return access(TUNE2FS_BIN, X_OK) == 0; |
267 | } | 286 | } |
268 | 287 | ||
269 | static ext4_fsblk_t ext4_r_blocks_count(struct ext4_super_block *es) | 288 | static bool run_tune2fs(const char* argv[], int argc) { |
270 | { | 289 | int ret; |
271 | return ((ext4_fsblk_t)le32_to_cpu(es->s_r_blocks_count_hi) << 32) | | 290 | |
272 | le32_to_cpu(es->s_r_blocks_count_lo); | 291 | ret = android_fork_execvp_ext(argc, const_cast<char**>(argv), nullptr, true, |
292 | LOG_KLOG | LOG_FILE, true, nullptr, nullptr, 0); | ||
293 | return ret == 0; | ||
273 | } | 294 | } |
274 | 295 | ||
275 | static int do_quota_with_shutdown_check(char *blk_device, char *fs_type, | 296 | // Enable/disable quota support on the filesystem if needed. |
276 | struct fstab_rec *rec, int *fs_stat) | 297 | static void tune_quota(const char* blk_device, const struct fstab_rec* rec, |
277 | { | 298 | const struct ext4_super_block* sb, int* fs_stat) { |
278 | int force_check = 0; | 299 | bool has_quota = (sb->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_QUOTA)) != 0; |
279 | if (!strcmp(fs_type, "ext4")) { | 300 | bool want_quota = fs_mgr_is_quota(rec) != 0; |
280 | /* | ||
281 | * Some system images do not have tune2fs for licensing reasons | ||
282 | * Detect these and skip reserve blocks. | ||
283 | */ | ||
284 | if (access(TUNE2FS_BIN, X_OK)) { | ||
285 | LERROR << "Not running " << TUNE2FS_BIN << " on " | ||
286 | << blk_device << " (executable not in system image)"; | ||
287 | } else { | ||
288 | const char* arg1 = nullptr; | ||
289 | const char* arg2 = nullptr; | ||
290 | int status = 0; | ||
291 | int ret = 0; | ||
292 | android::base::unique_fd fd( | ||
293 | TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC))); | ||
294 | if (fd >= 0) { | ||
295 | struct ext4_super_block sb; | ||
296 | ret = read_super_block(fd, &sb); | ||
297 | if (ret < 0) { | ||
298 | PERROR << "Can't read '" << blk_device << "' super block"; | ||
299 | return force_check; | ||
300 | } | ||
301 | if (sb.s_magic != EXT4_SUPER_MAGIC) { | ||
302 | LINFO << "Invalid ext4 magic:0x" << std::hex << sb.s_magic << "," << blk_device; | ||
303 | *fs_stat |= FS_STAT_EXT4_INVALID_MAGIC; | ||
304 | return 0; // not a valid fs, tune2fs, fsck, and mount will all fail. | ||
305 | } | ||
306 | *fs_stat |= FS_STAT_IS_EXT4; | ||
307 | LINFO << "superblock s_max_mnt_count:" << sb.s_max_mnt_count << "," << blk_device; | ||
308 | if (sb.s_max_mnt_count == 0xffff) { // -1 (int16) in ext2, but uint16 in ext4 | ||
309 | *fs_stat |= FS_STAT_NEW_IMAGE_VERSION; | ||
310 | } | ||
311 | if ((sb.s_feature_incompat & EXT4_FEATURE_INCOMPAT_RECOVER) != 0 || | ||
312 | (sb.s_state & EXT4_VALID_FS) == 0) { | ||
313 | LINFO << __FUNCTION__ << "(): was not clealy shutdown, state flag:" | ||
314 | << std::hex << sb.s_state | ||
315 | << "incompat flag:" << std::hex << sb.s_feature_incompat; | ||
316 | force_check = 1; | ||
317 | *fs_stat |= FS_STAT_UNCLEAN_SHUTDOWN; | ||
318 | } | ||
319 | int has_quota = (sb.s_feature_ro_compat | ||
320 | & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_QUOTA)) != 0; | ||
321 | int want_quota = fs_mgr_is_quota(rec) != 0; | ||
322 | |||
323 | if (has_quota == want_quota) { | ||
324 | LINFO << "Requested quota status is match on " << blk_device; | ||
325 | return force_check; | ||
326 | } else if (want_quota) { | ||
327 | LINFO << "Enabling quota on " << blk_device; | ||
328 | arg1 = "-Oquota"; | ||
329 | arg2 = "-Qusrquota,grpquota"; | ||
330 | force_check = 1; | ||
331 | *fs_stat |= FS_STAT_QUOTA_ENABLED; | ||
332 | } else { | ||
333 | LINFO << "Disabling quota on " << blk_device; | ||
334 | arg1 = "-Q^usrquota,^grpquota"; | ||
335 | arg2 = "-O^quota"; | ||
336 | } | ||
337 | } else { | ||
338 | PERROR << "Failed to open '" << blk_device << "'"; | ||
339 | return force_check; | ||
340 | } | ||
341 | 301 | ||
342 | const char *tune2fs_argv[] = { | 302 | if (has_quota == want_quota) { |
343 | TUNE2FS_BIN, | 303 | return; |
344 | arg1, | 304 | } |
345 | arg2, | 305 | |
346 | blk_device, | 306 | if (!tune2fs_available()) { |
347 | }; | 307 | LERROR << "Unable to " << (want_quota ? "enable" : "disable") << " quotas on " << blk_device |
348 | ret = android_fork_execvp_ext(ARRAY_SIZE(tune2fs_argv), | 308 | << " because " TUNE2FS_BIN " is missing"; |
349 | const_cast<char **>(tune2fs_argv), | 309 | return; |
350 | &status, true, LOG_KLOG | LOG_FILE, | 310 | } |
351 | true, NULL, NULL, 0); | 311 | |
352 | if (ret < 0) { | 312 | const char* argv[] = {TUNE2FS_BIN, nullptr, nullptr, blk_device}; |
353 | /* No need to check for error in fork, we can't really handle it now */ | 313 | |
354 | LERROR << "Failed trying to run " << TUNE2FS_BIN; | 314 | if (want_quota) { |
355 | *fs_stat |= FS_STAT_TUNE2FS_FAILED; | 315 | LINFO << "Enabling quotas on " << blk_device; |
356 | } | 316 | argv[1] = "-Oquota"; |
357 | } | 317 | argv[2] = "-Qusrquota,grpquota"; |
318 | *fs_stat |= FS_STAT_QUOTA_ENABLED; | ||
319 | } else { | ||
320 | LINFO << "Disabling quotas on " << blk_device; | ||
321 | argv[1] = "-O^quota"; | ||
322 | argv[2] = "-Q^usrquota,^grpquota"; | ||
323 | } | ||
324 | |||
325 | if (!run_tune2fs(argv, ARRAY_SIZE(argv))) { | ||
326 | LERROR << "Failed to run " TUNE2FS_BIN " to " << (want_quota ? "enable" : "disable") | ||
327 | << " quotas on " << blk_device; | ||
328 | *fs_stat |= FS_STAT_TOGGLE_QUOTAS_FAILED; | ||
358 | } | 329 | } |
359 | return force_check; | ||
360 | } | 330 | } |
361 | 331 | ||
362 | static void do_reserved_size(char *blk_device, char *fs_type, struct fstab_rec *rec, int *fs_stat) | 332 | // Set the number of reserved filesystem blocks if needed. |
363 | { | 333 | static void tune_reserved_size(const char* blk_device, const struct fstab_rec* rec, |
364 | /* Check for the types of filesystems we know how to check */ | 334 | const struct ext4_super_block* sb, int* fs_stat) { |
365 | if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) { | 335 | if (!(rec->fs_mgr_flags & MF_RESERVEDSIZE)) { |
366 | /* | 336 | return; |
367 | * Some system images do not have tune2fs for licensing reasons | 337 | } |
368 | * Detect these and skip reserve blocks. | ||
369 | */ | ||
370 | if (access(TUNE2FS_BIN, X_OK)) { | ||
371 | LERROR << "Not running " << TUNE2FS_BIN << " on " | ||
372 | << blk_device << " (executable not in system image)"; | ||
373 | } else { | ||
374 | LINFO << "Running " << TUNE2FS_BIN << " on " << blk_device; | ||
375 | |||
376 | int status = 0; | ||
377 | int ret = 0; | ||
378 | unsigned long reserved_blocks = 0; | ||
379 | android::base::unique_fd fd( | ||
380 | TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC))); | ||
381 | if (fd >= 0) { | ||
382 | struct ext4_super_block sb; | ||
383 | ret = read_super_block(fd, &sb); | ||
384 | if (ret < 0) { | ||
385 | PERROR << "Can't read '" << blk_device << "' super block"; | ||
386 | return; | ||
387 | } | ||
388 | reserved_blocks = rec->reserved_size / EXT4_BLOCK_SIZE(&sb); | ||
389 | unsigned long reserved_threshold = ext4_blocks_count(&sb) * 0.02; | ||
390 | if (reserved_threshold < reserved_blocks) { | ||
391 | LWARNING << "Reserved blocks " << reserved_blocks | ||
392 | << " is too large"; | ||
393 | reserved_blocks = reserved_threshold; | ||
394 | } | ||
395 | 338 | ||
396 | if (ext4_r_blocks_count(&sb) == reserved_blocks) { | 339 | // The size to reserve is given in the fstab, but we won't reserve more |
397 | LINFO << "Have reserved same blocks"; | 340 | // than 2% of the filesystem. |
398 | return; | 341 | const uint64_t max_reserved_blocks = ext4_blocks_count(sb) * 0.02; |
399 | } | 342 | uint64_t reserved_blocks = rec->reserved_size / EXT4_BLOCK_SIZE(sb); |
400 | } else { | ||
401 | PERROR << "Failed to open '" << blk_device << "'"; | ||
402 | return; | ||
403 | } | ||
404 | 343 | ||
405 | char buf[16] = {0}; | 344 | if (reserved_blocks > max_reserved_blocks) { |
406 | snprintf(buf, sizeof (buf), "-r %lu", reserved_blocks); | 345 | LWARNING << "Reserved blocks " << reserved_blocks << " is too large; " |
407 | const char *tune2fs_argv[] = { | 346 | << "capping to " << max_reserved_blocks; |
408 | TUNE2FS_BIN, | 347 | reserved_blocks = max_reserved_blocks; |
409 | buf, | 348 | } |
410 | blk_device, | ||
411 | }; | ||
412 | 349 | ||
413 | ret = android_fork_execvp_ext(ARRAY_SIZE(tune2fs_argv), | 350 | if (ext4_r_blocks_count(sb) == reserved_blocks) { |
414 | const_cast<char **>(tune2fs_argv), | 351 | return; |
415 | &status, true, LOG_KLOG | LOG_FILE, | 352 | } |
416 | true, NULL, NULL, 0); | ||
417 | 353 | ||
418 | if (ret < 0) { | 354 | if (!tune2fs_available()) { |
419 | /* No need to check for error in fork, we can't really handle it now */ | 355 | LERROR << "Unable to set the number of reserved blocks on " << blk_device |
420 | LERROR << "Failed trying to run " << TUNE2FS_BIN; | 356 | << " because " TUNE2FS_BIN " is missing"; |
421 | *fs_stat |= FS_STAT_TUNE2FS_FAILED; | 357 | return; |
358 | } | ||
359 | |||
360 | char buf[32]; | ||
361 | const char* argv[] = {TUNE2FS_BIN, "-r", buf, blk_device}; | ||
362 | |||
363 | snprintf(buf, sizeof(buf), "%" PRIu64, reserved_blocks); | ||
364 | LINFO << "Setting reserved block count on " << blk_device << " to " << reserved_blocks; | ||
365 | if (!run_tune2fs(argv, ARRAY_SIZE(argv))) { | ||
366 | LERROR << "Failed to run " TUNE2FS_BIN " to set the number of reserved blocks on " | ||
367 | << blk_device; | ||
368 | *fs_stat |= FS_STAT_SET_RESERVED_BLOCKS_FAILED; | ||
369 | } | ||
370 | } | ||
371 | |||
372 | // Enable file-based encryption if needed. | ||
373 | static void tune_encrypt(const char* blk_device, const struct fstab_rec* rec, | ||
374 | const struct ext4_super_block* sb, int* fs_stat) { | ||
375 | bool has_encrypt = (sb->s_feature_incompat & cpu_to_le32(EXT4_FEATURE_INCOMPAT_ENCRYPT)) != 0; | ||
376 | bool want_encrypt = fs_mgr_is_file_encrypted(rec) != 0; | ||
377 | |||
378 | if (has_encrypt || !want_encrypt) { | ||
379 | return; | ||
380 | } | ||
381 | |||
382 | if (!tune2fs_available()) { | ||
383 | LERROR << "Unable to enable ext4 encryption on " << blk_device | ||
384 | << " because " TUNE2FS_BIN " is missing"; | ||
385 | return; | ||
386 | } | ||
387 | |||
388 | const char* argv[] = {TUNE2FS_BIN, "-Oencrypt", blk_device}; | ||
389 | |||
390 | LINFO << "Enabling ext4 encryption on " << blk_device; | ||
391 | if (!run_tune2fs(argv, ARRAY_SIZE(argv))) { | ||
392 | LERROR << "Failed to run " TUNE2FS_BIN " to enable " | ||
393 | << "ext4 encryption on " << blk_device; | ||
394 | *fs_stat |= FS_STAT_ENABLE_ENCRYPTION_FAILED; | ||
395 | } | ||
396 | } | ||
397 | |||
398 | // | ||
399 | // Prepare the filesystem on the given block device to be mounted. | ||
400 | // | ||
401 | // If the "check" option was given in the fstab record, or it seems that the | ||
402 | // filesystem was uncleanly shut down, we'll run fsck on the filesystem. | ||
403 | // | ||
404 | // If needed, we'll also enable (or disable) filesystem features as specified by | ||
405 | // the fstab record. | ||
406 | // | ||
407 | static int prepare_fs_for_mount(const char* blk_device, const struct fstab_rec* rec) { | ||
408 | int fs_stat = 0; | ||
409 | |||
410 | if (is_extfs(rec->fs_type)) { | ||
411 | struct ext4_super_block sb; | ||
412 | |||
413 | if (read_ext4_superblock(blk_device, &sb, &fs_stat)) { | ||
414 | if ((sb.s_feature_incompat & EXT4_FEATURE_INCOMPAT_RECOVER) != 0 || | ||
415 | (sb.s_state & EXT4_VALID_FS) == 0) { | ||
416 | LINFO << "Filesystem on " << blk_device << " was not cleanly shutdown; " | ||
417 | << "state flags: 0x" << std::hex << sb.s_state << ", " | ||
418 | << "incompat feature flags: 0x" << std::hex << sb.s_feature_incompat; | ||
419 | fs_stat |= FS_STAT_UNCLEAN_SHUTDOWN; | ||
422 | } | 420 | } |
421 | |||
422 | // Note: quotas should be enabled before running fsck. | ||
423 | tune_quota(blk_device, rec, &sb, &fs_stat); | ||
424 | } else { | ||
425 | return fs_stat; | ||
426 | } | ||
427 | } | ||
428 | |||
429 | if ((rec->fs_mgr_flags & MF_CHECK) || | ||
430 | (fs_stat & (FS_STAT_UNCLEAN_SHUTDOWN | FS_STAT_QUOTA_ENABLED))) { | ||
431 | check_fs(blk_device, rec->fs_type, rec->mount_point, &fs_stat); | ||
432 | } | ||
433 | |||
434 | if (is_extfs(rec->fs_type) && (rec->fs_mgr_flags & (MF_RESERVEDSIZE | MF_FILEENCRYPTION))) { | ||
435 | struct ext4_super_block sb; | ||
436 | |||
437 | if (read_ext4_superblock(blk_device, &sb, &fs_stat)) { | ||
438 | tune_reserved_size(blk_device, rec, &sb, &fs_stat); | ||
439 | tune_encrypt(blk_device, rec, &sb, &fs_stat); | ||
423 | } | 440 | } |
424 | } | 441 | } |
442 | |||
443 | return fs_stat; | ||
425 | } | 444 | } |
426 | 445 | ||
427 | static void remove_trailing_slashes(char *n) | 446 | static void remove_trailing_slashes(char *n) |
@@ -457,6 +476,16 @@ int fs_mgr_set_blk_ro(const char *blockdev) | |||
457 | return rc; | 476 | return rc; |
458 | } | 477 | } |
459 | 478 | ||
479 | // Orange state means the device is unlocked, see the following link for details. | ||
480 | // https://source.android.com/security/verifiedboot/verified-boot#device_state | ||
481 | bool fs_mgr_is_device_unlocked() { | ||
482 | std::string verified_boot_state; | ||
483 | if (fs_mgr_get_boot_config("verifiedbootstate", &verified_boot_state)) { | ||
484 | return verified_boot_state == "orange"; | ||
485 | } | ||
486 | return false; | ||
487 | } | ||
488 | |||
460 | /* | 489 | /* |
461 | * __mount(): wrapper around the mount() system call which also | 490 | * __mount(): wrapper around the mount() system call which also |
462 | * sets the underlying block device to read-only if the mount is read-only. | 491 | * sets the underlying block device to read-only if the mount is read-only. |
@@ -476,10 +505,11 @@ static int __mount(const char *source, const char *target, const struct fstab_re | |||
476 | if ((info.st_mode & S_IFMT) == S_IFLNK) | 505 | if ((info.st_mode & S_IFMT) == S_IFLNK) |
477 | unlink(target); | 506 | unlink(target); |
478 | mkdir(target, 0755); | 507 | mkdir(target, 0755); |
508 | errno = 0; | ||
479 | ret = mount(source, target, rec->fs_type, mountflags, rec->fs_options); | 509 | ret = mount(source, target, rec->fs_type, mountflags, rec->fs_options); |
480 | save_errno = errno; | 510 | save_errno = errno; |
481 | LINFO << __FUNCTION__ << "(source=" << source << ",target=" | 511 | PINFO << __FUNCTION__ << "(source=" << source << ",target=" << target |
482 | << target << ",type=" << rec->fs_type << ")=" << ret; | 512 | << ",type=" << rec->fs_type << ")=" << ret; |
483 | if ((ret == 0) && (mountflags & MS_RDONLY) != 0) { | 513 | if ((ret == 0) && (mountflags & MS_RDONLY) != 0) { |
484 | fs_mgr_set_blk_ro(source); | 514 | fs_mgr_set_blk_ro(source); |
485 | } | 515 | } |
@@ -559,10 +589,7 @@ static int mount_with_alternatives(struct fstab *fstab, int start_idx, int *end_ | |||
559 | continue; | 589 | continue; |
560 | } | 590 | } |
561 | 591 | ||
562 | int fs_stat = 0; | 592 | int fs_stat = prepare_fs_for_mount(fstab->recs[i].blk_device, &fstab->recs[i]); |
563 | int force_check = do_quota_with_shutdown_check(fstab->recs[i].blk_device, | ||
564 | fstab->recs[i].fs_type, | ||
565 | &fstab->recs[i], &fs_stat); | ||
566 | if (fs_stat & FS_STAT_EXT4_INVALID_MAGIC) { | 593 | if (fs_stat & FS_STAT_EXT4_INVALID_MAGIC) { |
567 | LERROR << __FUNCTION__ << "(): skipping mount, invalid ext4, mountpoint=" | 594 | LERROR << __FUNCTION__ << "(): skipping mount, invalid ext4, mountpoint=" |
568 | << fstab->recs[i].mount_point << " rec[" << i | 595 | << fstab->recs[i].mount_point << " rec[" << i |
@@ -570,15 +597,6 @@ static int mount_with_alternatives(struct fstab *fstab, int start_idx, int *end_ | |||
570 | mount_errno = EINVAL; // continue bootup for FDE | 597 | mount_errno = EINVAL; // continue bootup for FDE |
571 | continue; | 598 | continue; |
572 | } | 599 | } |
573 | if ((fstab->recs[i].fs_mgr_flags & MF_CHECK) || force_check) { | ||
574 | check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type, | ||
575 | fstab->recs[i].mount_point, &fs_stat); | ||
576 | } | ||
577 | |||
578 | if (fstab->recs[i].fs_mgr_flags & MF_RESERVEDSIZE) { | ||
579 | do_reserved_size(fstab->recs[i].blk_device, fstab->recs[i].fs_type, | ||
580 | &fstab->recs[i], &fs_stat); | ||
581 | } | ||
582 | 600 | ||
583 | int retry_count = 2; | 601 | int retry_count = 2; |
584 | while (retry_count-- > 0) { | 602 | while (retry_count-- > 0) { |
@@ -756,19 +774,6 @@ static int handle_encryptable(const struct fstab_rec* rec) | |||
756 | } | 774 | } |
757 | } | 775 | } |
758 | 776 | ||
759 | // TODO: add ueventd notifiers if they don't exist. | ||
760 | // This is just doing a wait_for_device for maximum of 1s | ||
761 | int fs_mgr_test_access(const char *device) { | ||
762 | int tries = 25; | ||
763 | while (tries--) { | ||
764 | if (!access(device, F_OK) || errno != ENOENT) { | ||
765 | return 0; | ||
766 | } | ||
767 | usleep(40 * 1000); | ||
768 | } | ||
769 | return -1; | ||
770 | } | ||
771 | |||
772 | bool is_device_secure() { | 777 | bool is_device_secure() { |
773 | int ret = -1; | 778 | int ret = -1; |
774 | char value[PROP_VALUE_MAX]; | 779 | char value[PROP_VALUE_MAX]; |
@@ -829,9 +834,7 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) | |||
829 | } | 834 | } |
830 | 835 | ||
831 | /* Translate LABEL= file system labels into block devices */ | 836 | /* Translate LABEL= file system labels into block devices */ |
832 | if (!strcmp(fstab->recs[i].fs_type, "ext2") || | 837 | if (is_extfs(fstab->recs[i].fs_type)) { |
833 | !strcmp(fstab->recs[i].fs_type, "ext3") || | ||
834 | !strcmp(fstab->recs[i].fs_type, "ext4")) { | ||
835 | int tret = translate_ext_labels(&fstab->recs[i]); | 838 | int tret = translate_ext_labels(&fstab->recs[i]); |
836 | if (tret < 0) { | 839 | if (tret < 0) { |
837 | LERROR << "Could not translate label to block device"; | 840 | LERROR << "Could not translate label to block device"; |
@@ -839,8 +842,10 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) | |||
839 | } | 842 | } |
840 | } | 843 | } |
841 | 844 | ||
842 | if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { | 845 | if (fstab->recs[i].fs_mgr_flags & MF_WAIT && |
843 | wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); | 846 | !fs_mgr_wait_for_file(fstab->recs[i].blk_device, 20s)) { |
847 | LERROR << "Skipping '" << fstab->recs[i].blk_device << "' during mount_all"; | ||
848 | continue; | ||
844 | } | 849 | } |
845 | 850 | ||
846 | if (fstab->recs[i].fs_mgr_flags & MF_AVB) { | 851 | if (fstab->recs[i].fs_mgr_flags & MF_AVB) { |
@@ -1047,22 +1052,12 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, | |||
1047 | } | 1052 | } |
1048 | 1053 | ||
1049 | /* First check the filesystem if requested */ | 1054 | /* First check the filesystem if requested */ |
1050 | if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { | 1055 | if (fstab->recs[i].fs_mgr_flags & MF_WAIT && !fs_mgr_wait_for_file(n_blk_device, 20s)) { |
1051 | wait_for_file(n_blk_device, WAIT_TIMEOUT); | 1056 | LERROR << "Skipping mounting '" << n_blk_device << "'"; |
1057 | continue; | ||
1052 | } | 1058 | } |
1053 | 1059 | ||
1054 | int fs_stat = 0; | 1060 | int fs_stat = prepare_fs_for_mount(n_blk_device, &fstab->recs[i]); |
1055 | int force_check = do_quota_with_shutdown_check(n_blk_device, fstab->recs[i].fs_type, | ||
1056 | &fstab->recs[i], &fs_stat); | ||
1057 | |||
1058 | if ((fstab->recs[i].fs_mgr_flags & MF_CHECK) || force_check) { | ||
1059 | check_fs(n_blk_device, fstab->recs[i].fs_type, | ||
1060 | fstab->recs[i].mount_point, &fs_stat); | ||
1061 | } | ||
1062 | |||
1063 | if (fstab->recs[i].fs_mgr_flags & MF_RESERVEDSIZE) { | ||
1064 | do_reserved_size(n_blk_device, fstab->recs[i].fs_type, &fstab->recs[i], &fs_stat); | ||
1065 | } | ||
1066 | 1061 | ||
1067 | if (fstab->recs[i].fs_mgr_flags & MF_AVB) { | 1062 | if (fstab->recs[i].fs_mgr_flags & MF_AVB) { |
1068 | if (!avb_handle) { | 1063 | if (!avb_handle) { |
@@ -1221,8 +1216,11 @@ int fs_mgr_swapon_all(struct fstab *fstab) | |||
1221 | fclose(zram_fp); | 1216 | fclose(zram_fp); |
1222 | } | 1217 | } |
1223 | 1218 | ||
1224 | if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { | 1219 | if (fstab->recs[i].fs_mgr_flags & MF_WAIT && |
1225 | wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); | 1220 | !fs_mgr_wait_for_file(fstab->recs[i].blk_device, 20s)) { |
1221 | LERROR << "Skipping mkswap for '" << fstab->recs[i].blk_device << "'"; | ||
1222 | ret = -1; | ||
1223 | continue; | ||
1226 | } | 1224 | } |
1227 | 1225 | ||
1228 | /* Initialize the swap area */ | 1226 | /* Initialize the swap area */ |
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp index 2c99aa7c5..7824cfa70 100644 --- a/fs_mgr/fs_mgr_avb.cpp +++ b/fs_mgr/fs_mgr_avb.cpp | |||
@@ -397,7 +397,7 @@ static bool hashtree_dm_verity_setup(struct fstab_rec* fstab_entry, | |||
397 | fstab_entry->blk_device = strdup(verity_blk_name.c_str()); | 397 | fstab_entry->blk_device = strdup(verity_blk_name.c_str()); |
398 | 398 | ||
399 | // Makes sure we've set everything up properly. | 399 | // Makes sure we've set everything up properly. |
400 | if (wait_for_verity_dev && fs_mgr_test_access(verity_blk_name.c_str()) < 0) { | 400 | if (wait_for_verity_dev && !fs_mgr_wait_for_file(verity_blk_name, 1s)) { |
401 | return false; | 401 | return false; |
402 | } | 402 | } |
403 | 403 | ||
@@ -473,16 +473,6 @@ static bool get_hashtree_descriptor(const std::string& partition_name, | |||
473 | return true; | 473 | return true; |
474 | } | 474 | } |
475 | 475 | ||
476 | // Orange state means the device is unlocked, see the following link for details. | ||
477 | // https://source.android.com/security/verifiedboot/verified-boot#device_state | ||
478 | static inline bool IsDeviceUnlocked() { | ||
479 | std::string verified_boot_state; | ||
480 | if (fs_mgr_get_boot_config("verifiedbootstate", &verified_boot_state)) { | ||
481 | return verified_boot_state == "orange"; | ||
482 | } | ||
483 | return false; | ||
484 | } | ||
485 | |||
486 | FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const fstab& fstab) { | 476 | FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const fstab& fstab) { |
487 | FsManagerAvbOps avb_ops(fstab); | 477 | FsManagerAvbOps avb_ops(fstab); |
488 | return DoOpen(&avb_ops); | 478 | return DoOpen(&avb_ops); |
@@ -498,7 +488,7 @@ FsManagerAvbUniquePtr FsManagerAvbHandle::Open(ByNameSymlinkMap&& by_name_symlin | |||
498 | } | 488 | } |
499 | 489 | ||
500 | FsManagerAvbUniquePtr FsManagerAvbHandle::DoOpen(FsManagerAvbOps* avb_ops) { | 490 | FsManagerAvbUniquePtr FsManagerAvbHandle::DoOpen(FsManagerAvbOps* avb_ops) { |
501 | bool is_device_unlocked = IsDeviceUnlocked(); | 491 | bool is_device_unlocked = fs_mgr_is_device_unlocked(); |
502 | 492 | ||
503 | FsManagerAvbUniquePtr avb_handle(new FsManagerAvbHandle()); | 493 | FsManagerAvbUniquePtr avb_handle(new FsManagerAvbHandle()); |
504 | if (!avb_handle) { | 494 | if (!avb_handle) { |
diff --git a/fs_mgr/fs_mgr_avb_ops.cpp b/fs_mgr/fs_mgr_avb_ops.cpp index ba1262fde..43879fe56 100644 --- a/fs_mgr/fs_mgr_avb_ops.cpp +++ b/fs_mgr/fs_mgr_avb_ops.cpp | |||
@@ -142,10 +142,8 @@ AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t of | |||
142 | } | 142 | } |
143 | std::string path = iter->second; | 143 | std::string path = iter->second; |
144 | 144 | ||
145 | // Ensures the device path (a symlink created by init) is ready to | 145 | // Ensures the device path (a symlink created by init) is ready to access. |
146 | // access. fs_mgr_test_access() will test a few iterations if the | 146 | if (!fs_mgr_wait_for_file(path, 1s)) { |
147 | // path doesn't exist yet. | ||
148 | if (fs_mgr_test_access(path.c_str()) < 0) { | ||
149 | return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; | 147 | return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; |
150 | } | 148 | } |
151 | 149 | ||
diff --git a/fs_mgr/fs_mgr_boot_config.cpp b/fs_mgr/fs_mgr_boot_config.cpp index ab5beed81..911766752 100644 --- a/fs_mgr/fs_mgr_boot_config.cpp +++ b/fs_mgr/fs_mgr_boot_config.cpp | |||
@@ -14,6 +14,8 @@ | |||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <string> | ||
18 | |||
17 | #include <android-base/file.h> | 19 | #include <android-base/file.h> |
18 | #include <android-base/stringprintf.h> | 20 | #include <android-base/stringprintf.h> |
19 | #include <android-base/strings.h> | 21 | #include <android-base/strings.h> |
@@ -51,9 +53,11 @@ bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val) { | |||
51 | // lastly, check the device tree | 53 | // lastly, check the device tree |
52 | if (is_dt_compatible()) { | 54 | if (is_dt_compatible()) { |
53 | std::string file_name = kAndroidDtDir + "/" + key; | 55 | std::string file_name = kAndroidDtDir + "/" + key; |
54 | // DT entries terminate with '\0' but so do the properties | ||
55 | if (android::base::ReadFileToString(file_name, out_val)) { | 56 | if (android::base::ReadFileToString(file_name, out_val)) { |
56 | return true; | 57 | if (!out_val->empty()) { |
58 | out_val->pop_back(); // Trims the trailing '\0' out. | ||
59 | return true; | ||
60 | } | ||
57 | } | 61 | } |
58 | } | 62 | } |
59 | 63 | ||
diff --git a/fs_mgr/fs_mgr_format.cpp b/fs_mgr/fs_mgr_format.cpp index 75feee798..fc88217ce 100644 --- a/fs_mgr/fs_mgr_format.cpp +++ b/fs_mgr/fs_mgr_format.cpp | |||
@@ -38,7 +38,6 @@ static int format_ext4(char *fs_blkdev, char *fs_mnt_point, bool crypt_footer) | |||
38 | { | 38 | { |
39 | uint64_t dev_sz; | 39 | uint64_t dev_sz; |
40 | int fd, rc = 0; | 40 | int fd, rc = 0; |
41 | int status; | ||
42 | 41 | ||
43 | if ((fd = open(fs_blkdev, O_WRONLY)) < 0) { | 42 | if ((fd = open(fs_blkdev, O_WRONLY)) < 0) { |
44 | PERROR << "Cannot open block device"; | 43 | PERROR << "Cannot open block device"; |
@@ -62,7 +61,7 @@ static int format_ext4(char *fs_blkdev, char *fs_mnt_point, bool crypt_footer) | |||
62 | const char* const mke2fs_args[] = { | 61 | const char* const mke2fs_args[] = { |
63 | "/system/bin/mke2fs", "-t", "ext4", "-b", "4096", fs_blkdev, size_str.c_str(), nullptr}; | 62 | "/system/bin/mke2fs", "-t", "ext4", "-b", "4096", fs_blkdev, size_str.c_str(), nullptr}; |
64 | 63 | ||
65 | rc = android_fork_execvp_ext(arraysize(mke2fs_args), const_cast<char**>(mke2fs_args), &status, | 64 | rc = android_fork_execvp_ext(arraysize(mke2fs_args), const_cast<char**>(mke2fs_args), NULL, |
66 | true, LOG_KLOG, true, nullptr, nullptr, 0); | 65 | true, LOG_KLOG, true, nullptr, nullptr, 0); |
67 | if (rc) { | 66 | if (rc) { |
68 | LERROR << "mke2fs returned " << rc; | 67 | LERROR << "mke2fs returned " << rc; |
@@ -78,7 +77,7 @@ static int format_ext4(char *fs_blkdev, char *fs_mnt_point, bool crypt_footer) | |||
78 | nullptr}; | 77 | nullptr}; |
79 | 78 | ||
80 | rc = android_fork_execvp_ext(arraysize(e2fsdroid_args), const_cast<char**>(e2fsdroid_args), | 79 | rc = android_fork_execvp_ext(arraysize(e2fsdroid_args), const_cast<char**>(e2fsdroid_args), |
81 | &status, true, LOG_KLOG, true, nullptr, nullptr, 0); | 80 | NULL, true, LOG_KLOG, true, nullptr, nullptr, 0); |
82 | if (rc) { | 81 | if (rc) { |
83 | LERROR << "e2fsdroid returned " << rc; | 82 | LERROR << "e2fsdroid returned " << rc; |
84 | } | 83 | } |
@@ -88,10 +87,9 @@ static int format_ext4(char *fs_blkdev, char *fs_mnt_point, bool crypt_footer) | |||
88 | 87 | ||
89 | static int format_f2fs(char *fs_blkdev) | 88 | static int format_f2fs(char *fs_blkdev) |
90 | { | 89 | { |
91 | int status; | ||
92 | const char* const args[] = {"/system/bin/make_f2fs", "-f", "-O encrypt", fs_blkdev, nullptr}; | 90 | const char* const args[] = {"/system/bin/make_f2fs", "-f", "-O encrypt", fs_blkdev, nullptr}; |
93 | 91 | ||
94 | return android_fork_execvp_ext(arraysize(args), const_cast<char**>(args), &status, true, | 92 | return android_fork_execvp_ext(arraysize(args), const_cast<char**>(args), NULL, true, |
95 | LOG_KLOG, true, nullptr, nullptr, 0); | 93 | LOG_KLOG, true, nullptr, nullptr, 0); |
96 | } | 94 | } |
97 | 95 | ||
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp index 6c527c573..6dcbded49 100644 --- a/fs_mgr/fs_mgr_fstab.cpp +++ b/fs_mgr/fs_mgr_fstab.cpp | |||
@@ -864,32 +864,26 @@ int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab) | |||
864 | return fstab->fs_mgr_flags & MF_NOEMULATEDSD; | 864 | return fstab->fs_mgr_flags & MF_NOEMULATEDSD; |
865 | } | 865 | } |
866 | 866 | ||
867 | int fs_mgr_is_notrim(struct fstab_rec *fstab) | 867 | int fs_mgr_is_notrim(const struct fstab_rec* fstab) { |
868 | { | ||
869 | return fstab->fs_mgr_flags & MF_NOTRIM; | 868 | return fstab->fs_mgr_flags & MF_NOTRIM; |
870 | } | 869 | } |
871 | 870 | ||
872 | int fs_mgr_is_formattable(struct fstab_rec *fstab) | 871 | int fs_mgr_is_formattable(const struct fstab_rec* fstab) { |
873 | { | ||
874 | return fstab->fs_mgr_flags & (MF_FORMATTABLE); | 872 | return fstab->fs_mgr_flags & (MF_FORMATTABLE); |
875 | } | 873 | } |
876 | 874 | ||
877 | int fs_mgr_is_slotselect(struct fstab_rec *fstab) | 875 | int fs_mgr_is_slotselect(const struct fstab_rec* fstab) { |
878 | { | ||
879 | return fstab->fs_mgr_flags & MF_SLOTSELECT; | 876 | return fstab->fs_mgr_flags & MF_SLOTSELECT; |
880 | } | 877 | } |
881 | 878 | ||
882 | int fs_mgr_is_nofail(struct fstab_rec *fstab) | 879 | int fs_mgr_is_nofail(const struct fstab_rec* fstab) { |
883 | { | ||
884 | return fstab->fs_mgr_flags & MF_NOFAIL; | 880 | return fstab->fs_mgr_flags & MF_NOFAIL; |
885 | } | 881 | } |
886 | 882 | ||
887 | int fs_mgr_is_latemount(struct fstab_rec *fstab) | 883 | int fs_mgr_is_latemount(const struct fstab_rec* fstab) { |
888 | { | ||
889 | return fstab->fs_mgr_flags & MF_LATEMOUNT; | 884 | return fstab->fs_mgr_flags & MF_LATEMOUNT; |
890 | } | 885 | } |
891 | 886 | ||
892 | int fs_mgr_is_quota(struct fstab_rec *fstab) | 887 | int fs_mgr_is_quota(const struct fstab_rec* fstab) { |
893 | { | ||
894 | return fstab->fs_mgr_flags & MF_QUOTA; | 888 | return fstab->fs_mgr_flags & MF_QUOTA; |
895 | } | 889 | } |
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h index 3ca507b8b..a5d172b03 100644 --- a/fs_mgr/fs_mgr_priv.h +++ b/fs_mgr/fs_mgr_priv.h | |||
@@ -17,8 +17,12 @@ | |||
17 | #ifndef __CORE_FS_MGR_PRIV_H | 17 | #ifndef __CORE_FS_MGR_PRIV_H |
18 | #define __CORE_FS_MGR_PRIV_H | 18 | #define __CORE_FS_MGR_PRIV_H |
19 | 19 | ||
20 | #include <chrono> | ||
21 | #include <string> | ||
22 | |||
20 | #include <android-base/logging.h> | 23 | #include <android-base/logging.h> |
21 | #include <fs_mgr.h> | 24 | |
25 | #include "fs_mgr.h" | ||
22 | #include "fs_mgr_priv_boot_config.h" | 26 | #include "fs_mgr_priv_boot_config.h" |
23 | 27 | ||
24 | /* The CHECK() in logging.h will use program invocation name as the tag. | 28 | /* The CHECK() in logging.h will use program invocation name as the tag. |
@@ -43,8 +47,6 @@ | |||
43 | 47 | ||
44 | #define CRYPTO_TMPFS_OPTIONS "size=256m,mode=0771,uid=1000,gid=1000" | 48 | #define CRYPTO_TMPFS_OPTIONS "size=256m,mode=0771,uid=1000,gid=1000" |
45 | 49 | ||
46 | #define WAIT_TIMEOUT 20 | ||
47 | |||
48 | /* fstab has the following format: | 50 | /* fstab has the following format: |
49 | * | 51 | * |
50 | * Any line starting with a # is a comment and ignored | 52 | * Any line starting with a # is a comment and ignored |
@@ -111,9 +113,13 @@ | |||
111 | 113 | ||
112 | #define DM_BUF_SIZE 4096 | 114 | #define DM_BUF_SIZE 4096 |
113 | 115 | ||
116 | using namespace std::chrono_literals; | ||
117 | |||
114 | int fs_mgr_set_blk_ro(const char *blockdev); | 118 | int fs_mgr_set_blk_ro(const char *blockdev); |
115 | int fs_mgr_test_access(const char *device); | 119 | bool fs_mgr_wait_for_file(const std::string& filename, |
120 | const std::chrono::milliseconds relative_timeout); | ||
116 | bool fs_mgr_update_for_slotselect(struct fstab *fstab); | 121 | bool fs_mgr_update_for_slotselect(struct fstab *fstab); |
122 | bool fs_mgr_is_device_unlocked(); | ||
117 | bool is_dt_compatible(); | 123 | bool is_dt_compatible(); |
118 | bool is_device_secure(); | 124 | bool is_device_secure(); |
119 | int load_verity_state(struct fstab_rec* fstab, int* mode); | 125 | int load_verity_state(struct fstab_rec* fstab, int* mode); |
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp index 8904995aa..7f8e1e213 100644 --- a/fs_mgr/fs_mgr_verity.cpp +++ b/fs_mgr/fs_mgr_verity.cpp | |||
@@ -348,10 +348,13 @@ out: | |||
348 | 348 | ||
349 | static int was_verity_restart() | 349 | static int was_verity_restart() |
350 | { | 350 | { |
351 | static const char *files[] = { | 351 | static const char* files[] = { |
352 | // clang-format off | ||
353 | "/sys/fs/pstore/console-ramoops-0", | ||
352 | "/sys/fs/pstore/console-ramoops", | 354 | "/sys/fs/pstore/console-ramoops", |
353 | "/proc/last_kmsg", | 355 | "/proc/last_kmsg", |
354 | NULL | 356 | NULL |
357 | // clang-format on | ||
355 | }; | 358 | }; |
356 | int i; | 359 | int i; |
357 | 360 | ||
@@ -689,27 +692,55 @@ int load_verity_state(struct fstab_rec* fstab, int* mode) { | |||
689 | return read_verity_state(fstab->verity_loc, offset, mode); | 692 | return read_verity_state(fstab->verity_loc, offset, mode); |
690 | } | 693 | } |
691 | 694 | ||
692 | static void update_verity_table_blk_device(char *blk_device, char **table) | 695 | // Update the verity table using the actual block device path. |
693 | { | 696 | // Two cases: |
694 | std::string result, word; | 697 | // Case-1: verity table is shared for devices with different by-name prefix. |
698 | // Example: | ||
699 | // verity table token: /dev/block/bootdevice/by-name/vendor | ||
700 | // blk_device-1 (non-A/B): /dev/block/platform/soc.0/7824900.sdhci/by-name/vendor | ||
701 | // blk_device-2 (A/B): /dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor_a | ||
702 | // | ||
703 | // Case-2: append A/B suffix in the verity table. | ||
704 | // Example: | ||
705 | // verity table token: /dev/block/platform/soc.0/7824900.sdhci/by-name/vendor | ||
706 | // blk_device: /dev/block/platform/soc.0/7824900.sdhci/by-name/vendor_a | ||
707 | static void update_verity_table_blk_device(const std::string& blk_device, char** table, | ||
708 | bool slot_select) { | ||
709 | bool updated = false; | ||
710 | std::string result, ab_suffix; | ||
695 | auto tokens = android::base::Split(*table, " "); | 711 | auto tokens = android::base::Split(*table, " "); |
696 | 712 | ||
713 | // If slot_select is set, it means blk_device is already updated with ab_suffix. | ||
714 | if (slot_select) ab_suffix = fs_mgr_get_slot_suffix(); | ||
715 | |||
697 | for (const auto& token : tokens) { | 716 | for (const auto& token : tokens) { |
698 | if (android::base::StartsWith(token, "/dev/block/") && | 717 | std::string new_token; |
699 | android::base::StartsWith(blk_device, token.c_str())) { | 718 | if (android::base::StartsWith(token, "/dev/block/")) { |
700 | word = blk_device; | 719 | if (token == blk_device) return; // no need to update if they're already the same. |
720 | std::size_t found1 = blk_device.find("by-name"); | ||
721 | std::size_t found2 = token.find("by-name"); | ||
722 | if (found1 != std::string::npos && found2 != std::string::npos && | ||
723 | blk_device.substr(found1) == token.substr(found2) + ab_suffix) { | ||
724 | new_token = blk_device; | ||
725 | } | ||
726 | } | ||
727 | |||
728 | if (!new_token.empty()) { | ||
729 | updated = true; | ||
730 | LINFO << "Verity table: updated block device from '" << token << "' to '" << new_token | ||
731 | << "'"; | ||
701 | } else { | 732 | } else { |
702 | word = token; | 733 | new_token = token; |
703 | } | 734 | } |
704 | 735 | ||
705 | if (result.empty()) { | 736 | if (result.empty()) { |
706 | result = word; | 737 | result = new_token; |
707 | } else { | 738 | } else { |
708 | result += " " + word; | 739 | result += " " + new_token; |
709 | } | 740 | } |
710 | } | 741 | } |
711 | 742 | ||
712 | if (result.empty()) { | 743 | if (!updated) { |
713 | return; | 744 | return; |
714 | } | 745 | } |
715 | 746 | ||
@@ -751,8 +782,8 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev) | |||
751 | if (fec_verity_get_metadata(f, &verity) < 0) { | 782 | if (fec_verity_get_metadata(f, &verity) < 0) { |
752 | PERROR << "Failed to get verity metadata '" << fstab->blk_device << "'"; | 783 | PERROR << "Failed to get verity metadata '" << fstab->blk_device << "'"; |
753 | // Allow verity disabled when the device is unlocked without metadata | 784 | // Allow verity disabled when the device is unlocked without metadata |
754 | if ("0" == android::base::GetProperty("ro.boot.flash.locked", "")) { | 785 | if (fs_mgr_is_device_unlocked()) { |
755 | retval = FS_MGR_SETUP_VERITY_DISABLED; | 786 | retval = FS_MGR_SETUP_VERITY_SKIPPED; |
756 | LWARNING << "Allow invalid metadata when the device is unlocked"; | 787 | LWARNING << "Allow invalid metadata when the device is unlocked"; |
757 | } | 788 | } |
758 | goto out; | 789 | goto out; |
@@ -810,9 +841,15 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev) | |||
810 | 841 | ||
811 | // verify the signature on the table | 842 | // verify the signature on the table |
812 | if (verify_verity_signature(verity) < 0) { | 843 | if (verify_verity_signature(verity) < 0) { |
844 | // Allow signature verification error when the device is unlocked | ||
845 | if (fs_mgr_is_device_unlocked()) { | ||
846 | retval = FS_MGR_SETUP_VERITY_SKIPPED; | ||
847 | LWARNING << "Allow signature verification error when the device is unlocked"; | ||
848 | goto out; | ||
849 | } | ||
813 | if (params.mode == VERITY_MODE_LOGGING) { | 850 | if (params.mode == VERITY_MODE_LOGGING) { |
814 | // the user has been warned, allow mounting without dm-verity | 851 | // the user has been warned, allow mounting without dm-verity |
815 | retval = FS_MGR_SETUP_VERITY_SUCCESS; | 852 | retval = FS_MGR_SETUP_VERITY_SKIPPED; |
816 | goto out; | 853 | goto out; |
817 | } | 854 | } |
818 | 855 | ||
@@ -825,10 +862,9 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev) | |||
825 | LINFO << "Enabling dm-verity for " << mount_point.c_str() | 862 | LINFO << "Enabling dm-verity for " << mount_point.c_str() |
826 | << " (mode " << params.mode << ")"; | 863 | << " (mode " << params.mode << ")"; |
827 | 864 | ||
828 | if (fstab->fs_mgr_flags & MF_SLOTSELECT) { | 865 | // Update the verity params using the actual block device path |
829 | // Update the verity params using the actual block device path | 866 | update_verity_table_blk_device(fstab->blk_device, ¶ms.table, |
830 | update_verity_table_blk_device(fstab->blk_device, ¶ms.table); | 867 | fstab->fs_mgr_flags & MF_SLOTSELECT); |
831 | } | ||
832 | 868 | ||
833 | // load the verity mapping table | 869 | // load the verity mapping table |
834 | if (load_verity_table(io, mount_point, verity.data_size, fd, ¶ms, | 870 | if (load_verity_table(io, mount_point, verity.data_size, fd, ¶ms, |
@@ -899,7 +935,7 @@ loaded: | |||
899 | } | 935 | } |
900 | 936 | ||
901 | // make sure we've set everything up properly | 937 | // make sure we've set everything up properly |
902 | if (wait_for_verity_dev && fs_mgr_test_access(fstab->blk_device) < 0) { | 938 | if (wait_for_verity_dev && !fs_mgr_wait_for_file(fstab->blk_device, 1s)) { |
903 | goto out; | 939 | goto out; |
904 | } | 940 | } |
905 | 941 | ||
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h index e033d4749..c74f6c85c 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h | |||
@@ -22,11 +22,7 @@ | |||
22 | #include <stdbool.h> | 22 | #include <stdbool.h> |
23 | #include <linux/dm-ioctl.h> | 23 | #include <linux/dm-ioctl.h> |
24 | 24 | ||
25 | // C++ only headers | 25 | #include <fstab/fstab.h> |
26 | // TODO: move this into separate header files under include/fs_mgr/*.h | ||
27 | #ifdef __cplusplus | ||
28 | #include <string> | ||
29 | #endif | ||
30 | 26 | ||
31 | // Magic number at start of verity metadata | 27 | // Magic number at start of verity metadata |
32 | #define VERITY_METADATA_MAGIC_NUMBER 0xb001b001 | 28 | #define VERITY_METADATA_MAGIC_NUMBER 0xb001b001 |
@@ -53,49 +49,10 @@ enum mount_mode { | |||
53 | MOUNT_MODE_LATE = 2 | 49 | MOUNT_MODE_LATE = 2 |
54 | }; | 50 | }; |
55 | 51 | ||
56 | /* | ||
57 | * The entries must be kept in the same order as they were seen in the fstab. | ||
58 | * Unless explicitly requested, a lookup on mount point should always | ||
59 | * return the 1st one. | ||
60 | */ | ||
61 | struct fstab { | ||
62 | int num_entries; | ||
63 | struct fstab_rec *recs; | ||
64 | char *fstab_filename; | ||
65 | }; | ||
66 | |||
67 | struct fstab_rec { | ||
68 | char *blk_device; | ||
69 | char *mount_point; | ||
70 | char *fs_type; | ||
71 | unsigned long flags; | ||
72 | char *fs_options; | ||
73 | int fs_mgr_flags; | ||
74 | char *key_loc; | ||
75 | char* key_dir; | ||
76 | char *verity_loc; | ||
77 | long long length; | ||
78 | char *label; | ||
79 | int partnum; | ||
80 | int swap_prio; | ||
81 | int max_comp_streams; | ||
82 | unsigned int zram_size; | ||
83 | uint64_t reserved_size; | ||
84 | unsigned int file_contents_mode; | ||
85 | unsigned int file_names_mode; | ||
86 | unsigned int erase_blk_size; | ||
87 | unsigned int logical_blk_size; | ||
88 | }; | ||
89 | |||
90 | // Callback function for verity status | 52 | // Callback function for verity status |
91 | typedef void (*fs_mgr_verity_state_callback)(struct fstab_rec *fstab, | 53 | typedef void (*fs_mgr_verity_state_callback)(struct fstab_rec *fstab, |
92 | const char *mount_point, int mode, int status); | 54 | const char *mount_point, int mode, int status); |
93 | 55 | ||
94 | struct fstab *fs_mgr_read_fstab_default(); | ||
95 | struct fstab *fs_mgr_read_fstab_dt(); | ||
96 | struct fstab *fs_mgr_read_fstab(const char *fstab_path); | ||
97 | void fs_mgr_free_fstab(struct fstab *fstab); | ||
98 | |||
99 | #define FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED 7 | 56 | #define FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED 7 |
100 | #define FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION 6 | 57 | #define FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION 6 |
101 | #define FS_MGR_MNTALL_DEV_FILE_ENCRYPTED 5 | 58 | #define FS_MGR_MNTALL_DEV_FILE_ENCRYPTED 5 |
@@ -120,28 +77,6 @@ struct fstab_rec const* fs_mgr_get_crypt_entry(struct fstab const* fstab); | |||
120 | void fs_mgr_get_crypt_info(struct fstab* fstab, char* key_loc, char* real_blk_device, size_t size); | 77 | void fs_mgr_get_crypt_info(struct fstab* fstab, char* key_loc, char* real_blk_device, size_t size); |
121 | bool fs_mgr_load_verity_state(int* mode); | 78 | bool fs_mgr_load_verity_state(int* mode); |
122 | bool fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback); | 79 | bool fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback); |
123 | int fs_mgr_add_entry(struct fstab *fstab, | ||
124 | const char *mount_point, const char *fs_type, | ||
125 | const char *blk_device); | ||
126 | struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path); | ||
127 | int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab); | ||
128 | int fs_mgr_is_nonremovable(const struct fstab_rec *fstab); | ||
129 | int fs_mgr_is_verified(const struct fstab_rec *fstab); | ||
130 | int fs_mgr_is_verifyatboot(const struct fstab_rec *fstab); | ||
131 | int fs_mgr_is_avb(const struct fstab_rec *fstab); | ||
132 | int fs_mgr_is_encryptable(const struct fstab_rec *fstab); | ||
133 | int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab); | ||
134 | void fs_mgr_get_file_encryption_modes(const struct fstab_rec *fstab, | ||
135 | const char **contents_mode_ret, | ||
136 | const char **filenames_mode_ret); | ||
137 | int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab); | ||
138 | int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab); | ||
139 | int fs_mgr_is_notrim(struct fstab_rec *fstab); | ||
140 | int fs_mgr_is_formattable(struct fstab_rec *fstab); | ||
141 | int fs_mgr_is_slotselect(struct fstab_rec *fstab); | ||
142 | int fs_mgr_is_nofail(struct fstab_rec *fstab); | ||
143 | int fs_mgr_is_latemount(struct fstab_rec *fstab); | ||
144 | int fs_mgr_is_quota(struct fstab_rec *fstab); | ||
145 | int fs_mgr_swapon_all(struct fstab *fstab); | 80 | int fs_mgr_swapon_all(struct fstab *fstab); |
146 | 81 | ||
147 | int fs_mgr_do_format(struct fstab_rec *fstab, bool reserve_footer); | 82 | int fs_mgr_do_format(struct fstab_rec *fstab, bool reserve_footer); |
@@ -154,10 +89,4 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev); | |||
154 | 89 | ||
155 | __END_DECLS | 90 | __END_DECLS |
156 | 91 | ||
157 | // C++ only functions | ||
158 | // TODO: move this into separate header files under include/fs_mgr/*.h | ||
159 | #ifdef __cplusplus | ||
160 | std::string fs_mgr_get_slot_suffix(); | ||
161 | #endif | ||
162 | |||
163 | #endif /* __CORE_FS_MGR_H */ | 92 | #endif /* __CORE_FS_MGR_H */ |
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h new file mode 100644 index 000000000..15c8cafe6 --- /dev/null +++ b/fs_mgr/include_fstab/fstab/fstab.h | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef __CORE_FS_TAB_H | ||
18 | #define __CORE_FS_TAB_H | ||
19 | |||
20 | #include <linux/dm-ioctl.h> | ||
21 | #include <stdbool.h> | ||
22 | #include <stdint.h> | ||
23 | #include <stdio.h> | ||
24 | |||
25 | // C++ only headers | ||
26 | // TODO: move this into separate header files under include/fs_mgr/*.h | ||
27 | #ifdef __cplusplus | ||
28 | #include <string> | ||
29 | #endif | ||
30 | |||
31 | __BEGIN_DECLS | ||
32 | |||
33 | /* | ||
34 | * The entries must be kept in the same order as they were seen in the fstab. | ||
35 | * Unless explicitly requested, a lookup on mount point should always | ||
36 | * return the 1st one. | ||
37 | */ | ||
38 | struct fstab { | ||
39 | int num_entries; | ||
40 | struct fstab_rec* recs; | ||
41 | char* fstab_filename; | ||
42 | }; | ||
43 | |||
44 | struct fstab_rec { | ||
45 | char* blk_device; | ||
46 | char* mount_point; | ||
47 | char* fs_type; | ||
48 | unsigned long flags; | ||
49 | char* fs_options; | ||
50 | int fs_mgr_flags; | ||
51 | char* key_loc; | ||
52 | char* key_dir; | ||
53 | char* verity_loc; | ||
54 | long long length; | ||
55 | char* label; | ||
56 | int partnum; | ||
57 | int swap_prio; | ||
58 | int max_comp_streams; | ||
59 | unsigned int zram_size; | ||
60 | uint64_t reserved_size; | ||
61 | unsigned int file_contents_mode; | ||
62 | unsigned int file_names_mode; | ||
63 | unsigned int erase_blk_size; | ||
64 | unsigned int logical_blk_size; | ||
65 | }; | ||
66 | |||
67 | struct fstab* fs_mgr_read_fstab_default(); | ||
68 | struct fstab* fs_mgr_read_fstab_dt(); | ||
69 | struct fstab* fs_mgr_read_fstab(const char* fstab_path); | ||
70 | void fs_mgr_free_fstab(struct fstab* fstab); | ||
71 | |||
72 | int fs_mgr_add_entry(struct fstab* fstab, const char* mount_point, const char* fs_type, | ||
73 | const char* blk_device); | ||
74 | struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const char* path); | ||
75 | int fs_mgr_is_voldmanaged(const struct fstab_rec* fstab); | ||
76 | int fs_mgr_is_nonremovable(const struct fstab_rec* fstab); | ||
77 | int fs_mgr_is_verified(const struct fstab_rec* fstab); | ||
78 | int fs_mgr_is_verifyatboot(const struct fstab_rec* fstab); | ||
79 | int fs_mgr_is_avb(const struct fstab_rec* fstab); | ||
80 | int fs_mgr_is_encryptable(const struct fstab_rec* fstab); | ||
81 | int fs_mgr_is_file_encrypted(const struct fstab_rec* fstab); | ||
82 | void fs_mgr_get_file_encryption_modes(const struct fstab_rec* fstab, const char** contents_mode_ret, | ||
83 | const char** filenames_mode_ret); | ||
84 | int fs_mgr_is_convertible_to_fbe(const struct fstab_rec* fstab); | ||
85 | int fs_mgr_is_noemulatedsd(const struct fstab_rec* fstab); | ||
86 | int fs_mgr_is_notrim(const struct fstab_rec* fstab); | ||
87 | int fs_mgr_is_formattable(const struct fstab_rec* fstab); | ||
88 | int fs_mgr_is_slotselect(const struct fstab_rec* fstab); | ||
89 | int fs_mgr_is_nofail(const struct fstab_rec* fstab); | ||
90 | int fs_mgr_is_latemount(const struct fstab_rec* fstab); | ||
91 | int fs_mgr_is_quota(const struct fstab_rec* fstab); | ||
92 | |||
93 | __END_DECLS | ||
94 | |||
95 | // C++ only functions | ||
96 | // TODO: move this into separate header files under include/fs_mgr/*.h | ||
97 | #ifdef __cplusplus | ||
98 | std::string fs_mgr_get_slot_suffix(); | ||
99 | #endif | ||
100 | |||
101 | #endif /* __CORE_FS_TAB_H */ | ||
diff --git a/gatekeeperd/Android.mk b/gatekeeperd/Android.mk index 0dfd9d8a9..28f0b07ab 100644 --- a/gatekeeperd/Android.mk +++ b/gatekeeperd/Android.mk | |||
@@ -21,8 +21,7 @@ LOCAL_CFLAGS := -Wall -Wextra -Werror -Wunused | |||
21 | LOCAL_SRC_FILES := \ | 21 | LOCAL_SRC_FILES := \ |
22 | SoftGateKeeperDevice.cpp \ | 22 | SoftGateKeeperDevice.cpp \ |
23 | IGateKeeperService.cpp \ | 23 | IGateKeeperService.cpp \ |
24 | gatekeeperd.cpp \ | 24 | gatekeeperd.cpp |
25 | IUserManager.cpp | ||
26 | 25 | ||
27 | LOCAL_MODULE := gatekeeperd | 26 | LOCAL_MODULE := gatekeeperd |
28 | LOCAL_SHARED_LIBRARIES := \ | 27 | LOCAL_SHARED_LIBRARIES := \ |
diff --git a/gatekeeperd/IUserManager.cpp b/gatekeeperd/IUserM |