• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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