Implement magiskinit logging in Rust

This commit is contained in:
topjohnwu
2023-05-02 16:49:43 -07:00
parent 0d84f80b3c
commit b136aba1e2
8 changed files with 84 additions and 83 deletions
+1 -50
View File
@@ -117,55 +117,6 @@ static bool check_key_combo() {
return false;
}
static FILE *kmsg;
extern "C" void klog_write(const char *msg, int len) {
fprintf(kmsg, "%.*s", len, msg);
}
static int klog_with_rs(LogLevel level, const char *fmt, va_list ap) {
char buf[4096];
strscpy(buf, "magiskinit: ", sizeof(buf));
int len = vssprintf(buf + 12, sizeof(buf) - 12, fmt, ap) + 12;
log_with_rs(level, rust::Str(buf, len));
return len;
}
void setup_klog() {
// Shut down first 3 fds
int fd;
if (access("/dev/null", W_OK) == 0) {
fd = xopen("/dev/null", O_RDWR | O_CLOEXEC);
} else {
mknod("/null", S_IFCHR | 0666, makedev(1, 3));
fd = xopen("/null", O_RDWR | O_CLOEXEC);
unlink("/null");
}
xdup3(fd, STDIN_FILENO, O_CLOEXEC);
xdup3(fd, STDOUT_FILENO, O_CLOEXEC);
xdup3(fd, STDERR_FILENO, O_CLOEXEC);
if (fd > STDERR_FILENO)
close(fd);
if (access("/dev/kmsg", W_OK) == 0) {
fd = xopen("/dev/kmsg", O_WRONLY | O_CLOEXEC);
} else {
mknod("/kmsg", S_IFCHR | 0666, makedev(1, 11));
fd = xopen("/kmsg", O_WRONLY | O_CLOEXEC);
unlink("/kmsg");
}
kmsg = fdopen(fd, "w");
setbuf(kmsg, nullptr);
rust::setup_klog();
cpp_logger = klog_with_rs;
// Disable kmsg rate limiting
if (FILE *rate = fopen("/proc/sys/kernel/printk_devkmsg", "w")) {
fprintf(rate, "on\n");
fclose(rate);
}
}
void BootConfig::set(const kv_pairs &kv) {
for (const auto &[key, value] : kv) {
if (key == "androidboot.slot_suffix") {
@@ -231,7 +182,7 @@ void load_kernel_info(BootConfig *config) {
mount_list.emplace_back("/sys");
// Log to kernel
setup_klog();
rust::setup_klog();
config->set(parse_cmdline(full_read("/proc/cmdline")));
config->set(parse_bootconfig(full_read("/proc/bootconfig")));
+1
View File
@@ -90,6 +90,7 @@ int main(int argc, char *argv[]) {
BootConfig config{};
if (argc > 1 && argv[1] == "selinux_setup"sv) {
rust::setup_klog();
init = new SecondStageInit(argv);
} else {
// This will also mount /sys and /proc
-2
View File
@@ -28,7 +28,6 @@ int magisk_proxy_main(int argc, char *argv[]);
bool unxz(int fd, const uint8_t *buf, size_t size);
void load_kernel_info(BootConfig *config);
bool check_two_stage();
void setup_klog();
const char *backup_init();
void restore_ramdisk_init();
int dump_preload(const char *path, mode_t mode);
@@ -87,7 +86,6 @@ private:
bool prepare();
public:
SecondStageInit(char *argv[]) : MagiskInit(argv) {
setup_klog();
LOGD("%s\n", __FUNCTION__);
};
+56 -14
View File
@@ -1,27 +1,69 @@
use base::ffi::LogLevel;
use base::*;
use std::fmt::Arguments;
use std::fs;
use std::fs::File;
use std::io::Write;
use std::sync::OnceLock;
extern "C" {
fn klog_write(msg: *const u8, len: i32);
}
use base::ffi::LogLevel;
use base::libc::{
close, makedev, mknod, open, syscall, unlink, SYS_dup3, O_CLOEXEC, O_RDWR, STDERR_FILENO,
STDIN_FILENO, STDOUT_FILENO, S_IFCHR,
};
use base::*;
static KMSG: OnceLock<File> = OnceLock::new();
pub fn setup_klog() {
const PREFIX: &[u8; 12] = b"magiskinit: ";
const PFX_LEN: usize = PREFIX.len();
// Shut down first 3 fds
unsafe {
let mut fd = open(str_ptr!("/dev/null"), O_RDWR | O_CLOEXEC);
if fd < 0 {
mknod(str_ptr!("/null"), S_IFCHR | 0666, makedev(1, 3));
fd = open(str_ptr!("/null"), O_RDWR | O_CLOEXEC);
fs::remove_file("/null").ok();
}
syscall(SYS_dup3, fd, STDIN_FILENO, O_CLOEXEC);
syscall(SYS_dup3, fd, STDOUT_FILENO, O_CLOEXEC);
syscall(SYS_dup3, fd, STDERR_FILENO, O_CLOEXEC);
if fd > STDERR_FILENO {
close(fd);
}
}
if let Ok(kmsg) = File::options().write(true).open("/dev/kmsg") {
KMSG.set(kmsg).ok();
} else {
unsafe {
mknod(str_ptr!("/kmsg"), S_IFCHR | 0666, makedev(1, 11));
KMSG.set(File::options().write(true).open("/kmsg").unwrap())
.ok();
unlink(str_ptr!("/kmsg"));
}
}
// Disable kmsg rate limiting
if let Ok(mut rate) = File::options()
.write(true)
.open("/proc/sys/kernel/printk_devkmsg")
{
writeln!(rate, "on").ok();
}
fn klog_fmt(_: LogLevel, args: Arguments) {
let mut buf: [u8; 4096] = [0; 4096];
buf[..PFX_LEN].copy_from_slice(PREFIX);
let len = fmt_to_buf(&mut buf[PFX_LEN..], args) + PFX_LEN;
unsafe {
klog_write(buf.as_ptr(), len as i32);
if let Some(kmsg) = KMSG.get().as_mut() {
let mut buf: [u8; 4096] = [0; 4096];
let len = fmt_to_buf(&mut buf, format_args!("magiskinit: {}", args));
kmsg.write_all(&buf[..len]).ok();
}
}
fn klog_write_impl(_: LogLevel, msg: &[u8]) {
unsafe {
klog_write(msg.as_ptr(), msg.len() as i32);
if let Some(kmsg) = KMSG.get().as_mut() {
let mut buf: [u8; 4096] = [0; 4096];
let mut len = copy_str(&mut buf, b"magiskinit: ");
len += copy_str(&mut buf[len..], msg);
kmsg.write_all(&buf[..len]).ok();
}
}
+1 -1
View File
@@ -349,7 +349,7 @@ void MagiskInit::patch_rw_root() {
}
int magisk_proxy_main(int argc, char *argv[]) {
setup_klog();
rust::setup_klog();
LOGD("%s\n", __FUNCTION__);
// Mount rootfs as rw to do post-init rootfs patches