1 /*
2  * Copyright (C) 2008 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 #define LOG_TAG "dumpstate"
18 
19 #include <dirent.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <inttypes.h>
23 #include <libgen.h>
24 #include <limits.h>
25 #include <stdbool.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/poll.h>
30 #include <sys/prctl.h>
31 #include <sys/resource.h>
32 #include <sys/stat.h>
33 #include <sys/time.h>
34 #include <sys/wait.h>
35 #include <unistd.h>
36 
37 #include <chrono>
38 #include <fstream>
39 #include <functional>
40 #include <future>
41 #include <memory>
42 #include <regex>
43 #include <set>
44 #include <string>
45 #include <utility>
46 #include <vector>
47 
48 #include <android-base/file.h>
49 #include <android-base/properties.h>
50 #include <android-base/scopeguard.h>
51 #include <android-base/stringprintf.h>
52 #include <android-base/strings.h>
53 #include <android-base/unique_fd.h>
54 #include <android/content/pm/IPackageManagerNative.h>
55 #include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
56 #include <android/hidl/manager/1.0/IServiceManager.h>
57 #include <android/os/IIncidentCompanion.h>
58 #include <binder/IServiceManager.h>
59 #include <cutils/native_handle.h>
60 #include <cutils/properties.h>
61 #include <debuggerd/client.h>
62 #include <dumpsys.h>
63 #include <dumputils/dump_utils.h>
64 #include <hidl/ServiceManagement.h>
65 #include <openssl/sha.h>
66 #include <private/android_filesystem_config.h>
67 #include <private/android_logger.h>
68 #include <serviceutils/PriorityDumper.h>
69 #include <utils/StrongPointer.h>
70 #include "DumpstateInternal.h"
71 #include "DumpstateSectionReporter.h"
72 #include "DumpstateService.h"
73 #include "dumpstate.h"
74 
75 using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
76 using ::std::literals::chrono_literals::operator""ms;
77 using ::std::literals::chrono_literals::operator""s;
78 
79 // TODO: remove once moved to namespace
80 using android::defaultServiceManager;
81 using android::Dumpsys;
82 using android::INVALID_OPERATION;
83 using android::IServiceManager;
84 using android::OK;
85 using android::sp;
86 using android::status_t;
87 using android::String16;
88 using android::String8;
89 using android::TIMED_OUT;
90 using android::UNKNOWN_ERROR;
91 using android::Vector;
92 using android::base::StringPrintf;
93 using android::os::IDumpstateListener;
94 using android::os::dumpstate::CommandOptions;
95 using android::os::dumpstate::DumpFileToFd;
96 using android::os::dumpstate::DumpstateSectionReporter;
97 using android::os::dumpstate::GetPidByName;
98 using android::os::dumpstate::PropertiesHelper;
99 
100 typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
101 
102 /* read before root is shed */
103 static char cmdline_buf[16384] = "(unknown)";
104 static const char *dump_traces_path = nullptr;
105 static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
106 
107 // TODO: variables and functions below should be part of dumpstate object
108 
109 static std::set<std::string> mount_points;
110 void add_mountinfo();
111 
112 #define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
113 #define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
114 #define BLK_DEV_SYS_DIR "/sys/block"
115 
116 #define RECOVERY_DIR "/cache/recovery"
117 #define RECOVERY_DATA_DIR "/data/misc/recovery"
118 #define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
119 #define LOGPERSIST_DATA_DIR "/data/misc/logd"
120 #define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
121 #define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
122 #define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
123 #define WLUTIL "/vendor/xbin/wlutil"
124 #define WMTRACE_DATA_DIR "/data/misc/wmtrace"
125 
126 // TODO(narayan): Since this information has to be kept in sync
127 // with tombstoned, we should just put it in a common header.
128 //
129 // File: system/core/debuggerd/tombstoned/tombstoned.cpp
130 static const std::string TOMBSTONE_DIR = "/data/tombstones/";
131 static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
132 static const std::string ANR_DIR = "/data/anr/";
133 static const std::string ANR_FILE_PREFIX = "anr_";
134 
135 // TODO: temporary variables and functions used during C++ refactoring
136 static Dumpstate& ds = Dumpstate::GetInstance();
137 
138 #define RETURN_IF_USER_DENIED_CONSENT()                                                        \
139     if (ds.IsUserConsentDenied()) {                                                            \
140         MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
141         return Dumpstate::RunStatus::USER_CONSENT_DENIED;                                      \
142     }
143 
144 // Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
145 // if consent is found to be denied.
146 #define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
147     RETURN_IF_USER_DENIED_CONSENT();                        \
148     func_ptr(__VA_ARGS__);                                  \
149     RETURN_IF_USER_DENIED_CONSENT();
150 
151 namespace android {
152 namespace os {
153 namespace {
154 
Open(std::string path,int flags,mode_t mode=0)155 static int Open(std::string path, int flags, mode_t mode = 0) {
156     int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
157     if (fd == -1) {
158         MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
159     }
160     return fd;
161 }
162 
163 
OpenForRead(std::string path)164 static int OpenForRead(std::string path) {
165     return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
166 }
167 
CopyFile(int in_fd,int out_fd)168 bool CopyFile(int in_fd, int out_fd) {
169     char buf[4096];
170     ssize_t byte_count;
171     while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
172         if (!android::base::WriteFully(out_fd, buf, byte_count)) {
173             return false;
174         }
175     }
176     return (byte_count != -1);
177 }
178 
CopyFileToFd(const std::string & input_file,int out_fd)179 static bool CopyFileToFd(const std::string& input_file, int out_fd) {
180     MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
181 
182     // Obtain a handle to the source file.
183     android::base::unique_fd in_fd(OpenForRead(input_file));
184     if (out_fd != -1 && in_fd.get() != -1) {
185         if (CopyFile(in_fd.get(), out_fd)) {
186             return true;
187         }
188         MYLOGE("Failed to copy file: %s\n", strerror(errno));
189     }
190     return false;
191 }
192 
UnlinkAndLogOnError(const std::string & file)193 static bool UnlinkAndLogOnError(const std::string& file) {
194     if (unlink(file.c_str())) {
195         MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
196         return false;
197     }
198     return true;
199 }
200 
IsFileEmpty(const std::string & file_path)201 static bool IsFileEmpty(const std::string& file_path) {
202     std::ifstream file(file_path, std::ios::binary | std::ios::ate);
203     if(file.bad()) {
204         MYLOGE("Cannot open file: %s\n", file_path.c_str());
205         return true;
206     }
207     return file.tellg() <= 0;
208 }
209 
GetModuleMetadataVersion()210 int64_t GetModuleMetadataVersion() {
211     auto binder = defaultServiceManager()->getService(android::String16("package_native"));
212     if (binder == nullptr) {
213         MYLOGE("Failed to retrieve package_native service");
214         return 0L;
215     }
216     auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
217     std::string package_name;
218     auto status = package_service->getModuleMetadataPackageName(&package_name);
219     if (!status.isOk()) {
220         MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
221         return 0L;
222     }
223     MYLOGD("Module metadata package name: %s", package_name.c_str());
224     int64_t version_code;
225     status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
226                                                        &version_code);
227     if (!status.isOk()) {
228         MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
229         return 0L;
230     }
231     return version_code;
232 }
233 
234 }  // namespace
235 }  // namespace os
236 }  // namespace android
237 
RunCommand(const std::string & title,const std::vector<std::string> & fullCommand,const CommandOptions & options=CommandOptions::DEFAULT)238 static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
239                       const CommandOptions& options = CommandOptions::DEFAULT) {
240     return ds.RunCommand(title, fullCommand, options);
241 }
RunDumpsys(const std::string & title,const std::vector<std::string> & dumpsysArgs,const CommandOptions & options=Dumpstate::DEFAULT_DUMPSYS,long dumpsysTimeoutMs=0)242 static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
243                        const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
244                        long dumpsysTimeoutMs = 0) {
245     return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
246 }
DumpFile(const std::string & title,const std::string & path)247 static int DumpFile(const std::string& title, const std::string& path) {
248     return ds.DumpFile(title, path);
249 }
250 
251 // Relative directory (inside the zip) for all files copied as-is into the bugreport.
252 static const std::string ZIP_ROOT_DIR = "FS";
253 
254 static const std::string kProtoPath = "proto/";
255 static const std::string kProtoExt = ".proto";
256 static const std::string kDumpstateBoardFiles[] = {
257     "dumpstate_board.txt",
258     "dumpstate_board.bin"
259 };
260 static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
261 
262 static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
263 static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
264 static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
265 static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
266 static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
267 
268 static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
269 
270 /*
271  * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
272  * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
273  * is set, the vector only contains files that were written in the last 30 minutes.
274  * If |limit_by_count| is set, the vector only contains the ten latest files.
275  */
GetDumpFds(const std::string & dir_path,const std::string & file_prefix,bool limit_by_mtime,bool limit_by_count=true)276 static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
277                                         const std::string& file_prefix,
278                                         bool limit_by_mtime,
279                                         bool limit_by_count = true) {
280     const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
281 
282     std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
283 
284     if (dump_dir == nullptr) {
285         MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
286         return std::vector<DumpData>();
287     }
288 
289     std::vector<DumpData> dump_data;
290     struct dirent* entry = nullptr;
291     while ((entry = readdir(dump_dir.get()))) {
292         if (entry->d_type != DT_REG) {
293             continue;
294         }
295 
296         const std::string base_name(entry->d_name);
297         if (base_name.find(file_prefix) != 0) {
298             continue;
299         }
300 
301         const std::string abs_path = dir_path + base_name;
302         android::base::unique_fd fd(
303             TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
304         if (fd == -1) {
305             MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
306             break;
307         }
308 
309         struct stat st = {};
310         if (fstat(fd, &st) == -1) {
311             MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
312             continue;
313         }
314 
315         if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
316             MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
317             continue;
318         }
319 
320         dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
321     }
322 
323     // Sort in descending modification time so that we only keep the newest
324     // reports if |limit_by_count| is true.
325     std::sort(dump_data.begin(), dump_data.end(),
326               [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; });
327 
328     if (limit_by_count && dump_data.size() > 10) {
329         dump_data.erase(dump_data.begin() + 10, dump_data.end());
330     }
331 
332     return dump_data;
333 }
334 
AddDumps(const std::vector<DumpData>::const_iterator start,const std::vector<DumpData>::const_iterator end,const char * type_name,const bool add_to_zip)335 static bool AddDumps(const std::vector<DumpData>::const_iterator start,
336                      const std::vector<DumpData>::const_iterator end,
337                      const char* type_name, const bool add_to_zip) {
338     bool dumped = false;
339     for (auto it = start; it != end; ++it) {
340         const std::string& name = it->name;
341         const int fd = it->fd;
342         dumped = true;
343 
344         // Seek to the beginning of the file before dumping any data. A given
345         // DumpData entry might be dumped multiple times in the report.
346         //
347         // For example, the most recent ANR entry is dumped to the body of the
348         // main entry and it also shows up as a separate entry in the bugreport
349         // ZIP file.
350         if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
351             MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
352                    strerror(errno));
353         }
354 
355         if (ds.IsZipping() && add_to_zip) {
356             if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
357                 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
358             }
359         } else {
360             dump_file_from_fd(type_name, name.c_str(), fd);
361         }
362     }
363 
364     return dumped;
365 }
366 
367 // for_each_pid() callback to get mount info about a process.
do_mountinfo(int pid,const char * name)368 void do_mountinfo(int pid, const char* name __attribute__((unused))) {
369     char path[PATH_MAX];
370 
371     // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
372     // are added.
373     snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
374     char linkname[PATH_MAX];
375     ssize_t r = readlink(path, linkname, PATH_MAX);
376     if (r == -1) {
377         MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
378         return;
379     }
380     linkname[r] = '\0';
381 
382     if (mount_points.find(linkname) == mount_points.end()) {
383         // First time this mount point was found: add it
384         snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
385         if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
386             mount_points.insert(linkname);
387         } else {
388             MYLOGE("Unable to add mountinfo %s to zip file\n", path);
389         }
390     }
391 }
392 
add_mountinfo()393 void add_mountinfo() {
394     if (!ds.IsZipping()) return;
395     std::string title = "MOUNT INFO";
396     mount_points.clear();
397     DurationReporter duration_reporter(title, true);
398     for_each_pid(do_mountinfo, nullptr);
399     MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
400 }
401 
dump_dev_files(const char * title,const char * driverpath,const char * filename)402 static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
403 {
404     DIR *d;
405     struct dirent *de;
406     char path[PATH_MAX];
407 
408     d = opendir(driverpath);
409     if (d == nullptr) {
410         return;
411     }
412 
413     while ((de = readdir(d))) {
414         if (de->d_type != DT_LNK) {
415             continue;
416         }
417         snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
418         DumpFile(title, path);
419     }
420 
421     closedir(d);
422 }
423 
424 
425 
426 // dump anrd's trace and add to the zip file.
427 // 1. check if anrd is running on this device.
428 // 2. send a SIGUSR1 to its pid which will dump anrd's trace.
429 // 3. wait until the trace generation completes and add to the zip file.
dump_anrd_trace()430 static bool dump_anrd_trace() {
431     unsigned int pid;
432     char buf[50], path[PATH_MAX];
433     struct dirent *trace;
434     struct stat st;
435     DIR *trace_dir;
436     int retry = 5;
437     long max_ctime = 0, old_mtime;
438     long long cur_size = 0;
439     const char *trace_path = "/data/misc/anrd/";
440 
441     if (!ds.IsZipping()) {
442         MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
443         return false;
444     }
445 
446     // find anrd's pid if it is running.
447     pid = GetPidByName("/system/bin/anrd");
448 
449     if (pid > 0) {
450         if (stat(trace_path, &st) == 0) {
451             old_mtime = st.st_mtime;
452         } else {
453             MYLOGE("Failed to find: %s\n", trace_path);
454             return false;
455         }
456 
457         // send SIGUSR1 to the anrd to generate a trace.
458         sprintf(buf, "%u", pid);
459         if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
460                        CommandOptions::WithTimeout(1).Build())) {
461             MYLOGE("anrd signal timed out. Please manually collect trace\n");
462             return false;
463         }
464 
465         while (retry-- > 0 && old_mtime == st.st_mtime) {
466             sleep(1);
467             stat(trace_path, &st);
468         }
469 
470         if (retry < 0 && old_mtime == st.st_mtime) {
471             MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
472             return false;
473         }
474 
475         // identify the trace file by its creation time.
476         if (!(trace_dir = opendir(trace_path))) {
477             MYLOGE("Can't open trace file under %s\n", trace_path);
478         }
479         while ((trace = readdir(trace_dir))) {
480             if (strcmp(trace->d_name, ".") == 0
481                     || strcmp(trace->d_name, "..") == 0) {
482                 continue;
483             }
484             sprintf(path, "%s%s", trace_path, trace->d_name);
485             if (stat(path, &st) == 0) {
486                 if (st.st_ctime > max_ctime) {
487                     max_ctime = st.st_ctime;
488                     sprintf(buf, "%s", trace->d_name);
489                 }
490             }
491         }
492         closedir(trace_dir);
493 
494         // Wait until the dump completes by checking the size of the trace.
495         if (max_ctime > 0) {
496             sprintf(path, "%s%s", trace_path, buf);
497             while(true) {
498                 sleep(1);
499                 if (stat(path, &st) == 0) {
500                     if (st.st_size == cur_size) {
501                         break;
502                     } else if (st.st_size > cur_size) {
503                         cur_size = st.st_size;
504                     } else {
505                         return false;
506                     }
507                 } else {
508                     MYLOGE("Cant stat() %s anymore\n", path);
509                     return false;
510                 }
511             }
512             // Add to the zip file.
513             if (!ds.AddZipEntry("anrd_trace.txt", path)) {
514                 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
515             } else {
516                 android::os::UnlinkAndLogOnError(path);
517                 return true;
518             }
519         } else {
520             MYLOGE("Can't stats any trace file under %s\n", trace_path);
521         }
522     }
523     return false;
524 }
525 
skip_not_stat(const char * path)526 static bool skip_not_stat(const char *path) {
527     static const char stat[] = "/stat";
528     size_t len = strlen(path);
529     if (path[len - 1] == '/') { /* Directory? */
530         return false;
531     }
532     return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
533 }
534 
skip_none(const char * path)535 static bool skip_none(const char* path __attribute__((unused))) {
536     return false;
537 }
538 
539 unsigned long worst_write_perf = 20000; /* in KB/s */
540 
541 //
542 //  stat offsets
543 // Name            units         description
544 // ----            -----         -----------
545 // read I/Os       requests      number of read I/Os processed
546 #define __STAT_READ_IOS      0
547 // read merges     requests      number of read I/Os merged with in-queue I/O
548 #define __STAT_READ_MERGES   1
549 // read sectors    sectors       number of sectors read
550 #define __STAT_READ_SECTORS  2
551 // read ticks      milliseconds  total wait time for read requests
552 #define __STAT_READ_TICKS    3
553 // write I/Os      requests      number of write I/Os processed
554 #define __STAT_WRITE_IOS     4
555 // write merges    requests      number of write I/Os merged with in-queue I/O
556 #define __STAT_WRITE_MERGES  5
557 // write sectors   sectors       number of sectors written
558 #define __STAT_WRITE_SECTORS 6
559 // write ticks     milliseconds  total wait time for write requests
560 #define __STAT_WRITE_TICKS   7
561 // in_flight       requests      number of I/Os currently in flight
562 #define __STAT_IN_FLIGHT     8
563 // io_ticks        milliseconds  total time this block device has been active
564 #define __STAT_IO_TICKS      9
565 // time_in_queue   milliseconds  total wait time for all requests
566 #define __STAT_IN_QUEUE     10
567 #define __STAT_NUMBER_FIELD 11
568 //
569 // read I/Os, write I/Os
570 // =====================
571 //
572 // These values increment when an I/O request completes.
573 //
574 // read merges, write merges
575 // =========================
576 //
577 // These values increment when an I/O request is merged with an
578 // already-queued I/O request.
579 //
580 // read sectors, write sectors
581 // ===========================
582 //
583 // These values count the number of sectors read from or written to this
584 // block device.  The "sectors" in question are the standard UNIX 512-byte
585 // sectors, not any device- or filesystem-specific block size.  The
586 // counters are incremented when the I/O completes.
587 #define SECTOR_SIZE 512
588 //
589 // read ticks, write ticks
590 // =======================
591 //
592 // These values count the number of milliseconds that I/O requests have
593 // waited on this block device.  If there are multiple I/O requests waiting,
594 // these values will increase at a rate greater than 1000/second; for
595 // example, if 60 read requests wait for an average of 30 ms, the read_ticks
596 // field will increase by 60*30 = 1800.
597 //
598 // in_flight
599 // =========
600 //
601 // This value counts the number of I/O requests that have been issued to
602 // the device driver but have not yet completed.  It does not include I/O
603 // requests that are in the queue but not yet issued to the device driver.
604 //
605 // io_ticks
606 // ========
607 //
608 // This value counts the number of milliseconds during which the device has
609 // had I/O requests queued.
610 //
611 // time_in_queue
612 // =============
613 //
614 // This value counts the number of milliseconds that I/O requests have waited
615 // on this block device.  If there are multiple I/O requests waiting, this
616 // value will increase as the product of the number of milliseconds times the
617 // number of requests waiting (see "read ticks" above for an example).
618 #define S_TO_MS 1000
619 //
620 
dump_stat_from_fd(const char * title __unused,const char * path,int fd)621 static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
622     unsigned long long fields[__STAT_NUMBER_FIELD];
623     bool z;
624     char *cp, *buffer = nullptr;
625     size_t i = 0;
626     FILE *fp = fdopen(dup(fd), "rb");
627     getline(&buffer, &i, fp);
628     fclose(fp);
629     if (!buffer) {
630         return -errno;
631     }
632     i = strlen(buffer);
633     while ((i > 0) && (buffer[i - 1] == '\n')) {
634         buffer[--i] = '\0';
635     }
636     if (!*buffer) {
637         free(buffer);
638         return 0;
639     }
640     z = true;
641     for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
642         fields[i] = strtoull(cp, &cp, 10);
643         if (fields[i] != 0) {
644             z = false;
645         }
646     }
647     if (z) { /* never accessed */
648         free(buffer);
649         return 0;
650     }
651 
652     if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
653         path += sizeof(BLK_DEV_SYS_DIR) - 1;
654     }
655 
656     printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
657            "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
658            "W-wait", "in-fli", "activ", "T-wait", path, buffer);
659     free(buffer);
660 
661     if (fields[__STAT_IO_TICKS]) {
662         unsigned long read_perf = 0;
663         unsigned long read_ios = 0;
664         if (fields[__STAT_READ_TICKS]) {
665             unsigned long long divisor = fields[__STAT_READ_TICKS]
666                                        * fields[__STAT_IO_TICKS];
667             read_perf = ((unsigned long long)SECTOR_SIZE
668                            * fields[__STAT_READ_SECTORS]
669                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
670                                         / divisor;
671             read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
672                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
673                                         / divisor;
674         }
675 
676         unsigned long write_perf = 0;
677         unsigned long write_ios = 0;
678         if (fields[__STAT_WRITE_TICKS]) {
679             unsigned long long divisor = fields[__STAT_WRITE_TICKS]
680                                        * fields[__STAT_IO_TICKS];
681             write_perf = ((unsigned long long)SECTOR_SIZE
682                            * fields[__STAT_WRITE_SECTORS]
683                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
684                                         / divisor;
685             write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
686                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
687                                         / divisor;
688         }
689 
690         unsigned queue = (fields[__STAT_IN_QUEUE]
691                              + (fields[__STAT_IO_TICKS] >> 1))
692                                  / fields[__STAT_IO_TICKS];
693 
694         if (!write_perf && !write_ios) {
695             printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue);
696         } else {
697             printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf,
698                    read_ios, write_perf, write_ios, queue);
699         }
700 
701         /* bugreport timeout factor adjustment */
702         if ((write_perf > 1) && (write_perf < worst_write_perf)) {
703             worst_write_perf = write_perf;
704         }
705     }
706     return 0;
707 }
708 
709 static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
710 
711 /* timeout in ms to read a list of buffers */
logcat_timeout(const std::vector<std::string> & buffers)712 static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
713     unsigned long timeout_ms = 0;
714     for (const auto& buffer : buffers) {
715         log_id_t id = android_name_to_log_id(buffer.c_str());
716         unsigned long property_size = __android_logger_get_buffer_size(id);
717         /* Engineering margin is ten-fold our guess */
718         timeout_ms += 10 * (property_size + worst_write_perf) / worst_write_perf;
719     }
720     return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
721 }
722 
ConsentCallback()723 Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
724 }
725 
onReportApproved()726 android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
727     std::lock_guard<std::mutex> lock(lock_);
728     result_ = APPROVED;
729     MYLOGD("User approved consent to share bugreport\n");
730     return android::binder::Status::ok();
731 }
732 
onReportDenied()733 android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
734     std::lock_guard<std::mutex> lock(lock_);
735     result_ = DENIED;
736     MYLOGW("User denied consent to share bugreport\n");
737     return android::binder::Status::ok();
738 }
739 
getResult()740 UserConsentResult Dumpstate::ConsentCallback::getResult() {
741     std::lock_guard<std::mutex> lock(lock_);
742     return result_;
743 }
744 
getElapsedTimeMs() const745 uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
746     return Nanotime() - start_time_;
747 }
748 
PrintHeader() const749 void Dumpstate::PrintHeader() const {
750     std::string build, fingerprint, radio, bootloader, network;
751     char date[80];
752 
753     build = android::base::GetProperty("ro.build.display.id", "(unknown)");
754     fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
755     radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
756     bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
757     network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
758     strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
759 
760     printf("========================================================\n");
761     printf("== dumpstate: %s\n", date);
762     printf("========================================================\n");
763 
764     printf("\n");
765     printf("Build: %s\n", build.c_str());
766     // NOTE: fingerprint entry format is important for other tools.
767     printf("Build fingerprint: '%s'\n", fingerprint.c_str());
768     printf("Bootloader: %s\n", bootloader.c_str());
769     printf("Radio: %s\n", radio.c_str());
770     printf("Network: %s\n", network.c_str());
771     int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
772     if (module_metadata_version != 0) {
773         printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
774     }
775 
776     printf("Kernel: ");
777     DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
778     printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
779     printf("Uptime: ");
780     RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
781                    CommandOptions::WithTimeout(1).Always().Build());
782     printf("Bugreport format version: %s\n", version_.c_str());
783     printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
784            PropertiesHelper::IsDryRun(), options_->args.c_str(), options_->extra_options.c_str());
785     printf("\n");
786 }
787 
788 // List of file extensions that can cause a zip file attachment to be rejected by some email
789 // service providers.
790 static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
791       ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
792       ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
793       ".shb", ".sys", ".vb",  ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
794 };
795 
AddZipEntryFromFd(const std::string & entry_name,int fd,std::chrono::milliseconds timeout=0ms)796 status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
797                                       std::chrono::milliseconds timeout = 0ms) {
798     if (!IsZipping()) {
799         MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
800                entry_name.c_str());
801         return INVALID_OPERATION;
802     }
803     std::string valid_name = entry_name;
804 
805     // Rename extension if necessary.
806     size_t idx = entry_name.rfind('.');
807     if (idx != std::string::npos) {
808         std::string extension = entry_name.substr(idx);
809         std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
810         if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
811             valid_name = entry_name + ".renamed";
812             MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
813         }
814     }
815 
816     // Logging statement  below is useful to time how long each entry takes, but it's too verbose.
817     // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
818     int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
819                                                   get_mtime(fd, ds.now_));
820     if (err != 0) {
821         MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
822                ZipWriter::ErrorCodeString(err));
823         return UNKNOWN_ERROR;
824     }
825     bool finished_entry = false;
826     auto finish_entry = [this, &finished_entry] {
827         if (!finished_entry) {
828             // This should only be called when we're going to return an earlier error,
829             // which would've been logged. This may imply the file is already corrupt
830             // and any further logging from FinishEntry is more likely to mislead than
831             // not.
832             this->zip_writer_->FinishEntry();
833         }
834     };
835     auto scope_guard = android::base::make_scope_guard(finish_entry);
836     auto start = std::chrono::steady_clock::now();
837     auto end = start + timeout;
838     struct pollfd pfd = {fd, POLLIN};
839 
840     std::vector<uint8_t> buffer(65536);
841     while (1) {
842         if (timeout.count() > 0) {
843             // lambda to recalculate the timeout.
844             auto time_left_ms = [end]() {
845                 auto now = std::chrono::steady_clock::now();
846                 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
847                 return std::max(diff.count(), 0LL);
848             };
849 
850             int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
851             if (rc < 0) {
852                 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
853                        entry_name.c_str(), strerror(errno));
854                 return -errno;
855             } else if (rc == 0) {
856                 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
857                        entry_name.c_str(), strerror(errno), timeout.count());
858                 return TIMED_OUT;
859             }
860         }
861 
862         ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
863         if (bytes_read == 0) {
864             break;
865         } else if (bytes_read == -1) {
866             MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
867             return -errno;
868         }
869         err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
870         if (err) {
871             MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
872             return UNKNOWN_ERROR;
873         }
874     }
875 
876     err = zip_writer_->FinishEntry();
877     finished_entry = true;
878     if (err != 0) {
879         MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
880         return UNKNOWN_ERROR;
881     }
882 
883     return OK;
884 }
885 
AddZipEntry(const std::string & entry_name,const std::string & entry_path)886 bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
887     android::base::unique_fd fd(
888         TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
889     if (fd == -1) {
890         MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
891         return false;
892     }
893 
894     return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
895 }
896 
897 /* adds a file to the existing zipped bugreport */
_add_file_from_fd(const char * title,const char * path,int fd)898 static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
899     return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
900 }
901 
AddDir(const std::string & dir,bool recursive)902 void Dumpstate::AddDir(const std::string& dir, bool recursive) {
903     if (!IsZipping()) {
904         MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
905         return;
906     }
907     MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
908     DurationReporter duration_reporter(dir, true);
909     dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
910 }
911 
AddTextZipEntry(const std::string & entry_name,const std::string & content)912 bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
913     if (!IsZipping()) {
914         MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
915                entry_name.c_str());
916         return false;
917     }
918     MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
919     int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
920     if (err != 0) {
921         MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
922                ZipWriter::ErrorCodeString(err));
923         return false;
924     }
925 
926     err = zip_writer_->WriteBytes(content.c_str(), content.length());
927     if (err != 0) {
928         MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
929                ZipWriter::ErrorCodeString(err));
930         return false;
931     }
932 
933     err = zip_writer_->FinishEntry();
934     if (err != 0) {
935         MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
936         return false;
937     }
938 
939     return true;
940 }
941 
DoKmsg()942 static void DoKmsg() {
943     struct stat st;
944     if (!stat(PSTORE_LAST_KMSG, &st)) {
945         /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
946         DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
947     } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
948         DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
949     } else {
950         /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
951         DumpFile("LAST KMSG", "/proc/last_kmsg");
952     }
953 }
954 
DoKernelLogcat()955 static void DoKernelLogcat() {
956     unsigned long timeout_ms = logcat_timeout({"kernel"});
957     RunCommand(
958         "KERNEL LOG",
959         {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
960         CommandOptions::WithTimeoutInMs(timeout_ms).Build());
961 }
962 
DoLogcat()963 static void DoLogcat() {
964     unsigned long timeout_ms;
965     // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
966     // calculate timeout
967     timeout_ms = logcat_timeout({"main", "system", "crash"});
968     RunCommand("SYSTEM LOG",
969                {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
970                CommandOptions::WithTimeoutInMs(timeout_ms).Build());
971     timeout_ms = logcat_timeout({"events"});
972     RunCommand(
973         "EVENT LOG",
974         {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
975         CommandOptions::WithTimeoutInMs(timeout_ms).Build());
976     timeout_ms = logcat_timeout({"stats"});
977     RunCommand(
978         "STATS LOG",
979         {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
980         CommandOptions::WithTimeoutInMs(timeout_ms).Build());
981     timeout_ms = logcat_timeout({"radio"});
982     RunCommand(
983         "RADIO LOG",
984         {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
985         CommandOptions::WithTimeoutInMs(timeout_ms).Build());
986 
987     RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
988 
989     /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
990     RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
991                                "-v", "uid", "-d", "*:v"});
992 }
993 
DumpIpTablesAsRoot()994 static void DumpIpTablesAsRoot() {
995     RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
996     RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
997     RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
998     /* no ip6 nat */
999     RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1000     RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1001     RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1002     RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
1003 }
1004 
AddAnrTraceDir(const bool add_to_zip,const std::string & anr_traces_dir)1005 static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
1006     MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1007            anr_traces_dir.c_str());
1008 
1009     // If we're here, dump_traces_path will always be a temporary file
1010     // (created with mkostemp or similar) that contains dumps taken earlier
1011     // on in the process.
1012     if (dump_traces_path != nullptr) {
1013         if (add_to_zip) {
1014             ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
1015         } else {
1016             MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1017                    dump_traces_path);
1018             ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
1019         }
1020 
1021         const int ret = unlink(dump_traces_path);
1022         if (ret == -1) {
1023             MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1024                    strerror(errno));
1025         }
1026     }
1027 
1028     // Add a specific message for the first ANR Dump.
1029     if (ds.anr_data_.size() > 0) {
1030         AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
1031                  "VM TRACES AT LAST ANR", add_to_zip);
1032 
1033         // The "last" ANR will always be included as separate entry in the zip file. In addition,
1034         // it will be present in the body of the main entry if |add_to_zip| == false.
1035         //
1036         // Historical ANRs are always included as separate entries in the bugreport zip file.
1037         AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
1038                  "HISTORICAL ANR", true /* add_to_zip */);
1039     } else {
1040         printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1041     }
1042 }
1043 
AddAnrTraceFiles()1044 static void AddAnrTraceFiles() {
1045     const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
1046 
1047     std::string anr_traces_dir = "/data/anr";
1048 
1049     AddAnrTraceDir(add_to_zip, anr_traces_dir);
1050 
1051     RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1052 
1053     // Slow traces for slow operations.
1054     struct stat st;
1055     int i = 0;
1056     while (true) {
1057         const std::string slow_trace_path =
1058             anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1059         if (stat(slow_trace_path.c_str(), &st)) {
1060             // No traces file at this index, done with the files.
1061             break;
1062         }
1063         ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1064         i++;
1065     }
1066 }
1067 
DumpBlockStatFiles()1068 static void DumpBlockStatFiles() {
1069     DurationReporter duration_reporter("DUMP BLOCK STAT");
1070 
1071     std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1072 
1073     if (dirptr == nullptr) {
1074         MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1075         return;
1076     }
1077 
1078     printf("------ DUMP BLOCK STAT ------\n\n");
1079     while (struct dirent *d = readdir(dirptr.get())) {
1080         if ((d->d_name[0] == '.')
1081          && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1082           || (d->d_name[1] == '\0'))) {
1083             continue;
1084         }
1085         const std::string new_path =
1086             android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1087         printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1088         dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1089         printf("\n");
1090     }
1091      return;
1092 }
1093 
DumpPacketStats()1094 static void DumpPacketStats() {
1095     DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1096     DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1097     DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1098     DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1099     DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1100 }
1101 
DumpIpAddrAndRules()1102 static void DumpIpAddrAndRules() {
1103     /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1104     RunCommand("NETWORK INTERFACES", {"ip", "link"});
1105     RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1106     RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1107     RunCommand("IP RULES", {"ip", "rule", "show"});
1108     RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1109 }
1110 
RunDumpsysTextByPriority(const std::string & title,int priority,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1111 static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1112                                                      std::chrono::milliseconds timeout,
1113                                                      std::chrono::milliseconds service_timeout) {
1114     auto start = std::chrono::steady_clock::now();
1115     sp<android::IServiceManager> sm = defaultServiceManager();
1116     Dumpsys dumpsys(sm.get());
1117     Vector<String16> args;
1118     Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
1119     Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1120     for (const String16& service : services) {
1121         RETURN_IF_USER_DENIED_CONSENT();
1122         std::string path(title);
1123         path.append(" - ").append(String8(service).c_str());
1124         DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1125         size_t bytes_written = 0;
1126         status_t status = dumpsys.startDumpThread(service, args);
1127         if (status == OK) {
1128             dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1129             std::chrono::duration<double> elapsed_seconds;
1130             status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1131                                        /* as_proto = */ false, elapsed_seconds, bytes_written);
1132             section_reporter.setSize(bytes_written);
1133             dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1134             bool dump_complete = (status == OK);
1135             dumpsys.stopDumpThread(dump_complete);
1136         }
1137         section_reporter.setStatus(status);
1138 
1139         auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1140             std::chrono::steady_clock::now() - start);
1141         if (elapsed_duration > timeout) {
1142             MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1143                    elapsed_duration.count());
1144             break;
1145         }
1146     }
1147     return Dumpstate::RunStatus::OK;
1148 }
1149 
RunDumpsysText(const std::string & title,int priority,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1150 static void RunDumpsysText(const std::string& title, int priority,
1151                            std::chrono::milliseconds timeout,
1152                            std::chrono::milliseconds service_timeout) {
1153     DurationReporter duration_reporter(title);
1154     dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1155     fsync(STDOUT_FILENO);
1156     RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1157 }
1158 
1159 /* Dump all services registered with Normal or Default priority. */
RunDumpsysTextNormalPriority(const std::string & title,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1160 static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1161                                                          std::chrono::milliseconds timeout,
1162                                                          std::chrono::milliseconds service_timeout) {
1163     DurationReporter duration_reporter(title);
1164     dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1165     fsync(STDOUT_FILENO);
1166     RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1167                              service_timeout);
1168 
1169     RETURN_IF_USER_DENIED_CONSENT();
1170 
1171     return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1172                                     service_timeout);
1173 }
1174 
RunDumpsysProto(const std::string & title,int priority,std::chrono::milliseconds timeout,std::chrono::milliseconds service_timeout)1175 static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1176                                             std::chrono::milliseconds timeout,
1177                                             std::chrono::milliseconds service_timeout) {
1178     if (!ds.IsZipping()) {
1179         MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
1180         return Dumpstate::RunStatus::OK;
1181     }
1182     sp<android::IServiceManager> sm = defaultServiceManager();
1183     Dumpsys dumpsys(sm.get());
1184     Vector<String16> args;
1185     Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1186     DurationReporter duration_reporter(title);
1187 
1188     auto start = std::chrono::steady_clock::now();
1189     Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1190     for (const String16& service : services) {
1191         RETURN_IF_USER_DENIED_CONSENT();
1192         std::string path(kProtoPath);
1193         path.append(String8(service).c_str());
1194         if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1195             path.append("_CRITICAL");
1196         } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1197             path.append("_HIGH");
1198         }
1199         path.append(kProtoExt);
1200         DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1201         status_t status = dumpsys.startDumpThread(service, args);
1202         if (status == OK) {
1203             status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1204             bool dumpTerminated = (status == OK);
1205             dumpsys.stopDumpThread(dumpTerminated);
1206         }
1207         ZipWriter::FileEntry file_entry;
1208         ds.zip_writer_->GetLastEntry(&file_entry);
1209         section_reporter.setSize(file_entry.compressed_size);
1210         section_reporter.setStatus(status);
1211 
1212         auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1213             std::chrono::steady_clock::now() - start);
1214         if (elapsed_duration > timeout) {
1215             MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1216                    elapsed_duration.count());
1217             break;
1218         }
1219     }
1220     return Dumpstate::RunStatus::OK;
1221 }
1222 
1223 // Runs dumpsys on services that must dump first and will take less than 100ms to dump.
RunDumpsysCritical()1224 static Dumpstate::RunStatus RunDumpsysCritical() {
1225     RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1226                    /* timeout= */ 5s, /* service_timeout= */ 500ms);
1227 
1228     RETURN_IF_USER_DENIED_CONSENT();
1229 
1230     return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1231                            /* timeout= */ 5s, /* service_timeout= */ 500ms);
1232 }
1233 
1234 // Runs dumpsys on services that must dump first but can take up to 250ms to dump.
RunDumpsysHigh()1235 static Dumpstate::RunStatus RunDumpsysHigh() {
1236     // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1237     // high priority. Reduce timeout once they are able to dump in a shorter time or
1238     // moved to a parallel task.
1239     RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1240                    /* timeout= */ 90s, /* service_timeout= */ 30s);
1241 
1242     RETURN_IF_USER_DENIED_CONSENT();
1243 
1244     return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1245                            /* timeout= */ 5s, /* service_timeout= */ 1s);
1246 }
1247 
1248 // Runs dumpsys on services that must dump but can take up to 10s to dump.
RunDumpsysNormal()1249 static Dumpstate::RunStatus RunDumpsysNormal() {
1250     RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
1251 
1252     RETURN_IF_USER_DENIED_CONSENT();
1253 
1254     return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1255                            /* timeout= */ 90s, /* service_timeout= */ 10s);
1256 }
1257 
DumpHals()1258 static void DumpHals() {
1259     if (!ds.IsZipping()) {
1260         RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"},
1261                    CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
1262         return;
1263     }
1264     DurationReporter duration_reporter("DUMP HALS");
1265     RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
1266                CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
1267 
1268     using android::hidl::manager::V1_0::IServiceManager;
1269     using android::hardware::defaultServiceManager;
1270 
1271     sp<IServiceManager> sm = defaultServiceManager();
1272     if (sm == nullptr) {
1273         MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1274         return;
1275     }
1276 
1277     auto ret = sm->list([&](const auto& interfaces) {
1278         for (const std::string& interface : interfaces) {
1279             std::string cleanName = interface;
1280             std::replace_if(cleanName.begin(),
1281                             cleanName.end(),
1282                             [](char c) {
1283                                 return !isalnum(c) &&
1284                                     std::string("@-_:.").find(c) == std::string::npos;
1285                             }, '_');
1286             const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
1287 
1288             {
1289                 auto fd = android::base::unique_fd(
1290                     TEMP_FAILURE_RETRY(open(path.c_str(),
1291                     O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1292                     S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1293                 if (fd < 0) {
1294                     MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1295                     continue;
1296                 }
1297                 RunCommandToFd(fd,
1298                         "",
1299                         {"lshal", "debug", "-E", interface},
1300                         CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1301 
1302                 bool empty = 0 == lseek(fd, 0, SEEK_END);
1303                 if (!empty) {
1304                     ds.AddZipEntry("lshal-debug/" + cleanName + ".txt", path);
1305                 }
1306             }
1307 
1308             unlink(path.c_str());
1309         }
1310     });
1311 
1312     if (!ret.isOk()) {
1313         MYLOGE("Could not list hals from hwservicemanager.\n");
1314     }
1315 }
1316 
1317 // Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1318 // via the consent they are shown. Ignores other errors that occur while running various
1319 // commands. The consent checking is currently done around long running tasks, which happen to
1320 // be distributed fairly evenly throughout the function.
dumpstate()1321 static Dumpstate::RunStatus dumpstate() {
1322     DurationReporter duration_reporter("DUMPSTATE");
1323 
1324     // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1325     // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1326     // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
1327     dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
1328     RunCommand("UPTIME", {"uptime"});
1329     DumpBlockStatFiles();
1330     dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
1331     DumpFile("MEMORY INFO", "/proc/meminfo");
1332     RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
1333                             "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
1334 
1335     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1336 
1337     DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1338     DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1339     DumpFile("SLAB INFO", "/proc/slabinfo");
1340     DumpFile("ZONEINFO", "/proc/zoneinfo");
1341     DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1342     DumpFile("BUDDYINFO", "/proc/buddyinfo");
1343     DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
1344 
1345     DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1346     DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1347     DumpFile("KERNEL SYNC", "/d/sync");
1348 
1349     RunCommand("PROCESSES AND THREADS",
1350                {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
1351 
1352     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1353                                          CommandOptions::AS_ROOT);
1354 
1355     DumpHals();
1356 
1357     RunCommand("PRINTENV", {"printenv"});
1358     RunCommand("NETSTAT", {"netstat", "-nW"});
1359     struct stat s;
1360     if (stat("/proc/modules", &s) != 0) {
1361         MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1362     } else {
1363         RunCommand("LSMOD", {"lsmod"});
1364     }
1365 
1366     if (__android_logger_property_get_bool(
1367             "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) {
1368         DoKernelLogcat();
1369     } else {
1370         do_dmesg();
1371     }
1372 
1373     RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
1374 
1375     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1376 
1377     for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
1378     for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
1379 
1380     /* Dump Bluetooth HCI logs */
1381     ds.AddDir("/data/misc/bluetooth/logs", true);
1382 
1383     if (!ds.do_early_screenshot_) {
1384         MYLOGI("taking late screenshot\n");
1385         ds.TakeScreenshot();
1386     }
1387 
1388     DoLogcat();
1389 
1390     AddAnrTraceFiles();
1391 
1392     // NOTE: tombstones are always added as separate entries in the zip archive
1393     // and are not interspersed with the main report.
1394     const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
1395                                             "TOMBSTONE", true /* add_to_zip */);
1396     if (!tombstones_dumped) {
1397         printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
1398     }
1399 
1400     DumpPacketStats();
1401 
1402     RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1403 
1404     DoKmsg();
1405 
1406     DumpIpAddrAndRules();
1407 
1408     dump_route_tables();
1409 
1410     RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1411     RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1412     RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
1413 
1414     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
1415 
1416     RunCommand("SYSTEM PROPERTIES", {"getprop"});
1417 
1418     RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
1419 
1420     RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
1421 
1422     RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
1423 
1424     /* Binder state is expensive to look at as it uses a lot of memory. */
1425     DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1426     DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1427     DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1428     DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1429     DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
1430 
1431     RunDumpsys("WINSCOPE TRACE", {"window", "trace"});
1432     /* Add window and surface trace files. */
1433     if (!PropertiesHelper::IsUserBuild()) {
1434         ds.AddDir(WMTRACE_DATA_DIR, false);
1435     }
1436 
1437     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpstateBoard);
1438 
1439     /* Migrate the ril_dumpstate to a device specific dumpstate? */
1440     int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1441     if (rilDumpstateTimeout > 0) {
1442         // su does not exist on user builds, so try running without it.
1443         // This way any implementations of vril-dump that do not require
1444         // root can run on user builds.
1445         CommandOptions::CommandOptionsBuilder options =
1446             CommandOptions::WithTimeout(rilDumpstateTimeout);
1447         if (!PropertiesHelper::IsUserBuild()) {
1448             options.AsRoot();
1449         }
1450         RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
1451     }
1452 
1453     printf("========================================================\n");
1454     printf("== Android Framework Services\n");
1455     printf("========================================================\n");
1456 
1457     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
1458 
1459     printf("========================================================\n");
1460     printf("== Checkins\n");
1461     printf("========================================================\n");
1462 
1463     RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1464 
1465     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsys, "CHECKIN MEMINFO", {"meminfo", "--checkin"});
1466 
1467     RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1468     RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1469     RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1470     RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
1471 
1472     printf("========================================================\n");
1473     printf("== Running Application Activities\n");
1474     printf("========================================================\n");
1475 
1476     // The following dumpsys internally collects output from running apps, so it can take a long
1477     // time. So let's extend the timeout.
1478 
1479     const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1480 
1481     RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
1482 
1483     printf("========================================================\n");
1484     printf("== Running Application Services (platform)\n");
1485     printf("========================================================\n");
1486 
1487     RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1488             DUMPSYS_COMPONENTS_OPTIONS);
1489 
1490     printf("========================================================\n");
1491     printf("== Running Application Services (non-platform)\n");
1492     printf("========================================================\n");
1493 
1494     RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1495             DUMPSYS_COMPONENTS_OPTIONS);
1496 
1497     printf("========================================================\n");
1498     printf("== Running Application Providers (platform)\n");
1499     printf("========================================================\n");
1500 
1501     RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1502             DUMPSYS_COMPONENTS_OPTIONS);
1503 
1504     printf("========================================================\n");
1505     printf("== Running Application Providers (non-platform)\n");
1506     printf("========================================================\n");
1507 
1508     RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1509             DUMPSYS_COMPONENTS_OPTIONS);
1510 
1511     printf("========================================================\n");
1512     printf("== Dropbox crashes\n");
1513     printf("========================================================\n");
1514 
1515     RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1516     RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1517 
1518     printf("========================================================\n");
1519     printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1520            ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1521     printf("========================================================\n");
1522     printf("== dumpstate: done (id %d)\n", ds.id_);
1523     printf("========================================================\n");
1524 
1525     printf("========================================================\n");
1526     printf("== Obtaining statsd metadata\n");
1527     printf("========================================================\n");
1528     // This differs from the usual dumpsys stats, which is the stats report data.
1529     RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
1530     return Dumpstate::RunStatus::OK;
1531 }
1532 
1533 /*
1534  * Dumps state for the default case; drops root after it's no longer necessary.
1535  *
1536  * Returns RunStatus::OK if everything went fine.
1537  * Returns RunStatus::ERROR if there was an error.
1538  * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1539  * with the caller.
1540  */
DumpstateDefault()1541 static Dumpstate::RunStatus DumpstateDefault() {
1542     // Try to dump anrd trace if the daemon is running.
1543     dump_anrd_trace();
1544 
1545     // Invoking the following dumpsys calls before DumpTraces() to try and
1546     // keep the system stats as close to its initial state as possible.
1547     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysCritical);
1548 
1549     /* collect stack traces from Dalvik and native processes (needs root) */
1550     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpTraces, &dump_traces_path);
1551 
1552     /* Run some operations that require root. */
1553     ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1554     ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1555 
1556     ds.AddDir(RECOVERY_DIR, true);
1557     ds.AddDir(RECOVERY_DATA_DIR, true);
1558     ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1559     ds.AddDir(LOGPERSIST_DATA_DIR, false);
1560     if (!PropertiesHelper::IsUserBuild()) {
1561         ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1562         ds.AddDir(PROFILE_DATA_DIR_REF, true);
1563     }
1564     add_mountinfo();
1565     DumpIpTablesAsRoot();
1566 
1567     // Capture any IPSec policies in play. No keys are exposed here.
1568     RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1569 
1570     // Dump IPsec stats. No keys are exposed here.
1571     DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1572 
1573     // Run ss as root so we can see socket marks.
1574     RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1575 
1576     // Run iotop as root to show top 100 IO threads
1577     RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1578 
1579     // Gather shared memory buffer info if the product implements it
1580     struct stat st;
1581     if (!stat("/product/bin/dmabuf_dump", &st)) {
1582         RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
1583     }
1584 
1585     if (!DropRootUser()) {
1586         return Dumpstate::RunStatus::ERROR;
1587     }
1588 
1589     RETURN_IF_USER_DENIED_CONSENT();
1590     return dumpstate();
1591 }
1592 
1593 // This method collects common dumpsys for telephony and wifi
DumpstateRadioCommon()1594 static void DumpstateRadioCommon() {
1595     DumpIpTablesAsRoot();
1596 
1597     if (!DropRootUser()) {
1598         return;
1599     }
1600 
1601     do_dmesg();
1602     DoLogcat();
1603     DumpPacketStats();
1604     DoKmsg();
1605     DumpIpAddrAndRules();
1606     dump_route_tables();
1607 
1608     RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1609                CommandOptions::WithTimeout(10).Build());
1610 }
1611 
1612 // This method collects dumpsys for telephony debugging only
DumpstateTelephonyOnly()1613 static void DumpstateTelephonyOnly() {
1614     DurationReporter duration_reporter("DUMPSTATE");
1615     const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1616 
1617     DumpstateRadioCommon();
1618 
1619     RunCommand("SYSTEM PROPERTIES", {"getprop"});
1620 
1621     printf("========================================================\n");
1622     printf("== Android Framework Services\n");
1623     printf("========================================================\n");
1624 
1625     RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1626                SEC_TO_MSEC(10));
1627     RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
1628                SEC_TO_MSEC(10));
1629     RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1630     RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1631                SEC_TO_MSEC(10));
1632     RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1633                SEC_TO_MSEC(10));
1634     RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1635                SEC_TO_MSEC(10));
1636 
1637     printf("========================================================\n");
1638     printf("== Running Application Services\n");
1639     printf("========================================================\n");
1640 
1641     RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1642 
1643     printf("========================================================\n");
1644     printf("== Running Application Services (non-platform)\n");
1645     printf("========================================================\n");
1646 
1647     RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1648             DUMPSYS_COMPONENTS_OPTIONS);
1649 
1650     printf("========================================================\n");
1651     printf("== Checkins\n");
1652     printf("========================================================\n");
1653 
1654     RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1655 
1656     printf("========================================================\n");
1657     printf("== dumpstate: done (id %d)\n", ds.id_);
1658     printf("========================================================\n");
1659 }
1660 
1661 // This method collects dumpsys for wifi debugging only
DumpstateWifiOnly()1662 static void DumpstateWifiOnly() {
1663     DurationReporter duration_reporter("DUMPSTATE");
1664 
1665     DumpstateRadioCommon();
1666 
1667     printf("========================================================\n");
1668     printf("== Android Framework Services\n");
1669     printf("========================================================\n");
1670 
1671     RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1672                SEC_TO_MSEC(10));
1673     RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1674                SEC_TO_MSEC(10));
1675 
1676     DumpHals();
1677 
1678     printf("========================================================\n");
1679     printf("== dumpstate: done (id %d)\n", ds.id_);
1680     printf("========================================================\n");
1681 }
1682 
DumpTraces(const char ** path)1683 Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
1684     DurationReporter duration_reporter("DUMP TRACES");
1685 
1686     const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
1687     const size_t buf_size = temp_file_pattern.length() + 1;
1688     std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
1689     memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
1690 
1691     // Create a new, empty file to receive all trace dumps.
1692     //
1693     // TODO: This can be simplified once we remove support for the old style
1694     // dumps. We can have a file descriptor passed in to dump_traces instead
1695     // of creating a file, closing it and then reopening it again.
1696     android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
1697     if (fd < 0) {
1698         MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
1699         return RunStatus::OK;
1700     }
1701 
1702     // Nobody should have access to this temporary file except dumpstate, but we
1703     // temporarily grant 'read' to 'others' here because this file is created
1704     // when tombstoned is still running as root, but dumped after dropping. This
1705     // can go away once support for old style dumping has.
1706     const int chmod_ret = fchmod(fd, 0666);
1707     if (chmod_ret < 0) {
1708         MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
1709         return RunStatus::OK;
1710     }
1711 
1712     std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
1713     if (proc.get() == nullptr) {
1714         MYLOGE("opendir /proc failed: %s\n", strerror(errno));
1715         return RunStatus::OK;
1716     }
1717 
1718     // Number of times process dumping has timed out. If we encounter too many
1719     // failures, we'll give up.
1720     int timeout_failures = 0;
1721     bool dalvik_found = false;
1722 
1723     const std::set<int> hal_pids = get_interesting_hal_pids();
1724 
1725     struct dirent* d;
1726     while ((d = readdir(proc.get()))) {
1727         RETURN_IF_USER_DENIED_CONSENT();
1728         int pid = atoi(d->d_name);
1729         if (pid <= 0) {
1730             continue;
1731         }
1732 
1733         const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
1734         std::string exe;
1735         if (!android::base::Readlink(link_name, &exe)) {
1736             continue;
1737         }
1738 
1739         bool is_java_process;
1740         if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
1741             // Don't bother dumping backtraces for the zygote.
1742             if (IsZygote(pid)) {
1743                 continue;
1744             }
1745 
1746             dalvik_found = true;
1747             is_java_process = true;
1748         } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
1749             is_java_process = false;
1750         } else {
1751             // Probably a native process we don't care about, continue.
1752             continue;
1753         }
1754 
1755         // If 3 backtrace dumps fail in a row, consider debuggerd dead.
1756         if (timeout_failures == 3) {
1757             dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
1758             break;
1759         }
1760 
1761         const uint64_t start = Nanotime();
1762         const int ret = dump_backtrace_to_file_timeout(
1763             pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
1764             is_java_process ? 5 : 20, fd);
1765 
1766         if (ret == -1) {
1767             // For consistency, the header and footer to this message match those
1768             // dumped by debuggerd in the success case.
1769             dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
1770             dprintf(fd, "Dump failed, likely due to a timeout.\n");
1771             dprintf(fd, "---- end %d ----", pid);
1772             timeout_failures++;
1773             continue;
1774         }
1775 
1776         // We've successfully dumped stack traces, reset the failure count
1777         // and write a summary of the elapsed time to the file and continue with the
1778         // next process.
1779         timeout_failures = 0;
1780 
1781         dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
1782                 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
1783     }
1784 
1785     if (!dalvik_found) {
1786         MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
1787     }
1788 
1789     *path = file_name_buf.release();
1790     return RunStatus::OK;
1791 }
1792 
DumpstateBoard()1793 void Dumpstate::DumpstateBoard() {
1794     DurationReporter duration_reporter("dumpstate_board()");
1795     printf("========================================================\n");
1796     printf("== Board\n");
1797     printf("========================================================\n");
1798 
1799     if (!IsZipping()) {
1800         MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
1801         return;
1802     }
1803 
1804     std::vector<std::string> paths;
1805     std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
1806     for (int i = 0; i < NUM_OF_DUMPS; i++) {
1807         paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
1808                                         kDumpstateBoardFiles[i].c_str()));
1809         remover.emplace_back(android::base::make_scope_guard(
1810             std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
1811     }
1812 
1813     sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
1814     if (dumpstate_device == nullptr) {
1815         MYLOGE("No IDumpstateDevice implementation\n");
1816         return;
1817     }
1818 
1819     using ScopedNativeHandle =
1820             std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
1821     ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
1822                               [](native_handle_t* handle) {
1823                                   native_handle_close(handle);
1824                                   native_handle_delete(handle);
1825                               });
1826     if (handle == nullptr) {
1827         MYLOGE("Could not create native_handle\n");
1828         return;
1829     }
1830 
1831     // TODO(128270426): Check for consent in between?
1832     for (size_t i = 0; i < paths.size(); i++) {
1833         MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
1834 
1835         android::base::unique_fd fd(TEMP_FAILURE_RETRY(
1836             open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1837                  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1838         if (fd < 0) {
1839             MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
1840             return;
1841         }
1842         handle.get()->data[i] = fd.release();
1843     }
1844 
1845     // Given that bugreport is required to diagnose failures, it's better to
1846     // set an arbitrary amount of timeout for IDumpstateDevice than to block the
1847     // rest of bugreport. In the timeout case, we will kill dumpstate board HAL
1848     // and grab whatever dumped
1849     std::packaged_task<bool()>
1850             dumpstate_task([paths, dumpstate_device, &handle]() -> bool {
1851             android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle.get());
1852             if (!status.isOk()) {
1853                 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
1854                 return false;
1855             }
1856             return true;
1857         });
1858 
1859     auto result = dumpstate_task.get_future();
1860     std::thread(std::move(dumpstate_task)).detach();
1861 
1862     constexpr size_t timeout_sec = 30;
1863     if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
1864         MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
1865         if (!android::base::SetProperty("ctl.interface_restart",
1866                                         android::base::StringPrintf("%s/default",
1867                                                                     IDumpstateDevice::descriptor))) {
1868             MYLOGE("Couldn't restart dumpstate HAL\n");
1869         }
1870     }
1871     // Wait some time for init to kill dumpstate vendor HAL
1872     constexpr size_t killing_timeout_sec = 10;
1873     if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
1874         MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
1875                "there might be racing in content\n", killing_timeout_sec);
1876     }
1877 
1878     auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
1879     for (size_t i = 0; i < paths.size(); i++) {
1880         struct stat s;
1881         if (fstat(handle.get()->data[i], &s) == -1) {
1882             MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
1883                    strerror(errno));
1884             file_sizes[i] = -1;
1885             continue;
1886         }
1887         file_sizes[i] = s.st_size;
1888     }
1889 
1890     for (size_t i = 0; i < paths.size(); i++) {
1891         if (file_sizes[i] == -1) {
1892             continue;
1893         }
1894         if (file_sizes[i] == 0) {
1895             MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
1896             continue;
1897         }
1898         AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
1899     }
1900 
1901     printf("*** See dumpstate-board.txt entry ***\n");
1902 }
1903 
ShowUsage()1904 static void ShowUsage() {
1905     fprintf(stderr,
1906             "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
1907             "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1908             "  -h: display this help message\n"
1909             "  -b: play sound file instead of vibrate, at beginning of job\n"
1910             "  -e: play sound file instead of vibrate, at end of job\n"
1911             "  -o: write to file (instead of stdout)\n"
1912             "  -d: append date to filename (requires -o)\n"
1913             "  -p: capture screenshot to filename.png (requires -o)\n"
1914             "  -z: generate zipped file (requires -o)\n"
1915             "  -s: write output to control socket (for init)\n"
1916             "  -S: write file location to control socket (for init; requires -o and -z)\n"
1917             "  -q: disable vibrate\n"
1918             "  -B: send broadcast when finished (requires -o)\n"
1919             "  -P: send broadcast when started and update system properties on "
1920             "progress (requires -o and -B)\n"
1921             "  -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1922             "shouldn't be used with -P)\n"
1923             "  -w: start binder service and make it wait for a call to startBugreport\n"
1924             "  -v: prints the dumpstate header and exit\n");
1925 }
1926 
register_sig_handler()1927 static void register_sig_handler() {
1928     signal(SIGPIPE, SIG_IGN);
1929 }
1930 
FinishZipFile()1931 bool Dumpstate::FinishZipFile() {
1932     std::string entry_name = base_name_ + "-" + name_ + ".txt";
1933     MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
1934            tmp_path_.c_str());
1935     // Final timestamp
1936     char date[80];
1937     time_t the_real_now_please_stand_up = time(nullptr);
1938     strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
1939     MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
1940            the_real_now_please_stand_up - ds.now_);
1941 
1942     if (!ds.AddZipEntry(entry_name, tmp_path_)) {
1943         MYLOGE("Failed to add text entry to .zip file\n");
1944         return false;
1945     }
1946     if (!AddTextZipEntry("main_entry.txt", entry_name)) {
1947         MYLOGE("Failed to add main_entry.txt to .zip file\n");
1948         return false;
1949     }
1950 
1951     // Add log file (which contains stderr output) to zip...
1952     fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
1953     if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
1954         MYLOGE("Failed to add dumpstate log to .zip file\n");
1955         return false;
1956     }
1957     // TODO: Should truncate the existing file.
1958     // ... and re-open it for further logging.
1959     if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
1960         return false;
1961     }
1962     fprintf(stderr, "\n");
1963 
1964     int32_t err = zip_writer_->Finish();
1965     if (err != 0) {
1966         MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
1967         return false;
1968     }
1969 
1970     // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1971     ds.zip_file.reset(nullptr);
1972 
1973     MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1974     android::os::UnlinkAndLogOnError(tmp_path_);
1975 
1976     return true;
1977 }
1978 
SHA256_file_hash(const std::string & filepath)1979 static std::string SHA256_file_hash(const std::string& filepath) {
1980     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1981             | O_CLOEXEC | O_NOFOLLOW)));
1982     if (fd == -1) {
1983         MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
1984         return nullptr;
1985     }
1986 
1987     SHA256_CTX ctx;
1988     SHA256_Init(&ctx);
1989 
1990     std::vector<uint8_t> buffer(65536);
1991     while (1) {
1992         ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1993         if (bytes_read == 0) {
1994             break;
1995         } else if (bytes_read == -1) {
1996             MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
1997             return nullptr;
1998         }
1999 
2000         SHA256_Update(&ctx, buffer.data(), bytes_read);
2001     }
2002 
2003     uint8_t hash[SHA256_DIGEST_LENGTH];
2004     SHA256_Final(hash, &ctx);
2005 
2006     char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
2007     for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
2008         sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
2009     }
2010     hash_buffer[sizeof(hash_buffer) - 1] = 0;
2011     return std::string(hash_buffer);
2012 }
2013 
SendBroadcast(const std::string & action,const std::vector<std::string> & args)2014 static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2015     // clang-format off
2016     std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2017                     "--receiver-foreground", "--receiver-include-background", "-a", action};
2018     // clang-format on
2019 
2020     am.insert(am.end(), args.begin(), args.end());
2021 
2022     RunCommand("", am,
2023                CommandOptions::WithTimeout(20)
2024                    .Log("Sending broadcast: '%s'\n")
2025                    .Always()
2026                    .DropRoot()
2027                    .RedirectStderr()
2028                    .Build());
2029 }
2030 
Vibrate(int duration_ms)2031 static void Vibrate(int duration_ms) {
2032     // clang-format off
2033     RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
2034                CommandOptions::WithTimeout(10)
2035                    .Log("Vibrate: '%s'\n")
2036                    .Always()
2037                    .Build());
2038     // clang-format on
2039 }
2040 
MaybeResolveSymlink(std::string * path)2041 static void MaybeResolveSymlink(std::string* path) {
2042     std::string resolved_path;
2043     if (android::base::Readlink(*path, &resolved_path)) {
2044         *path = resolved_path;
2045     }
2046 }
2047 
2048 /*
2049  * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
2050  * if we are writing zip files and adds the version file.
2051  */
PrepareToWriteToFile()2052 static void PrepareToWriteToFile() {
2053     MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2054 
2055     std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2056     std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
2057     ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
2058     if (ds.options_->do_add_date) {
2059         char date[80];
2060         strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2061         ds.name_ = date;
2062     } else {
2063         ds.name_ = "undated";
2064     }
2065 
2066     if (ds.options_->telephony_only) {
2067         ds.base_name_ += "-telephony";
2068     } else if (ds.options_->wifi_only) {
2069         ds.base_name_ += "-wifi";
2070     }
2071 
2072     if (ds.options_->do_fb) {
2073         ds.screenshot_path_ = ds.GetPath(".png");
2074     }
2075     ds.tmp_path_ = ds.GetPath(".tmp");
2076     ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2077 
2078     std::string destination = ds.options_->bugreport_fd.get() != -1
2079                                   ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
2080                                   : ds.bugreport_internal_dir_.c_str();
2081     MYLOGD(
2082         "Bugreport dir: %s\n"
2083         "Base name: %s\n"
2084         "Suffix: %s\n"
2085         "Log path: %s\n"
2086         "Temporary path: %s\n"
2087         "Screenshot path: %s\n",
2088         destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2089         ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
2090 
2091     if (ds.options_->do_zip_file) {
2092         ds.path_ = ds.GetPath(".zip");
2093         MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2094         create_parent_dirs(ds.path_.c_str());
2095         ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2096         if (ds.zip_file == nullptr) {
2097             MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2098         } else {
2099             ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2100         }
2101         ds.AddTextZipEntry("version.txt", ds.version_);
2102     }
2103 }
2104 
2105 /*
2106  * Finalizes writing to the file by renaming or zipping the tmp file to the final location,
2107  * printing zipped file status, etc.
2108  */
FinalizeFile()2109 static void FinalizeFile() {
2110     /* check if user changed the suffix using system properties */
2111     std::string name =
2112         android::base::GetProperty(android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
2113     bool change_suffix = false;
2114     if (!name.empty()) {
2115         /* must whitelist which characters are allowed, otherwise it could cross directories */
2116         std::regex valid_regex("^[-_a-zA-Z0-9]+$");
2117         if (std::regex_match(name.c_str(), valid_regex)) {
2118             change_suffix = true;
2119         } else {
2120             MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
2121         }
2122     }
2123     if (change_suffix) {
2124         MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
2125         ds.name_ = name;
2126         if (!ds.screenshot_path_.empty()) {
2127             std::string new_screenshot_path = ds.GetPath(".png");
2128             if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
2129                 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
2130                        new_screenshot_path.c_str(), strerror(errno));
2131             } else {
2132                 ds.screenshot_path_ = new_screenshot_path;
2133             }
2134         }
2135     }
2136 
2137     bool do_text_file = true;
2138     if (ds.options_->do_zip_file) {
2139         if (!ds.FinishZipFile()) {
2140             MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2141             do_text_file = true;
2142         } else {
2143             do_text_file = false;
2144             // If the user has changed the suffix, we need to change the zip file name.
2145             std::string new_path = ds.GetPath(".zip");
2146             if (ds.path_ != new_path) {
2147                 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
2148                 if (rename(ds.path_.c_str(), new_path.c_str())) {
2149                     MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
2150                            strerror(errno));
2151                 } else {
2152                     ds.path_ = new_path;
2153                 }
2154             }
2155         }
2156     }
2157     if (do_text_file) {
2158         ds.path_ = ds.GetPath(".txt");
2159         MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str());
2160         if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
2161             MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno));
2162             ds.path_.clear();
2163         }
2164     }
2165     if (ds.options_->use_control_socket) {
2166         if (do_text_file) {
2167             dprintf(ds.control_socket_fd_,
2168                     "FAIL:could not create zip file, check %s "
2169                     "for more details\n",
2170                     ds.log_path_.c_str());
2171         } else {
2172             dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
2173         }
2174     }
2175 }
2176 
2177 /* Broadcasts that we are done with the bugreport */
SendBugreportFinishedBroadcast()2178 static void SendBugreportFinishedBroadcast() {
2179     // TODO(b/111441001): use callback instead of broadcast.
2180     if (!ds.path_.empty()) {
2181         MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
2182         // clang-format off
2183 
2184         std::vector<std::string> am_args = {
2185              "--receiver-permission", "android.permission.DUMP",
2186              "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
2187              "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
2188              "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
2189              "--es", "android.intent.extra.BUGREPORT", ds.path_,
2190              "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
2191         };
2192         // clang-format on
2193         if (ds.options_->do_fb && !android::os::IsFileEmpty(ds.screenshot_path_)) {
2194             am_args.push_back("--es");
2195             am_args.push_back("android.intent.extra.SCREENSHOT");
2196             am_args.push_back(ds.screenshot_path_);
2197         }
2198         if (!ds.options_->notification_title.empty()) {
2199             am_args.push_back("--es");
2200             am_args.push_back("android.intent.extra.TITLE");
2201             am_args.push_back(ds.options_->notification_title);
2202             if (!ds.options_->notification_description.empty()) {
2203                 am_args.push_back("--es");
2204                 am_args.push_back("android.intent.extra.DESCRIPTION");
2205                 am_args.push_back(ds.options_->notification_description);
2206             }
2207         }
2208         if (ds.options_->is_remote_mode) {
2209             am_args.push_back("--es");
2210             am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
2211             am_args.push_back(SHA256_file_hash(ds.path_));
2212             SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
2213         } else {
2214             SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
2215         }
2216     } else {
2217         MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
2218     }
2219 }
2220 
ModeToString(Dumpstate::BugreportMode mode)2221 static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2222     switch (mode) {
2223         case Dumpstate::BugreportMode::BUGREPORT_FULL:
2224             return "BUGREPORT_FULL";
2225         case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2226             return "BUGREPORT_INTERACTIVE";
2227         case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2228             return "BUGREPORT_REMOTE";
2229         case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2230             return "BUGREPORT_WEAR";
2231         case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2232             return "BUGREPORT_TELEPHONY";
2233         case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2234             return "BUGREPORT_WIFI";
2235         case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2236             return "BUGREPORT_DEFAULT";
2237     }
2238 }
2239 
SetOptionsFromMode(Dumpstate::BugreportMode mode,Dumpstate::DumpOptions * options)2240 static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options) {
2241     options->extra_options = ModeToString(mode);
2242     switch (mode) {
2243         case Dumpstate::BugreportMode::BUGREPORT_FULL:
2244             options->do_broadcast = true;
2245             options->do_fb = true;
2246             break;
2247         case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2248             // Currently, the dumpstate binder is only used by Shell to update progress.
2249             options->do_start_service = true;
2250             options->do_progress_updates = true;
2251             options->do_fb = false;
2252             options->do_broadcast = true;
2253             break;
2254         case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2255             options->do_vibrate = false;
2256             options->is_remote_mode = true;
2257             options->do_fb = false;
2258             options->do_broadcast = true;
2259             break;
2260         case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2261             options->do_start_service = true;
2262             options->do_progress_updates = true;
2263             options->do_zip_file = true;
2264             options->do_fb = true;
2265             options->do_broadcast = true;
2266             break;
2267         case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2268             options->telephony_only = true;
2269             options->do_fb = false;
2270             options->do_broadcast = true;
2271             break;
2272         case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2273             options->wifi_only = true;
2274             options->do_zip_file = true;
2275             options->do_fb = false;
2276             options->do_broadcast = true;
2277             break;
2278         case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2279             break;
2280     }
2281 }
2282 
getBugreportModeFromProperty()2283 static Dumpstate::BugreportMode getBugreportModeFromProperty() {
2284     // If the system property is not set, it's assumed to be a default bugreport.
2285     Dumpstate::BugreportMode mode = Dumpstate::BugreportMode::BUGREPORT_DEFAULT;
2286 
2287     std::string extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
2288     if (!extra_options.empty()) {
2289         // Framework uses a system property to override some command-line args.
2290         // Currently, it contains the type of the requested bugreport.
2291         if (extra_options == "bugreportplus") {
2292             mode = Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE;
2293         } else if (extra_options == "bugreportfull") {
2294             mode = Dumpstate::BugreportMode::BUGREPORT_FULL;
2295         } else if (extra_options == "bugreportremote") {
2296             mode = Dumpstate::BugreportMode::BUGREPORT_REMOTE;
2297         } else if (extra_options == "bugreportwear") {
2298             mode = Dumpstate::BugreportMode::BUGREPORT_WEAR;
2299         } else if (extra_options == "bugreporttelephony") {
2300             mode = Dumpstate::BugreportMode::BUGREPORT_TELEPHONY;
2301         } else if (extra_options == "bugreportwifi") {
2302             mode = Dumpstate::BugreportMode::BUGREPORT_WIFI;
2303         } else {
2304             MYLOGE("Unknown extra option: %s\n", extra_options.c_str());
2305         }
2306         // Reset the property
2307         android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
2308     }
2309     return mode;
2310 }
2311 
2312 // TODO: Move away from system properties when we have options passed via binder calls.
2313 /* Sets runtime options from the system properties and then clears those properties. */
SetOptionsFromProperties(Dumpstate::DumpOptions * options)2314 static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) {
2315     Dumpstate::BugreportMode mode = getBugreportModeFromProperty();
2316     SetOptionsFromMode(mode, options);
2317 
2318     options->notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
2319     if (!options->notification_title.empty()) {
2320         // Reset the property
2321         android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
2322 
2323         options->notification_description =
2324             android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
2325         if (!options->notification_description.empty()) {
2326             // Reset the property
2327             android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
2328         }
2329         MYLOGD("notification (title:  %s, description: %s)\n", options->notification_title.c_str(),
2330                options->notification_description.c_str());
2331     }
2332 }
2333 
LogDumpOptions(const Dumpstate::DumpOptions & options)2334 static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
2335     MYLOGI("do_zip_file: %d\n", options.do_zip_file);
2336     MYLOGI("do_add_date: %d\n", options.do_add_date);
2337     MYLOGI("do_vibrate: %d\n", options.do_vibrate);
2338     MYLOGI("use_socket: %d\n", options.use_socket);
2339     MYLOGI("use_control_socket: %d\n", options.use_control_socket);
2340     MYLOGI("do_fb: %d\n", options.do_fb);
2341     MYLOGI("do_broadcast: %d\n", options.do_broadcast);
2342     MYLOGI("is_remote_mode: %d\n", options.is_remote_mode);
2343     MYLOGI("show_header_only: %d\n", options.show_header_only);
2344     MYLOGI("do_start_service: %d\n", options.do_start_service);
2345     MYLOGI("telephony_only: %d\n", options.telephony_only);
2346     MYLOGI("wifi_only: %d\n", options.wifi_only);
2347     MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
2348     MYLOGI("fd: %d\n", options.bugreport_fd.get());
2349     MYLOGI("extra_options: %s\n", options.extra_options.c_str());
2350     MYLOGI("args: %s\n", options.args.c_str());
2351     MYLOGI("notification_title: %s\n", options.notification_title.c_str());
2352     MYLOGI("notification_description: %s\n", options.notification_description.c_str());
2353 }
2354 
Initialize(BugreportMode bugreport_mode,const android::base::unique_fd & bugreport_fd_in,const android::base::unique_fd & screenshot_fd_in)2355 void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2356                                         const android::base::unique_fd& bugreport_fd_in,
2357                                         const android::base::unique_fd& screenshot_fd_in) {
2358     // In the new API world, date is always added; output is always a zip file.
2359     // TODO(111441001): remove these options once they are obsolete.
2360     do_add_date = true;
2361     do_zip_file = true;
2362 
2363     // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2364     bugreport_fd.reset(dup(bugreport_fd_in.get()));
2365     screenshot_fd.reset(dup(screenshot_fd_in.get()));
2366 
2367     extra_options = ModeToString(bugreport_mode);
2368     SetOptionsFromMode(bugreport_mode, this);
2369 }
2370 
Initialize(int argc,char * argv[])2371 Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2372     RunStatus status = RunStatus::OK;
2373     int c;
2374     while ((c = getopt(argc, argv, "dho:svqzpPBRSV:w")) != -1) {
2375         switch (c) {
2376             // clang-format off
2377             case 'd': do_add_date = true;            break;
2378             case 'z': do_zip_file = true;            break;
2379             // o=use_outfile not supported anymore.
2380             // TODO(b/111441001): Remove when all callers have migrated.
2381             case 'o': break;
2382             case 's': use_socket = true;             break;
2383             case 'S': use_control_socket = true;     break;
2384             case 'v': show_header_only = true;       break;
2385             case 'q': do_vibrate = false;            break;
2386             case 'p': do_fb = true;                  break;
2387             case 'P': do_progress_updates = true;    break;
2388             case 'R': is_remote_mode = true;         break;
2389             case 'B': do_broadcast = true;           break;
2390             case 'V':                                break;  // compatibility no-op
2391             case 'w':
2392                 // This was already processed
2393                 break;
2394             case 'h':
2395                 status = RunStatus::HELP;
2396                 break;
2397             default:
2398                 fprintf(stderr, "Invalid option: %c\n", c);
2399                 status = RunStatus::INVALID_INPUT;
2400                 break;
2401                 // clang-format on
2402         }
2403     }
2404 
2405     // TODO: use helper function to convert argv into a string
2406     for (int i = 0; i < argc; i++) {
2407         args += argv[i];
2408         if (i < argc - 1) {
2409             args += " ";
2410         }
2411     }
2412 
2413     // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2414     optind = 1;
2415 
2416     SetOptionsFromProperties(this);
2417     return status;
2418 }
2419 
ValidateOptions() const2420 bool Dumpstate::DumpOptions::ValidateOptions() const {
2421     if (bugreport_fd.get() != -1 && !do_zip_file) {
2422         return false;
2423     }
2424 
2425     if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) && !OutputToFile()) {
2426         return false;
2427     }
2428 
2429     if (use_control_socket && !do_zip_file) {
2430         return false;
2431     }
2432 
2433     if (do_progress_updates && !do_broadcast) {
2434         return false;
2435     }
2436 
2437     if (is_remote_mode && (do_progress_updates || !do_broadcast || !do_zip_file || !do_add_date)) {
2438         return false;
2439     }
2440     return true;
2441 }
2442 
SetOptions(std::unique_ptr<DumpOptions> options)2443 void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2444     options_ = std::move(options);
2445 }
2446 
Run(int32_t calling_uid,const std::string & calling_package)2447 Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2448     Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
2449     if (listener_ != nullptr) {
2450         switch (status) {
2451             case Dumpstate::RunStatus::OK:
2452                 listener_->onFinished();
2453                 break;
2454             case Dumpstate::RunStatus::HELP:
2455                 break;
2456             case Dumpstate::RunStatus::INVALID_INPUT:
2457                 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
2458                 break;
2459             case Dumpstate::RunStatus::ERROR:
2460                 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2461                 break;
2462             case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2463                 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2464                 break;
2465             case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2466                 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
2467                 break;
2468         }
2469     }
2470     return status;
2471 }
2472 
2473 /*
2474  * Dumps relevant information to a bugreport based on the given options.
2475  *
2476  * The bugreport can be dumped to a file or streamed to a socket.
2477  *
2478  * How dumping to file works:
2479  * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2480  * stderr is redirected a log file.
2481  *
2482  * The temporary bugreport is then populated via printfs, dumping contents of files and
2483  * output of commands to stdout.
2484  *
2485  * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
2486  * text file.
2487  *
2488  * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
2489  * gets added to the archive.
2490  *
2491  * Bugreports are first generated in a local directory and later copied to the caller's fd if
2492  * supplied.
2493  */
RunInternal(int32_t calling_uid,const std::string & calling_package)2494 Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2495                                             const std::string& calling_package) {
2496     LogDumpOptions(*options_);
2497     if (!options_->ValidateOptions()) {
2498         MYLOGE("Invalid options specified\n");
2499         return RunStatus::INVALID_INPUT;
2500     }
2501     /* set as high priority, and protect from OOM killer */
2502     setpriority(PRIO_PROCESS, 0, -20);
2503 
2504     FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
2505     if (oom_adj) {
2506         fputs("-1000", oom_adj);
2507         fclose(oom_adj);
2508     } else {
2509         /* fallback to kernels <= 2.6.35 */
2510         oom_adj = fopen("/proc/self/oom_adj", "we");
2511         if (oom_adj) {
2512             fputs("-17", oom_adj);
2513             fclose(oom_adj);
2514         }
2515     }
2516 
2517     if (version_ == VERSION_DEFAULT) {
2518         version_ = VERSION_CURRENT;
2519     }
2520 
2521     if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
2522         MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
2523                version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
2524                VERSION_SPLIT_ANR.c_str());
2525         return RunStatus::INVALID_INPUT;
2526     }
2527 
2528     if (options_->show_header_only) {
2529         PrintHeader();
2530         return RunStatus::OK;
2531     }
2532 
2533     if (options_->bugreport_fd.get() != -1) {
2534         // If the output needs to be copied over to the caller's fd, get user consent.
2535         android::String16 package(calling_package.c_str());
2536         CheckUserConsent(calling_uid, package);
2537     }
2538 
2539     // Redirect output if needed
2540     bool is_redirecting = options_->OutputToFile();
2541 
2542     // TODO: temporarily set progress until it's part of the Dumpstate constructor
2543     std::string stats_path =
2544         is_redirecting
2545             ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
2546             : "";
2547     progress_.reset(new Progress(stats_path));
2548 
2549     /* gets the sequential id */
2550     uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2551     id_ = ++last_id;
2552     android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2553 
2554     MYLOGI("begin\n");
2555 
2556     register_sig_handler();
2557 
2558     // TODO(b/111441001): maybe skip if already started?
2559     if (options_->do_start_service) {
2560         MYLOGI("Starting 'dumpstate' service\n");
2561         android::status_t ret;
2562         if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2563             MYLOGE("Unable to start DumpstateService: %d\n", ret);
2564         }
2565     }
2566 
2567     if (PropertiesHelper::IsDryRun()) {
2568         MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2569     }
2570 
2571     MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", id_, options_->args.c_str(),
2572            options_->extra_options.c_str());
2573 
2574     MYLOGI("bugreport format version: %s\n", version_.c_str());
2575 
2576     do_early_screenshot_ = options_->do_progress_updates;
2577 
2578     // If we are going to use a socket, do it as early as possible
2579     // to avoid timeouts from bugreport.
2580     if (options_->use_socket) {
2581         if (!redirect_to_socket(stdout, "dumpstate")) {
2582             return ERROR;
2583         }
2584     }
2585 
2586     if (options_->use_control_socket) {
2587         MYLOGD("Opening control socket\n");
2588         control_socket_fd_ = open_socket("dumpstate");
2589         if (control_socket_fd_ == -1) {
2590             return ERROR;
2591         }
2592         options_->do_progress_updates = 1;
2593     }
2594 
2595     if (is_redirecting) {
2596         PrepareToWriteToFile();
2597 
2598         if (options_->do_progress_updates) {
2599             if (options_->do_broadcast) {
2600                 // clang-format off
2601                 std::vector<std::string> am_args = {
2602                      "--receiver-permission", "android.permission.DUMP",
2603                      "--es", "android.intent.extra.NAME", name_,
2604                      "--ei", "android.intent.extra.ID", std::to_string(id_),
2605                      "--ei", "android.intent.extra.PID", std::to_string(pid_),
2606                      "--ei", "android.intent.extra.MAX", std::to_string(progress_->GetMax()),
2607                 };
2608                 // clang-format on
2609                 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
2610             }
2611             if (options_->use_control_socket) {
2612                 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
2613             }
2614         }
2615     }
2616 
2617     /* read /proc/cmdline before dropping root */
2618     FILE *cmdline = fopen("/proc/cmdline", "re");
2619     if (cmdline) {
2620         fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2621         fclose(cmdline);
2622     }
2623 
2624     if (options_->do_vibrate) {
2625         Vibrate(150);
2626     }
2627 
2628     if (options_->do_fb && do_early_screenshot_) {
2629         if (screenshot_path_.empty()) {
2630             // should not have happened
2631             MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
2632         } else {
2633             MYLOGI("taking early screenshot\n");
2634             TakeScreenshot();
2635         }
2636     }
2637 
2638     if (options_->do_zip_file && zip_file != nullptr) {
2639         if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2640             MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
2641                    strerror(errno));
2642         }
2643     }
2644 
2645     int dup_stdout_fd;
2646     int dup_stderr_fd;
2647     if (is_redirecting) {
2648         // Redirect stderr to log_path_ for debugging.
2649         TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
2650         if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2651             return ERROR;
2652         }
2653         if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2654             MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2655                    strerror(errno));
2656         }
2657 
2658         // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2659         // moved into zip file later, if zipping.
2660         TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
2661         // TODO: why not write to a file instead of stdout to overcome this problem?
2662         /* TODO: rather than generating a text file now and zipping it later,
2663            it would be more efficient to redirect stdout to the zip entry
2664            directly, but the libziparchive doesn't support that option yet. */
2665         if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2666             return ERROR;
2667         }
2668         if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
2669             MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
2670                    tmp_path_.c_str(), strerror(errno));
2671         }
2672     }
2673 
2674     // Don't buffer stdout
2675     setvbuf(stdout, nullptr, _IONBF, 0);
2676 
2677     // NOTE: there should be no stdout output until now, otherwise it would break the header.
2678     // In particular, DurationReport objects should be created passing 'title, NULL', so their
2679     // duration is logged into MYLOG instead.
2680     PrintHeader();
2681 
2682     if (options_->telephony_only) {
2683         DumpstateTelephonyOnly();
2684         DumpstateBoard();
2685     } else if (options_->wifi_only) {
2686         DumpstateWifiOnly();
2687     } else {
2688         // Dump state for the default case. This also drops root.
2689         RunStatus s = DumpstateDefault();
2690         if (s != RunStatus::OK) {
2691             if (s == RunStatus::USER_CONSENT_TIMED_OUT) {
2692                 HandleUserConsentDenied();
2693             }
2694             return s;
2695         }
2696     }
2697 
2698     /* close output if needed */
2699     if (is_redirecting) {
2700         TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
2701     }
2702 
2703     // Rename, and/or zip the (now complete) .tmp file within the internal directory.
2704     if (options_->OutputToFile()) {
2705         FinalizeFile();
2706     }
2707 
2708     // Share the final file with the caller if the user has consented.
2709     Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
2710     if (options_->bugreport_fd.get() != -1) {
2711         status = CopyBugreportIfUserConsented();
2712         if (status != Dumpstate::RunStatus::OK &&
2713             status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2714             // Do an early return if there were errors. We make an exception for consent
2715             // timing out because it's possible the user got distracted. In this case the
2716             // bugreport is not shared but made available for manual retrieval.
2717             MYLOGI("User denied consent. Returning\n");
2718             return status;
2719         }
2720         if (options_->do_fb && options_->screenshot_fd.get() != -1) {
2721             bool copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
2722                                                             options_->screenshot_fd.get());
2723             if (copy_succeeded) {
2724                 android::os::UnlinkAndLogOnError(screenshot_path_);
2725             }
2726         }
2727         if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2728             MYLOGI(
2729                 "Did not receive user consent yet."
2730                 " Will not copy the bugreport artifacts to caller.\n");
2731             const String16 incidentcompanion("incidentcompanion");
2732             sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2733             if (ics != nullptr) {
2734                 MYLOGD("Canceling user consent request via incidentcompanion service\n");
2735                 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
2736                         consent_callback_.get());
2737             } else {
2738                 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
2739             }
2740         }
2741     }
2742 
2743     /* vibrate a few but shortly times to let user know it's finished */
2744     if (options_->do_vibrate) {
2745         for (int i = 0; i < 3; i++) {
2746             Vibrate(75);
2747             usleep((75 + 50) * 1000);
2748         }
2749     }
2750 
2751     /* tell activity manager we're done */
2752     if (options_->do_broadcast) {
2753         SendBugreportFinishedBroadcast();
2754         // Note that listener_ is notified in Run();
2755     }
2756 
2757     MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2758            progress_->GetInitialMax());
2759     progress_->Save();
2760     MYLOGI("done (id %d)\n", id_);
2761 
2762     if (is_redirecting) {
2763         TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
2764     }
2765 
2766     if (options_->use_control_socket && control_socket_fd_ != -1) {
2767         MYLOGD("Closing control socket\n");
2768         close(control_socket_fd_);
2769     }
2770 
2771     tombstone_data_.clear();
2772     anr_data_.clear();
2773 
2774     return (consent_callback_ != nullptr &&
2775             consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
2776                ? USER_CONSENT_TIMED_OUT
2777                : RunStatus::OK;
2778 }
2779 
CheckUserConsent(int32_t calling_uid,const android::String16 & calling_package)2780 void Dumpstate::CheckUserConsent(int32_t calling_uid, const android::String16& calling_package) {
2781     consent_callback_ = new ConsentCallback();
2782     const String16 incidentcompanion("incidentcompanion");
2783     sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2784     if (ics != nullptr) {
2785         MYLOGD("Checking user consent via incidentcompanion service\n");
2786         android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
2787             calling_uid, calling_package, String16(), String16(),
2788             0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
2789     } else {
2790         MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
2791     }
2792 }
2793 
IsUserConsentDenied() const2794 bool Dumpstate::IsUserConsentDenied() const {
2795     return ds.consent_callback_ != nullptr &&
2796            ds.consent_callback_->getResult() == UserConsentResult::DENIED;
2797 }
2798 
CleanupFiles()2799 void Dumpstate::CleanupFiles() {
2800     android::os::UnlinkAndLogOnError(tmp_path_);
2801     android::os::UnlinkAndLogOnError(screenshot_path_);
2802     android::os::UnlinkAndLogOnError(path_);
2803 }
2804 
HandleUserConsentDenied()2805 Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
2806     MYLOGD("User denied consent; deleting files and returning\n");
2807     CleanupFiles();
2808     return USER_CONSENT_DENIED;
2809 }
2810 
CopyBugreportIfUserConsented()2811 Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented() {
2812     // If the caller has asked to copy the bugreport over to their directory, we need explicit
2813     // user consent.
2814     UserConsentResult consent_result = consent_callback_->getResult();
2815     if (consent_result == UserConsentResult::UNAVAILABLE) {
2816         // User has not responded yet.
2817         uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
2818         if (elapsed_ms < USER_CONSENT_TIMEOUT_MS) {
2819             uint delay_seconds = (USER_CONSENT_TIMEOUT_MS - elapsed_ms) / 1000;
2820             MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
2821             sleep(delay_seconds);
2822         }
2823         consent_result = consent_callback_->getResult();
2824     }
2825     if (consent_result == UserConsentResult::DENIED) {
2826         // User has explicitly denied sharing with the app. To be safe delete the
2827         // internal bugreport & tmp files.
2828         return HandleUserConsentDenied();
2829     }
2830     if (consent_result == UserConsentResult::APPROVED) {
2831         bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
2832         if (copy_succeeded) {
2833             android::os::UnlinkAndLogOnError(path_);
2834         }
2835         return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
2836     } else if (consent_result == UserConsentResult::UNAVAILABLE) {
2837         // consent_result is still UNAVAILABLE. The user has likely not responded yet.
2838         // Since we do not have user consent to share the bugreport it does not get
2839         // copied over to the calling app but remains in the internal directory from
2840         // where the user can manually pull it.
2841         return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
2842     }
2843     // Unknown result; must be a programming error.
2844     MYLOGE("Unknown user consent result:%d\n", consent_result);
2845     return Dumpstate::RunStatus::ERROR;
2846 }
2847 
ParseCommandlineAndRun(int argc,char * argv[])2848 Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
2849     std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
2850     Dumpstate::RunStatus status = options->Initialize(argc, argv);
2851     if (status == Dumpstate::RunStatus::OK) {
2852         SetOptions(std::move(options));
2853         // When directly running dumpstate binary, the output is not expected to be written
2854         // to any external file descriptor.
2855         assert(options_->bugreport_fd.get() == -1);
2856 
2857         // calling_uid and calling_package are for user consent to share the bugreport with
2858         // an app; they are irrelvant here because bugreport is only written to a local
2859         // directory, and not shared.
2860         status = Run(-1 /* calling_uid */, "" /* calling_package */);
2861     }
2862     return status;
2863 }
2864 
2865 /* Main entry point for dumpstate binary. */
run_main(int argc,char * argv[])2866 int run_main(int argc, char* argv[]) {
2867     Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
2868 
2869     switch (status) {
2870         case Dumpstate::RunStatus::OK:
2871             exit(0);
2872         case Dumpstate::RunStatus::HELP:
2873             ShowUsage();
2874             exit(0);
2875         case Dumpstate::RunStatus::INVALID_INPUT:
2876             fprintf(stderr, "Invalid combination of args\n");
2877             ShowUsage();
2878             exit(1);
2879         case Dumpstate::RunStatus::ERROR:
2880             FALLTHROUGH_INTENDED;
2881         case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2882             FALLTHROUGH_INTENDED;
2883         case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2884             exit(2);
2885     }
2886 }
2887