blob: d0f85a7b12c7ee64f1eac754137ccde121564ab2 [file] [log] [blame]
Elly Jones03cd6d72012-06-11 13:04:28 -04001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Alex Vakulenko262be3f2014-07-30 15:25:50 -07005#include "debugd/src/log_tool.h"
Elly Jones03cd6d72012-06-11 13:04:28 -04006
Chinglin Yuaeb4ec72018-12-10 18:53:30 +08007#include <lzma.h>
Ben Chan8e9f6d02017-09-26 23:04:21 -07008#include <memory>
Luis Hector Chavezfc2566f2018-09-13 15:00:36 -07009#include <string>
Ben Chana0011d82014-05-13 00:19:29 -070010#include <vector>
11
Ben Chanab93abf2017-01-24 13:32:51 -080012#include <base/base64.h>
Ben Chancd8fda42014-09-05 08:21:06 -070013#include <base/files/file_util.h>
Ahmed Fakhry21140cf2016-03-04 17:15:19 -080014#include <base/json/json_writer.h>
Elly Jones03cd6d72012-06-11 13:04:28 -040015#include <base/logging.h>
Ben Chan9953a592014-02-05 23:32:00 -080016#include <base/strings/string_split.h>
17#include <base/strings/string_util.h>
Luis Hector Chavezfc2566f2018-09-13 15:00:36 -070018#include <base/strings/stringprintf.h>
19#include <base/strings/utf_string_conversion_utils.h>
Ahmed Fakhry21140cf2016-03-04 17:15:19 -080020#include <base/values.h>
Elly Jones03cd6d72012-06-11 13:04:28 -040021
Rebecca Silbersteine78af402014-10-02 10:55:04 -070022#include <chromeos/dbus/service_constants.h>
Eric Carusocc7106c2017-04-27 14:22:42 -070023#include <shill/dbus-proxies.h>
Rebecca Silbersteine78af402014-10-02 10:55:04 -070024
Ben Chanaf125862017-02-08 23:11:18 -080025#include "debugd/src/constants.h"
Chinglin Yuaeb4ec72018-12-10 18:53:30 +080026#include "debugd/src/perf_tool.h"
Alex Vakulenko262be3f2014-07-30 15:25:50 -070027#include "debugd/src/process_with_output.h"
Elly Jones03cd6d72012-06-11 13:04:28 -040028
Kartik Hegde1c4b97b2018-09-09 19:09:34 -060029#include "brillo/key_value_store.h"
30#include <brillo/osrelease_reader.h>
31
Elly Jones03cd6d72012-06-11 13:04:28 -040032namespace debugd {
33
Elly Jones03cd6d72012-06-11 13:04:28 -040034using std::string;
Elly Jones03cd6d72012-06-11 13:04:28 -040035
Eric Caruso96d03d32017-04-25 18:01:17 -070036using Strings = std::vector<string>;
Elly Jones03cd6d72012-06-11 13:04:28 -040037
Ahmed Fakhry21140cf2016-03-04 17:15:19 -080038namespace {
39
Ben Chanaf125862017-02-08 23:11:18 -080040const char kRoot[] = "root";
41const char kShell[] = "/bin/sh";
Kartik Hegde1c4b97b2018-09-09 19:09:34 -060042constexpr char kLsbReleasePath[] = "/etc/lsb-release";
Ahmed Fakhry21140cf2016-03-04 17:15:19 -080043
44// Minimum time in seconds needed to allow shill to test active connections.
45const int kConnectionTesterTimeoutSeconds = 5;
Ben Chanf6cd93a2012-10-14 19:37:00 -070046
Luis Hector Chavezfc2566f2018-09-13 15:00:36 -070047// Default maximum size of a log entry.
48constexpr const char kDefaultSizeCap[] = "512K";
49
Chinglin Yuaeb4ec72018-12-10 18:53:30 +080050// Default running perf for 2 seconds.
51constexpr const int kPerfDurationSecs = 2;
52
Elly Fong-Jonesd9a16cd2012-11-12 16:09:49 -050053struct Log {
Luis Hector Chavezfc2566f2018-09-13 15:00:36 -070054 const char* name;
55 const char* command;
56 const char* user = nullptr;
57 const char* group = nullptr;
58 const char* size_cap = kDefaultSizeCap; // passed as arg to 'tail -c'
59 LogTool::Encoding encoding = LogTool::Encoding::kAutodetect;
Elly Fong-Jonesd9a16cd2012-11-12 16:09:49 -050060};
61
Eric Carusoa879fd92017-10-11 12:57:10 -070062#define CMD_KERNEL_MODULE_PARAMS(module_name) \
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -070063 "cd /sys/module/" #module_name "/parameters 2>/dev/null && grep -sH ^ *"
Eric Carusoa879fd92017-10-11 12:57:10 -070064
Ben Chancf7d6412017-08-10 22:30:09 -070065const Log kCommandLogs[] = {
Mike Frysingerb0350992018-09-14 13:45:35 -040066 // We need to enter init's mount namespace because it has /home/chronos
67 // mounted which is where the consent knob lives. We don't have that mount
68 // in our own mount namespace (by design). https://crbug.com/884249
69 { "CLIENT_ID", "/usr/bin/nsenter -t1 -m /usr/bin/metrics_client -i",
70 kRoot,
71 kDebugfsGroup,
72 },
Elly Jones03cd6d72012-06-11 13:04:28 -040073 { "LOGDATE", "/bin/date" },
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -070074 { "atrus_logs", "cat /var/log/atrus.log 2>/dev/null" },
75 { "authpolicy", "cat /var/log/authpolicy.log" },
Kartik Hegdec0cd6f72018-09-25 16:20:18 -060076 { "bootstat_summary", "/usr/bin/bootstat_summary"},
Nicolas Norvez7c553bc2018-11-06 15:20:16 -080077 { "bio_crypto_init.log", "cat /var/log/bio_crypto_init/bio_crypto_init.log" },
Nicolas Norvezd573ff62018-08-08 18:30:13 -070078 { "biod.LATEST", "cat /var/log/biod/biod.LATEST" },
79 { "biod.PREVIOUS", "cat /var/log/biod/biod.PREVIOUS" },
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -070080 { "bios_info", "cat /var/log/bios_info.txt" },
Vadim Bendebury64aeeed2013-09-16 13:16:49 -070081 { "bios_log",
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -070082 "cat /sys/firmware/log "
83 "/proc/device-tree/chosen/ap-console-buffer 2>/dev/null" },
84 { "bios_times", "cat /var/log/bios_times.txt" },
Elly Jones03cd6d72012-06-11 13:04:28 -040085 { "board-specific",
Thiemo Nagela269ad22014-11-27 17:13:01 +010086 "/usr/share/userfeedback/scripts/get_board_specific_info" },
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -070087 { "buddyinfo", "cat /proc/buddyinfo" },
Daisuke Nojiri43c25332019-01-02 17:20:17 -080088 { "cbi_info", "/usr/share/userfeedback/scripts/cbi_info", kRoot, kRoot},
Luis Hector Chavez3d211102018-09-18 15:08:22 -070089 { "cheets_log", "cat /var/log/arc.log 2>/dev/null" },
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -070090 { "clobber.log", "cat /var/log/clobber.log 2>/dev/null" },
91 { "clobber-state.log", "cat /var/log/clobber-state.log 2>/dev/null" },
92 { "chrome_system_log", "cat /var/log/chrome/chrome" },
Dariusz Marcinkiewicza0597062018-09-11 10:53:53 +020093 { "chrome_system_log.PREVIOUS", "cat /var/log/chrome/chrome.PREVIOUS" },
Mike Frysinger32cdf3e2017-08-14 18:17:06 -040094 // There might be more than one record, so grab them all.
95 // Plus, for <linux-3.19, it's named "console-ramoops", but for newer
96 // versions, it's named "console-ramoops-#".
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -070097 { "console-ramoops", "cat /sys/fs/pstore/console-ramoops* 2>/dev/null" },
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -070098 { "cpuinfo", "cat /proc/cpuinfo" },
99 { "cr50_version", "cat /var/cache/cr50-version" },
Eric Caruso57333f12015-09-08 12:50:32 -0700100 { "cros_ec",
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700101 "cat /var/log/cros_ec.previous /var/log/cros_ec.log 2>/dev/null" },
Nicolas Boichat083795f2016-08-16 11:16:49 +0200102 { "cros_ec_panicinfo",
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700103 "cat /sys/kernel/debug/cros_ec/panicinfo 2>/dev/null",
Nicolas Boichatd51092b2016-09-01 10:36:46 +0800104 SandboxedProcess::kDefaultUser,
105 kDebugfsGroup
106 },
Shawn Nematbakhsh60813732017-07-13 10:46:23 -0700107 { "cros_ec_pdinfo",
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700108 "cat /sys/kernel/debug/cros_ec/pdinfo 2>/dev/null",
Shawn Nematbakhsh60813732017-07-13 10:46:23 -0700109 SandboxedProcess::kDefaultUser,
110 kDebugfsGroup
111 },
Vincent Palatine3588042018-04-04 17:02:38 +0200112 { "cros_fp",
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700113 "cat /var/log/cros_fp.previous /var/log/cros_fp.log 2>/dev/null" },
Elly Jones03cd6d72012-06-11 13:04:28 -0400114 { "dmesg", "/bin/dmesg" },
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700115 { "ec_info", "cat /var/log/ec_info.txt" },
Miguel Casas8d4e54f2018-03-29 09:42:52 -0400116 // The sed command replaces the EDID serial number (4 bytes at position 12)
117 // with zeroes. See https://en.wikipedia.org/wiki/EDID#EDID_1.4_data_format.
118 { "edid-decode",
Miguel Casas55b7c842018-08-15 13:10:10 -0400119 "for f in /sys/class/drm/card0-*/edid; do "
Miguel Casas8d4e54f2018-03-29 09:42:52 -0400120 "echo \"----------- ${f}\"; "
Miguel Casas1b8d2792018-08-17 20:00:52 -0400121 "sed -E 's/^(.{11}).{4}/\\1\\x0\\x0\\x0\\x0/' \"${f}\" | "
122 // edid-decode's stderr output is redundant, so silence it.
123 "edid-decode 2>/dev/null; "
Miguel Casas8d4e54f2018-03-29 09:42:52 -0400124 "done"
125 },
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700126 { "eventlog", "cat /var/log/eventlog.txt" },
Elly Fong-Jones215b5622013-03-20 14:32:18 -0400127 {
128 "exynos_gem_objects",
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700129 "cat /sys/kernel/debug/dri/0/exynos_gem_objects 2>/dev/null",
Elly Fong-Jones215b5622013-03-20 14:32:18 -0400130 SandboxedProcess::kDefaultUser,
131 kDebugfsGroup
132 },
Elly Jones03cd6d72012-06-11 13:04:28 -0400133 { "font_info", "/usr/share/userfeedback/scripts/font_info" },
Daisuke Nojiridebede0e2017-02-17 14:21:28 -0800134 { "sensor_info", "/usr/share/userfeedback/scripts/sensor_info" },
Wei-Han Chen9b7aa6a2018-09-19 22:30:22 +0800135 { "hammerd", "cat /var/log/hammerd.log 2>/dev/null" },
Elly Jones03cd6d72012-06-11 13:04:28 -0400136 { "hardware_class", "/usr/bin/crossystem hwid" },
137 { "hostname", "/bin/hostname" },
Elly Fong-Jones215b5622013-03-20 14:32:18 -0400138 {
139 "i915_gem_gtt",
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700140 "cat /sys/kernel/debug/dri/0/i915_gem_gtt 2>/dev/null",
Elly Fong-Jones215b5622013-03-20 14:32:18 -0400141 SandboxedProcess::kDefaultUser,
142 kDebugfsGroup
143 },
144 {
145 "i915_gem_objects",
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700146 "cat /sys/kernel/debug/dri/0/i915_gem_objects 2>/dev/null",
Elly Fong-Jones215b5622013-03-20 14:32:18 -0400147 SandboxedProcess::kDefaultUser,
148 kDebugfsGroup
149 },
150 {
151 "i915_error_state",
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700152 "/usr/bin/xz -c /sys/kernel/debug/dri/0/i915_error_state 2>/dev/null",
Elly Fong-Jones215b5622013-03-20 14:32:18 -0400153 SandboxedProcess::kDefaultUser,
154 kDebugfsGroup,
Luis Hector Chavezfc2566f2018-09-13 15:00:36 -0700155 kDefaultSizeCap,
156 LogTool::Encoding::kBinary,
Elly Fong-Jones215b5622013-03-20 14:32:18 -0400157 },
Daniel Erat982ab4b2014-04-09 07:32:38 -0700158 { "ifconfig", "/bin/ifconfig -a" },
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700159 { "input_devices", "cat /proc/bus/input/devices" },
Eric Carusob1820c02017-08-24 15:39:56 -0700160 // Information about the wiphy device, such as current channel.
161 { "iw_dev", "/usr/sbin/iw dev" },
162 // Hardware capabilities of the wiphy device.
163 { "iw_list", "/usr/sbin/iw list" },
Eric Carusoa879fd92017-10-11 12:57:10 -0700164#if USE_IWLWIFI_DUMP
165 { "iwlmvm_module_params", CMD_KERNEL_MODULE_PARAMS(iwlmvm) },
166 { "iwlwifi_module_params", CMD_KERNEL_MODULE_PARAMS(iwlwifi) },
167#endif // USE_IWLWIFI_DUMP
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700168 { "kernel-crashes", "cat /var/spool/crash/kernel.*.kcrash 2>/dev/null" },
169 { "logcat",
170 "/usr/sbin/android-sh -c '/system/bin/logcat -d'",
Kevin Cernekee143e2af2018-03-20 13:28:20 -0700171 kRoot,
172 kRoot,
Luis Hector Chavezfc2566f2018-09-13 15:00:36 -0700173 kDefaultSizeCap,
174 LogTool::Encoding::kUtf8,
Kevin Cernekee143e2af2018-03-20 13:28:20 -0700175 },
Elly Jones03cd6d72012-06-11 13:04:28 -0400176 { "lsmod", "lsmod" },
177 { "lspci", "/usr/sbin/lspci" },
Simon Que41c88b52017-06-19 14:05:07 -0400178 { "lsusb", "lsusb && lsusb -t" },
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700179 { "mali_memory", "cat /sys/class/misc/mali0/device/memory 2>/dev/null" },
Luigi Semenzato7f00dfb2018-06-26 11:34:02 -0700180 { "memd.parameters", "cat /var/log/memd/memd.parameters 2>/dev/null" },
181 { "memd clips", "cat /var/log/memd/memd.clip* 2>/dev/null" },
Elly Jones03cd6d72012-06-11 13:04:28 -0400182 { "meminfo", "cat /proc/meminfo" },
Mike Frysinger8fd2eee2017-11-03 14:35:26 -0400183 {
184 "memory_spd_info",
185 // mosys may use 'i2c-dev', which may not be loaded yet.
186 "modprobe i2c-dev 2>/dev/null && "
187 "mosys -l memory spd print all 2>/dev/null",
188 kRoot,
189 kDebugfsGroup,
190 },
Simon Quecb63b9c2017-06-19 14:53:31 -0400191 // The sed command finds the EDID blob (starting the line after "value:") and
192 // replaces the serial number with all zeroes.
193 //
194 // The EDID is printed as a hex dump over several lines, each line containing
195 // the contents of 16 bytes. The first 16 bytes are broken down as follows:
196 // uint64_t fixed_pattern; // Always 00 FF FF FF FF FF FF 00.
197 // uint16_t manufacturer_id; // Manufacturer ID, encoded as PNP IDs.
198 // uint16_t product_code; // Manufacturer product code, little-endian.
199 // uint32_t serial_number; // Serial number, little-endian.
200 // Source: https://en.wikipedia.org/wiki/EDID#EDID_1.3_data_format
201 //
202 // The subsequent substitution command looks for the fixed pattern followed by
203 // two 32-bit fields (manufacturer + product, serial number). It replaces the
204 // latter field with 8 bytes of zeroes.
205 //
206 // TODO(crbug.com/731133): Remove the sed command once modetest itself can
207 // remove serial numbers.
208 {
209 "modetest",
210 "(modetest; modetest -M evdi; modetest -M udl) | "
211 "sed -E '/EDID/ {:a;n;/value:/!ba;n;"
212 "s/(00f{12}00)([0-9a-f]{8})([0-9a-f]{8})/\\1\\200000000/}'",
213 kRoot,
214 kRoot,
215 },
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700216 { "mount-encrypted", "cat /var/log/mount-encrypted.log" },
217 { "mountinfo", "cat /proc/1/mountinfo" },
Nicolas Boichat0230b0b2017-08-17 11:20:19 +0800218 { "netlog", "/usr/share/userfeedback/scripts/getmsgs /var/log/net.log" },
Kevin Cernekee143e2af2018-03-20 13:28:20 -0700219 // --processes requires root.
220 { "netstat", "/sbin/ss --all --query inet --numeric --processes",
221 kRoot,
222 kRoot,
223 },
henryhsufa6daa12014-09-24 13:26:30 +0800224 {
225 "nvmap_iovmm",
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700226 "cat /sys/kernel/debug/nvmap/iovmm/allocations 2>/dev/null",
henryhsufa6daa12014-09-24 13:26:30 +0800227 SandboxedProcess::kDefaultUser,
228 kDebugfsGroup,
229 },
Todd Brocha0c13762018-05-03 11:31:25 -0700230 { "oemdata", "/usr/share/cros/oemdata.sh", kRoot, kRoot, },
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700231 { "pagetypeinfo", "cat /proc/pagetypeinfo" },
Mike Frysinger8fd2eee2017-11-03 14:35:26 -0400232 {
233 "platform_info",
234 // mosys may use 'i2c-dev', which may not be loaded yet.
235 "modprobe i2c-dev 2>/dev/null && "
236 "for param in "
237 "vendor "
238 "name "
239 "version "
240 "family "
241 "model "
242 "sku "
243 "customization "
244 "; do "
245 "mosys -l platform \"${param}\" 2>/dev/null; "
246 "done",
247 kRoot,
248 kDebugfsGroup,
249 },
Daniel Erat9b58b6d2013-04-30 14:58:56 -0700250 { "power_supply_info", "/usr/bin/power_supply_info" },
Daniel Eratd8b84992017-03-13 17:30:00 -0600251 { "power_supply_sysfs", "/usr/bin/print_sysfs_power_supply_data" },
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700252 { "powerd.LATEST", "cat /var/log/power_manager/powerd.LATEST" },
253 { "powerd.PREVIOUS", "cat /var/log/power_manager/powerd.PREVIOUS" },
254 { "powerd.out", "cat /var/log/powerd.out" },
255 { "powerwash_count", "cat /var/log/powerwash_count 2>/dev/null" },
Mattias Nissler887dce22017-07-03 14:44:35 +0200256 // Changed from 'ps ux' to 'ps aux' since we're running as debugd,
257 // not chronos.
Elly Jones03cd6d72012-06-11 13:04:28 -0400258 { "ps", "/bin/ps aux" },
yusukes34171ba2017-04-27 15:46:01 -0700259 // /proc/slabinfo is owned by root and has 0400 permission.
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700260 { "slabinfo", "cat /proc/slabinfo", kRoot, kRoot, },
261 { "storage_info", "cat /var/log/storage_info.txt" },
Alexis Saverybbb85132018-05-18 17:41:10 -0700262 { "swap_info",
263 "/usr/share/cros/init/swap.sh status 2>/dev/null",
264 SandboxedProcess::kDefaultUser,
265 kDebugfsGroup
266 },
Nicolas Boichat0230b0b2017-08-17 11:20:19 +0800267 { "syslog", "/usr/share/userfeedback/scripts/getmsgs /var/log/messages" },
Brandon Mayere24c7a22017-08-04 13:58:48 -0400268 { "system_log_stats", "echo 'BLOCK_SIZE=1024'; "
269 "find /var/log/ -type f -exec du --block-size=1024 {} + | sort -n -r",
270 kRoot, kRoot},
Kuo-Hsin Yang379846b2018-06-04 11:16:55 +0800271 { "threads", "/bin/ps -T axo pid,ppid,spid,pcpu,ni,stat,time,comm" },
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700272 { "tlsdate", "cat /var/log/tlsdate.log" },
Hsu-Cheng Tsaie8c31d52017-03-31 12:34:55 +0800273 { "top thread", "/usr/bin/top -Hb -n 1 | head -n 40"},
274 { "top memory", "/usr/bin/top -o \"+%MEM\" -bn 1 | head -n 57"},
Andrew de los Reyesc060c342013-04-10 13:46:30 -0700275 { "touch_fw_version", "grep -E"
Charlie Mooneybb08f982016-02-04 15:35:56 -0800276 " -e 'synaptics: Touchpad model'"
277 " -e 'chromeos-[a-z]*-touch-[a-z]*-update'"
Andrew de los Reyesc060c342013-04-10 13:46:30 -0700278 " /var/log/messages | tail -n 20" },
Mattias Nissler483d76f2017-08-23 16:53:36 +0200279 {
280 "tpm-firmware-updater",
281 "/usr/share/userfeedback/scripts/getmsgs /var/log/tpm-firmware-updater.log"
282 },
Mattias Nissler887dce22017-07-03 14:44:35 +0200283 // TODO(jorgelo,mnissler): Don't run this as root.
284 // On TPM 1.2 devices this will likely require adding a new user to the 'tss'
285 // group.
286 // On TPM 2.0 devices 'get_version_info' uses D-Bus and therefore can run as
287 // any user.
288 { "tpm_version", "/usr/sbin/tpm-manager get_version_info", kRoot, kRoot },
Charlie Mooney69f56702017-05-02 14:55:41 -0700289 { "atmel_ts_refs", "/opt/google/touch/scripts/atmel_tools.sh ts r",
290 kRoot, kRoot},
291 { "atmel_tp_refs", "/opt/google/touch/scripts/atmel_tools.sh tp r",
292 kRoot, kRoot},
293 { "atmel_ts_deltas", "/opt/google/touch/scripts/atmel_tools.sh ts d",
294 kRoot, kRoot},
295 { "atmel_tp_deltas", "/opt/google/touch/scripts/atmel_tools.sh tp d",
296 kRoot, kRoot},
Gwendal Grignou427d94e2016-10-25 11:34:51 -0700297 {
298 "trim",
299 "cat /var/lib/trim/stateful_trim_state /var/lib/trim/stateful_trim_data"
300 },
Elly Jones03cd6d72012-06-11 13:04:28 -0400301 { "ui_log", "/usr/share/userfeedback/scripts/get_log /var/log/ui/ui.LATEST" },
302 { "uname", "/bin/uname -a" },
303 { "update_engine.log", "cat $(ls -1tr /var/log/update_engine | tail -5 | sed"
Thiemo Nagela269ad22014-11-27 17:13:01 +0100304 " s.^./var/log/update_engine/.)" },
Dariusz Marcinkiewiczc4126882017-10-13 16:07:36 +0200305 { "uptime", "/usr/bin/cut -d' ' -f1 /proc/uptime" },
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700306 { "verified boot", "cat /var/log/debug_vboot_noisy.log" },
307 { "vmlog.1.LATEST", "cat /var/log/vmlog/vmlog.1.LATEST" },
308 { "vmlog.1.PREVIOUS", "cat /var/log/vmlog/vmlog.1.PREVIOUS" },
309 { "vmlog.LATEST", "cat /var/log/vmlog/vmlog.LATEST" },
310 { "vmlog.PREVIOUS", "cat /var/log/vmlog/vmlog.PREVIOUS" },
311 { "vmstat", "cat /proc/vmstat" },
312 { "vpd_2.0", "cat /var/log/vpd_2.0.txt" },
Samuel Tan107b6c82014-07-10 15:33:44 -0700313 { "wifi_status", "/usr/bin/network_diag --wifi-internal --no-log" },
Sonny Raoab5f9952013-07-17 14:13:53 -0700314 { "zram compressed data size",
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700315 "cat /sys/block/zram0/compr_data_size 2>/dev/null" },
Sonny Raoab5f9952013-07-17 14:13:53 -0700316 { "zram original data size",
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700317 "cat /sys/block/zram0/orig_data_size 2>/dev/null" },
Sonny Raoab5f9952013-07-17 14:13:53 -0700318 { "zram total memory used",
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700319 "cat /sys/block/zram0/mem_used_total 2>/dev/null" },
Sonny Raoab5f9952013-07-17 14:13:53 -0700320 { "zram total reads",
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700321 "cat /sys/block/zram0/num_reads 2>/dev/null" },
Sonny Raoab5f9952013-07-17 14:13:53 -0700322 { "zram total writes",
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700323 "cat /sys/block/zram0/num_writes 2>/dev/null" },
324 { "zram new stats names",
325 "echo orig_size compr_size used_total limit "
Luigi Semenzato4164de42017-07-06 10:42:54 -0700326 "used_max zero_pages migrated" },
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700327 { "zram new stats values", "cat /sys/block/zram0/mm_stat 2>/dev/null" },
328 { "cros_tp version", "cat /sys/class/chromeos/cros_tp/version" },
Wei-Ning Huang230b7d82017-07-14 16:19:13 +0800329 { "cros_tp console", "/usr/sbin/ectool --name=cros_tp console",
330 kRoot, kRoot },
Wei-Ning Huang23ffdcf2017-08-04 11:30:39 +0800331 { "cros_tp frame", "/usr/sbin/ectool --name=cros_tp tpframeget",
332 kRoot, kRoot },
Zach Reizner7eab48b2018-06-22 19:26:48 -0700333 { "crostini", "/usr/bin/cicerone_client --get_info" },
Gaurav Shah6e8fd892012-10-01 11:51:08 -0700334
Elly Jones03cd6d72012-06-11 13:04:28 -0400335 // Stuff pulled out of the original list. These need access to the running X
336 // session, which we'd rather not give to debugd, or return info specific to
337 // the current session (in the setsid(2) sense), which is not useful for
338 // debugd
339 // { "env", "set" },
340 // { "setxkbmap", "/usr/bin/setxkbmap -print -query" },
341 // { "xrandr", "/usr/bin/xrandr --verbose" }
Ben Chan64d19b22017-02-06 14:03:47 -0800342 { nullptr, nullptr }
Elly Jones533c7c42012-08-10 15:07:05 -0400343};
344
Kevin Cernekee143e2af2018-03-20 13:28:20 -0700345// netstat and logcat should appear in chrome://system but not in feedback
346// reports. Open sockets may have privacy implications, and logcat is
347// already incorporated via arc-bugreport.
348const std::vector<string> kCommandLogsExclude = {"netstat", "logcat"};
349
Ben Chancf7d6412017-08-10 22:30:09 -0700350const Log kExtraLogs[] = {
Ben Chan36e42282014-02-12 22:32:34 -0800351#if USE_CELLULAR
Elly Jones533c7c42012-08-10 15:07:05 -0400352 { "mm-status", "/usr/bin/modem status" },
Ben Chan36e42282014-02-12 22:32:34 -0800353#endif // USE_CELLULAR
Elly Jones533c7c42012-08-10 15:07:05 -0400354 { "network-devices", "/usr/bin/connectivity show devices" },
355 { "network-services", "/usr/bin/connectivity show services" },
Ben Chan64d19b22017-02-06 14:03:47 -0800356 { nullptr, nullptr }
Elly Jones533c7c42012-08-10 15:07:05 -0400357};
358
Ben Chancf7d6412017-08-10 22:30:09 -0700359const Log kFeedbackLogs[] = {
Ben Chan36e42282014-02-12 22:32:34 -0800360#if USE_CELLULAR
Elly Jones533c7c42012-08-10 15:07:05 -0400361 { "mm-status", "/usr/bin/modem status-feedback" },
Ben Chan36e42282014-02-12 22:32:34 -0800362#endif // USE_CELLULAR
Elly Jones533c7c42012-08-10 15:07:05 -0400363 { "network-devices", "/usr/bin/connectivity show-feedback devices" },
364 { "network-services", "/usr/bin/connectivity show-feedback services" },
Ben Chan64d19b22017-02-06 14:03:47 -0800365 { nullptr, nullptr }
Elly Jones03cd6d72012-06-11 13:04:28 -0400366};
367
Ahmed Fakhry1498b4e2016-03-30 12:42:20 -0700368// List of log files needed to be part of the feedback report that are huge and
369// must be sent back to the client via the file descriptor using
370// LogTool::GetBigFeedbackLogs().
Ben Chancf7d6412017-08-10 22:30:09 -0700371const Log kBigFeedbackLogs[] = {
Eric Carusoe3166f22016-06-10 15:36:02 -0700372 { "arc-bugreport",
Luigi Semenzato7e2c08f2018-06-26 14:58:49 -0700373 "cat /run/arc/bugreport/pipe 2>/dev/null",
Eric Carusoe3166f22016-06-10 15:36:02 -0700374 // ARC bugreport permissions are weird. Since we're just running cat, this
375 // shouldn't cause any issues.
376 kRoot,
Ricky Zhou4c473ca2016-06-21 17:46:58 -0700377 kRoot,
378 "10M",
Luis Hector Chavezfc2566f2018-09-13 15:00:36 -0700379 LogTool::Encoding::kUtf8,
Eric Carusoe3166f22016-06-10 15:36:02 -0700380 },
Ben Chan64d19b22017-02-06 14:03:47 -0800381 { nullptr, nullptr }
Ahmed Fakhry1498b4e2016-03-30 12:42:20 -0700382};
383
Gaurav Shahf6c8f2a2012-10-11 17:22:43 -0700384// List of log files that must directly be collected by Chrome. This is because
385// debugd is running under a VFS namespace and does not have access to later
386// cryptohome mounts.
Ben Chancf7d6412017-08-10 22:30:09 -0700387const Log kUserLogs[] = {
Elly Fong-Jones6456ce52013-04-17 13:31:13 -0400388 {"chrome_user_log", "log/chrome"},
Xiaohui Chen32b171d2018-08-27 17:18:44 -0700389 {"libassistant_user_log", "log/libassistant.log"},
Elly Fong-Jones6456ce52013-04-17 13:31:13 -0400390 {"login-times", "login-times"},
391 {"logout-times", "logout-times"},
Ben Chan64d19b22017-02-06 14:03:47 -0800392 { nullptr, nullptr}
Gaurav Shahf6c8f2a2012-10-11 17:22:43 -0700393};
394
Ahmed Fakhry21140cf2016-03-04 17:15:19 -0800395// TODO(ellyjones): sandbox. crosbug.com/35122
396string Run(const Log& log) {
397 string output;
398 ProcessWithOutput p;
Luis Hector Chavezfc2566f2018-09-13 15:00:36 -0700399 string tailed_cmdline =
400 base::StringPrintf("%s | tail -c %s", log.command, log.size_cap);
Ahmed Fakhry21140cf2016-03-04 17:15:19 -0800401 if (log.user && log.group)
402 p.SandboxAs(log.user, log.group);
403 if (!p.Init())
404 return "<not available>";
405 p.AddArg(kShell);
406 p.AddStringOption("-c", tailed_cmdline);
407 if (p.Run())
408 return "<not available>";
409 p.GetOutput(&output);
410 if (!output.size())
411 return "<empty>";
Luis Hector Chavezfc2566f2018-09-13 15:00:36 -0700412 return LogTool::EnsureUTF8String(output, log.encoding);
Ahmed Fakhry21140cf2016-03-04 17:15:19 -0800413}
414
415// Fills |dictionary| with the anonymized contents of the logs in |logs|.
416void GetLogsInDictionary(const struct Log* logs,
417 AnonymizerTool* anonymizer,
418 base::DictionaryValue* dictionary) {
419 for (size_t i = 0; logs[i].name; ++i) {
420 dictionary->SetStringWithoutPathExpansion(
421 logs[i].name, anonymizer->Anonymize(Run(logs[i])));
422 }
423}
424
425// Serializes the |dictionary| into the file with the given |fd| in a JSON
426// format.
427void SerializeLogsAsJSON(const base::DictionaryValue& dictionary,
Eric Caruso0b241882018-04-04 13:43:46 -0700428 const base::ScopedFD& fd) {
Eric Caruso96d03d32017-04-25 18:01:17 -0700429 string logs_json;
Ahmed Fakhry21140cf2016-03-04 17:15:19 -0800430 base::JSONWriter::WriteWithOptions(dictionary,
431 base::JSONWriter::OPTIONS_PRETTY_PRINT,
432 &logs_json);
Eric Caruso0b241882018-04-04 13:43:46 -0700433 base::WriteFileDescriptor(fd.get(), logs_json.c_str(), logs_json.size());
Ahmed Fakhry21140cf2016-03-04 17:15:19 -0800434}
435
Elly Jones533c7c42012-08-10 15:07:05 -0400436bool GetNamedLogFrom(const string& name, const struct Log* logs,
437 string* result) {
438 for (size_t i = 0; logs[i].name; i++) {
439 if (name == logs[i].name) {
Elly Fong-Jonesd9a16cd2012-11-12 16:09:49 -0500440 *result = Run(logs[i]);
Elly Jones533c7c42012-08-10 15:07:05 -0400441 return true;
442 }
443 }
444 *result = "<invalid log name>";
445 return false;
Elly Jones03cd6d72012-06-11 13:04:28 -0400446}
447
Ahmed Fakhry21140cf2016-03-04 17:15:19 -0800448void GetLogsFrom(const struct Log* logs, LogTool::LogMap* map) {
449 for (size_t i = 0; logs[i].name; i++)
450 (*map)[logs[i].name] = Run(logs[i]);
451}
452
Kartik Hegde1c4b97b2018-09-09 19:09:34 -0600453void GetLsbReleaseInfo(LogTool::LogMap* map) {
454 const base::FilePath lsb_release(kLsbReleasePath);
455 brillo::KeyValueStore store;
456 if (!store.Load(lsb_release)) {
457 // /etc/lsb-release might not be present (cros deploying a new
458 // configuration or no fields set at all). Just print a debug
459 // message and continue.
460 DLOG(INFO) << "Could not load fields from " << lsb_release.value();
461 } else {
462 for (const auto& key : store.GetKeys()) {
463 std::string value;
464 store.GetString(key, &value);
465 (*map)[key] = value;
466 }
467 }
468}
469
470void GetOsReleaseInfo(LogTool::LogMap* map) {
471 brillo::OsReleaseReader reader;
472 reader.Load();
473 for (const auto& key : reader.GetKeys()) {
474 std::string value;
475 reader.GetString(key, &value);
476 (*map)["os-release " + key] = value;
477 }
478}
479
480void PopulateDictionaryValue(const LogTool::LogMap& map,
481 base::DictionaryValue* dictionary) {
482 for (const auto& kv : map) {
483 dictionary->SetString(kv.first, kv.second);
484 }
485}
486
Chinglin Yuaeb4ec72018-12-10 18:53:30 +0800487bool CompressXzBuffer(const std::vector<uint8_t>& in_buffer,
488 std::vector<uint8_t>* out_buffer) {
489 size_t out_size = lzma_stream_buffer_bound(in_buffer.size());
490 out_buffer->resize(out_size);
491 size_t out_pos = 0;
492
493 lzma_ret ret = lzma_easy_buffer_encode(
494 LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC64, nullptr, in_buffer.data(),
495 in_buffer.size(), out_buffer->data(), &out_pos, out_size);
496
497 if (ret != LZMA_OK) {
498 out_buffer->clear();
499 return false;
500 }
501
502 out_buffer->resize(out_pos);
503 return true;
504}
505
506void GetPerfData(LogTool::LogMap* map) {
507 // Run perf to collect system-wide performance profile when user triggers
508 // feedback report. Perf runs at sampling frequency of ~500 hz (499 is used
509 // to avoid sampling periodic system activities), with callstack in each
510 // sample (-g).
511 std::vector<std::string> perf_args = {
512 "perf", "record", "-a", "-g", "-F", "499"
513 };
514 std::vector<uint8_t> perf_data;
515 int32_t status;
516
517 debugd::PerfTool perf_tool;
518 if (!perf_tool.GetPerfOutput(kPerfDurationSecs, perf_args, &perf_data,
519 nullptr, &status, nullptr))
520 return;
521
522 // XZ compress the profile data.
523 std::vector<uint8_t> perf_data_xz;
524 if (!CompressXzBuffer(perf_data, &perf_data_xz))
525 return;
526
527 // Base64 encode the compressed data.
528 std::string perf_data_str(reinterpret_cast<const char*>(perf_data_xz.data()),
529 perf_data_xz.size());
530 (*map)["perf-data"] =
531 LogTool::EnsureUTF8String(perf_data_str, LogTool::Encoding::kBinary);
532}
533
Ahmed Fakhry21140cf2016-03-04 17:15:19 -0800534} // namespace
535
Eric Carusof9091f82017-04-28 14:18:59 -0700536void LogTool::CreateConnectivityReport() {
Rebecca Silbersteine78af402014-10-02 10:55:04 -0700537 // Perform ConnectivityTrial to report connection state in feedback log.
Ben Chan8e9f6d02017-09-26 23:04:21 -0700538 auto shill = std::make_unique<org::chromium::flimflam::ManagerProxy>(bus_);
Rebecca Silbersteine78af402014-10-02 10:55:04 -0700539 // Give the connection trial time to test the connection and log the results
540 // before collecting the logs for feedback.
541 // TODO(silberst): Replace the simple approach of a single timeout with a more
542 // coordinated effort.
Eric Carusocc7106c2017-04-27 14:22:42 -0700543 if (shill && shill->CreateConnectivityReport(nullptr))
544 sleep(kConnectionTesterTimeoutSeconds);
Rebecca Silbersteine78af402014-10-02 10:55:04 -0700545}
546
Eric Carusoc93a15c2017-04-24 16:15:12 -0700547string LogTool::GetLog(const string& name) {
Elly Jones533c7c42012-08-10 15:07:05 -0400548 string result;
Ben Chancf7d6412017-08-10 22:30:09 -0700549 GetNamedLogFrom(name, kCommandLogs, &result)
550 || GetNamedLogFrom(name, kExtraLogs, &result)
551 || GetNamedLogFrom(name, kFeedbackLogs, &result);
Elly Jones533c7c42012-08-10 15:07:05 -0400552 return result;
553}
554
Eric Carusof9091f82017-04-28 14:18:59 -0700555LogTool::LogMap LogTool::GetAllLogs() {
556 CreateConnectivityReport();
Elly Jones533c7c42012-08-10 15:07:05 -0400557 LogMap result;
Ben Chancf7d6412017-08-10 22:30:09 -0700558 GetLogsFrom(kCommandLogs, &result);
559 GetLogsFrom(kExtraLogs, &result);
Kartik Hegde1c4b97b2018-09-09 19:09:34 -0600560 GetLsbReleaseInfo(&result);
561 GetOsReleaseInfo(&result);
Elly Jones533c7c42012-08-10 15:07:05 -0400562 return result;
563}
564
Brian Norrisca4fc042018-04-03 00:24:26 -0700565LogTool::LogMap LogTool::GetAllDebugLogs() {
566 CreateConnectivityReport();
567 LogMap result;
568 GetLogsFrom(kCommandLogs, &result);
569 GetLogsFrom(kExtraLogs, &result);
570 GetLogsFrom(kBigFeedbackLogs, &result);
Kartik Hegde1c4b97b2018-09-09 19:09:34 -0600571 GetLsbReleaseInfo(&result);
572 GetOsReleaseInfo(&result);
Brian Norrisca4fc042018-04-03 00:24:26 -0700573 return result;
574}
575
Eric Carusof9091f82017-04-28 14:18:59 -0700576LogTool::LogMap LogTool::GetFeedbackLogs() {
577 CreateConnectivityReport();
Elly Jones533c7c42012-08-10 15:07:05 -0400578 LogMap result;
Ben Chancf7d6412017-08-10 22:30:09 -0700579 GetLogsFrom(kCommandLogs, &result);
Kevin Cernekee143e2af2018-03-20 13:28:20 -0700580 for (const auto& key : kCommandLogsExclude) {
581 result.erase(key);
582 }
Ben Chancf7d6412017-08-10 22:30:09 -0700583 GetLogsFrom(kFeedbackLogs, &result);
Kartik Hegde1c4b97b2018-09-09 19:09:34 -0600584 GetLsbReleaseInfo(&result);
585 GetOsReleaseInfo(&result);
Darin Petkovce9b3a12013-01-10 16:38:54 +0100586 AnonymizeLogMap(&result);
Elly Jones03cd6d72012-06-11 13:04:28 -0400587 return result;
588}
589
Eric Caruso0b241882018-04-04 13:43:46 -0700590void LogTool::GetBigFeedbackLogs(const base::ScopedFD& fd) {
Eric Carusof9091f82017-04-28 14:18:59 -0700591 CreateConnectivityReport();
Chinglin Yuaeb4ec72018-12-10 18:53:30 +0800592 LogMap map;
593 GetPerfData(&map);
Ahmed Fakhry21140cf2016-03-04 17:15:19 -0800594 base::DictionaryValue dictionary;
Ben Chancf7d6412017-08-10 22:30:09 -0700595 GetLogsInDictionary(kCommandLogs, &anonymizer_, &dictionary);
Kevin Cernekee143e2af2018-03-20 13:28:20 -0700596 for (const auto& key : kCommandLogsExclude) {
597 dictionary.Remove(key, nullptr);
598 }
Ben Chancf7d6412017-08-10 22:30:09 -0700599 GetLogsInDictionary(kFeedbackLogs, &anonymizer_, &dictionary);
600 GetLogsInDictionary(kBigFeedbackLogs, &anonymizer_, &dictionary);
Kartik Hegde1c4b97b2018-09-09 19:09:34 -0600601 GetLsbReleaseInfo(&map);
602 GetOsReleaseInfo(&map);
603 PopulateDictionaryValue(map, &dictionary);
Ahmed Fakhry21140cf2016-03-04 17:15:19 -0800604 SerializeLogsAsJSON(dictionary, fd);
605}
606
Eric Carusoc93a15c2017-04-24 16:15:12 -0700607LogTool::LogMap LogTool::GetUserLogFiles() {
Gaurav Shahf6c8f2a2012-10-11 17:22:43 -0700608 LogMap result;
Ben Chancf7d6412017-08-10 22:30:09 -0700609 for (size_t i = 0; kUserLogs[i].name; ++i)
610 result[kUserLogs[i].name] = kUserLogs[i].command;
Gaurav Shahf6c8f2a2012-10-11 17:22:43 -0700611 return result;
612}
613
Luis Hector Chavezfc2566f2018-09-13 15:00:36 -0700614// static
615string LogTool::EnsureUTF8String(const string& value,
616 LogTool::Encoding source_encoding) {
617 if (source_encoding == LogTool::Encoding::kAutodetect) {
618 if (base::IsStringUTF8(value))
619 return value;
620 source_encoding = LogTool::Encoding::kBinary;
621 }
622
623 if (source_encoding == LogTool::Encoding::kUtf8) {
624 string output;
625 const char* src = value.data();
626 int32_t src_len = static_cast<int32_t>(value.length());
627
628 output.reserve(value.size());
629 for (int32_t char_index = 0; char_index < src_len; char_index++) {
630 uint32_t code_point;
631 if (!base::ReadUnicodeCharacter(src, src_len, &char_index, &code_point) ||
632 !base::IsValidCharacter(code_point)) {
633 // Replace invalid characters with U+FFFD REPLACEMENT CHARACTER.
634 code_point = 0xFFFD;
635 }
636 base::WriteUnicodeCharacter(code_point, &output);
637 }
638 return output;
639 } else {
640 string encoded_value;
641 base::Base64Encode(value, &encoded_value);
642 return "<base64>: " + encoded_value;
643 }
644}
645
Darin Petkovce9b3a12013-01-10 16:38:54 +0100646void LogTool::AnonymizeLogMap(LogMap* log_map) {
Ben Chane2fa3572017-02-08 22:46:18 -0800647 for (auto& entry : *log_map)
648 entry.second = anonymizer_.Anonymize(entry.second);
Darin Petkovce9b3a12013-01-10 16:38:54 +0100649}
650
Ben Chana0011d82014-05-13 00:19:29 -0700651} // namespace debugd