Commit 6952aa47 authored by Eric Seckler's avatar Eric Seckler Committed by Commit Bot

perfetto: Enable ClockSnapshots

Enables perfetto service to emit clock snapshots when tracing Chrome.
This is required to correctly import traces specifying a clock other
than BOOTTIME (Android, Linux, Fuchsia).

Since perfetto snapshots all clocks, this requires relaxing the
syscall filter of the sandbox to also allow CLOCK_BOOTTIME &
CLOCK_MONOTONIC_RAW access.

Bug: 1018134
Change-Id: I98e9ffee97bda4381da7170d917c3bd83beecaff
TBR: hidehiko@chromium.org
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1879894
Commit-Queue: Eric Seckler <eseckler@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Reviewed-by: default avatarSami Kyöstilä <skyostil@chromium.org>
Cr-Commit-Position: refs/heads/master@{#711670}
parent fb7efc52
......@@ -45,6 +45,7 @@
#include "sandbox/linux/system_headers/linux_futex.h"
#include "sandbox/linux/system_headers/linux_signal.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
#include "sandbox/linux/system_headers/linux_time.h"
// These defines are for PNaCl toolchain build.
#if !defined(F_DUPFD_CLOEXEC)
......@@ -59,10 +60,6 @@
#define PROT_GROWSDOWN 0x01000000
#endif
#if !defined(CLOCK_MONOTONIC_RAW)
#define CLOCK_MONOTONIC_RAW 4
#endif
#if !defined(AF_INET)
#define AF_INET 2
#endif
......@@ -586,11 +583,12 @@ BPF_TEST_C(NaClNonSfiSandboxTest,
}
BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
clock_gettime_crash_monotonic_raw,
clock_gettime_crash_clock_fd,
DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
nacl::nonsfi::NaClNonSfiBPFSandboxPolicy) {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
// Negative clock IDs are per pid/tid or clock FDs - and are disallowed.
clock_gettime(-1, &ts);
}
BPF_DEATH_TEST_C(NaClNonSfiSandboxTest,
......
......@@ -38,6 +38,7 @@
#include "sandbox/linux/services/thread_helpers.h"
#include "sandbox/linux/system_headers/linux_futex.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
#include "sandbox/linux/system_headers/linux_time.h"
#include "sandbox/linux/tests/test_utils.h"
#include "sandbox/linux/tests/unit_tests.h"
......@@ -394,7 +395,7 @@ BPF_DEATH_TEST_C(BaselinePolicy,
DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
BaselinePolicy) {
struct timespec ts;
syscall(SYS_clock_gettime, CLOCK_MONOTONIC_RAW, &ts);
syscall(SYS_clock_gettime, (~0) | CLOCKFD, &ts);
}
#if !defined(GRND_RANDOM)
......
......@@ -372,11 +372,10 @@ ResultExpr RestrictClockID() {
return
If((clockid & kIsPidBit) == 0,
Switch(clockid).CASES((
#if defined(OS_ANDROID)
CLOCK_BOOTTIME,
#endif
CLOCK_MONOTONIC,
CLOCK_MONOTONIC_COARSE,
CLOCK_MONOTONIC_RAW,
CLOCK_PROCESS_CPUTIME_ID,
CLOCK_REALTIME,
CLOCK_REALTIME_COARSE,
......
......@@ -86,12 +86,13 @@ SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictPrlimit64(pid_t target_pid);
// process).
SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictGetrusage();
// Restrict |clk_id| for clock_getres(), clock_gettime() and clock_settime().
// We allow accessing only CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID,
// CLOCK_REALTIME, and CLOCK_THREAD_CPUTIME_ID. In particular, this disallows
// access to arbitrary per-{process,thread} CPU-time clock IDs (such as those
// returned by {clock,pthread}_getcpuclockid), which can leak information
// about the state of the host OS.
// Restrict |clk_id| for clock_getres(), clock_gettime() and clock_settime(). We
// allow accessing only CLOCK_BOOTTIME, CLOCK_MONOTONIC{,_RAW,_COARSE},
// CLOCK_PROCESS_CPUTIME_ID, CLOCK_REALTIME{,_COARSE}, and
// CLOCK_THREAD_CPUTIME_ID. In particular, this disallows access to arbitrary
// per-{process,thread} CPU-time clock IDs (such as those returned by
// {clock,pthread}_getcpuclockid), which can leak information about the state of
// the host OS.
SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictClockID();
// Restrict the flags argument to getrandom() to allow only no flags, or
......
......@@ -85,10 +85,9 @@ BPF_TEST_C(ParameterRestrictions,
RestrictClockIdPolicy) {
CheckClock(CLOCK_MONOTONIC);
CheckClock(CLOCK_MONOTONIC_COARSE);
CheckClock(CLOCK_MONOTONIC_RAW);
CheckClock(CLOCK_PROCESS_CPUTIME_ID);
#if defined(OS_ANDROID)
CheckClock(CLOCK_BOOTTIME);
#endif
CheckClock(CLOCK_REALTIME);
CheckClock(CLOCK_REALTIME_COARSE);
CheckClock(CLOCK_THREAD_CPUTIME_ID);
......@@ -100,11 +99,11 @@ BPF_TEST_C(ParameterRestrictions,
}
BPF_DEATH_TEST_C(ParameterRestrictions,
clock_gettime_crash_monotonic_raw,
clock_gettime_crash_clock_fd,
DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
RestrictClockIdPolicy) {
struct timespec ts;
syscall(SYS_clock_gettime, CLOCK_MONOTONIC_RAW, &ts);
syscall(SYS_clock_gettime, (~0) | CLOCKFD, &ts);
}
#if !defined(OS_ANDROID)
......
......@@ -15,6 +15,10 @@
#define CLOCKFD 3
#endif
#if !defined(CLOCK_MONOTONIC_RAW)
#define CLOCK_MONOTONIC_RAW 4
#endif
#if !defined(CLOCK_REALTIME_COARSE)
#define CLOCK_REALTIME_COARSE 5
#endif
......@@ -23,4 +27,8 @@
#define CLOCK_MONOTONIC_COARSE 6
#endif
#if !defined(CLOCK_BOOTTIME)
#define CLOCK_BOOTTIME 7
#endif
#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_TIME_H_
......@@ -40,16 +40,6 @@ namespace {
const int32_t kEnableTracingTimeoutSeconds = 10;
perfetto::TraceConfig AdjustTraceConfig(
const perfetto::TraceConfig& trace_config) {
perfetto::TraceConfig trace_config_copy(trace_config);
// Clock snapshotting is incompatible with chrome's process sandboxing.
// Telemetry uses its own way of snapshotting clocks anyway.
auto* builtin_data_sources = trace_config_copy.mutable_builtin_data_sources();
builtin_data_sources->set_disable_clock_snapshotting(true);
return trace_config_copy;
}
} // namespace
class ConsumerHost::StreamWriter {
......@@ -148,10 +138,9 @@ ConsumerHost::TracingSession::TracingSession(
}
}
#endif
perfetto::TraceConfig trace_config_copy = AdjustTraceConfig(trace_config);
filtered_pids_.clear();
for (const auto& ds_config : trace_config_copy.data_sources()) {
for (const auto& ds_config : trace_config.data_sources()) {
if (ds_config.config().name() == mojom::kTraceEventDataSourceName) {
for (const auto& filter : ds_config.producer_name_filter()) {
base::ProcessId pid;
......@@ -167,7 +156,7 @@ ConsumerHost::TracingSession::TracingSession(
base::EraseIf(*pending_enable_tracing_ack_pids_,
[this](base::ProcessId pid) { return !IsExpectedPid(pid); });
host_->consumer_endpoint()->EnableTracing(trace_config_copy);
host_->consumer_endpoint()->EnableTracing(trace_config);
MaybeSendEnableTracingAck();
if (pending_enable_tracing_ack_pids_) {
......@@ -285,8 +274,7 @@ void ConsumerHost::TracingSession::ChangeTraceConfig(
const perfetto::TraceConfig& trace_config) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
perfetto::TraceConfig trace_config_copy = AdjustTraceConfig(trace_config);
host_->consumer_endpoint()->ChangeTraceConfig(trace_config_copy);
host_->consumer_endpoint()->ChangeTraceConfig(trace_config);
}
void ConsumerHost::TracingSession::DisableTracing() {
......
......@@ -25,6 +25,16 @@ struct MessageInfo {
const MessageInfo* const* const sub_messages;
};
// Proto Message: Clock
constexpr int kClockIndices[] = {1, 2, 3, 4, -1};
constexpr MessageInfo kClock = {kClockIndices, nullptr};
// Proto Message: ClockSnapshot
constexpr int kClockSnapshotIndices[] = {1, -1};
constexpr MessageInfo const* kClockSnapshotComplexMessages[] = {&kClock};
constexpr MessageInfo kClockSnapshot = {kClockSnapshotIndices,
kClockSnapshotComplexMessages};
// Proto Message: TaskExecution
constexpr int kTaskExecutionIndices[] = {1, -1};
constexpr MessageInfo kTaskExecution = {kTaskExecutionIndices, nullptr};
......@@ -35,10 +45,10 @@ constexpr int kLegacyEventIndices[] = {1, 2, 3, 4, 6, 8, 9, 10,
constexpr MessageInfo kLegacyEvent = {kLegacyEventIndices, nullptr};
// Proto Message: TrackEvent
constexpr int kTrackEventIndices[] = {1, 2, 3, 5, 6, 16, 17, -1};
constexpr int kTrackEventIndices[] = {1, 2, 3, 5, 6, 9, 10, 11, 16, 17, -1};
constexpr MessageInfo const* kTrackEventComplexMessages[] = {
nullptr, nullptr, nullptr, &kTaskExecution,
&kLegacyEvent, nullptr, nullptr};
nullptr, nullptr, nullptr, &kTaskExecution, &kLegacyEvent,
nullptr, nullptr, nullptr, nullptr, nullptr};
constexpr MessageInfo kTrackEvent = {kTrackEventIndices,
kTrackEventComplexMessages};
......@@ -138,17 +148,63 @@ constexpr int kStreamingProfilePacketIndices[] = {1, 2, -1};
constexpr MessageInfo kStreamingProfilePacket = {kStreamingProfilePacketIndices,
nullptr};
// EDIT: Contains field numbers: {3, 8, 58} which are not autogenerated.
// Proto Message: HeapGraphObject
constexpr int kHeapGraphObjectIndices[] = {1, 2, 3, 4, 5, -1};
constexpr MessageInfo kHeapGraphObject = {kHeapGraphObjectIndices, nullptr};
// Proto Message: InternedHeapGraphObjectTypes
constexpr int kInternedHeapGraphObjectTypesIndices[] = {1, 2, -1};
constexpr MessageInfo kInternedHeapGraphObjectTypes = {
kInternedHeapGraphObjectTypesIndices, nullptr};
// Proto Message: InternedHeapGraphReferenceFieldNames
constexpr int kInternedHeapGraphReferenceFieldNamesIndices[] = {1, 2, -1};
constexpr MessageInfo kInternedHeapGraphReferenceFieldNames = {
kInternedHeapGraphReferenceFieldNamesIndices, nullptr};
// Proto Message: HeapGraph
constexpr int kHeapGraphIndices[] = {1, 2, 3, 4, 5, 6, -1};
constexpr MessageInfo const* kHeapGraphComplexMessages[] = {
nullptr,
&kHeapGraphObject,
&kInternedHeapGraphObjectTypes,
&kInternedHeapGraphReferenceFieldNames,
nullptr,
nullptr};
constexpr MessageInfo kHeapGraph = {kHeapGraphIndices,
kHeapGraphComplexMessages};
// Proto Message: TrackEventDefaults
constexpr int kTrackEventDefaultsIndices[] = {10, -1};
constexpr MessageInfo kTrackEventDefaults = {kTrackEventDefaultsIndices,
nullptr};
// Proto Message: TracePacketDefaults
constexpr int kTracePacketDefaultsIndices[] = {11, 58, -1};
constexpr MessageInfo const* kTracePacketDefaultsComplexMessages[] = {
&kTrackEventDefaults, nullptr};
constexpr MessageInfo kTracePacketDefaults = {
kTracePacketDefaultsIndices, kTracePacketDefaultsComplexMessages};
// Proto Message: TrackDescriptor
constexpr int kTrackDescriptorIndices[] = {1, 3, 4, -1};
constexpr MessageInfo const* kTrackDescriptorComplexMessages[] = {
nullptr, &kProcessDescriptor, &kThreadDescriptor};
constexpr MessageInfo kTrackDescriptor = {kTrackDescriptorIndices,
kTrackDescriptorComplexMessages};
// Proto Message: TracePacket
constexpr int kTracePacketIndices[] = {3, 8, 10, 11, 12, 35, 36, 41,
42, 43, 44, 51, 54, 58, -1};
// EDIT: Manually whitelisted: 3 (trusted_uid).
constexpr int kTracePacketIndices[] = {3, 6, 8, 10, 11, 12, 13, 35, 36, 41,
42, 43, 44, 51, 54, 56, 58, 59, 60, -1};
constexpr MessageInfo const* kTracePacketComplexMessages[] = {
nullptr,
&kClockSnapshot,
nullptr,
nullptr,
&kTrackEvent,
&kInternedData,
nullptr,
&kTraceStats,
nullptr,
nullptr,
......@@ -157,7 +213,10 @@ constexpr MessageInfo const* kTracePacketComplexMessages[] = {
&kThreadDescriptor,
&kChromeMetadataPacket,
&kStreamingProfilePacket,
nullptr};
&kHeapGraph,
nullptr,
&kTracePacketDefaults,
&kTrackDescriptor};
constexpr MessageInfo kTracePacket = {kTracePacketIndices,
kTracePacketComplexMessages};
......
......@@ -64,7 +64,6 @@ perfetto::TraceConfig GetDefaultPerfettoConfig(
// Perfetto uses clock_gettime for its internal snapshotting, which gets
// blocked by the sandboxed and isn't needed for Chrome regardless.
auto* builtin_data_sources = perfetto_config.mutable_builtin_data_sources();
builtin_data_sources->set_disable_clock_snapshotting(true);
builtin_data_sources->set_disable_trace_config(privacy_filtering_enabled);
builtin_data_sources->set_disable_system_info(privacy_filtering_enabled);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment