• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <dirent.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <libgen.h>
21 #include <limits.h>
22 #include <memory>
23 #include <regex>
24 #include <set>
25 #include <stdbool.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string>
29 #include <string.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 <android-base/stringprintf.h>
38 #include <cutils/properties.h>
39 
40 #include "private/android_filesystem_config.h"
41 
42 #define LOG_TAG "dumpstate"
43 #include <cutils/log.h>
44 
45 #include "dumpstate.h"
46 #include "ScopedFd.h"
47 #include "ziparchive/zip_writer.h"
48 
49 #include "mincrypt/sha256.h"
50 
51 using android::base::StringPrintf;
52 
53 /* read before root is shed */
54 static char cmdline_buf[16384] = "(unknown)";
55 static const char *dump_traces_path = NULL;
56 
57 // TODO: variables below should be part of dumpstate object
58 static unsigned long id;
59 static char build_type[PROPERTY_VALUE_MAX];
60 static time_t now;
61 static std::unique_ptr<ZipWriter> zip_writer;
62 static std::set<std::string> mount_points;
63 void add_mountinfo();
64 int control_socket_fd = -1;
65 /* suffix of the bugreport files - it's typically the date (when invoked with -d),
66  * although it could be changed by the user using a system property */
67 static std::string suffix;
68 
69 #define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
70 #define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
71 
72 #define RAFT_DIR "/data/misc/raft"
73 #define RECOVERY_DIR "/cache/recovery"
74 #define RECOVERY_DATA_DIR "/data/misc/recovery"
75 #define LOGPERSIST_DATA_DIR "/data/misc/logd"
76 #define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
77 #define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
78 #define TOMBSTONE_DIR "/data/tombstones"
79 #define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
80 /* Can accomodate a tombstone number up to 9999. */
81 #define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
82 #define NUM_TOMBSTONES  10
83 #define WLUTIL "/vendor/xbin/wlutil"
84 
85 typedef struct {
86   char name[TOMBSTONE_MAX_LEN];
87   int fd;
88 } tombstone_data_t;
89 
90 static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
91 
92 const std::string ZIP_ROOT_DIR = "FS";
93 std::string bugreport_dir;
94 
95 /*
96  * List of supported zip format versions.
97  *
98  * See bugreport-format.txt for more info.
99  */
100 static std::string VERSION_DEFAULT = "1.0";
101 
is_user_build()102 bool is_user_build() {
103     return 0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1);
104 }
105 
106 /* gets the tombstone data, according to the bugreport type: if zipped gets all tombstones,
107  * otherwise gets just those modified in the last half an hour. */
get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES])108 static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
109     time_t thirty_minutes_ago = now - 60*30;
110     for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
111         snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
112         int fd = TEMP_FAILURE_RETRY(open(data[i].name,
113                                          O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
114         struct stat st;
115         if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) &&
116             (zip_writer || (time_t) st.st_mtime >= thirty_minutes_ago)) {
117         data[i].fd = fd;
118         } else {
119         close(fd);
120             data[i].fd = -1;
121         }
122     }
123 }
124 
125 // for_each_pid() callback to get mount info about a process.
do_mountinfo(int pid,const char * name)126 void do_mountinfo(int pid, const char *name) {
127     char path[PATH_MAX];
128 
129     // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
130     // are added.
131     snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
132     char linkname[PATH_MAX];
133     ssize_t r = readlink(path, linkname, PATH_MAX);
134     if (r == -1) {
135         MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
136         return;
137     }
138     linkname[r] = '\0';
139 
140     if (mount_points.find(linkname) == mount_points.end()) {
141         // First time this mount point was found: add it
142         snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
143         if (add_zip_entry(ZIP_ROOT_DIR + path, path)) {
144             mount_points.insert(linkname);
145         } else {
146             MYLOGE("Unable to add mountinfo %s to zip file\n", path);
147         }
148     }
149 }
150 
add_mountinfo()151 void add_mountinfo() {
152     if (!zip_writer) return;
153     const char *title = "MOUNT INFO";
154     mount_points.clear();
155     DurationReporter duration_reporter(title, NULL);
156     for_each_pid(do_mountinfo, NULL);
157     MYLOGD("%s: %d entries added to zip file\n", title, (int) mount_points.size());
158 }
159 
dump_dev_files(const char * title,const char * driverpath,const char * filename)160 static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
161 {
162     DIR *d;
163     struct dirent *de;
164     char path[PATH_MAX];
165 
166     d = opendir(driverpath);
167     if (d == NULL) {
168         return;
169     }
170 
171     while ((de = readdir(d))) {
172         if (de->d_type != DT_LNK) {
173             continue;
174         }
175         snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
176         dump_file(title, path);
177     }
178 
179     closedir(d);
180 }
181 
dump_systrace()182 static void dump_systrace() {
183     if (!zip_writer) {
184         MYLOGD("Not dumping systrace because zip_writer is not set\n");
185         return;
186     }
187     std::string systrace_path = bugreport_dir + "/systrace-" + suffix + ".txt";
188     if (systrace_path.empty()) {
189         MYLOGE("Not dumping systrace because path is empty\n");
190         return;
191     }
192     const char* path = "/sys/kernel/debug/tracing/tracing_on";
193     long int is_tracing;
194     if (read_file_as_long(path, &is_tracing)) {
195         return; // error already logged
196     }
197     if (is_tracing <= 0) {
198         MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
199         return;
200     }
201 
202     MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
203             systrace_path.c_str());
204     if (run_command("SYSTRACE", 120, "/system/bin/atrace", "--async_dump", "-o",
205             systrace_path.c_str(), NULL)) {
206         MYLOGE("systrace timed out, its zip entry will be incomplete\n");
207         // TODO: run_command tries to kill the process, but atrace doesn't die peacefully; ideally,
208         // we should call strace to stop itself, but there is no such option yet (just a
209         // --async_stop, which stops and dump
210         //        if (run_command("SYSTRACE", 10, "/system/bin/atrace", "--kill", NULL)) {
211         //            MYLOGE("could not stop systrace ");
212         //        }
213     }
214     if (!add_zip_entry("systrace.txt", systrace_path)) {
215         MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
216     } else {
217         if (remove(systrace_path.c_str())) {
218             MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
219         }
220     }
221 }
222 
dump_raft()223 static void dump_raft() {
224     if (is_user_build()) {
225         return;
226     }
227 
228     std::string raft_log_path = bugreport_dir + "/raft_log.txt";
229     if (raft_log_path.empty()) {
230         MYLOGD("raft_log_path is empty\n");
231         return;
232     }
233 
234     struct stat s;
235     if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
236         MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
237         return;
238     }
239 
240     if (!zip_writer) {
241         // Write compressed and encoded raft logs to stdout if not zip_writer.
242         run_command("RAFT LOGS", 600, "logcompressor", "-r", RAFT_DIR, NULL);
243         return;
244     }
245 
246     run_command("RAFT LOGS", 600, "logcompressor", "-n", "-r", RAFT_DIR,
247             "-o", raft_log_path.c_str(), NULL);
248     if (!add_zip_entry("raft_log.txt", raft_log_path)) {
249         MYLOGE("Unable to add raft log %s to zip file\n", raft_log_path.c_str());
250     } else {
251         if (remove(raft_log_path.c_str())) {
252             MYLOGE("Error removing raft file %s: %s\n", raft_log_path.c_str(), strerror(errno));
253         }
254     }
255 }
256 
skip_not_stat(const char * path)257 static bool skip_not_stat(const char *path) {
258     static const char stat[] = "/stat";
259     size_t len = strlen(path);
260     if (path[len - 1] == '/') { /* Directory? */
261         return false;
262     }
263     return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
264 }
265 
skip_none(const char * path)266 static bool skip_none(const char *path) {
267     return false;
268 }
269 
270 static const char mmcblk0[] = "/sys/block/mmcblk0/";
271 unsigned long worst_write_perf = 20000; /* in KB/s */
272 
273 //
274 //  stat offsets
275 // Name            units         description
276 // ----            -----         -----------
277 // read I/Os       requests      number of read I/Os processed
278 #define __STAT_READ_IOS      0
279 // read merges     requests      number of read I/Os merged with in-queue I/O
280 #define __STAT_READ_MERGES   1
281 // read sectors    sectors       number of sectors read
282 #define __STAT_READ_SECTORS  2
283 // read ticks      milliseconds  total wait time for read requests
284 #define __STAT_READ_TICKS    3
285 // write I/Os      requests      number of write I/Os processed
286 #define __STAT_WRITE_IOS     4
287 // write merges    requests      number of write I/Os merged with in-queue I/O
288 #define __STAT_WRITE_MERGES  5
289 // write sectors   sectors       number of sectors written
290 #define __STAT_WRITE_SECTORS 6
291 // write ticks     milliseconds  total wait time for write requests
292 #define __STAT_WRITE_TICKS   7
293 // in_flight       requests      number of I/Os currently in flight
294 #define __STAT_IN_FLIGHT     8
295 // io_ticks        milliseconds  total time this block device has been active
296 #define __STAT_IO_TICKS      9
297 // time_in_queue   milliseconds  total wait time for all requests
298 #define __STAT_IN_QUEUE     10
299 #define __STAT_NUMBER_FIELD 11
300 //
301 // read I/Os, write I/Os
302 // =====================
303 //
304 // These values increment when an I/O request completes.
305 //
306 // read merges, write merges
307 // =========================
308 //
309 // These values increment when an I/O request is merged with an
310 // already-queued I/O request.
311 //
312 // read sectors, write sectors
313 // ===========================
314 //
315 // These values count the number of sectors read from or written to this
316 // block device.  The "sectors" in question are the standard UNIX 512-byte
317 // sectors, not any device- or filesystem-specific block size.  The
318 // counters are incremented when the I/O completes.
319 #define SECTOR_SIZE 512
320 //
321 // read ticks, write ticks
322 // =======================
323 //
324 // These values count the number of milliseconds that I/O requests have
325 // waited on this block device.  If there are multiple I/O requests waiting,
326 // these values will increase at a rate greater than 1000/second; for
327 // example, if 60 read requests wait for an average of 30 ms, the read_ticks
328 // field will increase by 60*30 = 1800.
329 //
330 // in_flight
331 // =========
332 //
333 // This value counts the number of I/O requests that have been issued to
334 // the device driver but have not yet completed.  It does not include I/O
335 // requests that are in the queue but not yet issued to the device driver.
336 //
337 // io_ticks
338 // ========
339 //
340 // This value counts the number of milliseconds during which the device has
341 // had I/O requests queued.
342 //
343 // time_in_queue
344 // =============
345 //
346 // This value counts the number of milliseconds that I/O requests have waited
347 // on this block device.  If there are multiple I/O requests waiting, this
348 // value will increase as the product of the number of milliseconds times the
349 // number of requests waiting (see "read ticks" above for an example).
350 #define S_TO_MS 1000
351 //
352 
dump_stat_from_fd(const char * title __unused,const char * path,int fd)353 static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
354     unsigned long long fields[__STAT_NUMBER_FIELD];
355     bool z;
356     char *cp, *buffer = NULL;
357     size_t i = 0;
358     FILE *fp = fdopen(fd, "rb");
359     getline(&buffer, &i, fp);
360     fclose(fp);
361     if (!buffer) {
362         return -errno;
363     }
364     i = strlen(buffer);
365     while ((i > 0) && (buffer[i - 1] == '\n')) {
366         buffer[--i] = '\0';
367     }
368     if (!*buffer) {
369         free(buffer);
370         return 0;
371     }
372     z = true;
373     for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
374         fields[i] = strtoull(cp, &cp, 10);
375         if (fields[i] != 0) {
376             z = false;
377         }
378     }
379     if (z) { /* never accessed */
380         free(buffer);
381         return 0;
382     }
383 
384     if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
385         path += sizeof(mmcblk0) - 1;
386     }
387 
388     printf("%s: %s\n", path, buffer);
389     free(buffer);
390 
391     if (fields[__STAT_IO_TICKS]) {
392         unsigned long read_perf = 0;
393         unsigned long read_ios = 0;
394         if (fields[__STAT_READ_TICKS]) {
395             unsigned long long divisor = fields[__STAT_READ_TICKS]
396                                        * fields[__STAT_IO_TICKS];
397             read_perf = ((unsigned long long)SECTOR_SIZE
398                            * fields[__STAT_READ_SECTORS]
399                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
400                                         / divisor;
401             read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
402                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
403                                         / divisor;
404         }
405 
406         unsigned long write_perf = 0;
407         unsigned long write_ios = 0;
408         if (fields[__STAT_WRITE_TICKS]) {
409             unsigned long long divisor = fields[__STAT_WRITE_TICKS]
410                                        * fields[__STAT_IO_TICKS];
411             write_perf = ((unsigned long long)SECTOR_SIZE
412                            * fields[__STAT_WRITE_SECTORS]
413                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
414                                         / divisor;
415             write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
416                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
417                                         / divisor;
418         }
419 
420         unsigned queue = (fields[__STAT_IN_QUEUE]
421                              + (fields[__STAT_IO_TICKS] >> 1))
422                                  / fields[__STAT_IO_TICKS];
423 
424         if (!write_perf && !write_ios) {
425             printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n",
426                    path, read_perf, read_ios, queue);
427         } else {
428             printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n",
429                    path, read_perf, read_ios, write_perf, write_ios, queue);
430         }
431 
432         /* bugreport timeout factor adjustment */
433         if ((write_perf > 1) && (write_perf < worst_write_perf)) {
434             worst_write_perf = write_perf;
435         }
436     }
437     return 0;
438 }
439 
440 /* Copied policy from system/core/logd/LogBuffer.cpp */
441 
442 #define LOG_BUFFER_SIZE (256 * 1024)
443 #define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
444 #define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
445 
valid_size(unsigned long value)446 static bool valid_size(unsigned long value) {
447     if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
448         return false;
449     }
450 
451     long pages = sysconf(_SC_PHYS_PAGES);
452     if (pages < 1) {
453         return true;
454     }
455 
456     long pagesize = sysconf(_SC_PAGESIZE);
457     if (pagesize <= 1) {
458         pagesize = PAGE_SIZE;
459     }
460 
461     // maximum memory impact a somewhat arbitrary ~3%
462     pages = (pages + 31) / 32;
463     unsigned long maximum = pages * pagesize;
464 
465     if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
466         return true;
467     }
468 
469     return value <= maximum;
470 }
471 
property_get_size(const char * key)472 static unsigned long property_get_size(const char *key) {
473     unsigned long value;
474     char *cp, property[PROPERTY_VALUE_MAX];
475 
476     property_get(key, property, "");
477     value = strtoul(property, &cp, 10);
478 
479     switch(*cp) {
480     case 'm':
481     case 'M':
482         value *= 1024;
483     /* FALLTHRU */
484     case 'k':
485     case 'K':
486         value *= 1024;
487     /* FALLTHRU */
488     case '\0':
489         break;
490 
491     default:
492         value = 0;
493     }
494 
495     if (!valid_size(value)) {
496         value = 0;
497     }
498 
499     return value;
500 }
501 
502 /* timeout in ms */
logcat_timeout(const char * name)503 static unsigned long logcat_timeout(const char *name) {
504     static const char global_tuneable[] = "persist.logd.size"; // Settings App
505     static const char global_default[] = "ro.logd.size";       // BoardConfig.mk
506     char key[PROP_NAME_MAX];
507     unsigned long property_size, default_size;
508 
509     default_size = property_get_size(global_tuneable);
510     if (!default_size) {
511         default_size = property_get_size(global_default);
512     }
513 
514     snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
515     property_size = property_get_size(key);
516 
517     if (!property_size) {
518         snprintf(key, sizeof(key), "%s.%s", global_default, name);
519         property_size = property_get_size(key);
520     }
521 
522     if (!property_size) {
523         property_size = default_size;
524     }
525 
526     if (!property_size) {
527         property_size = LOG_BUFFER_SIZE;
528     }
529 
530     /* Engineering margin is ten-fold our guess */
531     return 10 * (property_size + worst_write_perf) / worst_write_perf;
532 }
533 
534 /* End copy from system/core/logd/LogBuffer.cpp */
535 
536 /* dumps the current system state to stdout */
print_header(std::string version)537 static void print_header(std::string version) {
538     char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
539     char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
540     char network[PROPERTY_VALUE_MAX], date[80];
541 
542     property_get("ro.build.display.id", build, "(unknown)");
543     property_get("ro.build.fingerprint", fingerprint, "(unknown)");
544     property_get("ro.build.type", build_type, "(unknown)");
545     property_get("gsm.version.baseband", radio, "(unknown)");
546     property_get("ro.bootloader", bootloader, "(unknown)");
547     property_get("gsm.operator.alpha", network, "(unknown)");
548     strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
549 
550     printf("========================================================\n");
551     printf("== dumpstate: %s\n", date);
552     printf("========================================================\n");
553 
554     printf("\n");
555     printf("Build: %s\n", build);
556     printf("Build fingerprint: '%s'\n", fingerprint); /* format is important for other tools */
557     printf("Bootloader: %s\n", bootloader);
558     printf("Radio: %s\n", radio);
559     printf("Network: %s\n", network);
560 
561     printf("Kernel: ");
562     dump_file(NULL, "/proc/version");
563     printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
564     printf("Bugreport format version: %s\n", version.c_str());
565     printf("Dumpstate info: id=%lu pid=%d\n", id, getpid());
566     printf("\n");
567 }
568 
569 // List of file extensions that can cause a zip file attachment to be rejected by some email
570 // service providers.
571 static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
572       ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
573       ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
574       ".shb", ".sys", ".vb",  ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
575 };
576 
add_zip_entry_from_fd(const std::string & entry_name,int fd)577 bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
578     if (!zip_writer) {
579         MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n",
580                 entry_name.c_str());
581         return false;
582     }
583     std::string valid_name = entry_name;
584 
585     // Rename extension if necessary.
586     size_t idx = entry_name.rfind(".");
587     if (idx != std::string::npos) {
588         std::string extension = entry_name.substr(idx);
589         std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
590         if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
591             valid_name = entry_name + ".renamed";
592             MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
593         }
594     }
595 
596     // Logging statement  below is useful to time how long each entry takes, but it's too verbose.
597     // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
598     int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(),
599             ZipWriter::kCompress, get_mtime(fd, now));
600     if (err) {
601         MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
602                 ZipWriter::ErrorCodeString(err));
603         return false;
604     }
605 
606     std::vector<uint8_t> buffer(65536);
607     while (1) {
608         ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), sizeof(buffer)));
609         if (bytes_read == 0) {
610             break;
611         } else if (bytes_read == -1) {
612             MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
613             return false;
614         }
615         err = zip_writer->WriteBytes(buffer.data(), bytes_read);
616         if (err) {
617             MYLOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
618             return false;
619         }
620     }
621 
622     err = zip_writer->FinishEntry();
623     if (err) {
624         MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
625         return false;
626     }
627 
628     return true;
629 }
630 
add_zip_entry(const std::string & entry_name,const std::string & entry_path)631 bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
632     ScopedFd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
633     if (fd.get() == -1) {
634         MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
635         return false;
636     }
637 
638     return add_zip_entry_from_fd(entry_name, fd.get());
639 }
640 
641 /* adds a file to the existing zipped bugreport */
_add_file_from_fd(const char * title,const char * path,int fd)642 static int _add_file_from_fd(const char *title, const char *path, int fd) {
643     return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
644 }
645 
646 // TODO: move to util.cpp
add_dir(const char * dir,bool recursive)647 void add_dir(const char *dir, bool recursive) {
648     if (!zip_writer) {
649         MYLOGD("Not adding dir %s because zip_writer is not set\n", dir);
650         return;
651     }
652     MYLOGD("Adding dir %s (recursive: %d)\n", dir, recursive);
653     DurationReporter duration_reporter(dir, NULL);
654     dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd);
655 }
656 
657 /* adds a text entry entry to the existing zip file. */
add_text_zip_entry(const std::string & entry_name,const std::string & content)658 static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) {
659     if (!zip_writer) {
660         MYLOGD("Not adding text zip entry %s because zip_writer is not set\n", entry_name.c_str());
661         return false;
662     }
663     MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
664     int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, now);
665     if (err) {
666         MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
667                 ZipWriter::ErrorCodeString(err));
668         return false;
669     }
670 
671     err = zip_writer->WriteBytes(content.c_str(), content.length());
672     if (err) {
673         MYLOGE("zip_writer->WriteBytes(%s): %s\n", entry_name.c_str(),
674                 ZipWriter::ErrorCodeString(err));
675         return false;
676     }
677 
678     err = zip_writer->FinishEntry();
679     if (err) {
680         MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
681         return false;
682     }
683 
684     return true;
685 }
686 
dump_iptables()687 static void dump_iptables() {
688     run_command("IPTABLES", 10, "iptables", "-L", "-nvx", NULL);
689     run_command("IP6TABLES", 10, "ip6tables", "-L", "-nvx", NULL);
690     run_command("IPTABLE NAT", 10, "iptables", "-t", "nat", "-L", "-nvx", NULL);
691     /* no ip6 nat */
692     run_command("IPTABLE RAW", 10, "iptables", "-t", "raw", "-L", "-nvx", NULL);
693     run_command("IP6TABLE RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
694 }
695 
dumpstate(const std::string & screenshot_path,const std::string & version)696 static void dumpstate(const std::string& screenshot_path, const std::string& version) {
697     DurationReporter duration_reporter("DUMPSTATE");
698     unsigned long timeout;
699 
700     dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
701     run_command("UPTIME", 10, "uptime", NULL);
702     dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
703     dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
704     dump_file("MEMORY INFO", "/proc/meminfo");
705     run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-H", NULL);
706     run_command("PROCRANK", 20, SU_PATH, "root", "procrank", NULL);
707     dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat");
708     dump_file("VMALLOC INFO", "/proc/vmallocinfo");
709     dump_file("SLAB INFO", "/proc/slabinfo");
710     dump_file("ZONEINFO", "/proc/zoneinfo");
711     dump_file("PAGETYPEINFO", "/proc/pagetypeinfo");
712     dump_file("BUDDYINFO", "/proc/buddyinfo");
713     dump_file("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
714 
715     dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources");
716     dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
717     dump_file("KERNEL SYNC", "/d/sync");
718 
719     run_command("PROCESSES AND THREADS", 10, "ps", "-Z", "-t", "-p", "-P", NULL);
720     run_command("LIBRANK", 10, SU_PATH, "root", "librank", NULL);
721 
722     run_command("PRINTENV", 10, "printenv", NULL);
723     run_command("NETSTAT", 10, "netstat", "-n", NULL);
724     run_command("LSMOD", 10, "lsmod", NULL);
725 
726     do_dmesg();
727 
728     run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
729     for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
730     for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
731     for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
732 
733     if (!screenshot_path.empty()) {
734         MYLOGI("taking late screenshot\n");
735         take_screenshot(screenshot_path);
736         MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
737     }
738 
739     // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
740     // calculate timeout
741     timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
742     if (timeout < 20000) {
743         timeout = 20000;
744     }
745     run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
746                                                         "-v", "printable",
747                                                         "-d",
748                                                         "*:v", NULL);
749     timeout = logcat_timeout("events");
750     if (timeout < 20000) {
751         timeout = 20000;
752     }
753     run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
754                                                        "-v", "threadtime",
755                                                        "-v", "printable",
756                                                        "-d",
757                                                        "*:v", NULL);
758     timeout = logcat_timeout("radio");
759     if (timeout < 20000) {
760         timeout = 20000;
761     }
762     run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
763                                                        "-v", "threadtime",
764                                                        "-v", "printable",
765                                                        "-d",
766                                                        "*:v", NULL);
767 
768     run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
769 
770     /* show the traces we collected in main(), if that was done */
771     if (dump_traces_path != NULL) {
772         dump_file("VM TRACES JUST NOW", dump_traces_path);
773     }
774 
775     /* only show ANR traces if they're less than 15 minutes old */
776     struct stat st;
777     char anr_traces_path[PATH_MAX];
778     property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
779     if (!anr_traces_path[0]) {
780         printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
781     } else {
782       int fd = TEMP_FAILURE_RETRY(open(anr_traces_path,
783                                        O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
784       if (fd < 0) {
785           printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
786       } else {
787           dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
788       }
789     }
790 
791     /* slow traces for slow operations */
792     if (anr_traces_path[0] != 0) {
793         int tail = strlen(anr_traces_path)-1;
794         while (tail > 0 && anr_traces_path[tail] != '/') {
795             tail--;
796         }
797         int i = 0;
798         while (1) {
799             sprintf(anr_traces_path+tail+1, "slow%02d.txt", i);
800             if (stat(anr_traces_path, &st)) {
801                 // No traces file at this index, done with the files.
802                 break;
803             }
804             dump_file("VM TRACES WHEN SLOW", anr_traces_path);
805             i++;
806         }
807     }
808 
809     int dumped = 0;
810     for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
811         if (tombstone_data[i].fd != -1) {
812             const char *name = tombstone_data[i].name;
813             int fd = tombstone_data[i].fd;
814             dumped = 1;
815             if (zip_writer) {
816                 if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) {
817                     MYLOGE("Unable to add tombstone %s to zip file\n", name);
818                 }
819             } else {
820                 dump_file_from_fd("TOMBSTONE", name, fd);
821             }
822             close(fd);
823             tombstone_data[i].fd = -1;
824         }
825     }
826     if (!dumped) {
827         printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
828     }
829 
830     dump_file("NETWORK DEV INFO", "/proc/net/dev");
831     dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
832     dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
833     dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
834     dump_file("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
835 
836     if (!stat(PSTORE_LAST_KMSG, &st)) {
837         /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
838         dump_file("LAST KMSG", PSTORE_LAST_KMSG);
839     } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
840         dump_file("LAST KMSG", ALT_PSTORE_LAST_KMSG);
841     } else {
842         /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
843         dump_file("LAST KMSG", "/proc/last_kmsg");
844     }
845 
846     /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
847     run_command("LAST LOGCAT", 10, "logcat", "-L",
848                                              "-b", "all",
849                                              "-v", "threadtime",
850                                              "-v", "printable",
851                                              "-d",
852                                              "*:v", NULL);
853 
854     /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
855 
856     run_command("NETWORK INTERFACES", 10, "ip", "link", NULL);
857 
858     run_command("IPv4 ADDRESSES", 10, "ip", "-4", "addr", "show", NULL);
859     run_command("IPv6 ADDRESSES", 10, "ip", "-6", "addr", "show", NULL);
860 
861     run_command("IP RULES", 10, "ip", "rule", "show", NULL);
862     run_command("IP RULES v6", 10, "ip", "-6", "rule", "show", NULL);
863 
864     dump_route_tables();
865 
866     run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
867     run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
868     run_command("MULTICAST ADDRESSES", 10, "ip", "maddr", NULL);
869     run_command("WIFI NETWORKS", 20, "wpa_cli", "IFNAME=wlan0", "list_networks", NULL);
870 
871 #ifdef FWDUMP_bcmdhd
872     run_command("ND OFFLOAD TABLE", 5,
873             SU_PATH, "root", WLUTIL, "nd_hostip", NULL);
874 
875     run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20,
876             SU_PATH, "root", WLUTIL, "counters", NULL);
877 
878     run_command("ND OFFLOAD STATUS (1)", 5,
879             SU_PATH, "root", WLUTIL, "nd_status", NULL);
880 
881 #endif
882     dump_file("INTERRUPTS (1)", "/proc/interrupts");
883 
884     run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "-t", "10", "connectivity", "--diag", NULL);
885 
886 #ifdef FWDUMP_bcmdhd
887     run_command("DUMP WIFI STATUS", 20,
888             SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL);
889 
890     run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20,
891             SU_PATH, "root", WLUTIL, "counters", NULL);
892 
893     run_command("ND OFFLOAD STATUS (2)", 5,
894             SU_PATH, "root", WLUTIL, "nd_status", NULL);
895 #endif
896     dump_file("INTERRUPTS (2)", "/proc/interrupts");
897 
898     print_properties();
899 
900     run_command("VOLD DUMP", 10, "vdc", "dump", NULL);
901     run_command("SECURE CONTAINERS", 10, "vdc", "asec", "list", NULL);
902 
903     run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL);
904 
905     run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL);
906 
907     printf("------ BACKLIGHTS ------\n");
908     printf("LCD brightness=");
909     dump_file(NULL, "/sys/class/leds/lcd-backlight/brightness");
910     printf("Button brightness=");
911     dump_file(NULL, "/sys/class/leds/button-backlight/brightness");
912     printf("Keyboard brightness=");
913     dump_file(NULL, "/sys/class/leds/keyboard-backlight/brightness");
914     printf("ALS mode=");
915     dump_file(NULL, "/sys/class/leds/lcd-backlight/als");
916     printf("LCD driver registers:\n");
917     dump_file(NULL, "/sys/class/leds/lcd-backlight/registers");
918     printf("\n");
919 
920     /* Binder state is expensive to look at as it uses a lot of memory. */
921     dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
922     dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
923     dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
924     dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats");
925     dump_file("BINDER STATE", "/sys/kernel/debug/binder/state");
926 
927     printf("========================================================\n");
928     printf("== Board\n");
929     printf("========================================================\n");
930 
931     dumpstate_board();
932     printf("\n");
933 
934     /* Migrate the ril_dumpstate to a dumpstate_board()? */
935     char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
936     property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
937     if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
938         if (is_user_build()) {
939             // su does not exist on user builds, so try running without it.
940             // This way any implementations of vril-dump that do not require
941             // root can run on user builds.
942             run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
943                     "vril-dump", NULL);
944         } else {
945             run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
946                     SU_PATH, "root", "vril-dump", NULL);
947         }
948     }
949 
950     printf("========================================================\n");
951     printf("== Android Framework Services\n");
952     printf("========================================================\n");
953 
954     run_command("DUMPSYS", 60, "dumpsys", "-t", "60", "--skip", "meminfo", "cpuinfo", NULL);
955 
956     printf("========================================================\n");
957     printf("== Checkins\n");
958     printf("========================================================\n");
959 
960     run_command("CHECKIN BATTERYSTATS", 30, "dumpsys", "-t", "30", "batterystats", "-c", NULL);
961     run_command("CHECKIN MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "--checkin", NULL);
962     run_command("CHECKIN NETSTATS", 30, "dumpsys", "-t", "30", "netstats", "--checkin", NULL);
963     run_command("CHECKIN PROCSTATS", 30, "dumpsys", "-t", "30", "procstats", "-c", NULL);
964     run_command("CHECKIN USAGESTATS", 30, "dumpsys", "-t", "30", "usagestats", "-c", NULL);
965     run_command("CHECKIN PACKAGE", 30, "dumpsys", "-t", "30", "package", "--checkin", NULL);
966 
967     printf("========================================================\n");
968     printf("== Running Application Activities\n");
969     printf("========================================================\n");
970 
971     run_command("APP ACTIVITIES", 30, "dumpsys", "-t", "30", "activity", "all", NULL);
972 
973     printf("========================================================\n");
974     printf("== Running Application Services\n");
975     printf("========================================================\n");
976 
977     run_command("APP SERVICES", 30, "dumpsys", "-t", "30", "activity", "service", "all", NULL);
978 
979     printf("========================================================\n");
980     printf("== Running Application Providers\n");
981     printf("========================================================\n");
982 
983     run_command("APP PROVIDERS", 30, "dumpsys", "-t", "30", "activity", "provider", "all", NULL);
984 
985 
986     printf("========================================================\n");
987     printf("== Final progress (pid %d): %d/%d (originally %d)\n",
988             getpid(), progress, weight_total, WEIGHT_TOTAL);
989     printf("========================================================\n");
990     printf("== dumpstate: done\n");
991     printf("========================================================\n");
992 }
993 
usage()994 static void usage() {
995   fprintf(stderr,
996           "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
997           "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
998           "  -h: display this help message\n"
999           "  -b: play sound file instead of vibrate, at beginning of job\n"
1000           "  -e: play sound file instead of vibrate, at end of job\n"
1001           "  -o: write to file (instead of stdout)\n"
1002           "  -d: append date to filename (requires -o)\n"
1003           "  -p: capture screenshot to filename.png (requires -o)\n"
1004           "  -z: generate zipped file (requires -o)\n"
1005           "  -s: write output to control socket (for init)\n"
1006           "  -S: write file location to control socket (for init; requires -o and -z)"
1007           "  -q: disable vibrate\n"
1008           "  -B: send broadcast when finished (requires -o)\n"
1009           "  -P: send broadcast when started and update system properties on "
1010           "progress (requires -o and -B)\n"
1011           "  -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1012           "shouldn't be used with -P)\n"
1013           "  -V: sets the bugreport format version (valid values: %s)\n",
1014           VERSION_DEFAULT.c_str());
1015 }
1016 
sigpipe_handler(int n)1017 static void sigpipe_handler(int n) {
1018     // don't complain to stderr or stdout
1019     _exit(EXIT_FAILURE);
1020 }
1021 
1022 /* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
1023    temporary file.
1024  */
finish_zip_file(const std::string & bugreport_name,const std::string & bugreport_path,time_t now)1025 static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
1026         time_t now) {
1027     if (!add_zip_entry(bugreport_name, bugreport_path)) {
1028         MYLOGE("Failed to add text entry to .zip file\n");
1029         return false;
1030     }
1031     if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
1032         MYLOGE("Failed to add main_entry.txt to .zip file\n");
1033         return false;
1034     }
1035 
1036     int32_t err = zip_writer->Finish();
1037     if (err) {
1038         MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
1039         return false;
1040     }
1041 
1042     if (is_user_build()) {
1043         MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
1044         if (remove(bugreport_path.c_str())) {
1045             ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
1046         }
1047     } else {
1048         MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
1049     }
1050 
1051     return true;
1052 }
1053 
SHA256_file_hash(std::string filepath)1054 static std::string SHA256_file_hash(std::string filepath) {
1055     ScopedFd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC
1056             | O_NOFOLLOW)));
1057     if (fd.get() == -1) {
1058         MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
1059         return NULL;
1060     }
1061 
1062     SHA256_CTX ctx;
1063     SHA256_init(&ctx);
1064 
1065     std::vector<uint8_t> buffer(65536);
1066     while (1) {
1067         ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1068         if (bytes_read == 0) {
1069             break;
1070         } else if (bytes_read == -1) {
1071             MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
1072             return NULL;
1073         }
1074 
1075         SHA256_update(&ctx, buffer.data(), bytes_read);
1076     }
1077 
1078     uint8_t hash[SHA256_DIGEST_SIZE];
1079     memcpy(hash, SHA256_final(&ctx), SHA256_DIGEST_SIZE);
1080     char hash_buffer[SHA256_DIGEST_SIZE * 2 + 1];
1081     for(size_t i = 0; i < SHA256_DIGEST_SIZE; i++) {
1082         sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
1083     }
1084     hash_buffer[sizeof(hash_buffer) - 1] = 0;
1085     return std::string(hash_buffer);
1086 }
1087 
main(int argc,char * argv[])1088 int main(int argc, char *argv[]) {
1089     struct sigaction sigact;
1090     int do_add_date = 0;
1091     int do_zip_file = 0;
1092     int do_vibrate = 1;
1093     char* use_outfile = 0;
1094     int use_socket = 0;
1095     int use_control_socket = 0;
1096     int do_fb = 0;
1097     int do_broadcast = 0;
1098     int do_early_screenshot = 0;
1099     int is_remote_mode = 0;
1100     std::string version = VERSION_DEFAULT;
1101 
1102     now = time(NULL);
1103 
1104     MYLOGI("begin\n");
1105 
1106     /* gets the sequential id */
1107     char last_id[PROPERTY_VALUE_MAX];
1108     property_get("dumpstate.last_id", last_id, "0");
1109     id = strtoul(last_id, NULL, 10) + 1;
1110     snprintf(last_id, sizeof(last_id), "%lu", id);
1111     property_set("dumpstate.last_id", last_id);
1112     MYLOGI("dumpstate id: %lu\n", id);
1113 
1114     /* clear SIGPIPE handler */
1115     memset(&sigact, 0, sizeof(sigact));
1116     sigact.sa_handler = sigpipe_handler;
1117     sigaction(SIGPIPE, &sigact, NULL);
1118 
1119     /* set as high priority, and protect from OOM killer */
1120     setpriority(PRIO_PROCESS, 0, -20);
1121 
1122     FILE *oom_adj = fopen("/proc/self/oom_score_adj", "we");
1123     if (oom_adj) {
1124         fputs("-1000", oom_adj);
1125         fclose(oom_adj);
1126     } else {
1127         /* fallback to kernels <= 2.6.35 */
1128         oom_adj = fopen("/proc/self/oom_adj", "we");
1129         if (oom_adj) {
1130             fputs("-17", oom_adj);
1131             fclose(oom_adj);
1132         }
1133     }
1134 
1135     /* parse arguments */
1136     std::string args;
1137     format_args(argc, const_cast<const char **>(argv), &args);
1138     MYLOGD("Dumpstate command line: %s\n", args.c_str());
1139     int c;
1140     while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
1141         switch (c) {
1142             case 'd': do_add_date = 1;          break;
1143             case 'z': do_zip_file = 1;          break;
1144             case 'o': use_outfile = optarg;     break;
1145             case 's': use_socket = 1;           break;
1146             case 'S': use_control_socket = 1;   break;
1147             case 'v': break;  // compatibility no-op
1148             case 'q': do_vibrate = 0;           break;
1149             case 'p': do_fb = 1;                break;
1150             case 'P': do_update_progress = 1;   break;
1151             case 'R': is_remote_mode = 1;       break;
1152             case 'B': do_broadcast = 1;         break;
1153             case 'V': version = optarg;         break;
1154             case '?': printf("\n");
1155             case 'h':
1156                 usage();
1157                 exit(1);
1158         }
1159     }
1160 
1161     if ((do_zip_file || do_add_date || do_update_progress || do_broadcast) && !use_outfile) {
1162         usage();
1163         exit(1);
1164     }
1165 
1166     if (use_control_socket && !do_zip_file) {
1167         usage();
1168         exit(1);
1169     }
1170 
1171     if (do_update_progress && !do_broadcast) {
1172         usage();
1173         exit(1);
1174     }
1175 
1176     if (is_remote_mode && (do_update_progress || !do_broadcast || !do_zip_file || !do_add_date)) {
1177         usage();
1178         exit(1);
1179     }
1180 
1181     if (version != VERSION_DEFAULT) {
1182       usage();
1183       exit(1);
1184     }
1185 
1186     MYLOGI("bugreport format version: %s\n", version.c_str());
1187 
1188     do_early_screenshot = do_update_progress;
1189 
1190     // If we are going to use a socket, do it as early as possible
1191     // to avoid timeouts from bugreport.
1192     if (use_socket) {
1193         redirect_to_socket(stdout, "dumpstate");
1194     }
1195 
1196     if (use_control_socket) {
1197         MYLOGD("Opening control socket\n");
1198         control_socket_fd = open_socket("dumpstate");
1199         do_update_progress = 1;
1200     }
1201 
1202     /* full path of the temporary file containing the bugreport */
1203     std::string tmp_path;
1204 
1205     /* full path of the file containing the dumpstate logs*/
1206     std::string log_path;
1207 
1208     /* full path of the systrace file, when enabled */
1209     std::string systrace_path;
1210 
1211     /* full path of the temporary file containing the screenshot (when requested) */
1212     std::string screenshot_path;
1213 
1214     /* base name (without suffix or extensions) of the bugreport files */
1215     std::string base_name;
1216 
1217     /* pointer to the actual path, be it zip or text */
1218     std::string path;
1219 
1220     /* pointer to the zipped file */
1221     std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
1222 
1223     /* redirect output if needed */
1224     bool is_redirecting = !use_socket && use_outfile;
1225 
1226     if (is_redirecting) {
1227         bugreport_dir = dirname(use_outfile);
1228         base_name = basename(use_outfile);
1229         if (do_add_date) {
1230             char date[80];
1231             strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
1232             suffix = date;
1233         } else {
1234             suffix = "undated";
1235         }
1236         char build_id[PROPERTY_VALUE_MAX];
1237         property_get("ro.build.id", build_id, "UNKNOWN_BUILD");
1238         base_name = base_name + "-" + build_id;
1239         if (do_fb) {
1240             // TODO: if dumpstate was an object, the paths could be internal variables and then
1241             // we could have a function to calculate the derived values, such as:
1242             //     screenshot_path = GetPath(".png");
1243             screenshot_path = bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1244         }
1245         tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp";
1246         log_path = bugreport_dir + "/dumpstate_log-" + suffix + "-"
1247                 + std::to_string(getpid()) + ".txt";
1248 
1249         MYLOGD("Bugreport dir: %s\n"
1250                 "Base name: %s\n"
1251                 "Suffix: %s\n"
1252                 "Log path: %s\n"
1253                 "Temporary path: %s\n"
1254                 "Screenshot path: %s\n",
1255                 bugreport_dir.c_str(), base_name.c_str(), suffix.c_str(),
1256                 log_path.c_str(), tmp_path.c_str(), screenshot_path.c_str());
1257 
1258         if (do_zip_file) {
1259             path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
1260             MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
1261             create_parent_dirs(path.c_str());
1262             zip_file.reset(fopen(path.c_str(), "wb"));
1263             if (!zip_file) {
1264                 MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
1265                 do_zip_file = 0;
1266             } else {
1267                 zip_writer.reset(new ZipWriter(zip_file.get()));
1268             }
1269             add_text_zip_entry("version.txt", version);
1270         }
1271 
1272         if (do_update_progress) {
1273             if (do_broadcast) {
1274                 // clang-format off
1275                 std::vector<std::string> am_args = {
1276                      "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1277                      "--es", "android.intent.extra.NAME", suffix,
1278                      "--ei", "android.intent.extra.ID", std::to_string(id),
1279                      "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1280                      "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
1281                 };
1282                 // clang-format on
1283                 send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
1284             }
1285             if (use_control_socket) {
1286                 dprintf(control_socket_fd, "BEGIN:%s\n", path.c_str());
1287             }
1288         }
1289     }
1290 
1291     /* read /proc/cmdline before dropping root */
1292     FILE *cmdline = fopen("/proc/cmdline", "re");
1293     if (cmdline) {
1294         fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1295         fclose(cmdline);
1296     }
1297 
1298     /* open the vibrator before dropping root */
1299     std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
1300     if (do_vibrate) {
1301         vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
1302         if (vibrator) {
1303             vibrate(vibrator.get(), 150);
1304         }
1305     }
1306 
1307     if (do_fb && do_early_screenshot) {
1308         if (screenshot_path.empty()) {
1309             // should not have happened
1310             MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
1311         } else {
1312             MYLOGI("taking early screenshot\n");
1313             take_screenshot(screenshot_path);
1314             MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
1315             if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
1316                 MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
1317                         screenshot_path.c_str(), strerror(errno));
1318             }
1319         }
1320     }
1321 
1322     if (do_zip_file) {
1323         if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
1324             MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
1325         }
1326     }
1327 
1328     if (is_redirecting) {
1329         redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
1330         if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
1331             MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1332                     log_path.c_str(), strerror(errno));
1333         }
1334         /* TODO: rather than generating a text file now and zipping it later,
1335            it would be more efficient to redirect stdout to the zip entry
1336            directly, but the libziparchive doesn't support that option yet. */
1337         redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
1338         if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
1339             MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
1340                     tmp_path.c_str(), strerror(errno));
1341         }
1342     }
1343     // NOTE: there should be no stdout output until now, otherwise it would break the header.
1344     // In particular, DurationReport objects should be created passing 'title, NULL', so their
1345     // duration is logged into MYLOG instead.
1346     print_header(version);
1347 
1348     // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1349     dump_systrace();
1350 
1351     // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1352     dump_raft();
1353 
1354     // Invoking the following dumpsys calls before dump_traces() to try and
1355     // keep the system stats as close to its initial state as possible.
1356     run_command_as_shell("DUMPSYS MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "-a", NULL);
1357     run_command_as_shell("DUMPSYS CPUINFO", 10, "dumpsys", "-t", "10", "cpuinfo", "-a", NULL);
1358 
1359     /* collect stack traces from Dalvik and native processes (needs root) */
1360     dump_traces_path = dump_traces();
1361 
1362     /* Run some operations that require root. */
1363     get_tombstone_fds(tombstone_data);
1364     add_dir(RECOVERY_DIR, true);
1365     add_dir(RECOVERY_DATA_DIR, true);
1366     add_dir(LOGPERSIST_DATA_DIR, false);
1367     if (!is_user_build()) {
1368         add_dir(PROFILE_DATA_DIR_CUR, true);
1369         add_dir(PROFILE_DATA_DIR_REF, true);
1370     }
1371     add_mountinfo();
1372     dump_iptables();
1373 
1374     if (!drop_root_user()) {
1375         return -1;
1376     }
1377 
1378     dumpstate(do_early_screenshot ? "": screenshot_path, version);
1379 
1380     /* close output if needed */
1381     if (is_redirecting) {
1382         fclose(stdout);
1383     }
1384 
1385     /* rename or zip the (now complete) .tmp file to its final location */
1386     if (use_outfile) {
1387 
1388         /* check if user changed the suffix using system properties */
1389         char key[PROPERTY_KEY_MAX];
1390         char value[PROPERTY_VALUE_MAX];
1391         snprintf(key, sizeof(key), "dumpstate.%d.name", getpid());
1392         property_get(key, value, "");
1393         bool change_suffix= false;
1394         if (value[0]) {
1395             /* must whitelist which characters are allowed, otherwise it could cross directories */
1396             std::regex valid_regex("^[-_a-zA-Z0-9]+$");
1397             if (std::regex_match(value, valid_regex)) {
1398                 change_suffix = true;
1399             } else {
1400                 MYLOGE("invalid suffix provided by user: %s\n", value);
1401             }
1402         }
1403         if (change_suffix) {
1404             MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), value);
1405             suffix = value;
1406             if (!screenshot_path.empty()) {
1407                 std::string new_screenshot_path =
1408                         bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1409                 if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
1410                     MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
1411                             new_screenshot_path.c_str(), strerror(errno));
1412                 } else {
1413                     screenshot_path = new_screenshot_path;
1414                 }
1415             }
1416         }
1417 
1418         bool do_text_file = true;
1419         if (do_zip_file) {
1420             std::string entry_name = base_name + "-" + suffix + ".txt";
1421             MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
1422             if (!finish_zip_file(entry_name, tmp_path, now)) {
1423                 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
1424                 do_text_file = true;
1425             } else {
1426                 do_text_file = false;
1427                 // Since zip file is already created, it needs to be renamed.
1428                 std::string new_path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
1429                 if (path != new_path) {
1430                     MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
1431                     if (rename(path.c_str(), new_path.c_str())) {
1432                         MYLOGE("rename(%s, %s): %s\n", path.c_str(),
1433                                 new_path.c_str(), strerror(errno));
1434                     } else {
1435                         path = new_path;
1436                     }
1437                 }
1438             }
1439         }
1440         if (do_text_file) {
1441             path = bugreport_dir + "/" + base_name + "-" + suffix + ".txt";
1442             MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
1443             if (rename(tmp_path.c_str(), path.c_str())) {
1444                 MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
1445                 path.clear();
1446             }
1447         }
1448         if (use_control_socket) {
1449             if (do_text_file) {
1450                 dprintf(control_socket_fd, "FAIL:could not create zip file, check %s "
1451                         "for more details\n", log_path.c_str());
1452             } else {
1453                 dprintf(control_socket_fd, "OK:%s\n", path.c_str());
1454             }
1455         }
1456     }
1457 
1458     /* vibrate a few but shortly times to let user know it's finished */
1459     if (vibrator) {
1460         for (int i = 0; i < 3; i++) {
1461             vibrate(vibrator.get(), 75);
1462             usleep((75 + 50) * 1000);
1463         }
1464     }
1465 
1466     /* tell activity manager we're done */
1467     if (do_broadcast) {
1468         if (!path.empty()) {
1469             MYLOGI("Final bugreport path: %s\n", path.c_str());
1470             // clang-format off
1471             std::vector<std::string> am_args = {
1472                  "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1473                  "--ei", "android.intent.extra.ID", std::to_string(id),
1474                  "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1475                  "--ei", "android.intent.extra.MAX", std::to_string(weight_total),
1476                  "--es", "android.intent.extra.BUGREPORT", path,
1477                  "--es", "android.intent.extra.DUMPSTATE_LOG", log_path
1478             };
1479             // clang-format on
1480             if (do_fb) {
1481                 am_args.push_back("--es");
1482                 am_args.push_back("android.intent.extra.SCREENSHOT");
1483                 am_args.push_back(screenshot_path);
1484             }
1485             if (is_remote_mode) {
1486                 am_args.push_back("--es");
1487                 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
1488                 am_args.push_back(SHA256_file_hash(path));
1489                 send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
1490             } else {
1491                 send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
1492             }
1493         } else {
1494             MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
1495         }
1496     }
1497 
1498     MYLOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
1499     MYLOGI("done\n");
1500 
1501     if (is_redirecting) {
1502         fclose(stderr);
1503     }
1504 
1505     if (use_control_socket && control_socket_fd != -1) {
1506       MYLOGD("Closing control socket\n");
1507       close(control_socket_fd);
1508     }
1509 
1510     return 0;
1511 }
1512