From 9eb44c0bed6b9d75e2387e55639734323ec619ee Mon Sep 17 00:00:00 2001 From: Zhou Kang Date: Tue, 15 Aug 2023 08:59:17 +0000 Subject: [PATCH] fix file owner and concurrent operations --- bin/daemon.rs | 30 ++++++++++++++++++++++++++---- src/elf_link_common.c | 13 +++++++++++++ src/elf_link_common.h | 3 +++ src/elf_link_elf.c | 25 ++++++++++++++++++++----- src/elf_write_elf.c | 12 ++++++++++-- src/elf_write_elf.h | 2 +- src/main.c | 12 +++++++++++- tests/bash/Makefile | 9 ++++++--- 8 files changed, 90 insertions(+), 16 deletions(-) diff --git a/bin/daemon.rs b/bin/daemon.rs index 353e2cd..8b24b16 100644 --- a/bin/daemon.rs +++ b/bin/daemon.rs @@ -58,6 +58,18 @@ impl FromStr for RtoConfig { } } +fn move_file(new_path: &String, old_path: &String) -> i32 { + match fs::rename(&new_path, &old_path) { + Ok(_) => {} + Err(e) => { + log::error!("move file failed: {}", e); + return -1; + } + } + + return 0; +} + fn is_symlink(path: &PathBuf) -> bool { let file_type = match fs::symlink_metadata(path) { Ok(metadata) => metadata.file_type(), @@ -168,19 +180,29 @@ fn set_ko_rto_flag(is_set: bool) -> i32 { return ret; } +// 生成rto文件 +// rto文件先生成到临时文件, 然后mv到最终路径, 避免并发操作文件问题 +// sysboost --output=/usr/bin/bash.tmp.rto -static /usr/bin/bash lib1 lib2 fn gen_app_rto(conf: &RtoConfig) -> i32 { if let Some(_p) = &conf.profile_path.clone() { log::error!("Configuration file fail"); return -1; } + let mut args: Vec = Vec::new(); - let arg_mode = format!("-{}", conf.mode); - args.push(arg_mode); + args.push(format!("--output={}.tmp.rto", conf.elf_path)); + args.push(format!("-{}", conf.mode)); args.push(conf.elf_path.to_owned()); for lib in conf.libs.iter() { args.push(lib.split_whitespace().collect()); } - return run_child(SYSBOOST_PATH, &args); + let mut ret = run_child(SYSBOOST_PATH, &args); + if ret != 0 { + return ret; + } + + ret = move_file(&format!("{}.rto", conf.elf_path), &format!("{}.tmp.rto", conf.elf_path)); + return ret; } fn bolt_optimize(conf: &RtoConfig) -> i32 { @@ -433,7 +455,7 @@ fn find_libs(conf: &RtoConfig, elf: &Elf) -> Vec { } } -//TODO: Supports hybrid mode, for example, use bolt to optimize dynamic library and then use static to merge them +// TODO: use bolt to optimize dynamic library and then merge them fn sysboost_core_process(conf: &RtoConfig) -> i32 { match conf.mode.as_str() { "bolt" => { diff --git a/src/elf_link_common.c b/src/elf_link_common.c index 9bbed35..bf14578 100644 --- a/src/elf_link_common.c +++ b/src/elf_link_common.c @@ -41,6 +41,19 @@ #define INDEX_SIX 6 #define INDEX_SEVEN 7 +bool is_empty_path(const char *path) +{ + if (path == NULL) { + return true; + } + + if (path[0] == '\0') { + return true; + } + + return false; +} + static char *special_dynsyms[] = { "__pointer_chk_guard", "_ITM_deregisterTMCloneTable", diff --git a/src/elf_link_common.h b/src/elf_link_common.h index 0547482..911d1ef 100644 --- a/src/elf_link_common.h +++ b/src/elf_link_common.h @@ -291,4 +291,7 @@ void append_symbol_mapping(elf_link_t *elf_link, const char *symbol_name, unsign unsigned long get_new_addr_by_symbol_mapping(elf_link_t *elf_link, char *symbol_name); void init_symbol_mapping(elf_link_t *elf_link); +// common +bool is_empty_path(const char *path); + #endif /* _ELF_LINK_COMMON_H */ diff --git a/src/elf_link_elf.c b/src/elf_link_elf.c index 826da7a..7606962 100644 --- a/src/elf_link_elf.c +++ b/src/elf_link_elf.c @@ -23,7 +23,7 @@ #include #include -#include "si_array.h" +#include #include "elf_check_elf.h" #include "elf_hugepage.h" @@ -139,7 +139,7 @@ int elf_link_set_mode(elf_link_t *elf_link, unsigned int mode) static int elf_link_prepare(elf_link_t *elf_link) { - char name[PATH_MAX] = {0}; + char path[PATH_MAX] = {0}; if (elf_link->link_mode == ELF_LINK_SHARE && elf_link->hook_func) { elf_link->hook_func_ef = elf_link_add_infile(elf_link, RELOCATION_ROOT_DIR "/libhook.so.relocation"); @@ -152,10 +152,25 @@ static int elf_link_prepare(elf_link_t *elf_link) return 0; } - // out file name is app.rto (RunTime Optimization) + // sysboostd 指定ouput临时路径, 避免使用ELF文件的并发操作 + bool is_empty = is_empty_path(elf_link->out_ef.file_name); elf_file_t *main_ef = get_main_ef(elf_link); - (void)snprintf(name, sizeof(name) - 1, "%s.rto", main_ef->file_name); - return create_elf_file(name, &elf_link->out_ef); + if (is_empty) { + // out file name is app.rto (RunTime Optimization) + (void)snprintf(path, sizeof(path) - 1, "%s.rto", main_ef->file_name); + } else { + (void)strncpy(path, elf_link->out_ef.file_name, PATH_MAX - 1); + } + + // mode and owner no change + struct stat sb; + int ret = fstat(main_ef->fd, &sb); + if (ret != 0) { + SI_LOG_ERR("fstat fail, %d\n", errno); + return -1; + } + + return create_elf_file(path, &elf_link->out_ef, sb.st_mode, sb.st_uid, sb.st_gid); } elf_file_t *elf_link_add_infile(elf_link_t *elf_link, char *path) diff --git a/src/elf_write_elf.c b/src/elf_write_elf.c index 5dbe31c..23fbdcf 100644 --- a/src/elf_write_elf.c +++ b/src/elf_write_elf.c @@ -526,11 +526,13 @@ void merge_data_relro_sections(elf_link_t *elf_link) merge_got_section(elf_link); } -int create_elf_file(char *file_name, elf_file_t *elf_file) +int create_elf_file(char *file_name, elf_file_t *elf_file, mode_t mode, uid_t owner, gid_t group) { +// max output file len #define MAX_ELF_FILE_LEN (0x100000 * 512) + size_t len = MAX_ELF_FILE_LEN; - int fd = open(file_name, O_CREAT | O_RDWR, 0744); + int fd = open(file_name, O_CREAT | O_RDWR, mode); size_t ret; if (fd == -1) { @@ -538,6 +540,12 @@ int create_elf_file(char *file_name, elf_file_t *elf_file) return -1; } + if (fchown(fd, owner, group) != 0) { + si_panic("fchown fail %d\n ", errno); + close(fd); + return -1; + } + elf_file->fd = fd; elf_file->file_name = strdup(file_name); lseek(fd, len - 1, SEEK_SET); diff --git a/src/elf_write_elf.h b/src/elf_write_elf.h index 48c05ec..0d9e005 100644 --- a/src/elf_write_elf.h +++ b/src/elf_write_elf.h @@ -47,7 +47,7 @@ Elf64_Shdr *merge_libc_ef_section(elf_link_t *elf_link, const char *sec_name); Elf64_Shdr *merge_template_ef_section(elf_link_t *elf_link, const char *sec_name); Elf64_Shdr *merge_all_ef_section(elf_link_t *elf_link, const char *name); -int create_elf_file(char *file_name, elf_file_t *elf_file); +int create_elf_file(char *file_name, elf_file_t *elf_file, mode_t mode, uid_t owner, gid_t group); void truncate_elf_file(elf_link_t *elf_link); #endif /* _ELF_WRITE_ELF_H */ diff --git a/src/main.c b/src/main.c index 5ff7037..3927b3c 100644 --- a/src/main.c +++ b/src/main.c @@ -39,7 +39,13 @@ int main(int argc, char *argv[]) bool debug = false; enum RtoMode mode = ELF_LINK_SHARE; + if (elf_link == NULL) { + SI_LOG_ERR("no memory\n"); + return -1; + } + static struct option long_options[] = { + {"output", required_argument, NULL, 'o'}, {"debug", no_argument, NULL, 'd'}, {"set", required_argument, NULL, 's'}, {"unset", required_argument, NULL, 'u'}, @@ -49,12 +55,16 @@ int main(int argc, char *argv[]) {ELF_LINK_STATIC_S, no_argument, NULL, 'S'}, {ELF_LINK_STATIC_NOLIBC_S, no_argument, NULL, 'N'}, {ELF_LINK_STATIC_NOLD_S, no_argument, NULL, 'I'}, - {NULL, 0, NULL, 0}}; + {NULL, 0, NULL, 0} + }; int option_index = 0; int c; while ((c = getopt_long(argc, argv, "ds:u:hSNI", long_options, &option_index)) != -1) { switch (c) { + case 'o': + elf_link->out_ef.file_name = optarg; + break; case 'd': debug = true; break; diff --git a/tests/bash/Makefile b/tests/bash/Makefile index 936fb19..99ca693 100644 --- a/tests/bash/Makefile +++ b/tests/bash/Makefile @@ -45,16 +45,18 @@ bash: make -C $(ROOT_DIR) $(SYSBOOSTD) --test-kmod @echo ===rto=== - $(SYSBOOST) $(MODE) $(BASH) $(LIBTINFO) $(LIBC) + $(SYSBOOST) --output=bash.tmp.rto $(MODE) $(BASH) $(LIBTINFO) $(LIBC) + mv -f bash.tmp.rto $(BASH).rto readelf -W -a $(BASH).rto > bash.rto.elf objdump -d $(BASH).rto > bash.rto.asm readelf -W -s $(BASH).rto > bash.rto.dynsym.elf readelf -W -s $(LIBC_R) > libc.so.dynsym.elf @echo ===run=== $(BASH).rto -c "echo 1" + $(BASH).rto -c "printenv LANG" rto: - gdb --args $(SYSBOOST) $(MODE) $(BASH) $(LIBTINFO) $(LIBC) + gdb --args $(SYSBOOST) --output=bash.tmp.rto $(MODE) $(BASH) $(LIBTINFO) $(LIBC) else @@ -72,6 +74,7 @@ bash: objdump -d $(BASH).rto > bash.rto.asm @echo ===run=== $(BASH).rto -c "echo 1" + $(BASH).rto -c "printenv LANG" rto: gdb --args $(SYSBOOST) $(MODE) $(BASH) $(LIBTINFO) @@ -79,7 +82,7 @@ rto: endif run: - gdb --args $(BASH).rto -c "echo 1" + gdb --args $(BASH).rto -c "printenv LANG" env: echo 0 > /proc/sys/kernel/randomize_va_space -- Gitee