From 0fd77f2934ac32819b169ac4a57666117123ca9d Mon Sep 17 00:00:00 2001 From: yangpan Date: Wed, 25 Oct 2023 17:29:09 +0800 Subject: [PATCH] Modify the crash detection and recovery functions --- src/sysboost_loader/Makefile | 2 +- src/sysboost_loader/binfmt_rto.h | 1 + src/sysboost_loader/binfmt_rto_604.c | 53 +++- src/sysboost_loader/main.c | 7 +- src/sysboost_loader/netlink_kernel.c | 57 +++++ src/sysboost_loader/netlink_kernel.h | 20 ++ src/sysboostd/Cargo.toml | 2 + src/sysboostd/coredump_monitor.rs | 356 +++++---------------------- src/sysboostd/daemon.rs | 12 +- src/sysboostd/main.rs | 12 +- src/sysboostd/netlink_client.rs | 100 ++++++++ 11 files changed, 312 insertions(+), 310 deletions(-) create mode 100644 src/sysboost_loader/netlink_kernel.c create mode 100644 src/sysboost_loader/netlink_kernel.h create mode 100644 src/sysboostd/netlink_client.rs diff --git a/src/sysboost_loader/Makefile b/src/sysboost_loader/Makefile index f1d9fe9..12c74eb 100644 --- a/src/sysboost_loader/Makefile +++ b/src/sysboost_loader/Makefile @@ -1,7 +1,7 @@ KDIR ?= /lib/modules/$(shell uname -r)/build obj-m := sysboost_loader.o -sysboost_loader-objs := main.o loader_device.o +sysboost_loader-objs := main.o loader_device.o netlink_kernel.o # 5.10内核和6.4内核binfmt_elf.c差异较大, 因此拆分不同文件 ifeq ($(findstring 5.10, $(KDIR)), 5.10) diff --git a/src/sysboost_loader/binfmt_rto.h b/src/sysboost_loader/binfmt_rto.h index 1d06986..b2e6416 100644 --- a/src/sysboost_loader/binfmt_rto.h +++ b/src/sysboost_loader/binfmt_rto.h @@ -5,6 +5,7 @@ #include #include "loader_device.h" +#include "netlink_kernel.h" int rto_populate(struct file *file, unsigned long vaddr, unsigned long offset, unsigned long size, struct loaded_seg *loaded_seg); diff --git a/src/sysboost_loader/binfmt_rto_604.c b/src/sysboost_loader/binfmt_rto_604.c index 1fcfb3e..376ce2a 100644 --- a/src/sysboost_loader/binfmt_rto_604.c +++ b/src/sysboost_loader/binfmt_rto_604.c @@ -105,6 +105,7 @@ static struct global_symbols { proc_symbol(elf_core_extra_data_size); proc_symbol(elf_core_write_extra_phdrs); proc_symbol(elf_core_write_extra_data); + proc_symbol(get_mm_exe_file); } g_sym; #define proc_symbol_char(x) #x @@ -133,7 +134,12 @@ static char *global_symbol_names[] = { proc_symbol_char(dump_user_range), proc_symbol_char(arch_align_stack), proc_symbol_char(task_cputime), - proc_symbol_char(thread_group_cputime) + proc_symbol_char(thread_group_cputime), + proc_symbol_char(elf_core_extra_phdrs), + proc_symbol_char(elf_core_extra_data_size), + proc_symbol_char(elf_core_write_extra_phdrs), + proc_symbol_char(elf_core_write_extra_data), + proc_symbol_char(get_mm_exe_file), }; int init_symbols(void) @@ -2409,6 +2415,21 @@ static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum, shdr4extnum->sh_info = segs; } +static int set_crash_info(struct file *exe_file, struct crash_info *msg) +{ + char *path; + char *buf = kmalloc(PATH_MAX, GFP_KERNEL); + if (!buf) { + pr_info("send binary path to sysboostd failed: kmalloc buf failed.\n"); + return -ENOMEM; + } + path = file_path(exe_file, buf, PATH_MAX); + msg->len = strlen(path); + strncpy(msg->path, path, msg->len); + kfree(buf); + return msg->len; +} + /* * Actual dumper * @@ -2427,7 +2448,37 @@ static int elf_core_dump(struct coredump_params *cprm) struct elf_shdr *shdr4extnum = NULL; Elf_Half e_phnum; elf_addr_t e_shoff; + struct crash_info *msg; + struct file *exe_file; + struct mm_struct *mm; + /* send binary path to sysboostd */ + msg = kmalloc(sizeof(struct crash_info), GFP_KERNEL); + if (!msg) { + pr_info("send binary path to sysboostd failed: kmalloc struct crash_info failed.\n"); + goto core_dump; + } + mm = get_task_mm(current); + if (!mm) { + pr_info("send binary path to sysboostd failed: get task mm failed.\n"); + goto mm_error; + } + exe_file = g_sym.get_mm_exe_file(mm); + mmput(mm); + if (!exe_file) { + pr_info("send binary path to sysboostd failed: get mm exe file failed.\n"); + goto mm_error; + } + if (set_crash_info(exe_file, msg) <= 0) { + pr_info("send binary path to sysboostd failed: set_crash_info failed.\n"); + goto crashinfo_error; + } + send_to_user(msg); +crashinfo_error: + fput(exe_file); +mm_error: + kfree(msg); +core_dump: /* * The number of segs are recored into ELF header as 16bit value. * Please check DEFAULT_MAX_MAP_COUNT definition when you modify here. diff --git a/src/sysboost_loader/main.c b/src/sysboost_loader/main.c index e6a362b..50ac1fd 100644 --- a/src/sysboost_loader/main.c +++ b/src/sysboost_loader/main.c @@ -70,9 +70,13 @@ static int __init sysboost_loader_init(void) ret = loader_device_init(); if (ret) goto error_device; - + ret = nl_trans_init(); + if (ret) + goto error_nl; return 0; +error_nl: + loader_device_exit(); error_device: exit_rto_binfmt(); error_rto: @@ -83,6 +87,7 @@ static void __exit sysboost_loader_exit(void) { loader_device_exit(); exit_rto_binfmt(); + nl_trans_exit(); } module_init(sysboost_loader_init); diff --git a/src/sysboost_loader/netlink_kernel.c b/src/sysboost_loader/netlink_kernel.c new file mode 100644 index 0000000..d6ea21e --- /dev/null +++ b/src/sysboost_loader/netlink_kernel.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include "netlink_kernel.h" + +/* Multicast group, consistent in both kernel prog and user prog. */ +#define GRP_NUMBER 21 + +static struct sock *nl_sk = NULL; + +int send_to_user(struct crash_info *msg) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + int msg_size = sizeof(struct crash_info); + int res; + skb = nlmsg_new(NLMSG_ALIGN(msg_size), GFP_KERNEL); + if (!skb) { + pr_err("netlink_kernel: allocate sk_buff fail.\n"); + return -ENOMEM; + } + nlh = nlmsg_put(skb, 0, 1, NLMSG_DONE, msg_size, 0); + if (!nlh) { + pr_err("netlink_kernel: put nlmsg fail.\n"); + nlmsg_free(skb); + return -EMSGSIZE; + } + memcpy(nlmsg_data(nlh), msg, msg_size); + NETLINK_CB(skb).dst_group = GRP_NUMBER; + res = netlink_broadcast(nl_sk, skb, 0, GRP_NUMBER, GFP_KERNEL); + if (res < 0) + pr_info("nlmsg_multicast() error: %d\n", res); + return res; +} + +int __init nl_trans_init(void) +{ + nl_sk = netlink_kernel_create(&init_net, NETLINK_USERSOCK, NULL); + if (!nl_sk) { + pr_err("netlink_kernel_create failed\n"); + return -ENOMEM; + } + return 0; +} + +void __exit nl_trans_exit(void) +{ + netlink_kernel_release(nl_sk); +} \ No newline at end of file diff --git a/src/sysboost_loader/netlink_kernel.h b/src/sysboost_loader/netlink_kernel.h new file mode 100644 index 0000000..5107974 --- /dev/null +++ b/src/sysboost_loader/netlink_kernel.h @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. + */ + +#ifndef NETLINK_KERNEL_H +#define NETLINK_KERNEL_H + +#define PATH_MAX 4096 +struct crash_info { + int len; + char path[PATH_MAX]; +}; + +int send_to_user(struct crash_info *msg); +int __init nl_trans_init(void); +void __exit nl_trans_exit(void); + + +#endif \ No newline at end of file diff --git a/src/sysboostd/Cargo.toml b/src/sysboostd/Cargo.toml index 9bf0131..c6d43da 100644 --- a/src/sysboostd/Cargo.toml +++ b/src/sysboostd/Cargo.toml @@ -26,3 +26,5 @@ goblin = "0.7" [dev-dependencies.tempfile] version = "3.2.0" +[dependencies.libc] +version = "0.2" \ No newline at end of file diff --git a/src/sysboostd/coredump_monitor.rs b/src/sysboostd/coredump_monitor.rs index eaacb90..7a16209 100644 --- a/src/sysboostd/coredump_monitor.rs +++ b/src/sysboostd/coredump_monitor.rs @@ -9,309 +9,75 @@ // See the Mulan PSL v2 for more details. // Create: 2023-7-13 -use crate::aot::set_app_link_flag; -use crate::daemon; - -use cnproc::PidEvent; -use cnproc::PidMonitor; -use lazy_static::lazy_static; +use std::path::Path; use log::{self}; -use procfs::Process; -use std::collections::HashMap; use std::fs; -use std::path::Path; -use std::sync::Mutex; - -const BASH_RTO_PATH: &str = "/usr/bin/bash.rto"; -const BASH_PATH: &str = "/usr/bin/bash"; -const BASH_TOML_PATH: &str = "/etc/sysboost.d/bash.toml"; -const BASH_LINK_PATH: &str = "/var/lib/sysboost/bash"; - -lazy_static! { - static ref MERGE_FILES: Mutex> = Mutex::new(Vec::new()); - static ref PID_INFOS: Mutex> = Mutex::new(HashMap::new()); -} -fn init_merge_file_list() { - MERGE_FILES.lock().unwrap().push(BASH_PATH.to_string()); -} - -fn process_exec_event(pid: i32) { - // get execute file_path - let process = match Process::new(pid) { - Ok(process) => process, - Err(e) => { - log::error!("Failed to get execte process: {}", e); - return; - } - }; - let file_path = match process.exe() { - Ok(file_path) => file_path, - Err(e) => { - log::error!("Failed to get excute file path: {}", e); - return; - } - }; - if MERGE_FILES.lock().unwrap().contains(&file_path.as_path().display().to_string()) == false { - return; - } - PID_INFOS.lock().unwrap().insert(pid, String::from(file_path.to_str().unwrap())); -} +use crate::netlink_client::{open_netlink, read_event}; +use crate::aot::set_app_link_flag; +use crate::daemon; -fn do_bash_rollback() -> i32 { - // unset flag - let ret = set_app_link_flag(&BASH_PATH.to_string(), false); +const SYSBOOST_DB_PATH: &str = "/var/lib/sysboost/"; +const SYSBOOST_TOML_PATH: &str = "/etc/sysboost.d/"; + +fn do_rollback(path: &String) -> i32 { + let paths: Vec<&str> = path.split(".rto").collect(); + let names: Vec<&str> = paths[0].split("/").collect(); + let binary_name = names[names.len() - 1]; + let file_path = paths[0]; + let rto_path = format!("{}.rto", file_path); + // unset flag + let ret = set_app_link_flag(&file_path.to_string(), false); if ret != 0 { log::error!("Failed to unset link flag for bash!"); return ret; } - // remove link - daemon::db_remove_link(&BASH_LINK_PATH.to_string()); - // remove bash.rto - let bash_rto = Path::new(BASH_RTO_PATH); - match fs::remove_file(&bash_rto) { - Ok(_) => {} - Err(e) => { - log::error!("remove file failed: {}", e); - return -1; - } - } - - // rename bash.toml - let bash_toml = Path::new(BASH_TOML_PATH); - let bash_toml_err = bash_toml.with_extension("toml.err"); - match fs::rename(&bash_toml, &bash_toml_err) { - Ok(_) => {} - Err(e) => { - log::error!("Mv failed: {}", e); - return -1; - } - } - return 0; -} - -fn do_common_rollback(file_path: &String) -> i32 { - let file_exist = Path::new(file_path).exists(); - if !file_exist { - log::error!("{} is not exist!", file_path); - } - match fs::remove_file(&file_path) { - Ok(_) => {} - Err(e) => { - log::error!("remove file failed: {}", e); - return -1; - } - } - return 0; -} - -fn process_coredump_event(pid: i32) { - // get file path by pid - if PID_INFOS.lock().unwrap().contains_key(&pid) == false { - log::info!("{} is not exist in PID_INFOS!", pid); - return; - } - - if let Some(file_path) = PID_INFOS.lock().unwrap().get(&pid) { - log::info!("{} has create a coredump!", file_path); - if MERGE_FILES.lock().unwrap().contains(&file_path) == false { - return; - } - - if file_path == BASH_PATH { - let ret = do_bash_rollback(); - if ret != 0 { - log::error!("rollback bash failed!"); - } - } else { - let ret = do_common_rollback(file_path); - if ret != 0 { - log::error!("rollback {} failed!", file_path); - } - } - } - - PID_INFOS.lock().unwrap().remove(&pid); -} - -fn process_exit_event(pid: i32) { - PID_INFOS.lock().unwrap().remove(&pid); + // remove link + let link_path = format!("{}{}.link", SYSBOOST_DB_PATH, binary_name); + let exist = Path::new(&link_path).exists(); + if exist { + daemon::db_remove_link(&link_path); + } + + // remove bash.rto + let exist = Path::new(&rto_path).exists(); + if exist { + match fs::remove_file(&rto_path) { + Ok(_) => {} + Err(e) => { + log::error!("remove file failed: {}", e); + } + } + } + + // rename .toml + let toml_path = format!("{}{}.toml", SYSBOOST_TOML_PATH, binary_name); + let exist = Path::new(&toml_path).exists(); + if exist { + let toml = Path::new(&toml_path); + let toml_err = toml.with_extension("toml.err"); + match fs::rename(&toml, &toml_err) { + Ok(_) => {} + Err(e) => { + log::error!("Mv toml failed: {}", e); + } + } + } + 0 } pub fn coredump_monitor_loop() { - init_merge_file_list(); - let mut monitor = match PidMonitor::new() { - Ok(p) => p, - Err(e) => panic!("create PidMonitor failed: {}", e), - }; - loop { - match monitor.recv() { - None => {} - Some(event) => match event { - PidEvent::Exec(pid) => process_exec_event(pid), - PidEvent::Coredump(pid) => process_coredump_event(pid), - PidEvent::Exit(pid) => process_exit_event(pid), - _ => {} - }, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::fs::File; - use std::process::Command; - use std::{thread, time}; - - const COREDUMP_TEST_PATH: &str = "tests/test_coredump/test.c"; - const EXCUTE_TEST_PATH: &str = "tests/test_coredump/test"; - - fn add_merge_file(file_path: String) { - MERGE_FILES.lock().unwrap().push(file_path); - } - - #[test] - fn test_coredump_monitor() { - // create excute file - let source_file = Path::new(COREDUMP_TEST_PATH); - let source_file = match fs::canonicalize(source_file) { - Ok(p) => p, - Err(e) => { - panic!("Failed to get realpath: {}", e); - } - }; - let source_file_exist = source_file.exists(); - assert!(source_file_exist == true, "coredump source file does not exist!"); - let excute_file = Path::new(EXCUTE_TEST_PATH); - - let output = Command::new("gcc") - .args(&["-o", &excute_file.to_str().unwrap(), &source_file.to_str().unwrap()]) - .output() - .expect("Faild to execute command!"); - if !output.status.success() { - panic!("Failed to create excute file!"); - } - let real_excute_file = match fs::canonicalize(excute_file) { - Ok(p) => p, - Err(e) => { - panic!("Failed to get realpath: {}", e); - } - }; - - let excute_file_exist = real_excute_file.exists(); - assert!(excute_file_exist == true, "excute file is not exist!"); - - add_merge_file(real_excute_file.to_str().unwrap().to_string()); - // do coredump monitor - let _coredump_monitor = thread::spawn(|| { - coredump_monitor_loop(); - }); - - // excute a coredump action - let excute_command = String::from("./") + excute_file.to_str().unwrap(); - let output = Command::new(&excute_command).output().expect("Failed to excute command!"); - - if output.status.success() { - panic!("Coredump has not created!"); - } - let excute_file_exist = excute_file.exists(); - assert!(excute_file_exist == false, "excute file is not deleted!"); - } - - fn create_or_backup_file(src_path: &str, dest_path: &str) { - let file = Path::new(src_path); - let file_exist = file.exists(); - if file_exist { - match fs::copy(src_path, dest_path) { - Ok(_p) => {} - Err(e) => { - panic!("Failed to rename file: {}", e); - } - } - } else { - match File::create(&src_path) { - Ok(_p) => (), - Err(e) => { - panic!("Failed to create file: {}", e); - } - } - } - } - - fn reset_file(bak_path: &str, src_path: &str) { - let file = Path::new(bak_path); - let file_exist = file.exists(); - if file_exist { - match fs::rename(bak_path, src_path) { - Ok(_p) => {} - Err(e) => { - panic!("Failed to rename file: {}", e); - } - } - } - } - - fn reset_env() { - let bash_link_backup: &str = "/var/lib/sysboost/bash.bak"; - let bash_link_path: &str = "/var/lib/sysboost/bash"; - reset_file(bash_link_backup, bash_link_path); - let bash_toml_backup: &str = "/etc/sysboost.d/bash.tomlbak"; - let bash_toml_path: &str = "/etc/sysboost.d/bash.toml"; - reset_file(bash_toml_backup, bash_toml_path); - let bash_rto_backup: &str = "/usr/bin/bash.rtobak"; - let bash_rto_path: &str = "/usr/bin/bash.rto"; - reset_file(bash_rto_backup, bash_rto_path); - } - - #[test] - fn test_bash_coredump() { - // create link file - let bash_link_path: &str = "/var/lib/sysboost/bash"; - let bash_link_backup: &str = "/var/lib/sysboost/bash.bak"; - create_or_backup_file(bash_link_path, bash_link_backup); - // create toml file - let bash_toml_path: &str = "/etc/sysboost.d/bash.toml"; - let bash_toml_err_path: &str = "/etc/sysboost.d/bash.toml.err"; - let bash_toml_backup: &str = "/etc/sysboost.d/bash.tomlbak"; - create_or_backup_file(bash_toml_path, bash_toml_backup); - // create bash rto file - let bash_rto_path: &str = "/usr/bin/bash.rto"; - let bash_rto_backup: &str = "/usr/bin/bash.rtobak"; - create_or_backup_file(bash_rto_path, bash_rto_backup); - - // start sysboost - let output = Command::new("systemctl").args(&["start", "sysboost.service"]).output().expect("Failed to start sysboost"); - if !output.status.success() { - panic!("Failed to start sysboost service: {}", String::from_utf8_lossy(&output.stderr)); - } - - let sleep_millis = time::Duration::from_millis(1000); - thread::sleep(sleep_millis); - - // create a coredump for bash - let output = Command::new("bash").arg("-c").arg("kill -s SIGSEGV $$").output().expect("Failed to excute command!"); - - if output.status.success() { - panic!("Coredump has not created!"); - } - - let bash_link_file = Path::new(bash_link_path); - let bash_link_exist = bash_link_file.exists(); - assert_eq!(bash_link_exist, false); - - let bash_toml_file = Path::new(bash_toml_path); - let bash_toml_exist = bash_toml_file.exists(); - assert_eq!(bash_toml_exist, false); - - let bash_toml_err_file = Path::new(bash_toml_err_path); - let bash_toml_err_exist = bash_toml_err_file.exists(); - assert_eq!(bash_toml_err_exist, true); - - let bash_rto_file = Path::new(bash_rto_path); - let bash_rto_exist = bash_rto_file.exists(); - assert_eq!(bash_rto_exist, false); - - reset_env(); - } -} + let _sock = open_netlink(); + let sock = match _sock { + Ok(data) => {data}, + Err(e) => panic!("sock error: {}", e), + }; + loop { + let _path = read_event(sock); + let path = match _path{ + Ok(data) => {data}, + Err(e) => panic!("get path error: {}", e), + }; + do_rollback(&path); + } +} \ No newline at end of file diff --git a/src/sysboostd/daemon.rs b/src/sysboostd/daemon.rs index 8d63f48..e95f879 100644 --- a/src/sysboostd/daemon.rs +++ b/src/sysboostd/daemon.rs @@ -110,17 +110,17 @@ fn process_config(path: PathBuf) -> Option { None => return None, }; - let elf = match parse_elf_file(&conf.elf_path) { - Some(elf) => elf, - None => return None, - }; + // let elf = match parse_elf_file(&conf.elf_path) { + // Some(elf) => elf, + // None => return None, + // }; // auto get lib path // In static-nolibc mode, ld and libc need to be deleted after detection. // In share mode, no detection is performed based on libs. if conf.mode == "static" { - let libs = find_libs(&conf, &elf); - conf.libs = libs; + // let libs = find_libs(&conf, &elf); + // conf.libs = libs; } else if conf.mode == "static-nolibc" { //let mut libs = find_libs(&conf, &elf); //libs.retain(|s| !s.contains(LDSO)); diff --git a/src/sysboostd/main.rs b/src/sysboostd/main.rs index e8b0682..69e72a4 100644 --- a/src/sysboostd/main.rs +++ b/src/sysboostd/main.rs @@ -17,6 +17,7 @@ mod coredump_monitor; mod daemon; mod kmod_util; mod lib; +mod netlink_client; use crate::coredump_monitor::coredump_monitor_loop; use crate::daemon::daemon_loop; @@ -104,13 +105,12 @@ fn main() { } // start up coredump monitor - // TODO: 监控性能有问题, 需要重新设计; 先用debug判断包住,避免编译告警 - if is_debug { - let _coredump_monitor_handle = thread::spawn(||{ + let _coredump_monitor_handle = thread::spawn(||{ coredump_monitor_loop(); - }); - } - + }); + // daemon service gen rto ELF with config daemon_loop(); + + _coredump_monitor_handle.join().unwrap() } diff --git a/src/sysboostd/netlink_client.rs b/src/sysboostd/netlink_client.rs new file mode 100644 index 0000000..89535f8 --- /dev/null +++ b/src/sysboostd/netlink_client.rs @@ -0,0 +1,100 @@ +// Copyright (c) 2023 Huawei Technologies Co., Ltd. +// sysboost is licensed under the Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +// PURPOSE. +// See the Mulan PSL v2 for more details. +// Create: 2023-10-26 + +use libc; +use std::io::{Error, Result}; + +pub const GRP_NUMBER: i32 = 21; +pub const PATH_MAX: usize = 4096; + +#[inline] +fn nlmsg_align(len: usize) -> usize { + (len + 3) & !3 +} + +#[inline] +fn nlmsg_hdrlen() -> usize { + nlmsg_align(std::mem::size_of::()) +} + +#[inline] +fn nlmsg_length(len: usize) -> usize { + len + nlmsg_hdrlen() +} + +#[repr(C)] +#[derive(Debug)] +pub struct crash_info { + pub len: libc::c_int, + pub path: [libc::c_char; PATH_MAX] +} + +pub fn open_netlink() -> Result { + let group = GRP_NUMBER; + let sock: i32 = unsafe { + libc::socket( + libc::AF_NETLINK, + libc::SOCK_RAW, + // for some reason bindgen doesn't make this + // a libc::c_int + libc::NETLINK_USERSOCK as i32, + ) + }; + let mut addr: libc::sockaddr_nl = unsafe { std::mem::zeroed::() }; + addr.nl_family = libc::AF_NETLINK as u16; + addr.nl_pid = std::process::id(); + if unsafe { + libc::bind( + sock, + &addr as *const libc::sockaddr_nl as _, + std::mem::size_of_val(&addr) as _, + ) + } < 0 + { + return Err(Error::last_os_error()); + } + if unsafe { + libc::setsockopt( + sock, + libc::SOL_NETLINK, + libc::NETLINK_ADD_MEMBERSHIP as i32, + &group as *const libc::c_int as _, + std::mem::size_of_val(&group) as _, + ) + } < 0 + { + return Err(std::io::Error::last_os_error()); + } + return Ok(sock); +} +pub fn read_event(sock: i32) -> Result { + let mut buffer: [libc::c_char;65536] = [0; 65536]; + let mut nladdr = unsafe { std::mem::zeroed() }; + let mut iov_vec = libc::iovec { + iov_len: std::mem::size_of_val(&buffer) as _, + iov_base: buffer.as_mut_ptr() as _, + }; + let mut msg:libc::msghdr = unsafe { std::mem::zeroed() }; + msg.msg_name = &mut nladdr as *mut libc::sockaddr_nl as _; + msg.msg_namelen = std::mem::size_of_val(&nladdr) as _; + msg.msg_iov = &mut iov_vec as *mut libc::iovec as _; + msg.msg_iovlen = 1; + + let len = unsafe {libc::recvmsg(sock, &mut msg as *mut libc::msghdr as _, 0)}; + if len < 0 { + return Err(Error::last_os_error()); + } + let header = buffer.as_ptr() as *const libc::nlmsghdr; + let msg = (header as usize + nlmsg_length(0)) as *const crash_info; + let slice = unsafe{core::slice::from_raw_parts((*msg).path.as_ptr(), (*msg).len as usize)}; + let data = core::str::from_utf8(slice).unwrap(); + return Ok(data.to_string()); +} \ No newline at end of file -- Gitee