underhill_init/
syslog.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! This module implements the an interface to the kernel logger.
5//!
6//! Underhill_init performs no filtering of its logging messages when running in
7//! a confidential VM. This is because it runs before any keys can be accessed
8//! or any guest code is executed, and therefore it can not leak anything
9//! sensitive.
10
11use std::fs::File;
12use std::fs::OpenOptions;
13use std::io;
14use std::io::Write;
15
16pub struct SysLog {
17    kmsg: File,
18}
19
20impl log::Log for SysLog {
21    fn enabled(&self, _metadata: &log::Metadata<'_>) -> bool {
22        true
23    }
24
25    fn log(&self, record: &log::Record<'_>) {
26        // Match the log levels fairly close to the kernel log level semantics.
27        let level = match record.level() {
28            log::Level::Error => kmsg_defs::LOGLEVEL_ERR,
29            log::Level::Warn => kmsg_defs::LOGLEVEL_WARNING,
30            log::Level::Info => kmsg_defs::LOGLEVEL_NOTICE,
31            log::Level::Debug => kmsg_defs::LOGLEVEL_INFO,
32            log::Level::Trace => kmsg_defs::LOGLEVEL_DEBUG,
33        };
34
35        let n = level | (kmsg_defs::UNDERHILL_INIT_KMSG_FACILITY << 3);
36
37        // Construct a local buffer so that the write to /dev/kmsg happens as a
38        // single write, which is necessary to ensure that the message stays
39        // together on one line.
40        let mut buf = Vec::new();
41        writeln!(buf, "<{}>{}: {}", n, record.target(), record.args()).unwrap();
42        let mut kmsg = &self.kmsg;
43        let _ = kmsg.write(&buf);
44    }
45
46    fn flush(&self) {}
47}
48
49impl SysLog {
50    pub fn new() -> io::Result<Self> {
51        Ok(Self {
52            kmsg: OpenOptions::new().write(true).open("/dev/kmsg")?,
53        })
54    }
55}