1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 use std::fs::File;
6 use std::fs::OpenOptions;
7 use std::io::Write;
8 use std::os::unix::io::AsRawFd;
9 use std::path::Path;
10 use std::sync::Mutex;
11
12 use base::error;
13 use base::RawDescriptor;
14 use once_cell::sync::OnceCell;
15
16 static TRACE_MARKER_FILE: OnceCell<Mutex<File>> = OnceCell::new();
17
18 // Trace marker wrapper macros
19 #[macro_export]
20 macro_rules! trace_event {
21 ($category:ident, $name:expr) => {
22 // TODO(b/259501910) Add support for scoped tracing using a Trace struct
23 None as Option<bool>
24 };
25 }
26
27 #[macro_export]
28 macro_rules! trace_event_begin {
29 // TODO(b/259501910) Trace marker backend doesn't support trace_event_begin yet
30 ($category:ident, $name:expr) => {};
31 }
32
33 #[macro_export]
34 macro_rules! trace_event_end {
35 // TODO(b/259501910) Trace marker backend doesn't support trace_event_end yet
36 ($category:ident) => {};
37 }
38
39 #[macro_export]
40 /// Prints a single non-scoped message without creating a trace context.
41 macro_rules! trace_simple_print {
42 ($($t:tt)*) => {{
43 $crate::trace_simple_print(std::format!($($t)*));
44 }}
45 }
46
47 #[macro_export]
48 /// Macro used to handle fd permanency across jailed devices.
49 /// If we run crosvm without `--disable-sandbox`, we need to add the trace_marker
50 /// file descriptor to the list of file descriptors allowed to be accessed by the
51 /// sandboxed process. We call this macro to add the file descriptor to the list
52 /// of `keep_rds` that the process is allowed to access every time we jail.
53 macro_rules! push_descriptors {
54 ($fd_vec:expr) => {
55 $crate::push_descriptors($fd_vec);
56 };
57 }
58
59 /// Platform-specific implementation of the `push_descriptors!` macro. If the
60 /// trace_marker file has been initialized properly, it adds its file descriptor
61 /// to the list of file descriptors that are allowed to be accessed when the process
62 /// is jailed in the sandbox.
63 ///
64 /// # Arguments
65 ///
66 /// * `keep_rds` - List of file descriptors that will be accessible after jailing
push_descriptors(keep_rds: &mut Vec<RawDescriptor>)67 pub fn push_descriptors(keep_rds: &mut Vec<RawDescriptor>) {
68 if let Some(file) = TRACE_MARKER_FILE.get() {
69 let fd = file.lock().unwrap().as_raw_fd();
70 if !keep_rds.contains(&fd) {
71 keep_rds.push(fd);
72 }
73 }
74 }
75
76 /// Platform-specific implementation of the `trace_simple_print!` macro. If tracing
77 /// is enabled on the system, it writes the given message to the trace_marker file.
78 ///
79 /// # Arguments
80 ///
81 /// * `message` - The message to be written
trace_simple_print(message: String)82 pub fn trace_simple_print(message: String) {
83 // In case tracing is not working or the trace marker file is None we can
84 // just ignore this. We don't need to handle the error here.
85 if let Some(file) = TRACE_MARKER_FILE.get() {
86 // We ignore the error here in case write!() fails, because the trace
87 // marker file would be normally closed by the system unless we are
88 // actively tracing the runtime. It is not an error.
89 write!(file.lock().unwrap(), "{}", message).ok();
90 };
91 }
92
93 /// Initializes the trace_marker backend. It attepts to open the trace_marker
94 /// file and keep a reference that can be shared throughout the lifetime of the
95 /// crosvm process.
96 ///
97 /// If tracefs is not available on the system or the file cannot be opened,
98 /// tracing will not work but the crosvm process will still continue execution
99 /// without tracing.
init()100 pub fn init() {
101 let path = Path::new("/sys/kernel/tracing/trace_marker");
102 let file = match OpenOptions::new().read(false).write(true).open(path) {
103 Ok(f) => f,
104 Err(e) => {
105 error!(
106 "Failed to open {}: {}. Tracing will not work.",
107 path.display(),
108 e
109 );
110 return;
111 }
112 };
113
114 if TRACE_MARKER_FILE.set(Mutex::new(file)).is_err() {
115 error!("Failed to create mutex. Tracing will not work.");
116 }
117 }
118
119 pub struct Trace {}
120
121 impl Trace {
start() -> anyhow::Result<Self>122 pub fn start() -> anyhow::Result<Self> {
123 Ok(Self {})
124 }
125
end(self)126 pub fn end(self) {}
127 }
128
129 impl Drop for Trace {
drop(&mut self)130 fn drop(&mut self) {
131 // TODO(b/259501910) - Add support for dropping traces
132 }
133 }
134