Neill Kapron | dd93f85 | 2024-08-07 22:39:57 +0000 | [diff] [blame] | 1 | /* |
| 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 Kapron | cbb87b6 | 2024-10-04 17:18:45 +0000 | [diff] [blame] | 18 | use android_logger::AndroidLogger; |
| 19 | use log::{error, info, Level, LevelFilter, Log, Metadata, Record, SetLoggerError}; |
| 20 | use 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 | |
| 30 | enum 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 | |
| 42 | fn 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. |
| 57 | pub struct BpfKmsgLogger { |
| 58 | log_level: LevelFilter, |
| 59 | tag: String, |
| 60 | kmsg_writer: Arc<Mutex<Box<dyn Write + Send>>>, |
| 61 | a_logger: AndroidLogger, |
| 62 | } |
| 63 | |
| 64 | impl 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 | |
| 92 | impl 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 Kapron | dd93f85 | 2024-08-07 22:39:57 +0000 | [diff] [blame] | 114 | |
Neill Kapron | 01249cb | 2024-08-22 19:09:18 +0000 | [diff] [blame] | 115 | #[cfg(enable_libbpf)] |
| 116 | fn load_libbpf_progs() { |
| 117 | // Libbpf loader functionality here. |
Neill Kapron | cbb87b6 | 2024-10-04 17:18:45 +0000 | [diff] [blame] | 118 | info!("Loading libbpf programs"); |
Neill Kapron | 01249cb | 2024-08-22 19:09:18 +0000 | [diff] [blame] | 119 | } |
| 120 | |
| 121 | #[cfg(not(enable_libbpf))] |
| 122 | fn load_libbpf_progs() { |
| 123 | // Empty stub for feature flag disabled case |
Neill Kapron | cbb87b6 | 2024-10-04 17:18:45 +0000 | [diff] [blame] | 124 | info!("Loading of libbpf programs DISABLED"); |
Neill Kapron | 01249cb | 2024-08-22 19:09:18 +0000 | [diff] [blame] | 125 | } |
| 126 | |
Neill Kapron | dd93f85 | 2024-08-07 22:39:57 +0000 | [diff] [blame] | 127 | fn main() { |
Neill Kapron | cbb87b6 | 2024-10-04 17:18:45 +0000 | [diff] [blame] | 128 | 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 Kapron | 01249cb | 2024-08-22 19:09:18 +0000 | [diff] [blame] | 141 | load_libbpf_progs(); |
Neill Kapron | cbb87b6 | 2024-10-04 17:18:45 +0000 | [diff] [blame] | 142 | info!("Done, loading legacy BPF progs"); |
Neill Kapron | 01249cb | 2024-08-22 19:09:18 +0000 | [diff] [blame] | 143 | |
Neill Kapron | dd93f85 | 2024-08-07 22:39:57 +0000 | [diff] [blame] | 144 | // SAFETY: Linking in the existing legacy bpfloader functionality. |
Maciej Żenczykowski | 7ff8310 | 2024-08-13 20:04:00 +0000 | [diff] [blame] | 145 | // Any of the four following bindgen functions can abort() or exit() |
Neill Kapron | dd93f85 | 2024-08-07 22:39:57 +0000 | [diff] [blame] | 146 | // on failure and execNetBpfLoadDone() execve()'s. |
| 147 | unsafe { |
| 148 | bpf_android_bindgen::initLogging(); |
Maciej Żenczykowski | 7ff8310 | 2024-08-13 20:04:00 +0000 | [diff] [blame] | 149 | bpf_android_bindgen::createBpfFsSubDirectories(); |
Neill Kapron | dd93f85 | 2024-08-07 22:39:57 +0000 | [diff] [blame] | 150 | bpf_android_bindgen::legacyBpfLoader(); |
| 151 | bpf_android_bindgen::execNetBpfLoadDone(); |
| 152 | } |
| 153 | } |