blob: a117f14e54cb02ba0f41e5e7539280519b4c43aa [file] [log] [blame]
Neill Kaprondd93f852024-08-07 22:39:57 +00001/*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//! BPF loader for system and vendor applications
Neill Kaproncbb87b62024-10-04 17:18:45 +000018use android_logger::AndroidLogger;
19use log::{error, info, Level, LevelFilter, Log, Metadata, Record, SetLoggerError};
20use std::{
21 cmp::max,
22 env,
23 fs::File,
24 io::{LineWriter, Write},
25 os::fd::FromRawFd,
26 panic,
27 sync::{Arc, Mutex},
28};
29
30enum KernelLevel {
31 // Commented out unused due to rust complaining...
32 // EMERG = 0,
33 // ALERT = 1,
34 // CRIT = 2,
35 ERR = 3,
36 WARNING = 4,
37 // NOTICE = 5,
38 INFO = 6,
39 DEBUG = 7,
40}
41
42fn level_to_kern_level(level: &Level) -> u8 {
43 let result = match level {
44 Level::Error => KernelLevel::ERR,
45 Level::Warn => KernelLevel::WARNING,
46 Level::Info => KernelLevel::INFO,
47 Level::Debug => KernelLevel::DEBUG,
48 Level::Trace => KernelLevel::DEBUG,
49 };
50 result as u8
51}
52
53/// A logger implementation to enable bpfloader to write to kmsg on error as
54/// bpfloader runs at early init prior to the availability of standard Android
55/// logging. If a crash were to occur, we can disrupt boot, and therefore we
56/// need the ability to access the logs on the serial port.
57pub struct BpfKmsgLogger {
58 log_level: LevelFilter,
59 tag: String,
60 kmsg_writer: Arc<Mutex<Box<dyn Write + Send>>>,
61 a_logger: AndroidLogger,
62}
63
64impl Log for BpfKmsgLogger {
65 fn enabled(&self, metadata: &Metadata) -> bool {
66 metadata.level() <= self.log_level || self.a_logger.enabled(metadata)
67 }
68
69 fn log(&self, record: &Record) {
70 if !self.enabled(record.metadata()) {
71 return;
72 }
73
74 if record.metadata().level() <= self.log_level {
75 let mut writer = self.kmsg_writer.lock().unwrap();
76 write!(
77 writer,
78 "<{}>{}: {}",
79 level_to_kern_level(&record.level()),
80 self.tag,
81 record.args()
82 )
83 .unwrap();
84 let _ = writer.flush();
85 }
86 self.a_logger.log(record);
87 }
88
89 fn flush(&self) {}
90}
91
92impl BpfKmsgLogger {
93 /// Initialize the logger
94 pub fn init(kmsg_file: File) -> Result<(), SetLoggerError> {
95 let alog_level = LevelFilter::Info;
96 let kmsg_level = LevelFilter::Error;
97
98 let log_config = android_logger::Config::default()
99 .with_tag("BpfLoader-rs")
100 .with_max_level(alog_level)
101 .with_log_buffer(android_logger::LogId::Main)
102 .format(|buf, record| writeln!(buf, "{}", record.args()));
103
104 let writer = Box::new(LineWriter::new(kmsg_file)) as Box<dyn Write + Send>;
105 log::set_max_level(max(alog_level, kmsg_level));
106 log::set_boxed_logger(Box::new(BpfKmsgLogger {
107 log_level: kmsg_level,
108 tag: "BpfLoader-rs".to_string(),
109 kmsg_writer: Arc::new(Mutex::new(writer)),
110 a_logger: AndroidLogger::new(log_config),
111 }))
112 }
113}
Neill Kaprondd93f852024-08-07 22:39:57 +0000114
Neill Kapron01249cb2024-08-22 19:09:18 +0000115#[cfg(enable_libbpf)]
116fn load_libbpf_progs() {
117 // Libbpf loader functionality here.
Neill Kaproncbb87b62024-10-04 17:18:45 +0000118 info!("Loading libbpf programs");
Neill Kapron01249cb2024-08-22 19:09:18 +0000119}
120
121#[cfg(not(enable_libbpf))]
122fn load_libbpf_progs() {
123 // Empty stub for feature flag disabled case
Neill Kaproncbb87b62024-10-04 17:18:45 +0000124 info!("Loading of libbpf programs DISABLED");
Neill Kapron01249cb2024-08-22 19:09:18 +0000125}
126
Neill Kaprondd93f852024-08-07 22:39:57 +0000127fn main() {
Neill Kaproncbb87b62024-10-04 17:18:45 +0000128 let kmsg_fd = env::var("ANDROID_FILE__dev_kmsg").unwrap().parse::<i32>().unwrap();
129 // SAFETY: The init script opens this file for us
130 let kmsg_file = unsafe { File::from_raw_fd(kmsg_fd) };
131
132 if let Err(logger) = BpfKmsgLogger::init(kmsg_file) {
133 error!("BpfLoader-rs: log::setlogger failed: {}", logger);
134 }
135
136 // Redirect panic messages to both logcat and serial port
137 panic::set_hook(Box::new(|panic_info| {
138 error!("{}", panic_info);
139 }));
140
Neill Kapron01249cb2024-08-22 19:09:18 +0000141 load_libbpf_progs();
Neill Kaproncbb87b62024-10-04 17:18:45 +0000142 info!("Done, loading legacy BPF progs");
Neill Kapron01249cb2024-08-22 19:09:18 +0000143
Neill Kaprondd93f852024-08-07 22:39:57 +0000144 // SAFETY: Linking in the existing legacy bpfloader functionality.
Maciej Żenczykowski7ff83102024-08-13 20:04:00 +0000145 // Any of the four following bindgen functions can abort() or exit()
Neill Kaprondd93f852024-08-07 22:39:57 +0000146 // on failure and execNetBpfLoadDone() execve()'s.
147 unsafe {
148 bpf_android_bindgen::initLogging();
Maciej Żenczykowski7ff83102024-08-13 20:04:00 +0000149 bpf_android_bindgen::createBpfFsSubDirectories();
Neill Kaprondd93f852024-08-07 22:39:57 +0000150 bpf_android_bindgen::legacyBpfLoader();
151 bpf_android_bindgen::execNetBpfLoadDone();
152 }
153}