From 5909c8dc3045c63b342b8592a9d59cd8b8ce0558 Mon Sep 17 00:00:00 2001 From: ningyu <405888464@qq.com> Date: Thu, 28 Dec 2023 16:05:41 +0800 Subject: [PATCH] update to 1.2.0-10 Sync patch --- ...ling-multiple-kpatch-may-lead-soft-l.patch | 31 + ...x-upatch-manage-detach-failure-issue.patch | 2203 +++++++++++++++++ ...upatch-remove-upatch-manage-log-file.patch | 70 + 0004-upatch-remove-redudant-log-output.patch | 25 + 0005-upatch-manage-close-dup-fd.patch | 32 + ...check-patch-before-patch-restoration.patch | 252 ++ 0007-upatch-elf-verification.patch | 217 ++ 0008-upatch-check-build-id.patch | 42 + ...xample-for-kernel-module-patch-build.patch | 38 + 0010-daemon-fix-check-build-id-logic.patch | 41 + 0011-upatch-diff-fix-a-nullptr-issue.patch | 40 + 0012-daemon-fix-rust-1.60-compile-issue.patch | 49 + ...upatchd-create-config-dir-at-startup.patch | 106 + ...care-move-files-to-working-directory.patch | 1382 +++++++++++ 0015-upatch-fix-memory-leak.patch | 363 +++ syscare.spec | 28 +- 16 files changed, 4918 insertions(+), 1 deletion(-) create mode 100644 0001-builder-fix-enabling-multiple-kpatch-may-lead-soft-l.patch create mode 100644 0002-upatch-fix-upatch-manage-detach-failure-issue.patch create mode 100644 0003-upatch-remove-upatch-manage-log-file.patch create mode 100644 0004-upatch-remove-redudant-log-output.patch create mode 100644 0005-upatch-manage-close-dup-fd.patch create mode 100644 0006-daemon-check-patch-before-patch-restoration.patch create mode 100644 0007-upatch-elf-verification.patch create mode 100644 0008-upatch-check-build-id.patch create mode 100644 0009-README-add-example-for-kernel-module-patch-build.patch create mode 100644 0010-daemon-fix-check-build-id-logic.patch create mode 100644 0011-upatch-diff-fix-a-nullptr-issue.patch create mode 100644 0012-daemon-fix-rust-1.60-compile-issue.patch create mode 100644 0013-upatchd-create-config-dir-at-startup.patch create mode 100644 0014-syscare-move-files-to-working-directory.patch create mode 100644 0015-upatch-fix-memory-leak.patch diff --git a/0001-builder-fix-enabling-multiple-kpatch-may-lead-soft-l.patch b/0001-builder-fix-enabling-multiple-kpatch-may-lead-soft-l.patch new file mode 100644 index 0000000..babea2f --- /dev/null +++ b/0001-builder-fix-enabling-multiple-kpatch-may-lead-soft-l.patch @@ -0,0 +1,31 @@ +From 92f5334a547ddd7c1a8f787cdde7373965942835 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 8 Dec 2023 17:33:00 +0800 +Subject: [PATCH 01/15] builder: fix 'enabling multiple kpatch may lead + soft-lockup' issue + +Signed-off-by: renoseven +--- + builder/src/patch/kernel_patch/kpatch_builder.rs | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/builder/src/patch/kernel_patch/kpatch_builder.rs b/builder/src/patch/kernel_patch/kpatch_builder.rs +index d0f58b4..69c0cee 100644 +--- a/builder/src/patch/kernel_patch/kpatch_builder.rs ++++ b/builder/src/patch/kernel_patch/kpatch_builder.rs +@@ -212,9 +212,9 @@ impl KernelPatchBuilder { + fn parse_kbuild_cmd_envs(&self, build_root: &Path) -> ExternCommandEnvs { + ExternCommandEnvs::new() + .env("CACHEDIR", build_root) +- .env("NO_PROFILING_CALLS", "1") +- .env("DISABLE_AFTER_LOAD", "1") +- .env("KEEP_JUMP_LABEL", "1") ++ .env("NO_PROFILING_CALLS", "yes") ++ .env("DISABLE_AFTER_LOAD", "yes") ++ .env("KEEP_JUMP_LABEL", "yes") + } + + fn invoke_kpatch_build( +-- +2.33.0 + diff --git a/0002-upatch-fix-upatch-manage-detach-failure-issue.patch b/0002-upatch-fix-upatch-manage-detach-failure-issue.patch new file mode 100644 index 0000000..eecd108 --- /dev/null +++ b/0002-upatch-fix-upatch-manage-detach-failure-issue.patch @@ -0,0 +1,2203 @@ +From 205d718e13214f49c08c60d291e051dd67f1708a Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Tue, 19 Dec 2023 18:01:48 +0800 +Subject: [PATCH 02/15] upatch: fix upatch manage detach failure issue + +Signed-off-by: renoseven +--- + upatch/upatch-manage/arch/aarch64/insn.c | 4 +- + upatch/upatch-manage/arch/aarch64/resolve.c | 16 +- + upatch/upatch-manage/arch/x86_64/resolve.c | 14 +- + .../upatch-manage/ebpf/upatch-manager.bpf.c | 2 +- + upatch/upatch-manage/ebpf/upatch-manager.c | 2 +- + upatch/upatch-manage/upatch-elf.c | 312 +++++++++--------- + upatch/upatch-manage/upatch-elf.h | 2 + + upatch/upatch-manage/upatch-manage.c | 99 +++--- + upatch/upatch-manage/upatch-patch.c | 198 +++++------ + upatch/upatch-manage/upatch-process.c | 300 +++++++++-------- + upatch/upatch-manage/upatch-process.h | 6 +- + upatch/upatch-manage/upatch-ptrace.c | 114 ++++--- + upatch/upatch-manage/upatch-relocation.c | 3 +- + upatch/upatch-manage/upatch-resolve.c | 31 +- + 14 files changed, 545 insertions(+), 558 deletions(-) + +diff --git a/upatch/upatch-manage/arch/aarch64/insn.c b/upatch/upatch-manage/arch/aarch64/insn.c +index 02faa3e..0a0004f 100644 +--- a/upatch/upatch-manage/arch/aarch64/insn.c ++++ b/upatch/upatch-manage/arch/aarch64/insn.c +@@ -110,7 +110,7 @@ u64 extract_insn_imm(s64 sval, int len, int lsb) + imm_mask = (BIT(lsb + len) - 1) >> lsb; + imm = imm & imm_mask; + +- log_debug("upatch: extract imm, X=0x%lx, X[%d:%d]=0x%lx \n", sval, ++ log_debug("upatch: extract imm, X=0x%lx, X[%d:%d]=0x%lx\n", sval, + (len + lsb - 1), lsb, imm); + return imm; + } +@@ -124,7 +124,7 @@ u32 insert_insn_imm(enum aarch64_insn_imm_type imm_type, void *place, u64 imm) + + log_debug( + "upatch: insert imm, P=0x%lx, insn=0x%x, imm_type=%d, imm=0x%lx, " +- "new_insn=0x%x \n", ++ "new_insn=0x%x\n", + (u64)place, insn, imm_type, imm, new_insn); + return new_insn; + } +diff --git a/upatch/upatch-manage/arch/aarch64/resolve.c b/upatch/upatch-manage/arch/aarch64/resolve.c +index a3ea30f..2c9c882 100644 +--- a/upatch/upatch-manage/arch/aarch64/resolve.c ++++ b/upatch/upatch-manage/arch/aarch64/resolve.c +@@ -40,7 +40,7 @@ static unsigned long setup_jmp_table(struct upatch_elf *uelf, + uelf->core_layout.kbase + uelf->jmp_offs; + unsigned int index = uelf->jmp_cur_entry; + if (index >= uelf->jmp_max_entry) { +- log_error("jmp table overflow \n"); ++ log_error("jmp table overflow\n"); + return 0; + } + +@@ -62,7 +62,7 @@ static unsigned long setup_got_table(struct upatch_elf *uelf, + unsigned int index = uelf->jmp_cur_entry; + + if (index >= uelf->jmp_max_entry) { +- log_error("got table overflow \n"); ++ log_error("got table overflow\n"); + return 0; + } + +@@ -84,14 +84,14 @@ unsigned long insert_plt_table(struct upatch_elf *uelf, struct object_file *obj, + + if (upatch_process_mem_read(obj->proc, addr, &jmp_addr, + sizeof(jmp_addr))) { +- log_error("copy address failed \n"); ++ log_error("copy address failed\n"); + goto out; + } + + if (r_type == R_AARCH64_TLSDESC && + upatch_process_mem_read(obj->proc, addr + sizeof(unsigned long), + &tls_addr, sizeof(tls_addr))) { +- log_error("copy address failed \n"); ++ log_error("copy address failed\n"); + goto out; + } + +@@ -100,7 +100,7 @@ unsigned long insert_plt_table(struct upatch_elf *uelf, struct object_file *obj, + else + elf_addr = setup_jmp_table(uelf, jmp_addr, (unsigned long)addr); + +- log_debug("0x%lx: jmp_addr=0x%lx, tls_addr=0x%lx \n", elf_addr, ++ log_debug("0x%lx: jmp_addr=0x%lx, tls_addr=0x%lx\n", elf_addr, + jmp_addr, tls_addr); + + out: +@@ -116,20 +116,20 @@ unsigned long insert_got_table(struct upatch_elf *uelf, struct object_file *obj, + + if (upatch_process_mem_read(obj->proc, addr, &jmp_addr, + sizeof(jmp_addr))) { +- log_error("copy address failed \n"); ++ log_error("copy address failed\n"); + goto out; + } + + if (r_type == R_AARCH64_TLSDESC && + upatch_process_mem_read(obj->proc, addr + sizeof(unsigned long), + &tls_addr, sizeof(tls_addr))) { +- log_error("copy address failed \n"); ++ log_error("copy address failed\n"); + goto out; + } + + elf_addr = setup_got_table(uelf, jmp_addr, tls_addr); + +- log_debug("0x%lx: jmp_addr=0x%lx, tls_addr=0x%lx \n", elf_addr, ++ log_debug("0x%lx: jmp_addr=0x%lx, tls_addr=0x%lx\n", elf_addr, + jmp_addr, tls_addr); + + out: +diff --git a/upatch/upatch-manage/arch/x86_64/resolve.c b/upatch/upatch-manage/arch/x86_64/resolve.c +index 9d3e539..e05d670 100644 +--- a/upatch/upatch-manage/arch/x86_64/resolve.c ++++ b/upatch/upatch-manage/arch/x86_64/resolve.c +@@ -32,7 +32,7 @@ static unsigned long setup_jmp_table(struct upatch_elf *uelf, + uelf->core_layout.kbase + uelf->jmp_offs; + unsigned int index = uelf->jmp_cur_entry; + if (index >= uelf->jmp_max_entry) { +- log_error("jmp table overflow \n"); ++ log_error("jmp table overflow\n"); + return 0; + } + +@@ -57,7 +57,7 @@ static unsigned long setup_got_table(struct upatch_elf *uelf, + uelf->core_layout.kbase + uelf->jmp_offs; + unsigned int index = uelf->jmp_cur_entry; + if (index >= uelf->jmp_max_entry) { +- log_error("got table overflow \n"); ++ log_error("got table overflow\n"); + return 0; + } + +@@ -76,13 +76,13 @@ unsigned long insert_plt_table(struct upatch_elf *uelf, struct object_file *obj, + + if (upatch_process_mem_read(obj->proc, addr, &jmp_addr, + sizeof(jmp_addr))) { +- log_error("copy address failed \n"); ++ log_error("copy address failed\n"); + goto out; + } + + elf_addr = setup_jmp_table(uelf, jmp_addr); + +- log_debug("0x%lx: jmp_addr=0x%lx \n", elf_addr, jmp_addr); ++ log_debug("0x%lx: jmp_addr=0x%lx\n", elf_addr, jmp_addr); + + out: + return elf_addr; +@@ -97,7 +97,7 @@ unsigned long insert_got_table(struct upatch_elf *uelf, struct object_file *obj, + + if (upatch_process_mem_read(obj->proc, addr, &jmp_addr, + sizeof(jmp_addr))) { +- log_error("copy address failed \n"); ++ log_error("copy address failed\n"); + goto out; + } + +@@ -109,13 +109,13 @@ unsigned long insert_got_table(struct upatch_elf *uelf, struct object_file *obj, + if (r_type == R_X86_64_DTPMOD64 && + upatch_process_mem_read(obj->proc, addr + sizeof(unsigned long), + &tls_addr, sizeof(tls_addr))) { +- log_error("copy address failed \n"); ++ log_error("copy address failed\n"); + goto out; + } + + elf_addr = setup_got_table(uelf, jmp_addr, tls_addr); + +- log_debug("0x%lx: jmp_addr=0x%lx \n", elf_addr, jmp_addr); ++ log_debug("0x%lx: jmp_addr=0x%lx\n", elf_addr, jmp_addr); + + out: + return elf_addr; +diff --git a/upatch/upatch-manage/ebpf/upatch-manager.bpf.c b/upatch/upatch-manage/ebpf/upatch-manager.bpf.c +index d91a446..eb9282c 100644 +--- a/upatch/upatch-manage/ebpf/upatch-manager.bpf.c ++++ b/upatch/upatch-manage/ebpf/upatch-manager.bpf.c +@@ -36,6 +36,6 @@ int BPF_KPROBE(install_breakpoint, struct uprobe *uprobe, struct mm_struct *mm, + ep.ino = BPF_CORE_READ(uprobe, inode, i_ino); + ep.pid = BPF_CORE_READ(mm, owner, pid); + bpf_map_update_elem(&elf_process_maps, &ep, &initial_entry, BPF_ANY); +- bpf_printk("ino %lu works for pid %d in addr 0x%lx \n", ep.ino, ep.pid, vaddr); ++ bpf_printk("ino %lu works for pid %d in addr 0x%lx\n", ep.ino, ep.pid, vaddr); + return 0; + } +\ No newline at end of file +diff --git a/upatch/upatch-manage/ebpf/upatch-manager.c b/upatch/upatch-manage/ebpf/upatch-manager.c +index f573d72..0215464 100644 +--- a/upatch/upatch-manage/ebpf/upatch-manager.c ++++ b/upatch/upatch-manage/ebpf/upatch-manager.c +@@ -58,7 +58,7 @@ int main(int argc, char **argv) + skel->progs.install_breakpoint, false, "install_breakpoint"); + if (!skel->links.install_breakpoint) { + err = -errno; +- fprintf(stderr, "Failed to attach kprobe for install_breakpoint: %d \n", err); ++ fprintf(stderr, "Failed to attach kprobe for install_breakpoint: %d\n", err); + goto cleanup; + } + +diff --git a/upatch/upatch-manage/upatch-elf.c b/upatch/upatch-manage/upatch-elf.c +index edcafe0..2bd3175 100644 +--- a/upatch/upatch-manage/upatch-elf.c ++++ b/upatch/upatch-manage/upatch-elf.c +@@ -21,204 +21,190 @@ + + static int read_from_offset(int fd, void **buf, int len, off_t offset) + { +- int ret = -1; +- size_t size; ++ *buf = malloc(len); ++ if (*buf == NULL) { ++ return -errno; ++ } + +- *buf = malloc(len); +- if (*buf == NULL) { +- printf("malloc failed \n"); +- goto out; +- } +- +- size = pread(fd, *buf, len, offset); +- if (size == -1) { +- ret = -errno; +- printf("read file failed - %d \n", -ret); +- goto out; +- } ++ int size = pread(fd, *buf, len, offset); ++ if (size == -1) { ++ return -errno; ++ } + +- ret = 0; +-out: +- return ret; ++ return 0; + } + + static int open_elf(struct elf_info *einfo, const char *name) + { +- int ret = 0, fd = -1, i; +- char *sec_name; +- struct stat st; +- +- // TODO: check ELF +- fd = open(name, O_RDONLY); +- if (fd == -1) +- ERROR("open %s failed with errno %d \n", name, errno); +- +- ret = stat(name, &st); +- if (ret) +- ERROR("get %s stat failed with errno %d \n", name, errno); +- +- ret = read_from_offset(fd, (void **)&einfo->patch_buff, st.st_size, 0); +- if (ret) +- goto out; +- +- einfo->name = name; +- einfo->inode = st.st_ino; +- einfo->patch_size = st.st_size; +- einfo->hdr = (void *)einfo->patch_buff; +- einfo->shdrs = (void *)einfo->hdr + einfo->hdr->e_shoff; +- einfo->shstrtab = (void *)einfo->hdr + +- einfo->shdrs[einfo->hdr->e_shstrndx].sh_offset; +- +- for (i = 0; i < einfo->hdr->e_shnum; ++i) { +- sec_name = einfo->shstrtab + einfo->shdrs[i].sh_name; +- if (streql(sec_name, BUILD_ID_NAME) && +- einfo->shdrs[i].sh_type == SHT_NOTE) { +- einfo->num_build_id = i; +- break; +- } +- } +- +- if (einfo->num_build_id == 0) { +- ret = -EINVAL; +- log_error("no %s found \n", BUILD_ID_NAME); +- goto out; +- } ++ int ret = 0, fd = -1, i; ++ char *sec_name; ++ struct stat st; ++ ++ fd = open(name, O_RDONLY); ++ if (fd == -1) { ++ ret = -errno; ++ log_error("Failed to open file '%s', ret=%d\n", name, ret); ++ goto out; ++ } ++ ++ ret = stat(name, &st); ++ if (ret != 0) { ++ ret = -errno; ++ log_error("Failed to stat file '%s', ret=%d\n", name, ret); ++ goto out; ++ } ++ ++ ret = read_from_offset(fd, (void **)&einfo->patch_buff, st.st_size, 0); ++ if (ret != 0) { ++ log_error("Failed to read file '%s', ret=%d\n", name, ret); ++ goto out; ++ } ++ ++ einfo->name = name; ++ einfo->inode = st.st_ino; ++ einfo->patch_size = st.st_size; ++ einfo->hdr = (void *)einfo->patch_buff; ++ einfo->shdrs = (void *)einfo->hdr + einfo->hdr->e_shoff; ++ einfo->shstrtab = (void *)einfo->hdr + einfo->shdrs[einfo->hdr->e_shstrndx].sh_offset; ++ ++ for (i = 0; i < einfo->hdr->e_shnum; ++i) { ++ sec_name = einfo->shstrtab + einfo->shdrs[i].sh_name; ++ if (streql(sec_name, BUILD_ID_NAME) && einfo->shdrs[i].sh_type == SHT_NOTE) { ++ einfo->num_build_id = i; ++ break; ++ } ++ } ++ ++ if (einfo->num_build_id == 0) { ++ ret = -EINVAL; ++ log_error("Cannot find section '%s'\n", BUILD_ID_NAME); ++ goto out; ++ } ++ ++ ret = 0; + +- log_error("no %ld found \n", einfo->inode); +- +- ret = 0; + out: +- if (fd != -1) +- close(fd); +- return ret; ++ if (fd > 0) { ++ close(fd); ++ } ++ return ret; + } + + int upatch_init(struct upatch_elf *uelf, const char *name) + { +- int ret = 0, i; +- char *sec_name; +- +- memset(uelf, 0, sizeof(struct upatch_elf)); +- +- ret = open_elf(&uelf->info, name); +- if (ret) +- goto out; +- +- for (i = 1; i < uelf->info.hdr->e_shnum; ++i) { +- sec_name = uelf->info.shstrtab + uelf->info.shdrs[i].sh_name; +- if (uelf->info.shdrs[i].sh_type == SHT_SYMTAB) { +- uelf->num_syms = +- uelf->info.shdrs[i].sh_size / sizeof(GElf_Sym); +- uelf->index.sym = i; +- uelf->index.str = uelf->info.shdrs[i].sh_link; +- uelf->strtab = +- (char *)uelf->info.hdr + +- uelf->info.shdrs[uelf->info.shdrs[i].sh_link] +- .sh_offset; +- } else if (streql(sec_name, UPATCH_FUNC_NAME)) { +- uelf->index.upatch_funcs = i; +- } +- } +- +- ret = 0; +- +-out: +- return ret; ++ int ret = open_elf(&uelf->info, name); ++ if (ret) { ++ log_error("Failed to open elf '%s', ret=%d\n", name, ret); ++ return ret; ++ } ++ ++ for (int i = 1; i < uelf->info.hdr->e_shnum; ++i) { ++ char *sec_name = uelf->info.shstrtab + uelf->info.shdrs[i].sh_name; ++ if (uelf->info.shdrs[i].sh_type == SHT_SYMTAB) { ++ uelf->num_syms = uelf->info.shdrs[i].sh_size / sizeof(GElf_Sym); ++ uelf->index.sym = i; ++ uelf->index.str = uelf->info.shdrs[i].sh_link; ++ uelf->strtab = (char *)uelf->info.hdr + ++ uelf->info.shdrs[uelf->info.shdrs[i].sh_link].sh_offset; ++ } else if (streql(sec_name, UPATCH_FUNC_NAME)) { ++ uelf->index.upatch_funcs = i; ++ } ++ } ++ ++ return 0; + } + + int binary_init(struct running_elf *relf, const char *name) + { +- int ret = 0, i; +- char *sec_name; +- +- memset(relf, 0, sizeof(struct running_elf)); +- +- ret = open_elf(&relf->info, name); +- if (ret) +- goto out; +- +- relf->phdrs = (void *)relf->info.hdr + relf->info.hdr->e_phoff; +- +- for (i = 1; i < relf->info.hdr->e_shnum; i++) { +- sec_name = relf->info.shstrtab + relf->info.shdrs[i].sh_name; +- if (relf->info.shdrs[i].sh_type == SHT_SYMTAB) { +- relf->num_syms = +- relf->info.shdrs[i].sh_size / sizeof(GElf_Sym); +- relf->index.sym = i; +- relf->index.str = relf->info.shdrs[i].sh_link; +- relf->strtab = +- (char *)relf->info.hdr + +- relf->info.shdrs[relf->info.shdrs[i].sh_link] +- .sh_offset; +- } else if (relf->info.shdrs[i].sh_type == SHT_DYNSYM) { +- relf->index.dynsym = i; +- relf->index.dynstr = relf->info.shdrs[i].sh_link; +- relf->dynstrtab = +- (char *)relf->info.hdr + +- relf->info.shdrs[relf->info.shdrs[i].sh_link] +- .sh_offset; +- log_debug("found dynsym with %d \n", i); +- } else if (relf->info.shdrs[i].sh_type == SHT_DYNAMIC) { +- /* Currently, we don't utilize it */ +- } else if (streql(sec_name, PLT_RELA_NAME) && +- relf->info.shdrs[i].sh_type == SHT_RELA) { +- relf->index.rela_plt = i; +- log_debug("found %s with %d \n", PLT_RELA_NAME, i); +- } else if (streql(sec_name, GOT_RELA_NAME) && +- relf->info.shdrs[i].sh_type == SHT_RELA) { +- relf->index.rela_dyn = i; +- log_debug("found %s with %d \n", GOT_RELA_NAME, i); +- } +- } +- +- for (i = 0; i < relf->info.hdr->e_phnum; i++) { +- if (relf->phdrs[i].p_type == PT_TLS) { +- relf->tls_size = relf->phdrs[i].p_memsz; +- relf->tls_align = relf->phdrs[i].p_align; +- log_debug("found TLS size = %ld, memsz = %ld \n", +- relf->tls_size, relf->tls_align); +- break; +- } +- } +- +- ret = 0; +- +-out: +- return ret; ++ int ret = open_elf(&relf->info, name); ++ if (ret) { ++ log_error("Failed to open elf '%s', ret=%d\n", name, ret); ++ return ret; ++ } ++ ++ for (int i = 1; i < relf->info.hdr->e_shnum; i++) { ++ char *sec_name = relf->info.shstrtab + relf->info.shdrs[i].sh_name; ++ if (relf->info.shdrs[i].sh_type == SHT_SYMTAB) { ++ log_debug("Found section '%s', idx=%d\n", SYMTAB_NAME, i); ++ relf->num_syms = relf->info.shdrs[i].sh_size / sizeof(GElf_Sym); ++ relf->index.sym = i; ++ relf->index.str = relf->info.shdrs[i].sh_link; ++ relf->strtab = (char *)relf->info.hdr + ++ relf->info.shdrs[relf->info.shdrs[i].sh_link].sh_offset; ++ } else if (relf->info.shdrs[i].sh_type == SHT_DYNSYM) { ++ log_debug("Found section '%s', idx=%d\n", DYNSYM_NAME, i); ++ relf->index.dynsym = i; ++ relf->index.dynstr = relf->info.shdrs[i].sh_link; ++ relf->dynstrtab = (char *)relf->info.hdr + ++ relf->info.shdrs[relf->info.shdrs[i].sh_link].sh_offset; ++ } else if (relf->info.shdrs[i].sh_type == SHT_DYNAMIC) { ++ /* Currently, we don't utilize it */ ++ } else if (streql(sec_name, PLT_RELA_NAME) && ++ relf->info.shdrs[i].sh_type == SHT_RELA) { ++ log_debug("Found section '%s', idx=%d\n", PLT_RELA_NAME, i); ++ relf->index.rela_plt = i; ++ } else if (streql(sec_name, GOT_RELA_NAME) && ++ relf->info.shdrs[i].sh_type == SHT_RELA) { ++ log_debug("Found section '%s' idx=%d\n", GOT_RELA_NAME, i); ++ relf->index.rela_dyn = i; ++ } ++ } ++ ++ relf->phdrs = (void *)relf->info.hdr + relf->info.hdr->e_phoff; ++ for (int i = 0; i < relf->info.hdr->e_phnum; i++) { ++ if (relf->phdrs[i].p_type == PT_TLS) { ++ relf->tls_size = relf->phdrs[i].p_memsz; ++ relf->tls_align = relf->phdrs[i].p_align; ++ log_debug("Found TLS size = %ld, align = %ld\n", relf->tls_size, relf->tls_align); ++ break; ++ } ++ } ++ ++ return 0; + } + + bool check_build_id(struct elf_info *uelf, struct elf_info *relf) + { +- return uelf->shdrs[uelf->num_build_id].sh_size == +- relf->shdrs[relf->num_build_id].sh_size && +- !memcmp(uelf->hdr + uelf->shdrs[uelf->num_build_id].sh_offset, +- relf->hdr + relf->shdrs[relf->num_build_id].sh_offset, +- uelf->shdrs[uelf->num_build_id].sh_size); ++ if (uelf->shdrs[uelf->num_build_id].sh_size != relf->shdrs[relf->num_build_id].sh_size) { ++ return false; ++ } ++ ++ void* uelf_build_id = (void *)uelf->hdr + uelf->shdrs[uelf->num_build_id].sh_offset; ++ void* relf_build_id = (void *)relf->hdr + relf->shdrs[relf->num_build_id].sh_offset; ++ size_t build_id_len = uelf->shdrs[uelf->num_build_id].sh_size; ++ ++ if (memcmp(uelf_build_id, relf_build_id, build_id_len) != 0) { ++ return false; ++ } ++ return true; + } + + void binary_close(struct running_elf *relf) + { +- // TODO: free relf +- if (relf->info.patch_buff) +- free(relf->info.patch_buff); ++ // TODO: free relf ++ if (relf->info.patch_buff) { ++ free(relf->info.patch_buff); ++ } + } + + void upatch_close(struct upatch_elf *uelf) + { +- // TODO: free uelf +- if (uelf->info.patch_buff) +- free(uelf->info.patch_buff); ++ // TODO: free uelf ++ if (uelf->info.patch_buff) { ++ free(uelf->info.patch_buff); ++ } + +- if (uelf->core_layout.kbase) +- free(uelf->core_layout.kbase); ++ if (uelf->core_layout.kbase) { ++ free(uelf->core_layout.kbase); ++ } + } + + bool is_upatch_section(const char *name) + { +- return !strncmp(name, ".upatch.", strlen(".upatch.")); ++ return !strncmp(name, ".upatch.", strlen(".upatch.")); + } + + bool is_note_section(GElf_Word type) + { +- return type == SHT_NOTE; ++ return type == SHT_NOTE; + } +diff --git a/upatch/upatch-manage/upatch-elf.h b/upatch/upatch-manage/upatch-elf.h +index 438b573..b4d9b28 100644 +--- a/upatch/upatch-manage/upatch-elf.h ++++ b/upatch/upatch-manage/upatch-elf.h +@@ -17,6 +17,8 @@ + + #include "list.h" + ++#define SYMTAB_NAME ".symtab" ++#define DYNSYM_NAME ".dynsym" + #define GOT_RELA_NAME ".rela.dyn" + #define PLT_RELA_NAME ".rela.plt" + #define BUILD_ID_NAME ".note.gnu.build-id" +diff --git a/upatch/upatch-manage/upatch-manage.c b/upatch/upatch-manage/upatch-manage.c +index f827794..b36ff0d 100644 +--- a/upatch/upatch-manage/upatch-manage.c ++++ b/upatch/upatch-manage/upatch-manage.c +@@ -124,55 +124,32 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) + + static struct argp argp = { options, parse_opt, args_doc, program_doc }; + +-static void show_program_info(struct arguments *arguments) +-{ +- log_debug("pid: %d\n", arguments->pid); +- log_debug("upatch object: %s\n", arguments->upatch); +- log_debug("binary object: %s\n", arguments->binary); +- log_debug("uuid object: %s\n", arguments->uuid); +-} ++FILE *upatch_manage_log_fd = NULL; + + int patch_upatch(const char *uuid, const char *binary_path, const char *upatch_path, int pid) + { +- int ret; + struct upatch_elf uelf; + struct running_elf relf; + memset(&uelf, 0, sizeof(struct upatch_elf)); + memset(&relf, 0, sizeof(struct running_elf)); + +- ret = upatch_init(&uelf, upatch_path); +- if (ret) { +- log_error("upatch_init failed %d \n", ret); +- goto out; +- } +- +- /*ret = binary_init(&relf, binary_path); ++ int ret = upatch_init(&uelf, upatch_path); + if (ret) { +- log_error("binary_init failed %d \n", ret); ++ log_error("Failed to initialize patch, ret=%d\n", ret); + goto out; + } + +- uelf.relf = &relf; +-*/ +- // ret = check_build_id(&uelf.info, &relf.info); +- // if (ret) { +- // log_error("check build id failed %d \n", ret); +- // goto out; +- // } +- + ret = process_patch(pid, &uelf, &relf, uuid, binary_path); + if (ret) { +- log_error("process patch failed %d \n", ret); ++ log_error("Failed to patch process, pid=%d ret=%d\n", pid, ret); + goto out; + } ++ log_normal("SUCCESS\n"); + + out: + upatch_close(&uelf); + binary_close(&relf); +- if (ret) +- log_normal("FAIL\n"); +- else +- log_normal("SUCCESS\n"); ++ + return ret; + } + +@@ -182,66 +159,64 @@ int unpatch_upatch(const char *uuid, const char *binary_path, const char *upatch + + ret = process_unpatch(pid, uuid); + if (ret) { +- log_error("process patch failed %d \n", ret); +- goto out; ++ log_error("Failed to unpatch process, pid=%d, ret=%d\n", pid, ret); ++ return ret; + } ++ log_normal("SUCCESS\n"); + +-out: +- if (ret) +- log_normal("FAIL\n"); +- else +- log_normal("SUCCESS\n"); +- return ret; ++ return 0; + } + + int info_upatch(const char *binary_path, const char *upatch_path, int pid) + { +- int ret = 0; +- +- ret = process_info(pid); +- if (ret) { +- log_error("process patch failed %d \n", ret); +- goto out; ++ int ret = process_info(pid); ++ if (ret != 0) { ++ log_error("Failed to get patch info, pid=%d, ret=%d\n", pid, ret); ++ return ret; + } ++ log_normal("SUCCESS\n"); + +-out: +- return ret; ++ return 0; + } + +-FILE *upatch_manage_log_fd = NULL; + int main(int argc, char *argv[]) + { +- struct arguments arguments; ++ struct arguments args; + int ret; +- upatch_manage_log_fd = fopen("/tmp/upatch-manage.log", "w"); + +- if (upatch_manage_log_fd < 0) ++ upatch_manage_log_fd = fopen("/tmp/upatch-manage.log", "w"); ++ if (upatch_manage_log_fd < 0) { + return -1; +- memset(&arguments, 0, sizeof(arguments)); +- argp_parse(&argp, argc, argv, 0, NULL, &arguments); +- if (arguments.verbose) ++ } ++ ++ memset(&args, 0, sizeof(struct arguments)); ++ argp_parse(&argp, argc, argv, 0, NULL, &args); ++ if (args.verbose) { + loglevel = DEBUG; ++ } ++ ++ logprefix = basename(args.upatch); ++ log_debug("PID: %d\n", args.pid); ++ log_debug("UUID: %s\n", args.uuid); ++ log_debug("Patch: %s\n", args.upatch); ++ log_debug("Binary: %s\n", args.binary); + +- logprefix = basename(arguments.upatch); +- show_program_info(&arguments); +- switch (arguments.cmd) { ++ switch (args.cmd) { + case PATCH: +- ret = patch_upatch(arguments.uuid, arguments.binary, arguments.upatch, +- arguments.pid); ++ ret = patch_upatch(args.uuid, args.binary, args.upatch, args.pid); + break; + case UNPATCH: +- ret = unpatch_upatch(arguments.uuid, arguments.binary, arguments.upatch, +- arguments.pid); ++ ret = unpatch_upatch(args.uuid, args.binary, args.upatch, args.pid); + break; + case INFO: +- ret = info_upatch(arguments.binary, arguments.upatch, +- arguments.pid); ++ ret = info_upatch(args.binary, args.upatch, args.pid); + break; + default: +- ERROR("unknown command"); ++ ERROR("Unknown command"); + ret = EINVAL; + break; + } ++ + fclose(upatch_manage_log_fd); + return abs(ret); + } +diff --git a/upatch/upatch-manage/upatch-patch.c b/upatch/upatch-manage/upatch-patch.c +index bdb9631..762641c 100644 +--- a/upatch/upatch-manage/upatch-patch.c ++++ b/upatch/upatch-manage/upatch-patch.c +@@ -18,6 +18,7 @@ + #include "log.h" + #include "upatch-common.h" + #include "upatch-patch.h" ++#include "upatch-process.h" + #include "upatch-ptrace.h" + #include "upatch-relocation.h" + #include "upatch-resolve.h" +@@ -101,7 +102,7 @@ static int rewrite_section_headers(struct upatch_elf *uelf) + /* Mark all sections sh_addr with their address in the + temporary image. */ + shdr->sh_addr = (size_t)uelf->info.hdr + shdr->sh_offset; +- log_debug("section %s at 0x%lx \n", ++ log_debug("section %s at 0x%lx\n", + uelf->info.shstrtab + shdr->sh_name, shdr->sh_addr); + } + +@@ -165,7 +166,7 @@ static void layout_sections(struct upatch_elf *uelf) + for (i = 0; i < uelf->info.hdr->e_shnum; i++) + uelf->info.shdrs[i].sh_entsize = ~0UL; + +- log_debug("upatch section allocation order: \n"); ++ log_debug("upatch section allocation order:\n"); + for (m = 0; m < ARRAY_SIZE(masks); ++m) { + for (i = 0; i < uelf->info.hdr->e_shnum; ++i) { + GElf_Shdr *s = &uelf->info.shdrs[i]; +@@ -279,18 +280,17 @@ static void *upatch_alloc(struct object_file *obj, size_t sz) + MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, + 0); + if (addr == 0) { +- log_error("remote alloc memory for patch failed\n"); ++ log_error("Failed to alloc remote patch memory\n"); + return NULL; + } + +- log_debug("allocated 0x%lx bytes at 0x%lx for '%s' patch\n", sz, addr, +- obj->name); ++ log_debug("Allocated 0x%lx bytes at 0x%lx of '%s'\n", sz, addr, obj->name); + + // log_debug("Marking this space as busy\n"); + ret = vm_hole_split(hole, addr, addr + sz); + if (ret) { + // TODO: clear +- log_error("vm_hole_split failed\n"); ++ log_error("Failed to split vm hole\n"); + return NULL; + } + +@@ -300,10 +300,9 @@ static void *upatch_alloc(struct object_file *obj, size_t sz) + static void __upatch_memfree(struct object_file *obj, void *base, + unsigned int size) + { +- log_debug("munmap upatch memory at: %p\n", base); +- if (upatch_munmap_remote(proc2pctx(obj->proc), (unsigned long)base, +- size)) { +- log_error("Failed to munmap upatch memory at: %p\n", base); ++ log_debug("Free patch memory %p\n", base); ++ if (upatch_munmap_remote(proc2pctx(obj->proc), (unsigned long)base, size)) { ++ log_error("Failed to free patch memory %p\n", base); + } + } + +@@ -313,8 +312,7 @@ static int __alloc_memory(struct object_file *obj_file, + /* Do the allocs. */ + layout->base = upatch_alloc(obj_file, layout->size); + if (!layout->base) { +- log_error("alloc upatch core_layout memory failed: %p \n", +- layout->base); ++ log_error("Failed to alloc patch core layout %p\n", layout->base); + return -ENOMEM; + } + +@@ -336,25 +334,28 @@ static int alloc_memory(struct upatch_elf *uelf, struct object_file *obj) + /* Do the allocs. */ + ret = __alloc_memory(obj, &uelf->core_layout); + if (ret) { +- log_error("alloc upatch module memory failed: %d \n", ret); ++ log_error("Failed to alloc patch memory, ret=%d\n", ret); + return ret; + } + + /* Transfer each section which specifies SHF_ALLOC */ +- log_debug("final section addresses:\n"); ++ log_debug("Final section addresses:\n"); + for (i = 0; i < uelf->info.hdr->e_shnum; i++) { + void *kdest; + void *dest; + GElf_Shdr *shdr = &uelf->info.shdrs[i]; + +- if (!(shdr->sh_flags & SHF_ALLOC)) ++ if (!(shdr->sh_flags & SHF_ALLOC)) { + continue; ++ } + + kdest = uelf->core_layout.kbase + shdr->sh_entsize; + dest = uelf->core_layout.base + shdr->sh_entsize; + +- if (shdr->sh_type != SHT_NOBITS) ++ if (shdr->sh_type != SHT_NOBITS) { + memcpy(kdest, (void *)shdr->sh_addr, shdr->sh_size); ++ } ++ + shdr->sh_addr = (unsigned long)kdest; + /* overuse this attr to record user address */ + shdr->sh_addralign = (unsigned long)dest; +@@ -369,7 +370,7 @@ static int post_memory(struct upatch_elf *uelf, struct object_file *obj) + { + int ret = 0; + +- log_debug("post kbase %lx(%x) to base %lx\n", ++ log_debug("Post kbase %lx(%x) to base %lx\n", + (unsigned long)uelf->core_layout.kbase, + uelf->core_layout.size, + (unsigned long)uelf->core_layout.base); +@@ -377,7 +378,7 @@ static int post_memory(struct upatch_elf *uelf, struct object_file *obj) + (unsigned long)uelf->core_layout.base, + uelf->core_layout.size); + if (ret) { +- log_error("can't move kbase to base - %d\n", ret); ++ log_error("Failed to move kbase to base, ret=%d\n", ret); + goto out; + } + +@@ -404,7 +405,7 @@ static int complete_info(struct upatch_elf *uelf, struct object_file *obj, const + sizeof(struct upatch_patch_func); + memcpy(uinfo->id, uuid, strlen(uuid)); + +- log_debug("change insn:\n"); ++ log_debug("Changed insn:\n"); + for (i = 0; i < uinfo->changed_func_num; ++i) { + struct upatch_info_func *upatch_func = + (void *)uelf->core_layout.kbase + +@@ -440,26 +441,21 @@ static int unapply_patch(struct object_file *obj, + struct upatch_info_func *funcs, + unsigned int changed_func_num) + { +- int ret = 0, i; +- +- log_debug("change insn:\n"); +- for (i = 0; i < changed_func_num; ++i) { ++ log_debug("Changed insn:\n"); ++ for (int i = 0; i < changed_func_num; ++i) { + log_debug("\t0x%lx(0x%lx -> 0x%lx)\n", funcs[i].old_addr, + funcs[i].new_insn, funcs[i].old_insn[0]); + +- ret = upatch_process_mem_write(obj->proc, &funcs[i].old_insn, +- (unsigned long)funcs[i].old_addr, +- get_origin_insn_len()); ++ int ret = upatch_process_mem_write(obj->proc, &funcs[i].old_insn, ++ (unsigned long)funcs[i].old_addr, get_origin_insn_len()); + + if (ret) { +- log_error("can't write old insn at 0x%lx - %d\n", +- funcs[i].old_addr, ret); +- goto out; ++ log_error("Failed to write old insn at 0x%lx, ret=%d\n", ++ funcs[i].old_addr, ret); ++ return ret; + } + } +- +-out: +- return ret; ++ return 0; + } + + static int apply_patch(struct upatch_elf *uelf, struct object_file *obj) +@@ -475,40 +471,37 @@ static int apply_patch(struct upatch_elf *uelf, struct object_file *obj) + sizeof(struct upatch_info) + + i * sizeof(struct upatch_info_func); + +- // write jumper insn to first 8bytes +- ret = upatch_process_mem_write( +- obj->proc, &upatch_func->new_insn, +- (unsigned long)upatch_func->old_addr, +- get_upatch_insn_len()); ++ // write jumper insn to first 8 bytes ++ ret = upatch_process_mem_write(obj->proc, &upatch_func->new_insn, ++ (unsigned long)upatch_func->old_addr, get_upatch_insn_len()); + if (ret) { + log_error( +- "can't ptrace upatch func at 0x%lx(0x%lx) - %d\n", ++ "Failed to ptrace upatch func at 0x%lx(0x%lx) - %d\n", + upatch_func->old_addr, upatch_func->new_insn, + ret); + goto out; + } +- // write 64bit new addr to second 8bytes +- ret = upatch_process_mem_write( +- obj->proc, &upatch_func->new_addr, ++ // write 64bit new addr to second 8 bytes ++ ret = upatch_process_mem_write(obj->proc, &upatch_func->new_addr, + (unsigned long)upatch_func->old_addr + get_upatch_insn_len(), + get_upatch_addr_len()); + if (ret) { +- log_error( +- "can't ptrace upatch func at 0x%lx(0x%lx) - %d\n", +- upatch_func->old_addr + get_upatch_insn_len(), ++ log_error( ++ "Failed to ptrace upatch func at 0x%lx(0x%lx) - %d\n", ++ upatch_func->old_addr + get_upatch_insn_len(), + upatch_func->new_addr, +- ret); +- goto out; +- } ++ ret); ++ goto out; ++ } + } + + out: + if (ret) { + unapply_patch(obj, +- (void *)uelf->core_layout.kbase + +- uelf->core_layout.info_size + +- sizeof(struct upatch_info), +- i); ++ (void *)uelf->core_layout.kbase + ++ uelf->core_layout.info_size + ++ sizeof(struct upatch_info), ++ i); + } + return ret; + } +@@ -523,8 +516,7 @@ static int upatch_mprotect(struct upatch_elf *uelf, struct object_file *obj) + (unsigned long)uelf->core_layout.base, + uelf->core_layout.text_size, PROT_READ | PROT_EXEC); + if (ret < 0) { +- log_error( +- "Failed to change upatch text protection to r-x"); ++ log_error("Failed to change upatch text protection to r-x"); + return ret; + } + } +@@ -532,13 +524,11 @@ static int upatch_mprotect(struct upatch_elf *uelf, struct object_file *obj) + if (uelf->core_layout.ro_size > uelf->core_layout.text_size) { + ret = upatch_mprotect_remote( + proc2pctx(obj->proc), +- (unsigned long)uelf->core_layout.base + +- uelf->core_layout.text_size, ++ (unsigned long)uelf->core_layout.base + uelf->core_layout.text_size, + uelf->core_layout.ro_size - uelf->core_layout.text_size, + PROT_READ); + if (ret < 0) { +- log_error( +- "Failed to change upatch ro protection to r--"); ++ log_error("Failed to change upatch ro protection to r--"); + return ret; + } + } +@@ -546,14 +536,11 @@ static int upatch_mprotect(struct upatch_elf *uelf, struct object_file *obj) + if (uelf->core_layout.ro_after_init_size > uelf->core_layout.ro_size) { + ret = upatch_mprotect_remote( + proc2pctx(obj->proc), +- (unsigned long)uelf->core_layout.base + +- uelf->core_layout.ro_size, +- uelf->core_layout.ro_after_init_size - +- uelf->core_layout.ro_size, ++ (unsigned long)uelf->core_layout.base + uelf->core_layout.ro_size, ++ uelf->core_layout.ro_after_init_size - uelf->core_layout.ro_size, + PROT_READ); + if (ret < 0) { +- log_error( +- "Failed to change upatch ro init protection to r--"); ++ log_error("Failed to change upatch ro init protection to r--"); + return ret; + } + } +@@ -562,14 +549,11 @@ static int upatch_mprotect(struct upatch_elf *uelf, struct object_file *obj) + uelf->core_layout.ro_after_init_size) { + ret = upatch_mprotect_remote( + proc2pctx(obj->proc), +- (unsigned long)uelf->core_layout.base + +- uelf->core_layout.ro_after_init_size, +- uelf->core_layout.info_size - +- uelf->core_layout.ro_after_init_size, ++ (unsigned long)uelf->core_layout.base + uelf->core_layout.ro_after_init_size, ++ uelf->core_layout.info_size - uelf->core_layout.ro_after_init_size, + PROT_READ | PROT_WRITE); + if (ret < 0) { +- log_error( +- "Failed to change upatch rw protection to rw-"); ++ log_error("Failed to change upatch rw protection to rw-"); + return ret; + } + } +@@ -577,13 +561,11 @@ static int upatch_mprotect(struct upatch_elf *uelf, struct object_file *obj) + if (uelf->core_layout.size > uelf->core_layout.info_size) { + ret = upatch_mprotect_remote( + proc2pctx(obj->proc), +- (unsigned long)uelf->core_layout.base + +- uelf->core_layout.info_size, ++ (unsigned long)uelf->core_layout.base + uelf->core_layout.info_size, + uelf->core_layout.size - uelf->core_layout.info_size, + PROT_READ); + if (ret < 0) { +- log_error( +- "Failed to change upatch info protection to r--"); ++ log_error("Failed to change upatch info protection to r--"); + return ret; + } + } +@@ -628,9 +610,9 @@ static int upatch_apply_patches(struct upatch_process *proc, + layout_symtab(uelf); + layout_upatch_info(uelf); + +- log_debug("calculate core_layout = %x \n", uelf->core_layout.size); ++ log_debug("calculate core layout = %x\n", uelf->core_layout.size); + log_debug( +- "core_layout: text_size = %x, ro_size = %x, ro_after_init_size = " ++ "Core layout: text_size = %x, ro_size = %x, ro_after_init_size = " + "%x, info = %x, size = %x\n", + uelf->core_layout.text_size, uelf->core_layout.ro_size, + uelf->core_layout.ro_after_init_size, +@@ -641,35 +623,42 @@ static int upatch_apply_patches(struct upatch_process *proc, + * Otherwise we can't use 32-bit jumps. + */ + ret = alloc_memory(uelf, obj); +- if (ret) ++ if (ret) { + goto free; ++ } + + ret = upatch_mprotect(uelf, obj); +- if (ret) ++ if (ret) { + goto free; ++ } + + /* Fix up syms, so that st_value is a pointer to location. */ + ret = simplify_symbols(uelf, obj); +- if (ret) ++ if (ret) { + goto free; ++ } + + /* upatch new address will be updated */ + ret = apply_relocations(uelf); +- if (ret) ++ if (ret) { + goto free; ++ } + + /* upatch upatch info */ + ret = complete_info(uelf, obj, uuid); +- if (ret) ++ if (ret) { + goto free; ++ } + + ret = post_memory(uelf, obj); +- if (ret) ++ if (ret) { + goto free; ++ } + + ret = apply_patch(uelf, obj); +- if (ret) ++ if (ret) { + goto free; ++ } + + ret = 0; + goto out; +@@ -686,12 +675,14 @@ int upatch_process_uuid_exist(struct upatch_process *proc, const char *uuid) + struct object_file *obj; + struct object_patch *patch; + list_for_each_entry(obj, &proc->objs, list) { +- if (!obj->is_patch) ++ if (!obj->is_patch) { + continue; ++ } + list_for_each_entry(patch, &obj->applied_patch, list) { +- if (strncmp(patch->uinfo->id, uuid, UPATCH_ID_LEN) == 0) ++ if (strncmp(patch->uinfo->id, uuid, UPATCH_ID_LEN) == 0) { + return -EEXIST; + } ++ } + } + return 0; + } +@@ -707,15 +698,16 @@ int process_patch(int pid, struct upatch_elf *uelf, struct running_elf *relf, co + // 查看process的信息,pid: maps, mem, cmdline, exe + ret = upatch_process_init(&proc, pid); + if (ret < 0) { +- log_error("cannot init process %d\n", pid); ++ log_error("Failed to init process %d, ret=%d\n", pid, ret); + goto out; + } + + upatch_process_print_short(&proc); + + ret = upatch_process_mem_open(&proc, MEM_READ); +- if (ret < 0) ++ if (ret < 0) { + goto out_free; ++ } + + // use uprobe to hack function. the program has been executed to the entry + // point +@@ -736,7 +728,7 @@ int process_patch(int pid, struct upatch_elf *uelf, struct running_elf *relf, co + } + ret = binary_init(relf, binary_path); + if (ret) { +- log_error("binary_init failed %d \n", ret); ++ log_error("Failed to load binary, ret=%d\n", ret); + goto out_free; + } + +@@ -759,7 +751,9 @@ int process_patch(int pid, struct upatch_elf *uelf, struct running_elf *relf, co + ret = 0; + + out_free: +- upatch_process_memfree(&proc); ++ upatch_process_detach(&proc); ++ upatch_process_destroy(&proc); ++ + out: + if (is_calc_time) { + gettimeofday(&end_tv, NULL); +@@ -856,18 +850,22 @@ int process_unpatch(int pid, const char *uuid) + + /* Finally, attach to process */ + ret = upatch_process_attach(&proc); +- if (ret < 0) ++ if (ret < 0) { + goto out_free; ++ } + + // 应用 + ret = upatch_unapply_patches(&proc, uuid); +- if (ret < 0) ++ if (ret < 0) { + goto out_free; ++ } + + ret = 0; + + out_free: +- upatch_process_memfree(&proc); ++ upatch_process_detach(&proc); ++ upatch_process_destroy(&proc); ++ + out: + if (is_calc_time) { + gettimeofday(&end_tv, NULL); +@@ -916,29 +914,33 @@ int process_info(int pid) + // 查看process的信息,pid: maps, mem, cmdline, exe + ret = upatch_process_init(&proc, pid); + if (ret < 0) { +- log_error("cannot init process %d\n", pid); ++ log_error("Failed to init process %d, ret=%d\n", pid, ret); + goto out; + } + + ret = upatch_process_mem_open(&proc, MEM_READ); +- if (ret < 0) ++ if (ret < 0) { + goto out_free; ++ } + + ret = upatch_process_map_object_files(&proc, NULL); +- if (ret < 0) ++ if (ret < 0) { + goto out_free; ++ } + +- // 应用 + ret = upatch_info(&proc); +- if (ret) ++ if (ret) { + status = "active"; +- else ++ } ++ else { + status = "removed"; ++ } + + ret = 0; + + out_free: +- upatch_process_memfree(&proc); ++ upatch_process_destroy(&proc); ++ + out: + log_normal("%s\n", status); + return ret; +diff --git a/upatch/upatch-manage/upatch-process.c b/upatch/upatch-manage/upatch-process.c +index 2437ce1..aeb5705 100644 +--- a/upatch/upatch-manage/upatch-process.c ++++ b/upatch/upatch-manage/upatch-process.c +@@ -19,6 +19,8 @@ + #include "upatch-process.h" + #include "upatch-ptrace.h" + ++static const int MAX_ATTACH_ATTEMPTS = 3; ++ + /* + * Locks process by opening /proc//maps + * This ensures that task_struct will not be +@@ -32,17 +34,26 @@ static int lock_process(int pid) + + log_debug("Locking PID %d...", pid); + snprintf(path, sizeof(path), "/proc/%d/maps", pid); ++ + fd = open(path, O_RDONLY); + if (fd < 0) { +- log_error("cannot open '/proc/%d/maps'\n", pid); ++ log_error("Failed to open '%s'\n", path); + return -1; + } + log_debug("OK\n"); ++ + return fd; + } + ++static void unlock_process(int pid, int fdmaps) ++{ ++ int errsv = errno; ++ close(fdmaps); ++ errno = errsv; ++} ++ + // TODO: get addr_space +-int upatch_coroutines_init(struct upatch_process *proc) ++static int upatch_coroutines_init(struct upatch_process *proc) + { + INIT_LIST_HEAD(&proc->coro.coros); + +@@ -56,17 +67,20 @@ static int process_get_comm(struct upatch_process *proc) + char *bn, *c; + ssize_t ret; + +- log_debug("process_get_comm %d...", proc->pid); + snprintf(path, sizeof(path), "/proc/%d/exe", proc->pid); ++ log_debug("Reading from '%s'...", path); + + ret = readlink(path, realpath, sizeof(realpath)); +- if (ret < 0) ++ if (ret < 0) { + return -1; ++ } ++ + realpath[ret] = '\0'; + bn = basename(realpath); + strncpy(path, bn, sizeof(path) - 1); +- if ((c = strstr(path, " (deleted)"))) ++ if ((c = strstr(path, " (deleted)"))) { + *c = '\0'; ++ } + + proc->comm[sizeof(proc->comm) - 1] = '\0'; + memcpy(proc->comm, path, sizeof(proc->comm) - 1); +@@ -76,20 +90,14 @@ static int process_get_comm(struct upatch_process *proc) + return 0; + } + +-static void unlock_process(int pid, int fdmaps) +-{ +- int errsv = errno; +- close(fdmaps); +- errno = errsv; +-} +- + int upatch_process_init(struct upatch_process *proc, int pid) + { + int fdmaps; + + fdmaps = lock_process(pid); +- if (fdmaps < 0) ++ if (fdmaps < 0) { + goto out_err; ++ } + + memset(proc, 0, sizeof(*proc)); + +@@ -102,10 +110,13 @@ int upatch_process_init(struct upatch_process *proc, int pid) + INIT_LIST_HEAD(&proc->vmaholes); + proc->num_objs = 0; + +- if (upatch_coroutines_init(proc)) ++ if (upatch_coroutines_init(proc)) { + goto out_unlock; +- if (process_get_comm(proc)) ++ } ++ ++ if (process_get_comm(proc)) { + goto out_unlock; ++ } + + return 0; + +@@ -115,15 +126,63 @@ out_err: + return -1; + } + ++static void upatch_object_memfree(struct object_file *obj) ++{ ++ struct object_patch *opatch, *opatch_safe; ++ struct obj_vm_area *ovma, *ovma_safe; ++ ++ if (obj->name) { ++ free(obj->name); ++ } ++ ++ list_for_each_entry_safe(opatch, opatch_safe, &obj->applied_patch, list) { ++ if (opatch->uinfo) { ++ free(opatch->uinfo); ++ } ++ if (opatch->funcs) { ++ free(opatch->funcs); ++ } ++ free(opatch); ++ } ++ ++ list_for_each_entry_safe(ovma, ovma_safe, &obj->vma, list) { ++ free(ovma); ++ } ++} ++ ++static void upatch_process_memfree(struct upatch_process *proc) ++{ ++ struct upatch_ptrace_ctx *p, *p_safe; ++ struct object_file *obj, *obj_safe; ++ struct vm_hole *hole, *hole_safe; ++ ++ list_for_each_entry_safe(p, p_safe, &proc->ptrace.pctxs, list) { ++ free(p); ++ } ++ ++ list_for_each_entry_safe(hole, hole_safe, &proc->vmaholes, list) { ++ free(hole); ++ } ++ ++ list_for_each_entry_safe(obj, obj_safe, &proc->objs, list) { ++ upatch_object_memfree(obj); ++ free(obj); ++ } ++} ++ ++void upatch_process_destroy(struct upatch_process *proc) ++{ ++ unlock_process(proc->pid, proc->fdmaps); ++ upatch_process_memfree(proc); ++} ++ + static void process_print_cmdline(struct upatch_process *proc) + { +- char buf[1024]; +- int fd; ++ char buf[PATH_MAX]; + ssize_t i, rv; + +- snprintf(buf, sizeof("/proc/0123456789/cmdline"), "/proc/%d/cmdline", +- proc->pid); +- fd = open(buf, O_RDONLY); ++ snprintf(buf, PATH_MAX, "/proc/%d/cmdline", proc->pid); ++ int fd = open(buf, O_RDONLY); + if (fd == -1) { + log_error("open\n"); + return; +@@ -144,10 +203,12 @@ static void process_print_cmdline(struct upatch_process *proc) + break; + + for (i = 0; i < rv; i++) { +- if (buf[i] != '\n' && isprint(buf[i])) ++ if (buf[i] != '\n' && isprint(buf[i])) { + putchar(buf[i]); +- else ++ } ++ else { + printf("\\x%02x", (unsigned char)buf[i]); ++ } + } + } + +@@ -164,7 +225,7 @@ void upatch_process_print_short(struct upatch_process *proc) + + int upatch_process_mem_open(struct upatch_process *proc, int mode) + { +- char path[sizeof("/proc/0123456789/mem")]; ++ char path[PATH_MAX]; + + if (proc->memfd >= 0) { + close(proc->memfd); +@@ -272,7 +333,7 @@ process_new_object(struct upatch_process *proc, dev_t dev, int inode, + + o = malloc(sizeof(*o)); + if (!o) { +- log_error("FAIL\n"); ++ log_error("FAILED\n"); + return NULL; + } + memset(o, 0, sizeof(struct object_file)); +@@ -288,7 +349,7 @@ process_new_object(struct upatch_process *proc, dev_t dev, int inode, + + o->previous_hole = hole; + if (object_add_vm_area(o, vma, hole) < 0) { +- log_error("can't add vm_area for %s\n", name); ++ log_error("Cannot add vm area for %s\n", name); + free(o); + return NULL; + } +@@ -298,6 +359,7 @@ process_new_object(struct upatch_process *proc, dev_t dev, int inode, + + list_add(&o->list, &proc->objs); + proc->num_objs++; ++ + log_debug("OK\n"); + return o; + } +@@ -332,19 +394,22 @@ static int process_add_object_vma(struct upatch_process *proc, dev_t dev, + } + + o = process_new_object(proc, dev, inode, name, vma, hole); +- if (o == NULL) ++ if (o == NULL) { + return -1; ++ } + + if (object_type == OBJECT_UPATCH) { + struct object_patch *opatch; + + opatch = malloc(sizeof(struct object_patch)); +- if (opatch == NULL) ++ if (opatch == NULL) { + return -1; ++ } + + opatch->uinfo = malloc(sizeof(struct upatch_info)); +- if (opatch->uinfo == NULL) ++ if (opatch->uinfo == NULL) { + return -1; ++ } + + memcpy(opatch->uinfo, header_buf, sizeof(struct upatch_info)); + opatch->funcs = malloc(opatch->uinfo->changed_func_num * +@@ -372,7 +437,7 @@ static int process_add_object_vma(struct upatch_process *proc, dev_t dev, + int upatch_process_parse_proc_maps(struct upatch_process *proc) + { + FILE *f; +- int ret, fd, is_libc_base_set = 0; ++ int ret, is_libc_base_set = 0; + unsigned long hole_start = 0; + struct vm_hole *hole = NULL; + +@@ -383,7 +448,7 @@ int upatch_process_parse_proc_maps(struct upatch_process *proc) + * of the object (we might have references to them + * in the patch). + */ +- fd = dup(proc->fdmaps); ++ int fd = dup(proc->fdmaps); + if (fd < 0) { + log_error("unable to dup fd %d", proc->fdmaps); + return -1; +@@ -405,17 +470,20 @@ int upatch_process_parse_proc_maps(struct upatch_process *proc) + char perms[5], name_[256], *name = name_; + int r; + +- if (!fgets(line, sizeof(line), f)) ++ if (!fgets(line, sizeof(line), f)) { + break; ++ } ++ + r = sscanf(line, "%lx-%lx %s %lx %x:%x %d %255s", &start, &end, + perms, &offset, &maj, &min, &inode, name_); +- + if (r == EOF) { +- log_error("sscanf failed: end of file"); ++ log_error("Failed to read maps: unexpected EOF"); + goto error; + } +- if (r != 8) ++ ++ if (r != 8) { + strcpy(name, "[anonymous]"); ++ } + + vma.start = start; + vma.end = end; +@@ -451,7 +519,7 @@ int upatch_process_parse_proc_maps(struct upatch_process *proc) + } while (1); + fclose(f); + +- log_debug("Found %d object file(s) \n", proc->num_objs); ++ log_debug("Found %d object file(s)\n", proc->num_objs); + + if (!is_libc_base_set) { + log_error("Can't find libc_base required for manipulations: %d", +@@ -497,29 +565,30 @@ static int process_list_threads(struct upatch_process *proc, int **ppids, + { + DIR *dir = NULL; + struct dirent *de; +- char path[128]; ++ char path[PATH_MAX]; + int *pids = *ppids; + + snprintf(path, sizeof(path), "/proc/%d/task", proc->pid); ++ + dir = opendir(path); + if (!dir) { +- log_error("can't open '%s' directory\n", path); ++ log_error("Failed to open directory '%s'\n", path); + goto dealloc; + } + + *npids = 0; + while ((de = readdir(dir))) { + int *t; +- if (de->d_name[0] == '.') ++ if (de->d_name[0] == '.') { + continue; ++ } + + if (*npids >= *alloc) { + *alloc = *alloc ? *alloc * 2 : 1; + + t = realloc(pids, *alloc * sizeof(*pids)); + if (t == NULL) { +- log_error( +- "Failed to (re)allocate memory for pids\n"); ++ log_error("Failed to (re)allocate memory for pids\n"); + goto dealloc; + } + +@@ -536,62 +605,25 @@ static int process_list_threads(struct upatch_process *proc, int **ppids, + return *npids; + + dealloc: +- if (dir) ++ if (dir) { + closedir(dir); ++ } + free(pids); + *ppids = NULL; + *alloc = *npids = 0; + return -1; + } + +-static void process_detach(struct upatch_process *proc) +-{ +- struct upatch_ptrace_ctx *p, *ptmp; +- int status; +- pid_t pid; +- +- if (proc->memfd >= 0 && close(proc->memfd) < 0) +- log_error("can't close memfd"); +- proc->memfd = -1; +- +- list_for_each_entry_safe(p, ptmp, &proc->ptrace.pctxs, list) { +- /** +- * If upatch_ptrace_detach(p) return -ESRCH, there are two situations, +- * as described below: +- * 1. the specified thread does not exist, it means the thread dead +- * during the attach processing, so we need to wait for the thread +- * to exit; +- * 2. the specified thread is not currently being traced by us, +- * or is not stopped, so we just ignore it; +- * +- * We using the running variable of the struct upatch_ptrace_ctx to +- * distinguish them: +- * 1. if pctx->running = 0, it means the thread is traced by us, we +- * will wait for the thread to exit; +- * 2. if pctx->running = 1, it means we can not sure about the status of +- * the thread, we just ignore it; +- */ +- if (upatch_ptrace_detach(p) == -ESRCH && !p->running) { +- do { +- pid = waitpid(p->pid, &status, __WALL); +- } while (pid > 0 && !WIFEXITED(status)); +- } +- // upatch_ptrace_ctx_destroy(p); +- } +- log_debug("Finished ptrace detaching.\n"); +-} +- +-static const int max_attach_attempts = 3; +- + int upatch_process_attach(struct upatch_process *proc) + { + int *pids = NULL, ret; + size_t i, npids = 0, alloc = 0, prevnpids = 0, nattempts; + +- if (upatch_process_mem_open(proc, MEM_WRITE) < 0) ++ if (upatch_process_mem_open(proc, MEM_WRITE) < 0) { + return -1; ++ } + +- for (nattempts = 0; nattempts < max_attach_attempts; nattempts++) { ++ for (nattempts = 0; nattempts < MAX_ATTACH_ATTEMPTS; nattempts++) { + ret = process_list_threads(proc, &pids, &npids, &alloc); + if (ret == -1) + goto detach; +@@ -627,25 +659,64 @@ int upatch_process_attach(struct upatch_process *proc) + prevnpids = npids; + } + +- if (nattempts == max_attach_attempts) { +- log_error("unable to catch up with process, bailing\n"); ++ if (nattempts == MAX_ATTACH_ATTEMPTS) { ++ log_error("Unable to catch up with process, bailing\n"); + goto detach; + } + +- log_debug("attached to %lu thread(s): %d", npids, pids[0]); +- for (i = 1; i < npids; i++) ++ log_debug("Attached to %lu thread(s): %d", npids, pids[0]); ++ for (i = 1; i < npids; i++) { + log_debug(", %d", pids[i]); ++ } + log_debug("\n"); + + free(pids); + return 0; + + detach: +- process_detach(proc); ++ upatch_process_detach(proc); + free(pids); + return -1; + } + ++void upatch_process_detach(struct upatch_process *proc) ++{ ++ struct upatch_ptrace_ctx *p, *ptmp; ++ int status; ++ pid_t pid; ++ ++ if (proc->memfd >= 0 && close(proc->memfd) < 0) { ++ log_error("Failed to close memfd"); ++ } ++ proc->memfd = -1; ++ ++ list_for_each_entry_safe(p, ptmp, &proc->ptrace.pctxs, list) { ++ /** ++ * If upatch_ptrace_detach(p) return -ESRCH, there are two situations, ++ * as described below: ++ * 1. the specified thread does not exist, it means the thread dead ++ * during the attach processing, so we need to wait for the thread ++ * to exit; ++ * 2. the specified thread is not currently being traced by us, ++ * or is not stopped, so we just ignore it; ++ * ++ * We using the running variable of the struct upatch_ptrace_ctx to ++ * distinguish them: ++ * 1. if pctx->running = 0, it means the thread is traced by us, we ++ * will wait for the thread to exit; ++ * 2. if pctx->running = 1, it means we can not sure about the status of ++ * the thread, we just ignore it; ++ */ ++ if (upatch_ptrace_detach(p) == -ESRCH && !p->running) { ++ do { ++ pid = waitpid(p->pid, &status, __WALL); ++ } while (pid > 0 && !WIFEXITED(status)); ++ } ++ // upatch_ptrace_ctx_destroy(p); ++ } ++ log_debug("Process detached\n"); ++} ++ + static inline struct vm_hole *next_hole(struct vm_hole *hole, + struct list_head *head) + { +@@ -765,13 +836,12 @@ unsigned long object_find_patch_region(struct object_file *obj, size_t memsize, + } + + if (region_start == region_end) { +- log_error("can't find suitable region for patch on '%s'\n", +- obj->name); ++ log_error("Cannot find suitable region for patch '%s'\n", obj->name); + return -1UL; + } + + region_start = (region_start >> PAGE_SHIFT) << PAGE_SHIFT; +- log_debug("Found patch region for '%s' at %lx\n", obj->name, ++ log_debug("Found patch region for '%s' at 0x%lx\n", obj->name, + region_start); + + return region_start; +@@ -801,58 +871,12 @@ unsigned long object_find_patch_region_nolimit(struct object_file *obj, size_t m + left_hole = prev_hole(left_hole, head); + } + +- log_error("can't find suitable region for patch on '%s'\n", +- obj->name); ++ log_error("Cannot find suitable region for patch '%s'\n", obj->name); + return -1UL; + found: + region_start = ((*hole)->start >> PAGE_SHIFT) << PAGE_SHIFT; +- log_debug("Found patch region for '%s' at %lx\n", obj->name, ++ log_debug("Found patch region for '%s' 0xat %lx\n", obj->name, + region_start); + + return region_start; + } +- +-static void upatch_object_memfree(struct object_file *obj) +-{ +- struct object_patch *opatch, *opatch_safe; +- struct obj_vm_area *ovma, *ovma_safe; +- +- if (obj->name) +- free(obj->name); +- +- list_for_each_entry_safe(opatch, opatch_safe, &obj->applied_patch, +- list) { +- if (opatch->uinfo) +- free(opatch->uinfo); +- if (opatch->funcs) +- free(opatch->funcs); +- free(opatch); +- } +- +- list_for_each_entry_safe(ovma, ovma_safe, &obj->vma, list) { +- free(ovma); +- } +-} +- +-void upatch_process_memfree(struct upatch_process *proc) +-{ +- struct upatch_ptrace_ctx *p, *p_safe; +- struct object_file *obj, *obj_safe; +- struct vm_hole *hole, *hole_safe; +- +- list_for_each_entry_safe(p, p_safe, &proc->ptrace.pctxs, list) { +- free(p); +- } +- +- list_for_each_entry_safe(hole, hole_safe, &proc->vmaholes, list) { +- free(hole); +- } +- +- list_for_each_entry_safe(obj, obj_safe, &proc->objs, list) { +- upatch_object_memfree(obj); +- free(obj); +- } +- +- unlock_process(proc->pid, proc->fdmaps); +- process_detach(proc); +-} +diff --git a/upatch/upatch-manage/upatch-process.h b/upatch/upatch-manage/upatch-process.h +index 9c3aecc..2a212fa 100644 +--- a/upatch/upatch-manage/upatch-process.h ++++ b/upatch/upatch-manage/upatch-process.h +@@ -107,6 +107,8 @@ struct upatch_process { + + int upatch_process_init(struct upatch_process *, int); + ++void upatch_process_destroy(struct upatch_process *); ++ + void upatch_process_print_short(struct upatch_process *); + + int upatch_process_mem_open(struct upatch_process *, int); +@@ -115,6 +117,8 @@ int upatch_process_map_object_files(struct upatch_process *, const char *); + + int upatch_process_attach(struct upatch_process *); + ++void upatch_process_detach(struct upatch_process *proc); ++ + int vm_hole_split(struct vm_hole *, unsigned long, unsigned long); + + unsigned long object_find_patch_region(struct object_file *, size_t, +@@ -122,6 +126,4 @@ unsigned long object_find_patch_region(struct object_file *, size_t, + unsigned long object_find_patch_region_nolimit(struct object_file *, size_t, + struct vm_hole **); + +-void upatch_process_memfree(struct upatch_process *); +- + #endif +diff --git a/upatch/upatch-manage/upatch-ptrace.c b/upatch/upatch-manage/upatch-ptrace.c +index 4144fbe..4c9944a 100644 +--- a/upatch/upatch-manage/upatch-ptrace.c ++++ b/upatch/upatch-manage/upatch-ptrace.c +@@ -12,27 +12,23 @@ + + /* process's memory access */ + int upatch_process_mem_read(struct upatch_process *proc, unsigned long src, +- void *dst, size_t size) ++ void *dst, size_t size) + { +- ssize_t r; +- +- r = pread(proc->memfd, dst, size, (off_t)src); ++ ssize_t r = pread(proc->memfd, dst, size, (off_t)src); + + return r != size ? -1 : 0; + } + + static int upatch_process_mem_write_ptrace(struct upatch_process *proc, +- void *src, unsigned long dst, +- size_t size) ++ void *src, unsigned long dst, size_t size) + { + int ret; + + while (ROUND_DOWN(size, sizeof(long)) != 0) { +- ret = ptrace(PTRACE_POKEDATA, proc->pid, dst, +- *(unsigned long *)src); +- if (ret) ++ ret = ptrace(PTRACE_POKEDATA, proc->pid, dst, *(unsigned long *)src); ++ if (ret) { + return -1; +- ++ } + dst += sizeof(long); + src += sizeof(long); + size -= sizeof(long); +@@ -42,26 +38,29 @@ static int upatch_process_mem_write_ptrace(struct upatch_process *proc, + unsigned long tmp; + + tmp = ptrace(PTRACE_PEEKDATA, proc->pid, dst, NULL); +- if (tmp == (unsigned long)-1 && errno) ++ if (tmp == (unsigned long)-1 && errno) { + return -1; ++ } + memcpy(&tmp, src, size); + + ret = ptrace(PTRACE_POKEDATA, proc->pid, dst, tmp); +- if (ret) ++ if (ret) { + return -1; ++ } + } + + return 0; + } + + int upatch_process_mem_write(struct upatch_process *proc, void *src, +- unsigned long dst, size_t size) ++ unsigned long dst, size_t size) + { + static int use_pwrite = 1; + ssize_t w; + +- if (use_pwrite) ++ if (use_pwrite) { + w = pwrite(proc->memfd, src, size, (off_t)dst); ++ } + if (!use_pwrite || (w == -1 && errno == EINVAL)) { + use_pwrite = 0; + return upatch_process_mem_write_ptrace(proc, src, dst, size); +@@ -70,14 +69,16 @@ int upatch_process_mem_write(struct upatch_process *proc, void *src, + return w != size ? -1 : 0; + } + +-static struct upatch_ptrace_ctx * +-upatch_ptrace_ctx_alloc(struct upatch_process *proc) ++static struct upatch_ptrace_ctx* upatch_ptrace_ctx_alloc( ++ struct upatch_process *proc) + { + struct upatch_ptrace_ctx *p; + + p = malloc(sizeof(*p)); +- if (!p) ++ if (!p) { + return NULL; ++ } ++ + memset(p, 0, sizeof(*p)); + + p->execute_until = 0UL; +@@ -86,56 +87,54 @@ upatch_ptrace_ctx_alloc(struct upatch_process *proc) + + INIT_LIST_HEAD(&p->list); + list_add(&p->list, &proc->ptrace.pctxs); ++ + return p; + } + + int upatch_ptrace_attach_thread(struct upatch_process *proc, int tid) + { +- long ret; +- int status; +- struct upatch_ptrace_ctx *pctx; +- +- pctx = upatch_ptrace_ctx_alloc(proc); ++ struct upatch_ptrace_ctx *pctx = upatch_ptrace_ctx_alloc(proc); + if (pctx == NULL) { +- log_error("Can't alloc upatch_ptrace_ctx"); ++ log_error("Failed to alloc ptrace context"); + return -1; + } + + pctx->pid = tid; +- log_debug("Attaching to %d...", pctx->pid); ++ log_debug("Attaching to %d...", tid); + +- ret = ptrace(PTRACE_ATTACH, pctx->pid, NULL, NULL); ++ long ret = ptrace(PTRACE_ATTACH, tid, NULL, NULL); + if (ret < 0) { +- log_error("can't attach to %d\n", pctx->pid); ++ log_error("Failed to attach thread, pid=%d, ret=%ld\n", tid, ret); + return -1; + } + + do { ++ int status = 0; ++ + ret = waitpid(tid, &status, __WALL); + if (ret < 0) { +- log_error("can't wait for thread\n"); ++ log_error("Failed to wait thread, tid=%d, ret=%ld\n", tid, ret); + return -1; + } + + /* We are expecting SIGSTOP */ +- if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) ++ if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) { + break; ++ } + + /* If we got SIGTRAP because we just got out of execve, wait + * for the SIGSTOP + */ +- if (WIFSTOPPED(status)) +- status = (WSTOPSIG(status) == SIGTRAP) ? +- 0 : +- WSTOPSIG(status); +- else if (WIFSIGNALED(status)) ++ if (WIFSTOPPED(status)) { ++ status = (WSTOPSIG(status) == SIGTRAP) ? 0 : WSTOPSIG(status); ++ } else if (WIFSIGNALED(status)) { + /* Resend signal */ + status = WTERMSIG(status); ++ } + +- ret = ptrace(PTRACE_CONT, pctx->pid, NULL, +- (void *)(uintptr_t)status); ++ ret = ptrace(PTRACE_CONT, tid, NULL, (void *)(uintptr_t)status); + if (ret < 0) { +- log_error("can't cont tracee\n"); ++ log_error("Failed to continue thread, tid=%d, ret=%ld\n", tid, ret); + return -1; + } + } while (1); +@@ -152,23 +151,22 @@ int wait_for_stop(struct upatch_ptrace_ctx *pctx, const void *data) + log_debug("wait_for_stop(pctx->pid=%d, pid=%d)\n", pctx->pid, pid); + + while (1) { +- ret = ptrace(PTRACE_CONT, pctx->pid, NULL, +- (void *)(uintptr_t)status); ++ ret = ptrace(PTRACE_CONT, pctx->pid, NULL, (void *)(uintptr_t)status); + if (ret < 0) { +- log_error("can't start tracee %d\n", pctx->pid); ++ log_error("Cannot start tracee %d, ret=%d\n", pctx->pid, ret); + return -1; + } + + ret = waitpid(pid, &status, __WALL); + if (ret < 0) { +- log_error("can't wait tracee %d\n", pid); ++ log_error("Cannot wait tracee %d, ret=%d\n", pid, ret); + return -1; + } + + if (WIFSTOPPED(status)) { +- if (WSTOPSIG(status) == SIGSTOP || +- WSTOPSIG(status) == SIGTRAP) ++ if (WSTOPSIG(status) == SIGSTOP || WSTOPSIG(status) == SIGTRAP) { + break; ++ } + status = WSTOPSIG(status); + continue; + } +@@ -181,17 +179,16 @@ int wait_for_stop(struct upatch_ptrace_ctx *pctx, const void *data) + + int upatch_ptrace_detach(struct upatch_ptrace_ctx *pctx) + { +- long ret; +- +- if (!pctx->pid) ++ if (!pctx->pid) { + return 0; +- log_debug("Detaching from %d...\n", pctx->pid); +- ret = ptrace(PTRACE_DETACH, pctx->pid, NULL, NULL); ++ } ++ ++ log_debug("Detaching from %d...", pctx->pid); ++ long ret = ptrace(PTRACE_DETACH, pctx->pid, NULL, NULL); + if (ret < 0) { +- log_error("can't detach from %d\n", pctx->pid); ++ log_error("Failed to detach from process, pid=%d, ret=%ld\n", pctx->pid, ret); + return -errno; + } +- + log_debug("OK\n"); + + pctx->running = 1; +@@ -200,16 +197,16 @@ int upatch_ptrace_detach(struct upatch_ptrace_ctx *pctx) + } + + int upatch_execute_remote(struct upatch_ptrace_ctx *pctx, +- const unsigned char *code, size_t codelen, +- struct user_regs_struct *pregs) ++ const unsigned char *code, size_t codelen, ++ struct user_regs_struct *pregs) + { +- return upatch_arch_execute_remote_func(pctx, code, codelen, pregs, +- wait_for_stop, NULL); ++ return upatch_arch_execute_remote_func( ++ pctx, code, codelen, pregs, wait_for_stop, NULL); + } + + unsigned long upatch_mmap_remote(struct upatch_ptrace_ctx *pctx, +- unsigned long addr, size_t length, int prot, +- int flags, int fd, off_t offset) ++ unsigned long addr, size_t length, int prot, ++ int flags, int fd, off_t offset) + { + int ret; + unsigned long res = 0; +@@ -218,8 +215,9 @@ unsigned long upatch_mmap_remote(struct upatch_ptrace_ctx *pctx, + prot, flags, fd, offset); + ret = upatch_arch_syscall_remote(pctx, __NR_mmap, (unsigned long)addr, + length, prot, flags, fd, offset, &res); +- if (ret < 0) ++ if (ret < 0) { + return 0; ++ } + if (ret == 0 && res >= (unsigned long)-MAX_ERRNO) { + errno = -(long)res; + return 0; +@@ -228,7 +226,7 @@ unsigned long upatch_mmap_remote(struct upatch_ptrace_ctx *pctx, + } + + int upatch_mprotect_remote(struct upatch_ptrace_ctx *pctx, unsigned long addr, +- size_t length, int prot) ++ size_t length, int prot) + { + int ret; + unsigned long res; +@@ -248,7 +246,7 @@ int upatch_mprotect_remote(struct upatch_ptrace_ctx *pctx, unsigned long addr, + } + + int upatch_munmap_remote(struct upatch_ptrace_ctx *pctx, unsigned long addr, +- size_t length) ++ size_t length) + { + int ret; + unsigned long res; +diff --git a/upatch/upatch-manage/upatch-relocation.c b/upatch/upatch-manage/upatch-relocation.c +index 4c9c360..1baeecf 100644 +--- a/upatch/upatch-manage/upatch-relocation.c ++++ b/upatch/upatch-manage/upatch-relocation.c +@@ -31,11 +31,10 @@ int apply_relocations(struct upatch_elf *uelf) + if (!(uelf->info.shdrs[infosec].sh_flags & SHF_ALLOC)) + continue; + ++ log_debug("Relocate '%s'\n", name); + if (uelf->info.shdrs[i].sh_type == SHT_REL) { +- log_error("do rel relocations for %s \n", name); + return -EPERM; + } else if (uelf->info.shdrs[i].sh_type == SHT_RELA) { +- log_debug("do rela relocations for %s \n", name); + err = apply_relocate_add(uelf, uelf->index.sym, i); + } + +diff --git a/upatch/upatch-manage/upatch-resolve.c b/upatch/upatch-manage/upatch-resolve.c +index 9c140fe..1a462d9 100644 +--- a/upatch/upatch-manage/upatch-resolve.c ++++ b/upatch/upatch-manage/upatch-resolve.c +@@ -121,7 +121,7 @@ static unsigned long resolve_rela_plt(struct upatch_elf *uelf, + unsigned long sym_addr = relf->load_bias + rela_plt[i].r_offset; + elf_addr = insert_plt_table(uelf, obj, GELF_R_TYPE(rela_plt[i].r_info), sym_addr); + +- log_debug("resolved %s from .rela_plt at 0x%lx\n", name, elf_addr); ++ log_debug("Resolved '%s' from '.rela_plt' at 0x%lx\n", name, elf_addr); + break; + } + +@@ -160,7 +160,7 @@ static unsigned long resolve_dynsym(struct upatch_elf *uelf, + unsigned long sym_addr = relf->load_bias + dynsym[i].st_value; + elf_addr = insert_got_table(uelf, obj, 0, sym_addr); + +- log_debug("resolved %s from .dynsym at 0x%lx\n", name, elf_addr); ++ log_debug("Resolved '%s' from '.dynsym' at 0x%lx\n", name, elf_addr); + break; + } + +@@ -198,7 +198,7 @@ static unsigned long resolve_sym(struct upatch_elf *uelf, + + elf_addr = relf->load_bias + sym[i].st_value; + +- log_debug("resolved %s from .sym at 0x%lx\n", name, elf_addr); ++ log_debug("Resolved '%s' from '.sym' at 0x%lx\n", name, elf_addr); + break; + } + +@@ -220,7 +220,7 @@ static unsigned long resolve_patch_sym(struct upatch_elf *uelf, + } + + elf_addr = relf->load_bias + patch_sym->st_value; +- log_debug("resolved %s from patch .sym at 0x%lx\n", name, elf_addr); ++ log_debug("Resolved '%s' from patch '.sym' at 0x%lx\n", name, elf_addr); + + return elf_addr; + } +@@ -268,7 +268,7 @@ static unsigned long resolve_symbol(struct upatch_elf *uelf, + } + + if (!elf_addr) { +- log_error("Cannot resolve symbol %s\n", name); ++ log_error("Cannot resolve symbol '%s'\n", name); + } + return elf_addr; + } +@@ -286,38 +286,37 @@ int simplify_symbols(struct upatch_elf *uelf, struct object_file *obj) + + if (GELF_ST_TYPE(sym[i].st_info) == STT_SECTION && + sym[i].st_shndx < uelf->info.hdr->e_shnum) +- name = uelf->info.shstrtab + +- uelf->info.shdrs[sym[i].st_shndx].sh_name; ++ name = uelf->info.shstrtab + uelf->info.shdrs[sym[i].st_shndx].sh_name; + else + name = uelf->strtab + sym[i].st_name; + + switch (sym[i].st_shndx) { + case SHN_COMMON: +- log_debug("unsupported Common symbol: %s\n", name); ++ log_debug("Unsupported common symbol '%s'\n", name); + ret = -ENOEXEC; + break; + case SHN_ABS: + break; + case SHN_UNDEF: + elf_addr = resolve_symbol(uelf, obj, name, sym[i]); +- if (!elf_addr) ++ if (!elf_addr) { + ret = -ENOEXEC; ++ } + sym[i].st_value = elf_addr; +- log_debug("resolved symbol %s at 0x%lx\n", name, +- (unsigned long)sym[i].st_value); ++ log_debug("Resolved symbol '%s' at 0x%lx\n", ++ name, (unsigned long)sym[i].st_value); + break; + case SHN_LIVEPATCH: + sym[i].st_value += uelf->relf->load_bias; +- log_debug("resolved livepatch symbol %s at 0x%lx\n", ++ log_debug("Resolved livepatch symbol '%s' at 0x%lx\n", + name, (unsigned long)sym[i].st_value); + break; + default: + /* use real address to calculate secbase */ +- secbase = +- uelf->info.shdrs[sym[i].st_shndx].sh_addralign; ++ secbase = uelf->info.shdrs[sym[i].st_shndx].sh_addralign; + sym[i].st_value += secbase; +- log_debug("normal symbol %s at 0x%lx\n", name, +- (unsigned long)sym[i].st_value); ++ log_debug("Symbol '%s' at 0x%lx\n", ++ name, (unsigned long)sym[i].st_value); + break; + } + } +-- +2.33.0 + diff --git a/0003-upatch-remove-upatch-manage-log-file.patch b/0003-upatch-remove-upatch-manage-log-file.patch new file mode 100644 index 0000000..ce58ba5 --- /dev/null +++ b/0003-upatch-remove-upatch-manage-log-file.patch @@ -0,0 +1,70 @@ +From bad9504ed575d86dd93ffcfdd466827cc3b3dadb Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 20 Dec 2023 10:46:44 +0800 +Subject: [PATCH 03/15] upatch: remove upatch manage log file + +1. remove /tmp/upatch-manage.log +2. print log to stdout + +Signed-off-by: renoseven +--- + upatch/upatch-manage/log.h | 3 +-- + upatch/upatch-manage/upatch-manage.c | 8 -------- + 2 files changed, 1 insertion(+), 10 deletions(-) + +diff --git a/upatch/upatch-manage/log.h b/upatch/upatch-manage/log.h +index 4d1fd7a..80fed3a 100644 +--- a/upatch/upatch-manage/log.h ++++ b/upatch/upatch-manage/log.h +@@ -30,7 +30,6 @@ + /* Files that include log.h must define loglevel and logprefix */ + extern enum loglevel loglevel; + extern char *logprefix; +-extern FILE *upatch_manage_log_fd; + + enum exit_status { + EXIT_STATUS_SUCCESS = 0, +@@ -58,7 +57,7 @@ enum exit_status { + #define log(level, format, ...) \ + ({ \ + if (loglevel <= (level)) \ +- fprintf(upatch_manage_log_fd, format, ##__VA_ARGS__); \ ++ printf(format, ##__VA_ARGS__); \ + }) + + #define REQUIRE(COND, message) \ +diff --git a/upatch/upatch-manage/upatch-manage.c b/upatch/upatch-manage/upatch-manage.c +index b36ff0d..a109db7 100644 +--- a/upatch/upatch-manage/upatch-manage.c ++++ b/upatch/upatch-manage/upatch-manage.c +@@ -124,8 +124,6 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) + + static struct argp argp = { options, parse_opt, args_doc, program_doc }; + +-FILE *upatch_manage_log_fd = NULL; +- + int patch_upatch(const char *uuid, const char *binary_path, const char *upatch_path, int pid) + { + struct upatch_elf uelf; +@@ -184,11 +182,6 @@ int main(int argc, char *argv[]) + struct arguments args; + int ret; + +- upatch_manage_log_fd = fopen("/tmp/upatch-manage.log", "w"); +- if (upatch_manage_log_fd < 0) { +- return -1; +- } +- + memset(&args, 0, sizeof(struct arguments)); + argp_parse(&argp, argc, argv, 0, NULL, &args); + if (args.verbose) { +@@ -217,6 +210,5 @@ int main(int argc, char *argv[]) + break; + } + +- fclose(upatch_manage_log_fd); + return abs(ret); + } +-- +2.33.0 + diff --git a/0004-upatch-remove-redudant-log-output.patch b/0004-upatch-remove-redudant-log-output.patch new file mode 100644 index 0000000..f37d3c2 --- /dev/null +++ b/0004-upatch-remove-redudant-log-output.patch @@ -0,0 +1,25 @@ +From 295f6f406b86b70142bed9b17abc56b72962ac3d Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 20 Dec 2023 12:18:11 +0800 +Subject: [PATCH 04/15] upatch: remove redudant log output + +Signed-off-by: renoseven +--- + upatch/upatch-tool/upatch-meta.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/upatch/upatch-tool/upatch-meta.c b/upatch/upatch-tool/upatch-meta.c +index cf60cff..c625115 100644 +--- a/upatch/upatch-tool/upatch-meta.c ++++ b/upatch/upatch-tool/upatch-meta.c +@@ -573,7 +573,6 @@ patch_status_e meta_get_patch_status(const char *uuid) + } + patch = find_patch_by_uuid(uuid); + if (patch == NULL) { +- log_warn("can't find patch uuid:%s failed to get status\n", uuid); + return UPATCH_PATCH_STATUS_NOT_APPLIED; + } + return patch->status; +-- +2.33.0 + diff --git a/0005-upatch-manage-close-dup-fd.patch b/0005-upatch-manage-close-dup-fd.patch new file mode 100644 index 0000000..45801f4 --- /dev/null +++ b/0005-upatch-manage-close-dup-fd.patch @@ -0,0 +1,32 @@ +From 532e5680087cc1a69f88692c31e523e2eab70145 Mon Sep 17 00:00:00 2001 +From: ningyu <405888464@qq.com> +Date: Wed, 20 Dec 2023 15:34:13 +0800 +Subject: [PATCH 05/15] upatch-manage: close dup fd + +--- + upatch/upatch-manage/upatch-process.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/upatch/upatch-manage/upatch-process.c b/upatch/upatch-manage/upatch-process.c +index aeb5705..2216db2 100644 +--- a/upatch/upatch-manage/upatch-process.c ++++ b/upatch/upatch-manage/upatch-process.c +@@ -518,6 +518,7 @@ int upatch_process_parse_proc_maps(struct upatch_process *proc) + + } while (1); + fclose(f); ++ close(fd); + + log_debug("Found %d object file(s)\n", proc->num_objs); + +@@ -531,6 +532,7 @@ int upatch_process_parse_proc_maps(struct upatch_process *proc) + + error: + fclose(f); ++ close(fd); + return -1; + } + +-- +2.33.0 + diff --git a/0006-daemon-check-patch-before-patch-restoration.patch b/0006-daemon-check-patch-before-patch-restoration.patch new file mode 100644 index 0000000..9947b67 --- /dev/null +++ b/0006-daemon-check-patch-before-patch-restoration.patch @@ -0,0 +1,252 @@ +From fdb0d2ab35085bd97d5cae420df0a2c9c6f99c0a Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 22 Dec 2023 13:40:29 +0800 +Subject: [PATCH 06/15] daemon: check patch before patch restoration + +Signed-off-by: renoseven +--- + daemon/src/patch/manager/driver/kpatch/mod.rs | 37 +++++++++--- + daemon/src/patch/manager/driver/mod.rs | 2 +- + daemon/src/patch/manager/driver/upatch/mod.rs | 58 +++++++++++++------ + daemon/src/patch/manager/mod.rs | 3 +- + daemon/src/patch/transaction.rs | 2 +- + daemon/src/rpc/skeleton_impl/patch.rs | 2 +- + 6 files changed, 73 insertions(+), 31 deletions(-) + +diff --git a/daemon/src/patch/manager/driver/kpatch/mod.rs b/daemon/src/patch/manager/driver/kpatch/mod.rs +index 57aa127..efe80e5 100644 +--- a/daemon/src/patch/manager/driver/kpatch/mod.rs ++++ b/daemon/src/patch/manager/driver/kpatch/mod.rs +@@ -2,7 +2,7 @@ use std::{ffi::OsString, os::unix::prelude::OsStrExt, path::Path}; + + use anyhow::{anyhow, bail, ensure, Context, Result}; + use lazy_static::lazy_static; +-use log::{debug, warn}; ++use log::debug; + + use syscare_abi::PatchStatus; + use syscare_common::{ +@@ -87,15 +87,10 @@ impl KernelPatchDriver { + } + } + +-impl PatchDriver for KernelPatchDriver { +- fn check(&self, patch: &Patch, flag: PatchOpFlag) -> Result<()> { ++impl KernelPatchDriver { ++ fn check_compatiblity(&self, patch: &Patch) -> Result<()> { + const KERNEL_NAME_PREFIX: &str = "kernel-"; + +- if flag == PatchOpFlag::SkipCheck { +- warn!("Skipped patch \"{}\" check", patch); +- return Ok(()); +- } +- + let kernel_version = os::kernel::version(); + let current_kernel = OsString::from(KERNEL_NAME_PREFIX).concat(kernel_version); + +@@ -113,18 +108,42 @@ impl PatchDriver for KernelPatchDriver { + ); + } + ++ Ok(()) ++ } ++ ++ fn check_consistency(&self, patch: &Patch) -> Result<()> { + let patch_ext: &KernelPatchExt = (&patch.info_ext).into(); + let patch_file = patch_ext.patch_file.as_path(); + let real_checksum = digest::file(patch_file)?; ++ debug!("Target checksum: {}", patch.checksum); ++ debug!("Expected checksum: {}", real_checksum); ++ + ensure!( + patch.checksum.eq(&real_checksum), +- "Kpatch: Patch file \"{}\" checksum failed", ++ "Kpatch: Patch \"{}\" consistency check failed", + patch_file.display() + ); + + Ok(()) + } + ++ fn check_confliction(&self, _patch: &Patch) -> Result<()> { ++ Ok(()) ++ } ++} ++ ++impl PatchDriver for KernelPatchDriver { ++ fn check(&self, patch: &Patch, flag: PatchOpFlag) -> Result<()> { ++ self.check_compatiblity(patch)?; ++ self.check_consistency(patch)?; ++ ++ if flag != PatchOpFlag::Force { ++ self.check_confliction(patch)?; ++ } ++ ++ Ok(()) ++ } ++ + fn status(&self, patch: &Patch, _flag: PatchOpFlag) -> Result { + Self::get_patch_status(patch) + } +diff --git a/daemon/src/patch/manager/driver/mod.rs b/daemon/src/patch/manager/driver/mod.rs +index 9beb999..c3a4ca4 100644 +--- a/daemon/src/patch/manager/driver/mod.rs ++++ b/daemon/src/patch/manager/driver/mod.rs +@@ -13,7 +13,7 @@ use super::entity::*; + #[derive(PartialEq, Clone, Copy)] + pub enum PatchOpFlag { + Normal, +- SkipCheck, ++ Force, + } + + /// Basic abstraction of patch operation +diff --git a/daemon/src/patch/manager/driver/upatch/mod.rs b/daemon/src/patch/manager/driver/upatch/mod.rs +index 993c116..e4a914b 100644 +--- a/daemon/src/patch/manager/driver/upatch/mod.rs ++++ b/daemon/src/patch/manager/driver/upatch/mod.rs +@@ -1,6 +1,5 @@ + use std::{ +- ffi::OsString, +- os::unix::prelude::OsStringExt, ++ ffi::CStr, + path::{Path, PathBuf}, + }; + +@@ -9,7 +8,7 @@ use anyhow::{anyhow, bail, ensure, Result}; + use indexmap::IndexMap; + use lazy_static::lazy_static; + use libc::{c_char, EEXIST, EFAULT, ENOENT, EPERM}; +-use log::{info, warn}; ++use log::{debug, info}; + use parking_lot::Mutex; + use syscare_abi::PatchStatus; + use syscare_common::util::digest; +@@ -92,25 +91,33 @@ impl UserPatchDriver { + } + } + +-impl PatchDriver for UserPatchDriver { +- fn check(&self, patch: &Patch, flag: PatchOpFlag) -> Result<()> { +- const ERR_MSG_LEN: usize = 512; +- +- if flag == PatchOpFlag::SkipCheck { +- warn!("Skipped patch \"{}\" check", patch); +- return Ok(()); +- } ++impl UserPatchDriver { ++ fn check_compatiblity(&self, _patch: &Patch) -> Result<()> { ++ Ok(()) ++ } + ++ fn check_consistency(&self, patch: &Patch) -> Result<()> { + let patch_ext: &UserPatchExt = (&patch.info_ext).into(); + let patch_file = &patch_ext.patch_file; + + let real_checksum = digest::file(patch_file).map_err(|e| anyhow!("Upatch: {}", e))?; ++ debug!("Target checksum: {}", patch.checksum); ++ debug!("Expected checksum: {}", real_checksum); ++ + ensure!( + patch.checksum.eq(&real_checksum), +- "Upatch: Patch file \"{}\" checksum failed", ++ "Upatch: Patch \"{}\" consistency check failed", + patch_file.display() + ); + ++ Ok(()) ++ } ++ ++ fn check_confliction(&self, patch: &Patch) -> Result<()> { ++ const ERR_MSG_LEN: usize = 512; ++ ++ let patch_ext: &UserPatchExt = (&patch.info_ext).into(); ++ + let target_elf = patch_ext.target_elf.to_cstring()?; + let patch_file = patch_ext.patch_file.to_cstring()?; + let mut msg_buf = vec![0; ERR_MSG_LEN]; +@@ -123,11 +130,28 @@ impl PatchDriver for UserPatchDriver { + msg_buf.capacity(), + ) + }; ++ if ret_val != 0 { ++ match CStr::from_bytes_until_nul(&msg_buf) { ++ Ok(err_msg) => bail!(format!("Upatch: {}", err_msg.to_string_lossy())), ++ Err(_) => bail!(format!( ++ "Upatch: {}", ++ std::io::Error::from_raw_os_error(ret_val) ++ )), ++ } ++ } + +- ensure!( +- ret_val == 0, +- OsString::from_vec(msg_buf).to_string_lossy().to_string() +- ); ++ Ok(()) ++ } ++} ++ ++impl PatchDriver for UserPatchDriver { ++ fn check(&self, patch: &Patch, flag: PatchOpFlag) -> Result<()> { ++ self.check_compatiblity(patch)?; ++ self.check_consistency(patch)?; ++ ++ if flag != PatchOpFlag::Force { ++ self.check_confliction(patch)?; ++ } + + Ok(()) + } +@@ -151,7 +175,7 @@ impl PatchDriver for UserPatchDriver { + patch_uuid.as_ptr(), + target_elf.as_ptr(), + patch_file.as_ptr(), +- matches!(flag, PatchOpFlag::SkipCheck), ++ matches!(flag, PatchOpFlag::Force), + ) + }; + +diff --git a/daemon/src/patch/manager/mod.rs b/daemon/src/patch/manager/mod.rs +index 3b1aa8c..fdb218d 100644 +--- a/daemon/src/patch/manager/mod.rs ++++ b/daemon/src/patch/manager/mod.rs +@@ -267,8 +267,7 @@ impl PatchManager { + "Restore patch \"{}\" status to \"{}\"", + patch, target_status + ); +- if let Err(e) = self.do_status_transition(&patch, target_status, PatchOpFlag::SkipCheck) +- { ++ if let Err(e) = self.do_status_transition(&patch, target_status, PatchOpFlag::Force) { + error!("{}", e); + } + } +diff --git a/daemon/src/patch/transaction.rs b/daemon/src/patch/transaction.rs +index 16bab46..079b024 100644 +--- a/daemon/src/patch/transaction.rs ++++ b/daemon/src/patch/transaction.rs +@@ -70,7 +70,7 @@ where + fn rollback(&mut self) -> Result<()> { + let mut patch_manager = self.patch_manager.write(); + while let Some((patch, status)) = self.finish_list.pop() { +- patch_manager.do_status_transition(&patch, status, PatchOpFlag::SkipCheck)?; ++ patch_manager.do_status_transition(&patch, status, PatchOpFlag::Force)?; + } + Ok(()) + } +diff --git a/daemon/src/rpc/skeleton_impl/patch.rs b/daemon/src/rpc/skeleton_impl/patch.rs +index 4517a03..8d4f57b 100644 +--- a/daemon/src/rpc/skeleton_impl/patch.rs ++++ b/daemon/src/rpc/skeleton_impl/patch.rs +@@ -82,7 +82,7 @@ impl PatchSkeleton for PatchSkeletonImpl { + PatchManager::apply_patch, + match force { + false => PatchOpFlag::Normal, +- true => PatchOpFlag::SkipCheck, ++ true => PatchOpFlag::Force, + }, + identifier, + )? +-- +2.33.0 + diff --git a/0007-upatch-elf-verification.patch b/0007-upatch-elf-verification.patch new file mode 100644 index 0000000..a77b254 --- /dev/null +++ b/0007-upatch-elf-verification.patch @@ -0,0 +1,217 @@ +From 727ece331961c5a495350b38afa982f1598e5b82 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 22 Dec 2023 13:45:48 +0800 +Subject: [PATCH 07/15] upatch: elf verification + +Signed-off-by: renoseven +--- + daemon/src/patch/manager/driver/upatch/mod.rs | 4 +- + upatch/upatch-manage/upatch-elf.c | 7 ++ + upatch/upatch-tool/log.h | 1 + + upatch/upatch-tool/upatch-elf.c | 102 ++++++++++-------- + upatch/upatch-tool/upatch-tool-lib.c | 9 +- + 5 files changed, 72 insertions(+), 51 deletions(-) + +diff --git a/daemon/src/patch/manager/driver/upatch/mod.rs b/daemon/src/patch/manager/driver/upatch/mod.rs +index e4a914b..4d06e84 100644 +--- a/daemon/src/patch/manager/driver/upatch/mod.rs ++++ b/daemon/src/patch/manager/driver/upatch/mod.rs +@@ -7,7 +7,7 @@ use anyhow::{anyhow, bail, ensure, Result}; + + use indexmap::IndexMap; + use lazy_static::lazy_static; +-use libc::{c_char, EEXIST, EFAULT, ENOENT, EPERM}; ++use libc::{c_char, EEXIST, EFAULT, ENOENT, ENOEXEC, EPERM}; + use log::{debug, info}; + use parking_lot::Mutex; + use syscare_abi::PatchStatus; +@@ -182,7 +182,7 @@ impl PatchDriver for UserPatchDriver { + match ret_val { + 0 => Ok(()), + EPERM => bail!("Upatch: Operation not permitted"), +- ENOENT => bail!("Upatch: Patch symbol is empty"), ++ ENOEXEC => bail!("Upatch: Patch format error"), + EEXIST => bail!("Upatch: Patch is already exist"), + _ => bail!("Upatch: {}", std::io::Error::from_raw_os_error(ret_val)), + } +diff --git a/upatch/upatch-manage/upatch-elf.c b/upatch/upatch-manage/upatch-elf.c +index 2bd3175..31180b5 100644 +--- a/upatch/upatch-manage/upatch-elf.c ++++ b/upatch/upatch-manage/upatch-elf.c +@@ -67,6 +67,13 @@ static int open_elf(struct elf_info *einfo, const char *name) + einfo->shdrs = (void *)einfo->hdr + einfo->hdr->e_shoff; + einfo->shstrtab = (void *)einfo->hdr + einfo->shdrs[einfo->hdr->e_shstrndx].sh_offset; + ++ void *einfo_eof = einfo->hdr + einfo->patch_size; ++ if ((void *)einfo->shdrs > einfo_eof || (void *)einfo->shstrtab > einfo_eof) { ++ log_error("File '%s' is not a valid elf\n", name); ++ ret = -ENOEXEC; ++ goto out; ++ } ++ + for (i = 0; i < einfo->hdr->e_shnum; ++i) { + sec_name = einfo->shstrtab + einfo->shdrs[i].sh_name; + if (streql(sec_name, BUILD_ID_NAME) && einfo->shdrs[i].sh_type == SHT_NOTE) { +diff --git a/upatch/upatch-tool/log.h b/upatch/upatch-tool/log.h +index 75213d8..e42e290 100644 +--- a/upatch/upatch-tool/log.h ++++ b/upatch/upatch-tool/log.h +@@ -11,5 +11,6 @@ + #define log_debug(format, ...) log(DEBUG, format, ##__VA_ARGS__) + #define log_normal(format, ...) log(NORMAL, format, ##__VA_ARGS__) + #define log_warn(format, ...) log(WARN, format, ##__VA_ARGS__) ++#define log_error(format, ...) log(ERR, format, ##__VA_ARGS__) + + #endif +diff --git a/upatch/upatch-tool/upatch-elf.c b/upatch/upatch-tool/upatch-elf.c +index 5b9b0bd..def536c 100644 +--- a/upatch/upatch-tool/upatch-elf.c ++++ b/upatch/upatch-tool/upatch-elf.c +@@ -44,53 +44,65 @@ out: + + static int open_elf(struct elf_info *einfo, const char *name) + { +- int ret = 0, fd = -1, i; +- char *sec_name; +- struct stat st; +- +- // TODO: check ELF +- fd = open(name, O_RDONLY); +- if (fd == -1) +- log_warn("open %s failed with errno %d \n", name, errno); ++ int ret = 0, fd = -1, i; ++ char *sec_name; ++ struct stat st; ++ ++ fd = open(name, O_RDONLY); ++ if (fd == -1) { ++ ret = -errno; ++ log_error("Failed to open file '%s', ret=%d\n", name, ret); ++ goto out; ++ } ++ ++ ret = stat(name, &st); ++ if (ret != 0) { ++ ret = -errno; ++ log_error("Failed to stat file '%s', ret=%d\n", name, ret); ++ goto out; ++ } ++ ++ ret = read_from_offset(fd, (void **)&einfo->patch_buff, st.st_size, 0); ++ if (ret != 0) { ++ log_error("Failed to read file '%s', ret=%d\n", name, ret); ++ goto out; ++ } ++ ++ einfo->name = name; ++ einfo->inode = st.st_ino; ++ einfo->patch_size = st.st_size; ++ einfo->hdr = (void *)einfo->patch_buff; ++ einfo->shdrs = (void *)einfo->hdr + einfo->hdr->e_shoff; ++ einfo->shstrtab = (void *)einfo->hdr + einfo->shdrs[einfo->hdr->e_shstrndx].sh_offset; ++ ++ void *einfo_eof = einfo->hdr + einfo->patch_size; ++ if ((void *)einfo->shdrs > einfo_eof || (void *)einfo->shstrtab > einfo_eof) { ++ log_error("File '%s' is not a valid elf\n", name); ++ ret = -ENOEXEC; ++ goto out; ++ } ++ ++ for (i = 0; i < einfo->hdr->e_shnum; ++i) { ++ sec_name = einfo->shstrtab + einfo->shdrs[i].sh_name; ++ if (streql(sec_name, BUILD_ID_NAME) && einfo->shdrs[i].sh_type == SHT_NOTE) { ++ einfo->num_build_id = i; ++ break; ++ } ++ } ++ ++ if (einfo->num_build_id == 0) { ++ ret = -EINVAL; ++ log_error("Cannot find section '%s'\n", BUILD_ID_NAME); ++ goto out; ++ } ++ ++ ret = 0; + +- ret = stat(name, &st); +- if (ret) +- log_warn("get %s stat failed with errno %d \n", name, errno); +- +- ret = read_from_offset(fd, (void **)&einfo->patch_buff, st.st_size, 0); +- if (ret) +- goto out; +- +- einfo->name = name; +- einfo->inode = st.st_ino; +- einfo->patch_size = st.st_size; +- einfo->hdr = (void *)einfo->patch_buff; +- einfo->shdrs = (void *)einfo->hdr + einfo->hdr->e_shoff; +- einfo->shstrtab = (void *)einfo->hdr + +- einfo->shdrs[einfo->hdr->e_shstrndx].sh_offset; +- +- for (i = 0; i < einfo->hdr->e_shnum; ++i) { +- sec_name = einfo->shstrtab + einfo->shdrs[i].sh_name; +- if (streql(sec_name, BUILD_ID_NAME) && +- einfo->shdrs[i].sh_type == SHT_NOTE) { +- einfo->num_build_id = i; +- break; +- } +- } +- +- if (einfo->num_build_id == 0) { +- ret = EINVAL; +- log_warn("no %s found \n", BUILD_ID_NAME); +- goto out; +- } +- +- log_warn("no %ld found \n", einfo->inode); +- +- ret = 0; + out: +- if (fd != -1) +- close(fd); +- return ret; ++ if (fd > 0) { ++ close(fd); ++ } ++ return ret; + } + + int upatch_init(struct upatch_elf *uelf, const char *name) +diff --git a/upatch/upatch-tool/upatch-tool-lib.c b/upatch/upatch-tool/upatch-tool-lib.c +index 4f816bb..4e5bda1 100644 +--- a/upatch/upatch-tool/upatch-tool-lib.c ++++ b/upatch/upatch-tool/upatch-tool-lib.c +@@ -22,7 +22,8 @@ int upatch_check(const char *target_elf, const char *patch_file, char *err_msg, + { + struct list_head *patch_syms = patch_symbols_resolve(target_elf, patch_file); + if (patch_syms == NULL) { +- return ENOENT; ++ snprintf(err_msg, max_len, "Patch format error"); ++ return ENOEXEC; + } + + struct list_head *collision_list = meta_get_symbol_collision(target_elf, patch_syms); +@@ -30,7 +31,7 @@ int upatch_check(const char *target_elf, const char *patch_file, char *err_msg, + return 0; + } + +- int offset = snprintf(err_msg, max_len, "Upatch: Patch is conflicted with "); ++ int offset = snprintf(err_msg, max_len, "Patch is conflicted with "); + symbol_collision *collision = NULL; + list_for_each_entry(collision, collision_list, self) { + err_msg += offset; +@@ -61,8 +62,8 @@ int upatch_load(const char *uuid, const char *target, const char *patch, bool fo + // Resolve patch symbols + struct list_head *patch_syms = patch_symbols_resolve(target, patch); + if (patch_syms == NULL) { +- log_warn("{%s}: Patch symbol is empty\n", uuid); +- return ENOENT; ++ log_warn("{%s}: Patch format error\n", uuid); ++ return ENOEXEC; + } + + // Check patch symbol collision +-- +2.33.0 + diff --git a/0008-upatch-check-build-id.patch b/0008-upatch-check-build-id.patch new file mode 100644 index 0000000..6c23fc3 --- /dev/null +++ b/0008-upatch-check-build-id.patch @@ -0,0 +1,42 @@ +From b23af1223e0a284a6dd603ed21c60612170d6767 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 18 Dec 2023 18:34:52 +0800 +Subject: [PATCH 08/15] upatch: check build id + +Signed-off-by: renoseven +--- + upatch/upatch-tool/upatch-resolve.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/upatch/upatch-tool/upatch-resolve.c b/upatch/upatch-tool/upatch-resolve.c +index d12bdae..aeb655c 100644 +--- a/upatch/upatch-tool/upatch-resolve.c ++++ b/upatch/upatch-tool/upatch-resolve.c +@@ -65,18 +65,22 @@ struct list_head* patch_symbols_resolve(const char *target_elf, const char *patc + INIT_LIST_HEAD(head); + + int ret = upatch_init(&uelf, patch_file); +- + if (ret < 0) { + log_warn("upatch-resolve: upatch_init failed\n"); + goto out; + } + + ret = binary_init(&relf, target_elf); +- if (ret) { ++ if (ret < 0) { + log_warn("upatch-resolve: binary_init failed %d \n", ret); + goto out; + } + ++ if (check_build_id(&uelf.info, &relf.info) == false) { ++ log_error("upatch-resolve: Build id mismatched!\n"); ++ goto out; ++ } ++ + uelf.relf = &relf; + upatch_shdr = &uelf.info.shdrs[uelf.index.upatch_funcs]; + upatch_funcs = uelf.info.patch_buff + upatch_shdr->sh_offset; +-- +2.33.0 + diff --git a/0009-README-add-example-for-kernel-module-patch-build.patch b/0009-README-add-example-for-kernel-module-patch-build.patch new file mode 100644 index 0000000..2e40573 --- /dev/null +++ b/0009-README-add-example-for-kernel-module-patch-build.patch @@ -0,0 +1,38 @@ +From bbfe75e66815319360af6e3773d78862ee7e65cc Mon Sep 17 00:00:00 2001 +From: ningyu +Date: Fri, 22 Dec 2023 06:33:51 +0000 +Subject: [PATCH 09/15] README: add example for kernel module patch build + +--- + README.md | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/README.md b/README.md +index 6c3728b..e86d063 100644 +--- a/README.md ++++ b/README.md +@@ -63,7 +63,20 @@ $ syscare build \ + --source ./redis-6.2.5-1.src.rpm \ + --debuginfo ./redis-debuginfo-6.2.5-1.x86_64.rpm \ + --output ./output \ +- ./0001-Prevent-unauthenticated-client-from-easily-consuming.patch ++ --patch ./0001-Prevent-unauthenticated-client-from-easily-consuming.patch ++``` ++ ++### 内核模块热补丁制作 ++``` ++$ syscare build \ ++ --patch-name HP001 \ ++ --source ./kernel-5.10.0-60.91.0.115.src.rpm \ ++ --source ./testmod-1-1.src.rpm \ ++ --debuginfo ./kernel-debuginfo-5.10.0-60.91.0.115.aarch64.rpm \ ++ --output ./output \ ++ --verbose \ ++ --skip-cleanup \ ++ --patch ./0001-test.patch + ``` + + 补丁制作详细使用说明请见[build/README.md](https://gitee.com/openeuler/syscare/blob/master/build/README.md) +-- +2.33.0 + diff --git a/0010-daemon-fix-check-build-id-logic.patch b/0010-daemon-fix-check-build-id-logic.patch new file mode 100644 index 0000000..8c87c8d --- /dev/null +++ b/0010-daemon-fix-check-build-id-logic.patch @@ -0,0 +1,41 @@ +From ed7492d5090a249c50c49501e8865c05de481c94 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 22 Dec 2023 15:22:03 +0800 +Subject: [PATCH 10/15] daemon: fix check build id logic + +Signed-off-by: renoseven +--- + upatch/upatch-tool/upatch-elf.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/upatch/upatch-tool/upatch-elf.c b/upatch/upatch-tool/upatch-elf.c +index def536c..730c3bd 100644 +--- a/upatch/upatch-tool/upatch-elf.c ++++ b/upatch/upatch-tool/upatch-elf.c +@@ -201,11 +201,18 @@ out: + + bool check_build_id(struct elf_info *uelf, struct elf_info *relf) + { +- return uelf->shdrs[uelf->num_build_id].sh_size == +- relf->shdrs[relf->num_build_id].sh_size && +- !memcmp(uelf->hdr + uelf->shdrs[uelf->num_build_id].sh_offset, +- relf->hdr + relf->shdrs[relf->num_build_id].sh_offset, +- uelf->shdrs[uelf->num_build_id].sh_size); ++ if (uelf->shdrs[uelf->num_build_id].sh_size != relf->shdrs[relf->num_build_id].sh_size) { ++ return false; ++ } ++ ++ void* uelf_build_id = (void *)uelf->hdr + uelf->shdrs[uelf->num_build_id].sh_offset; ++ void* relf_build_id = (void *)relf->hdr + relf->shdrs[relf->num_build_id].sh_offset; ++ size_t build_id_len = uelf->shdrs[uelf->num_build_id].sh_size; ++ ++ if (memcmp(uelf_build_id, relf_build_id, build_id_len) != 0) { ++ return false; ++ } ++ return true; + } + + void binary_close(struct running_elf *relf) +-- +2.33.0 + diff --git a/0011-upatch-diff-fix-a-nullptr-issue.patch b/0011-upatch-diff-fix-a-nullptr-issue.patch new file mode 100644 index 0000000..571f3ca --- /dev/null +++ b/0011-upatch-diff-fix-a-nullptr-issue.patch @@ -0,0 +1,40 @@ +From b4a11e983c78d7f856a551e058b84c0ea4bde8c7 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 18 Dec 2023 20:20:19 +0800 +Subject: [PATCH 11/15] upatch-diff: fix a nullptr issue + +Signed-off-by: renoseven +--- + upatch/upatch-diff/elf-correlate.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/upatch/upatch-diff/elf-correlate.c b/upatch/upatch-diff/elf-correlate.c +index 2dd665c..0773016 100644 +--- a/upatch/upatch-diff/elf-correlate.c ++++ b/upatch/upatch-diff/elf-correlate.c +@@ -116,11 +116,13 @@ static void correlate_section(struct section *sec_orig, struct section *sec_patc + __correlate_section(sec_orig->rela, sec_patched->rela); + } + +- if (sec_orig->secsym) ++ if (sec_orig->secsym && sec_patched->secsym) { + correlate_symbol(sec_orig->secsym, sec_patched->secsym); ++ } + +- if (sec_orig->sym) ++ if (sec_orig->sym) { + correlate_symbol(sec_orig->sym, sec_patched->sym); ++ } + } + + void upatch_correlate_sections(struct upatch_elf *uelf_source, struct upatch_elf *uelf_patched) +@@ -397,4 +399,4 @@ void upatch_correlate_static_local_variables(struct upatch_elf *uelf_source, str + } + + return check_static_variable_correlate(uelf_source, uelf_patched); +-} +\ No newline at end of file ++} +-- +2.33.0 + diff --git a/0012-daemon-fix-rust-1.60-compile-issue.patch b/0012-daemon-fix-rust-1.60-compile-issue.patch new file mode 100644 index 0000000..d972759 --- /dev/null +++ b/0012-daemon-fix-rust-1.60-compile-issue.patch @@ -0,0 +1,49 @@ +From d6ca7e72c9ab04bcebbd557e08f795dbbba1dc8a Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 22 Dec 2023 18:04:50 +0800 +Subject: [PATCH 12/15] daemon: fix rust 1.60 compile issue + +Signed-off-by: renoseven +--- + daemon/src/patch/manager/driver/upatch/mod.rs | 21 +++++++------------ + 1 file changed, 8 insertions(+), 13 deletions(-) + +diff --git a/daemon/src/patch/manager/driver/upatch/mod.rs b/daemon/src/patch/manager/driver/upatch/mod.rs +index 4d06e84..191b327 100644 +--- a/daemon/src/patch/manager/driver/upatch/mod.rs ++++ b/daemon/src/patch/manager/driver/upatch/mod.rs +@@ -1,7 +1,4 @@ +-use std::{ +- ffi::CStr, +- path::{Path, PathBuf}, +-}; ++use std::path::{Path, PathBuf}; + + use anyhow::{anyhow, bail, ensure, Result}; + +@@ -130,15 +127,13 @@ impl UserPatchDriver { + msg_buf.capacity(), + ) + }; +- if ret_val != 0 { +- match CStr::from_bytes_until_nul(&msg_buf) { +- Ok(err_msg) => bail!(format!("Upatch: {}", err_msg.to_string_lossy())), +- Err(_) => bail!(format!( +- "Upatch: {}", +- std::io::Error::from_raw_os_error(ret_val) +- )), +- } +- } ++ ensure!( ++ ret_val == 0, ++ format!( ++ "Upatch: {}", ++ String::from_utf8_lossy(&msg_buf).trim_end_matches(|c| c == '\0') ++ ) ++ ); + + Ok(()) + } +-- +2.33.0 + diff --git a/0013-upatchd-create-config-dir-at-startup.patch b/0013-upatchd-create-config-dir-at-startup.patch new file mode 100644 index 0000000..41ca4f0 --- /dev/null +++ b/0013-upatchd-create-config-dir-at-startup.patch @@ -0,0 +1,106 @@ +From 5feeef470d6088cc03e04e4a8f750b6f3ae816ba Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 27 Dec 2023 17:17:16 +0800 +Subject: [PATCH 13/15] upatchd: create config dir at startup + +1. rename arg '--config-file' to '--config-dir' +2. try to create config directory at startup + +Signed-off-by: renoseven +--- + upatch/upatch-daemon/src/args/matcher.rs | 4 ++-- + upatch/upatch-daemon/src/args/mod.rs | 8 ++++---- + upatch/upatch-daemon/src/main.rs | 7 ++++++- + 3 files changed, 12 insertions(+), 7 deletions(-) + +diff --git a/upatch/upatch-daemon/src/args/matcher.rs b/upatch/upatch-daemon/src/args/matcher.rs +index 66cf316..0badaf6 100644 +--- a/upatch/upatch-daemon/src/args/matcher.rs ++++ b/upatch/upatch-daemon/src/args/matcher.rs +@@ -2,8 +2,8 @@ use clap::{clap_app, crate_description, crate_name, crate_version, AppSettings, + + const DEFAULT_PID_FILE: &str = "/var/run/upatchd.pid"; + const DEFAULT_SOCKET_FILE: &str = "/var/run/upatchd.sock"; +-const DEFAULT_CONFIG_FILE: &str = "/etc/syscare/upatchd.yaml"; + const DEFAULT_WORK_DIR: &str = "/var/run/syscare"; ++const DEFAULT_CONFIG_DIR: &str = "/etc/syscare"; + const DEFAULT_LOG_DIR: &str = "/var/log/syscare"; + const DEFAULT_LOG_LEVEL: &str = "info"; + +@@ -24,7 +24,7 @@ impl ArgMatcher { + (@arg daemon: short("d") long("daemon") "Run as a daemon") + (@arg pid_file: long("pid-file") +takes_value value_name("PID_FILE") default_value(DEFAULT_PID_FILE) "Path for daemon pid file") + (@arg socket_file: long("socket-file") +takes_value value_name("SOCKET_FILE") default_value(DEFAULT_SOCKET_FILE) "Path for daemon unix socket") +- (@arg config_file: long("config-file") +takes_value value_name("CONFIG_FILE") default_value(DEFAULT_CONFIG_FILE) "Path for daemon config file") ++ (@arg config_file: long("config-dir") +takes_value value_name("CONFIG_DIR") default_value(DEFAULT_CONFIG_DIR) "Daemon config directory") + (@arg work_dir: long("work-dir") +takes_value value_name("WORK_DIR") default_value(DEFAULT_WORK_DIR) "Daemon working directory") + (@arg log_dir: long("log-dir") +takes_value value_name("LOG_DIR") default_value(DEFAULT_LOG_DIR) "Daemon logging directory") + (@arg log_level: short("l") long("log-level") +takes_value value_name("LOG_LEVEL") default_value(DEFAULT_LOG_LEVEL) "Set the logging level (\"trace\"|\"debug\"|\"info\"|\"warn\"|\"error\")") +diff --git a/upatch/upatch-daemon/src/args/mod.rs b/upatch/upatch-daemon/src/args/mod.rs +index e20d66b..318470e 100644 +--- a/upatch/upatch-daemon/src/args/mod.rs ++++ b/upatch/upatch-daemon/src/args/mod.rs +@@ -23,8 +23,8 @@ pub struct Arguments { + /// Path for daemon unix socket + pub socket_file: PathBuf, + +- /// Path for daemon configuration file +- pub config_file: PathBuf, ++ /// Daemon config directory ++ pub config_dir: PathBuf, + + /// Daemon working directory + pub work_dir: PathBuf, +@@ -45,7 +45,7 @@ impl Parser<'_> for Arguments { + daemon: ArgParserImpl::is_present(matches, "daemon"), + pid_file: ArgParserImpl::parse_arg(matches, "pid_file")?, + socket_file: ArgParserImpl::parse_arg(matches, "socket_file")?, +- config_file: ArgParserImpl::parse_arg(matches, "config_file")?, ++ config_dir: ArgParserImpl::parse_arg(matches, "config_dir")?, + work_dir: ArgParserImpl::parse_arg(matches, "work_dir")?, + log_dir: ArgParserImpl::parse_arg(matches, "log_dir")?, + log_level: ArgParserImpl::parse_arg(matches, "log_level")?, +@@ -64,7 +64,7 @@ impl Arguments { + fn normalize_pathes(mut self) -> Result { + self.pid_file = fs::normalize(&self.pid_file)?; + self.socket_file = fs::normalize(&self.socket_file)?; +- self.config_file = fs::normalize(&self.config_file)?; ++ self.config_dir = fs::normalize(&self.config_dir)?; + self.work_dir = fs::normalize(self.work_dir)?; + self.log_dir = fs::normalize(&self.log_dir)?; + +diff --git a/upatch/upatch-daemon/src/main.rs b/upatch/upatch-daemon/src/main.rs +index cda98b2..80c292f 100644 +--- a/upatch/upatch-daemon/src/main.rs ++++ b/upatch/upatch-daemon/src/main.rs +@@ -28,6 +28,8 @@ use args::Arguments; + use logger::Logger; + use rpc::{Skeleton, SkeletonImpl}; + ++const CONFIG_FILE_NAME: &str = "upatchd.yaml"; ++ + const DAEMON_VERSION: &str = env!("CARGO_PKG_VERSION"); + const DAEMON_UMASK: u32 = 0o027; + const DAEMON_PARK_TIMEOUT: u64 = 100; +@@ -67,6 +69,8 @@ impl Daemon { + } + + fn prepare_environment(&self) -> Result<()> { ++ self.prepare_directory(&self.args.config_dir)?; ++ + self.prepare_directory(&self.args.work_dir)?; + self.prepare_directory(&self.args.log_dir)?; + Ok(()) +@@ -99,7 +103,8 @@ impl Daemon { + fn initialize_skeleton(&self) -> Result { + let mut io_handler = IoHandler::new(); + +- io_handler.extend_with(SkeletonImpl::new(&self.args.config_file)?.to_delegate()); ++ let config_file = self.args.config_dir.join(CONFIG_FILE_NAME); ++ io_handler.extend_with(SkeletonImpl::new(config_file)?.to_delegate()); + + Ok(io_handler) + } +-- +2.33.0 + diff --git a/0014-syscare-move-files-to-working-directory.patch b/0014-syscare-move-files-to-working-directory.patch new file mode 100644 index 0000000..3830cec --- /dev/null +++ b/0014-syscare-move-files-to-working-directory.patch @@ -0,0 +1,1382 @@ +From c2c863a88390c7e479fc4c77350c01dd6edf8ac4 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 28 Dec 2023 10:32:42 +0800 +Subject: [PATCH 14/15] syscare: move files to working directory + +syscared & syscare: +1. move pid file to /var/run/syscare/syscared.pid +2. move socket file to /var/run/syscare/syscared.sock +3. move lock file to /var/run/syscare/patch_op.lock + +upatchd & upatch-build: +1. move pid file to /var/run/syscare/upatchd.pid +2. move socket file to /var/run/syscare/upatchd.sock +3. rewrite compiler hacking & unhacking logic + +syscare-build & upatch-build: +1. reuse '--work-dir' as daemon working directory, ie. /var/run/syscare +2. add '--build-root' as build temp directory +3. rename WorkDir to BuildRoot + +Signed-off-by: renoseven +--- + builder/src/args/matcher.rs | 6 +- + builder/src/args/mod.rs | 10 +- + builder/src/build_params.rs | 5 +- + builder/src/{workdir => build_root}/mod.rs | 8 +- + .../{workdir => build_root}/package_root.rs | 0 + .../src/{workdir => build_root}/patch_root.rs | 0 + builder/src/main.rs | 38 ++--- + .../src/patch/kernel_patch/kpatch_builder.rs | 6 +- + .../src/patch/user_patch/upatch_builder.rs | 10 +- + cli/src/args/matcher.rs | 4 +- + cli/src/args/mod.rs | 6 +- + cli/src/executor/patch.rs | 25 ++-- + cli/src/main.rs | 15 +- + daemon/src/args/matcher.rs | 4 - + daemon/src/args/mod.rs | 10 -- + daemon/src/main.rs | 36 +++-- + daemon/src/patch/manager/entity/mod.rs | 2 +- + .../upatch-build/src/upatch/args/matcher.rs | 6 +- + upatch/upatch-build/src/upatch/args/mod.rs | 18 ++- + upatch/upatch-build/src/upatch/build.rs | 51 ++++--- + .../src/upatch/{workdir.rs => build_root.rs} | 10 +- + upatch/upatch-build/src/upatch/compiler.rs | 137 +++++++----------- + upatch/upatch-build/src/upatch/mod.rs | 4 +- + upatch/upatch-daemon/src/args/matcher.rs | 6 +- + upatch/upatch-daemon/src/args/mod.rs | 10 -- + upatch/upatch-daemon/src/main.rs | 36 +++-- + 26 files changed, 238 insertions(+), 225 deletions(-) + rename builder/src/{workdir => build_root}/mod.rs (91%) + rename builder/src/{workdir => build_root}/package_root.rs (100%) + rename builder/src/{workdir => build_root}/patch_root.rs (100%) + rename upatch/upatch-build/src/upatch/{workdir.rs => build_root.rs} (89%) + +diff --git a/builder/src/args/matcher.rs b/builder/src/args/matcher.rs +index 8bc89a2..93e9420 100644 +--- a/builder/src/args/matcher.rs ++++ b/builder/src/args/matcher.rs +@@ -6,7 +6,8 @@ use syscare_common::os; + const DEFAULT_PATCH_VERSION: &str = "1"; + const DEFAULT_PATCH_RELEASE: &str = "1"; + const DEFAULT_PATCH_DESCRIPTION: &str = "(none)"; +-const DEFAULT_WORK_DIR: &str = "."; ++const DEFAULT_WORK_DIR: &str = "/var/run/syscare"; ++const DEFAULT_BUILD_ROOT: &str = "."; + const DEFAULT_OUTPUT_DIR: &str = "."; + + lazy_static! { +@@ -38,7 +39,8 @@ impl ArgMatcher { + (@arg source: short("s") long("source") +required +takes_value +multiple value_name("SOURCE") "Source package(s)") + (@arg debuginfo: short("d") long("debuginfo") +required +takes_value +multiple value_name("DEBUGINFO") "Debuginfo package(s)") + (@arg patch: short("p") long("patch") +required +takes_value +multiple value_name("PATCH") "Patch file(s)") +- (@arg workdir: long("workdir") +takes_value value_name("WORKDIR") default_value(DEFAULT_WORK_DIR) "Working directory") ++ (@arg work_dir: long("work-dir") +takes_value value_name("WORK_DIR") default_value(DEFAULT_WORK_DIR) "Working directory") ++ (@arg build_root: long("build-root") +takes_value value_name("BUILD_ROOT") default_value(DEFAULT_BUILD_ROOT) "Build temporary directory") + (@arg output: short("o") long("output") +takes_value value_name("OUTPUT") default_value(DEFAULT_OUTPUT_DIR) "Output directory") + (@arg jobs: short("j") long("jobs") +takes_value value_name("JOBS") default_value(&DEFAULT_BUILD_JOBS) "Parallel build jobs") + (@arg skip_compiler_check: long("skip-compiler-check") "Skip compiler version check (not recommended)") +diff --git a/builder/src/args/mod.rs b/builder/src/args/mod.rs +index 7fe575b..f81d26e 100644 +--- a/builder/src/args/mod.rs ++++ b/builder/src/args/mod.rs +@@ -41,7 +41,10 @@ pub struct Arguments { + pub patch: Vec, + + /// Working directory +- pub workdir: PathBuf, ++ pub work_dir: PathBuf, ++ ++ /// Build temporary directory ++ pub build_root: PathBuf, + + /// Generated patch output directory + pub output: PathBuf, +@@ -74,7 +77,8 @@ impl Parser<'_> for Arguments { + source: ArgParserImpl::parse_args(matches, "source")?, + debuginfo: ArgParserImpl::parse_args(matches, "debuginfo")?, + patch: ArgParserImpl::parse_args(matches, "patch")?, +- workdir: ArgParserImpl::parse_arg(matches, "workdir")?, ++ work_dir: ArgParserImpl::parse_arg(matches, "work_dir")?, ++ build_root: ArgParserImpl::parse_arg(matches, "build_root")?, + output: ArgParserImpl::parse_arg(matches, "output")?, + jobs: ArgParserImpl::parse_arg(matches, "jobs")?, + skip_compiler_check: ArgParserImpl::is_present(matches, "skip_compiler_check"), +@@ -102,7 +106,7 @@ impl Arguments { + for patch_file in &mut self.patch { + *patch_file = fs::normalize(&patch_file)?; + } +- self.workdir = fs::normalize(&self.workdir)?; ++ self.build_root = fs::normalize(&self.build_root)?; + self.output = fs::normalize(&self.output)?; + + Ok(self) +diff --git a/builder/src/build_params.rs b/builder/src/build_params.rs +index f252ec7..a8296a3 100644 +--- a/builder/src/build_params.rs ++++ b/builder/src/build_params.rs +@@ -2,7 +2,7 @@ use std::path::PathBuf; + + use syscare_abi::{PackageInfo, PatchFile, PatchType}; + +-use crate::{package::PackageBuildRoot, workdir::WorkDir}; ++use crate::{build_root::BuildRoot, package::PackageBuildRoot}; + + #[derive(Debug, Clone)] + pub struct BuildEntry { +@@ -12,7 +12,8 @@ pub struct BuildEntry { + } + + pub struct BuildParameters { +- pub workdir: WorkDir, ++ pub work_dir: PathBuf, ++ pub build_root: BuildRoot, + pub pkg_build_root: PackageBuildRoot, + pub build_entry: BuildEntry, + pub kernel_build_entry: Option, +diff --git a/builder/src/workdir/mod.rs b/builder/src/build_root/mod.rs +similarity index 91% +rename from builder/src/workdir/mod.rs +rename to builder/src/build_root/mod.rs +index 871e628..329a318 100644 +--- a/builder/src/workdir/mod.rs ++++ b/builder/src/build_root/mod.rs +@@ -19,14 +19,14 @@ const PATCH_ROOT_NAME: &str = "patch"; + const BUILD_LOG_NAME: &str = "build.log"; + + #[derive(Debug, Clone)] +-pub struct WorkDir { ++pub struct BuildRoot { + pub path: PathBuf, + pub package: PackageRoot, + pub patch: PatchRoot, + pub log_file: PathBuf, + } + +-impl WorkDir { ++impl BuildRoot { + pub fn new>(path: P) -> Result { + let path = path.as_ref().to_path_buf(); + let package = PackageRoot::new(path.join(PACKAGE_ROOT_NAME))?; +@@ -46,7 +46,7 @@ impl WorkDir { + } + } + +-impl Deref for WorkDir { ++impl Deref for BuildRoot { + type Target = Path; + + fn deref(&self) -> &Self::Target { +@@ -54,7 +54,7 @@ impl Deref for WorkDir { + } + } + +-impl AsRef for WorkDir { ++impl AsRef for BuildRoot { + fn as_ref(&self) -> &OsStr { + self.as_os_str() + } +diff --git a/builder/src/workdir/package_root.rs b/builder/src/build_root/package_root.rs +similarity index 100% +rename from builder/src/workdir/package_root.rs +rename to builder/src/build_root/package_root.rs +diff --git a/builder/src/workdir/patch_root.rs b/builder/src/build_root/patch_root.rs +similarity index 100% +rename from builder/src/workdir/patch_root.rs +rename to builder/src/build_root/patch_root.rs +diff --git a/builder/src/main.rs b/builder/src/main.rs +index 3e92019..1b40122 100644 +--- a/builder/src/main.rs ++++ b/builder/src/main.rs +@@ -1,5 +1,5 @@ + use std::path::{Path, PathBuf}; +-use std::{ops::Deref, process::exit, sync::Arc}; ++use std::{process::exit, sync::Arc}; + + use anyhow::{anyhow, bail, ensure, Context, Result}; + use lazy_static::lazy_static; +@@ -11,18 +11,18 @@ use syscare_common::{os, util::fs}; + + mod args; + mod build_params; ++mod build_root; + mod logger; + mod package; + mod patch; + mod util; +-mod workdir; + + use args::Arguments; + use build_params::{BuildEntry, BuildParameters}; ++use build_root::BuildRoot; + use logger::Logger; + use package::{PackageBuildRoot, PackageBuilderFactory, PackageFormat, PackageImpl}; + use patch::{PatchBuilderFactory, PatchHelper, PatchMetadata, PATCH_FILE_EXT}; +-use workdir::WorkDir; + + use crate::package::{PackageSpecBuilderFactory, PackageSpecWriterFactory}; + +@@ -37,7 +37,7 @@ lazy_static! { + + pub struct SyscareBuilder { + args: Arguments, +- workdir: WorkDir, ++ build_root: BuildRoot, + } + + impl SyscareBuilder { +@@ -200,7 +200,7 @@ impl SyscareBuilder { + } + + fn prepare_to_build(&mut self) -> Result { +- let pkg_root = &self.workdir.package; ++ let pkg_root = &self.build_root.package; + + debug!("- Collecting patch file(s)"); + let mut patch_files = PatchHelper::collect_patch_files(&self.args.patch) +@@ -249,7 +249,8 @@ impl SyscareBuilder { + + debug!("- Generating build parameters"); + let build_params = BuildParameters { +- workdir: self.workdir.to_owned(), ++ work_dir: self.args.work_dir.to_owned(), ++ build_root: self.build_root.to_owned(), + pkg_build_root, + build_entry, + kernel_build_entry, +@@ -271,10 +272,10 @@ impl SyscareBuilder { + } + + fn build_patch_package(&self, patch_info: &PatchInfo) -> Result<()> { +- let pkg_build_root = &self.workdir.package.build_root; ++ let pkg_build_root = &self.build_root.package.build_root; + let pkg_source_dir = &pkg_build_root.sources; + let pkg_spec_dir = &pkg_build_root.specs; +- let patch_output_dir = &self.workdir.patch.output; ++ let patch_output_dir = &self.build_root.patch.output; + + debug!("- Writing patch metadata"); + let metadata_file = pkg_source_dir.join(PatchMetadata::metadata_file_name()); +@@ -359,23 +360,24 @@ impl SyscareBuilder { + } + + fn clean_up(&mut self) { +- self.workdir.remove().ok(); ++ self.build_root.remove().ok(); + } + } + + impl SyscareBuilder { + fn new() -> Result { +- let args = Arguments::new()?; ++ let mut args = Arguments::new()?; + Self::check_input_args(&args)?; + + os::umask::set_umask(CLI_UMASK); +- let workdir = WorkDir::new( +- args.workdir +- .join(format!("syscare-build.{}", os::process::id())), +- )?; ++ ++ args.build_root = args ++ .build_root ++ .join(format!("syscare-build.{}", os::process::id())); ++ let build_root = BuildRoot::new(&args.build_root)?; + + Logger::initialize( +- workdir.deref(), ++ &args.build_root, + LevelFilter::Trace, + match &args.verbose { + false => LevelFilter::Info, +@@ -383,7 +385,7 @@ impl SyscareBuilder { + }, + )?; + +- Ok(SyscareBuilder { args, workdir }) ++ Ok(SyscareBuilder { args, build_root }) + } + + fn check_input_args(args: &Arguments) -> Result<()> { +@@ -407,7 +409,7 @@ impl SyscareBuilder { + } + } + +- let workdir = &args.workdir; ++ let workdir = &args.work_dir; + if !workdir.exists() { + fs::create_dir_all(workdir)?; + } +@@ -431,7 +433,7 @@ impl SyscareBuilder { + } + + fn build_main(mut self, log_file: Arc>) -> Result<()> { +- *log_file.lock() = self.workdir.log_file.clone(); ++ *log_file.lock() = self.build_root.log_file.clone(); + + info!("=============================="); + info!("{}", CLI_ABOUT); +diff --git a/builder/src/patch/kernel_patch/kpatch_builder.rs b/builder/src/patch/kernel_patch/kpatch_builder.rs +index 69c0cee..eec39a6 100644 +--- a/builder/src/patch/kernel_patch/kpatch_builder.rs ++++ b/builder/src/patch/kernel_patch/kpatch_builder.rs +@@ -59,8 +59,8 @@ impl KernelPatchBuilder { + + debug!("- Finding kernel directories"); + let pkg_build_dir = build_params.pkg_build_root.build.clone(); +- let patch_build_root = build_params.workdir.patch.build.clone(); +- let patch_output_dir: PathBuf = build_params.workdir.patch.output.clone(); ++ let patch_build_root = build_params.build_root.patch.build.clone(); ++ let patch_output_dir: PathBuf = build_params.build_root.patch.output.clone(); + + let kernel_pkg = &kernel_entry.target_pkg; + let kernel_source_dir: PathBuf = PKG_IMPL +@@ -72,7 +72,7 @@ impl KernelPatchBuilder { + ), + ) + .context("Cannot find kernel source directory")?; +- let kernel_debug_dir = &build_params.workdir.package.debuginfo; ++ let kernel_debug_dir = &build_params.build_root.package.debuginfo; + let oot_source_dir = oot_module_entry.map(|build_entry| build_entry.build_source.clone()); + + debug!("- Generating kernel default config"); +diff --git a/builder/src/patch/user_patch/upatch_builder.rs b/builder/src/patch/user_patch/upatch_builder.rs +index 89166fa..5901656 100644 +--- a/builder/src/patch/user_patch/upatch_builder.rs ++++ b/builder/src/patch/user_patch/upatch_builder.rs +@@ -26,6 +26,7 @@ lazy_static! { + } + + struct UBuildParameters { ++ work_dir: PathBuf, + pkg_binary_dir: PathBuf, + pkg_output_dir: PathBuf, + patch_build_root: PathBuf, +@@ -89,11 +90,11 @@ impl UserPatchBuilder { + let pkg_build_root = &build_params.pkg_build_root; + let pkg_binary_dir = pkg_build_root.buildroot.clone(); + let pkg_output_dir = pkg_build_root.rpms.clone(); +- let debuginfo_pkg_root = &build_params.workdir.package.debuginfo; ++ let debuginfo_pkg_root = &build_params.build_root.package.debuginfo; + + let build_entry = &build_params.build_entry; +- let patch_build_root = build_params.workdir.patch.build.clone(); +- let patch_output_dir = build_params.workdir.patch.output.clone(); ++ let patch_build_root = build_params.build_root.patch.build.clone(); ++ let patch_output_dir = build_params.build_root.patch.output.clone(); + let patch_source_dir = build_entry.build_source.clone(); + + let patch_spec = &build_entry.build_spec; +@@ -136,6 +137,7 @@ impl UserPatchBuilder { + } + + let ubuild_params = UBuildParameters { ++ work_dir: build_params.work_dir.to_owned(), + pkg_binary_dir, + pkg_output_dir, + patch_build_root, +@@ -163,6 +165,8 @@ impl UserPatchBuilder { + fn parse_ubuild_cmd_args(&self, ubuild_params: &UBuildParameters) -> ExternCommandArgs { + let mut cmd_args = ExternCommandArgs::new() + .arg("--work-dir") ++ .arg(&ubuild_params.work_dir) ++ .arg("--build-root") + .arg(&ubuild_params.patch_build_root) + .arg("--source-dir") + .arg(&ubuild_params.patch_source_dir) +diff --git a/cli/src/args/matcher.rs b/cli/src/args/matcher.rs +index de041a9..eb8cb97 100644 +--- a/cli/src/args/matcher.rs ++++ b/cli/src/args/matcher.rs +@@ -1,6 +1,6 @@ + use clap::{clap_app, crate_description, crate_name, crate_version, AppSettings, ArgMatches}; + +-const DEFAULT_SOCKET_FILE: &str = "/var/run/syscared.sock"; ++const DEFAULT_WORK_DIR: &str = "/var/run/syscare"; + + pub struct ArgMatcher; + +@@ -21,7 +21,7 @@ impl ArgMatcher { + AppSettings::VersionlessSubcommands, + AppSettings::DisableHelpSubcommand, + ]) +- (@arg socket_file: short("s") long("socket-file") value_name("SOCKET_FILE") +takes_value default_value(DEFAULT_SOCKET_FILE) "Path for daemon unix socket") ++ (@arg work_dir: short("w") long("work-dir") value_name("WORK_DIR") +takes_value default_value(DEFAULT_WORK_DIR) "Path for working directory") + (@arg verbose: short("v") long("verbose") "Provide more detailed info") + (@subcommand build => + (about: "Build a patch") +diff --git a/cli/src/args/mod.rs b/cli/src/args/mod.rs +index 19ea65b..e0a2467 100644 +--- a/cli/src/args/mod.rs ++++ b/cli/src/args/mod.rs +@@ -17,7 +17,7 @@ use syscare_common::util::fs; + #[derive(Debug)] + pub struct Arguments { + pub command: SubCommand, +- pub socket_file: PathBuf, ++ pub work_dir: PathBuf, + pub verbose: bool, + } + +@@ -30,7 +30,7 @@ impl Arguments { + } + + fn normalize_pathes(mut self) -> Result { +- self.socket_file = fs::normalize(self.socket_file)?; ++ self.work_dir = fs::normalize(self.work_dir)?; + Ok(self) + } + } +@@ -42,7 +42,7 @@ impl Parser<'_> for Arguments { + { + Ok(Self { + command: SubCommand::parse(matches)?, +- socket_file: ArgParserImpl::parse_arg(matches, "socket_file")?, ++ work_dir: ArgParserImpl::parse_arg(matches, "work_dir")?, + verbose: ArgParserImpl::parse_arg(matches, "verbose")?, + }) + } +diff --git a/cli/src/executor/patch.rs b/cli/src/executor/patch.rs +index 1c9711e..e61c1da 100644 +--- a/cli/src/executor/patch.rs ++++ b/cli/src/executor/patch.rs +@@ -1,3 +1,5 @@ ++use std::path::PathBuf; ++ + use anyhow::{anyhow, ensure, Error, Result}; + use log::info; + +@@ -7,15 +9,14 @@ use crate::{args::SubCommand, flock::ExclusiveFileLockGuard, rpc::RpcProxy}; + + use super::CommandExecutor; + +-const PATCH_OP_LOCK_PATH: &str = "/tmp/syscare_patch_op.lock"; +- + pub struct PatchCommandExecutor { + proxy: RpcProxy, ++ lock_file: PathBuf, + } + + impl PatchCommandExecutor { +- pub fn new(proxy: RpcProxy) -> Self { +- Self { proxy } ++ pub fn new(proxy: RpcProxy, lock_file: PathBuf) -> Self { ++ Self { proxy, lock_file } + } + } + +@@ -122,7 +123,7 @@ impl CommandExecutor for PatchCommandExecutor { + Self::show_patch_list(self.proxy.get_patch_list()?); + } + SubCommand::Check { identifiers } => { +- let _flock_guard = ExclusiveFileLockGuard::new(PATCH_OP_LOCK_PATH)?; ++ let _flock_guard = ExclusiveFileLockGuard::new(&self.lock_file)?; + + let mut error_list = vec![]; + for identifier in identifiers { +@@ -134,7 +135,7 @@ impl CommandExecutor for PatchCommandExecutor { + ensure!(error_list.is_empty(), Self::build_error_msg(error_list)); + } + SubCommand::Apply { identifiers, force } => { +- let _flock_guard = ExclusiveFileLockGuard::new(PATCH_OP_LOCK_PATH)?; ++ let _flock_guard = ExclusiveFileLockGuard::new(&self.lock_file)?; + + let mut status_list = vec![]; + let mut error_list = vec![]; +@@ -149,7 +150,7 @@ impl CommandExecutor for PatchCommandExecutor { + ensure!(error_list.is_empty(), Self::build_error_msg(error_list)); + } + SubCommand::Remove { identifiers } => { +- let _flock_guard = ExclusiveFileLockGuard::new(PATCH_OP_LOCK_PATH)?; ++ let _flock_guard = ExclusiveFileLockGuard::new(&self.lock_file)?; + + let mut status_list = vec![]; + let mut error_list = vec![]; +@@ -164,7 +165,7 @@ impl CommandExecutor for PatchCommandExecutor { + ensure!(error_list.is_empty(), Self::build_error_msg(error_list)); + } + SubCommand::Active { identifiers } => { +- let _flock_guard = ExclusiveFileLockGuard::new(PATCH_OP_LOCK_PATH)?; ++ let _flock_guard = ExclusiveFileLockGuard::new(&self.lock_file)?; + + let mut status_list = vec![]; + let mut error_list = vec![]; +@@ -179,7 +180,7 @@ impl CommandExecutor for PatchCommandExecutor { + ensure!(error_list.is_empty(), Self::build_error_msg(error_list)); + } + SubCommand::Deactive { identifiers } => { +- let _flock_guard = ExclusiveFileLockGuard::new(PATCH_OP_LOCK_PATH)?; ++ let _flock_guard = ExclusiveFileLockGuard::new(&self.lock_file)?; + + let mut status_list = vec![]; + let mut error_list = vec![]; +@@ -194,7 +195,7 @@ impl CommandExecutor for PatchCommandExecutor { + ensure!(error_list.is_empty(), Self::build_error_msg(error_list)); + } + SubCommand::Accept { identifiers } => { +- let _flock_guard = ExclusiveFileLockGuard::new(PATCH_OP_LOCK_PATH)?; ++ let _flock_guard = ExclusiveFileLockGuard::new(&self.lock_file)?; + + let mut status_list = vec![]; + let mut error_list = vec![]; +@@ -209,12 +210,12 @@ impl CommandExecutor for PatchCommandExecutor { + ensure!(error_list.is_empty(), Self::build_error_msg(error_list)); + } + SubCommand::Save => { +- let _flock_guard = ExclusiveFileLockGuard::new(PATCH_OP_LOCK_PATH)?; ++ let _flock_guard = ExclusiveFileLockGuard::new(&self.lock_file)?; + + self.proxy.save_patch_status()?; + } + SubCommand::Restore { accepted } => { +- let _flock_guard = ExclusiveFileLockGuard::new(PATCH_OP_LOCK_PATH)?; ++ let _flock_guard = ExclusiveFileLockGuard::new(&self.lock_file)?; + + self.proxy.restore_patch_status(*accepted)?; + } +diff --git a/cli/src/main.rs b/cli/src/main.rs +index ef0878f..d0ac5b9 100644 +--- a/cli/src/main.rs ++++ b/cli/src/main.rs +@@ -13,6 +13,12 @@ use args::Arguments; + use executor::{build::BuildCommandExecutor, patch::PatchCommandExecutor, CommandExecutor}; + use logger::Logger; + use rpc::{RpcProxy, RpcRemote}; ++use syscare_common::os; ++ ++const CLI_UMASK: u32 = 0o077; ++ ++const SOCKET_FILE_NAME: &str = "syscared.sock"; ++const PATCH_OP_LOCK_NAME: &str = "patch_op.lock"; + + struct SyscareCLI { + args: Arguments, +@@ -20,6 +26,8 @@ struct SyscareCLI { + + impl SyscareCLI { + fn start_and_run() -> Result<()> { ++ os::umask::set_umask(CLI_UMASK); ++ + let instance = Self { + args: Arguments::new()?, + }; +@@ -30,15 +38,18 @@ impl SyscareCLI { + debug!("Start with {:#?}", instance.args); + + debug!("Initializing remote procedure call client..."); +- let remote = Rc::new(RpcRemote::new(&instance.args.socket_file)); ++ let socket_file = instance.args.work_dir.join(SOCKET_FILE_NAME); ++ let remote = Rc::new(RpcRemote::new(socket_file)); + + debug!("Initializing remote procedure calls..."); + let patch_proxy = RpcProxy::new(remote); + + debug!("Initializing command executors..."); ++ let patch_lock_file = instance.args.work_dir.join(PATCH_OP_LOCK_NAME); + let executors = vec![ + Box::new(BuildCommandExecutor) as Box, +- Box::new(PatchCommandExecutor::new(patch_proxy)) as Box, ++ Box::new(PatchCommandExecutor::new(patch_proxy, patch_lock_file)) ++ as Box, + ]; + + let command = instance.args.command; +diff --git a/daemon/src/args/matcher.rs b/daemon/src/args/matcher.rs +index 2fbca35..d3d2203 100644 +--- a/daemon/src/args/matcher.rs ++++ b/daemon/src/args/matcher.rs +@@ -1,7 +1,5 @@ + use clap::{clap_app, crate_description, crate_name, crate_version, AppSettings, ArgMatches}; + +-const DEFAULT_PID_FILE: &str = "/var/run/syscared.pid"; +-const DEFAULT_SOCKET_FILE: &str = "/var/run/syscared.sock"; + const DEFAULT_DATA_DIR: &str = "/usr/lib/syscare"; + const DEFAULT_WORK_DIR: &str = "/var/run/syscare"; + const DEFAULT_LOG_DIR: &str = "/var/log/syscare"; +@@ -22,8 +20,6 @@ impl ArgMatcher { + AppSettings::UnifiedHelpMessage, + ]) + (@arg daemon: short("d") long("daemon") "Run as a daemon") +- (@arg pid_file: long("pid-file") +takes_value value_name("PID_FILE") default_value(DEFAULT_PID_FILE) "Path for daemon pid file") +- (@arg socket_file: long("socket-file") +takes_value value_name("SOCKET_FILE") default_value(DEFAULT_SOCKET_FILE) "Path for daemon unix socket") + (@arg data_dir: long("data-dir") +takes_value value_name("DATA_DIR") default_value(DEFAULT_DATA_DIR) "Daemon data directory") + (@arg work_dir: long("work-dir") +takes_value value_name("WORK_DIR") default_value(DEFAULT_WORK_DIR) "Daemon working directory") + (@arg log_dir: long("log-dir") +takes_value value_name("LOG_DIR") default_value(DEFAULT_LOG_DIR) "Daemon logging directory") +diff --git a/daemon/src/args/mod.rs b/daemon/src/args/mod.rs +index cdac224..5273609 100644 +--- a/daemon/src/args/mod.rs ++++ b/daemon/src/args/mod.rs +@@ -17,12 +17,6 @@ pub struct Arguments { + /// Run as a daemon + pub daemon: bool, + +- /// Path for daemon pid file +- pub pid_file: PathBuf, +- +- /// Path for daemon unix socket +- pub socket_file: PathBuf, +- + /// Daemon working directory + pub work_dir: PathBuf, + +@@ -43,8 +37,6 @@ impl Parser<'_> for Arguments { + { + Ok(Self { + daemon: ArgParserImpl::is_present(matches, "daemon"), +- pid_file: ArgParserImpl::parse_arg(matches, "pid_file")?, +- socket_file: ArgParserImpl::parse_arg(matches, "socket_file")?, + work_dir: ArgParserImpl::parse_arg(matches, "work_dir")?, + data_dir: ArgParserImpl::parse_arg(matches, "data_dir")?, + log_dir: ArgParserImpl::parse_arg(matches, "log_dir")?, +@@ -62,8 +54,6 @@ impl Arguments { + } + + fn normalize_pathes(mut self) -> Result { +- self.pid_file = fs::normalize(&self.pid_file)?; +- self.socket_file = fs::normalize(&self.socket_file)?; + self.work_dir = fs::normalize(self.work_dir)?; + self.data_dir = fs::normalize(&self.data_dir)?; + self.log_dir = fs::normalize(&self.log_dir)?; +diff --git a/daemon/src/main.rs b/daemon/src/main.rs +index 094c6fc..e926859 100644 +--- a/daemon/src/main.rs ++++ b/daemon/src/main.rs +@@ -1,5 +1,6 @@ + use std::{ +- fs, ++ fs::{self, Permissions}, ++ os::unix::fs::PermissionsExt, + path::Path, + process, + sync::{ +@@ -36,8 +37,12 @@ use rpc::{ + use crate::patch::{PatchManager, PatchMonitor}; + + const DAEMON_VERSION: &str = env!("CARGO_PKG_VERSION"); +-const DAEMON_UMASK: u32 = 0o027; +-const DAEMON_SLEEP_TIME: u64 = 100; ++const DAEMON_UMASK: u32 = 0o077; ++const DAEMON_PARK_TIME: u64 = 100; ++ ++const WORK_DIR_PERMISSION: u32 = 0o755; ++const PID_FILE_NAME: &str = "syscared.pid"; ++const SOCKET_FILE_NAME: &str = "syscared.sock"; + + struct Daemon { + args: Arguments, +@@ -75,6 +80,11 @@ impl Daemon { + + fn prepare_environment(&self) -> Result<()> { + self.prepare_directory(&self.args.work_dir)?; ++ fs::set_permissions( ++ &self.args.work_dir, ++ Permissions::from_mode(WORK_DIR_PERMISSION), ++ )?; ++ + self.prepare_directory(&self.args.data_dir)?; + self.prepare_directory(&self.args.log_dir)?; + +@@ -97,10 +107,11 @@ impl Daemon { + return Ok(()); + } + ++ let pid_file = self.args.work_dir.join(PID_FILE_NAME); + Daemonize::new() +- .pid_file(&self.args.pid_file) +- .working_directory(&self.args.work_dir) + .umask(DAEMON_UMASK) ++ .working_directory(&self.args.work_dir) ++ .pid_file(pid_file) + .start() + .context("Daemonize failed") + } +@@ -124,15 +135,14 @@ impl Daemon { + } + + fn start_rpc_server(&self, io_handler: IoHandler) -> Result { +- let socket_path = &self +- .args +- .socket_file +- .to_str() +- .context("Failed to convert socket path to string")?; +- ++ let socket_file = self.args.work_dir.join(SOCKET_FILE_NAME); + let server = ServerBuilder::new(io_handler) + .set_client_buffer_size(1) +- .start(socket_path)?; ++ .start( ++ socket_file ++ .to_str() ++ .context("Failed to convert socket path to string")?, ++ )?; + + Ok(server) + } +@@ -177,7 +187,7 @@ impl Daemon { + + info!("Daemon is running..."); + while !instance.term_flag.load(Ordering::Relaxed) { +- std::thread::sleep(Duration::from_millis(DAEMON_SLEEP_TIME)); ++ std::thread::park_timeout(Duration::from_millis(DAEMON_PARK_TIME)); + } + + info!("Shutting down..."); +diff --git a/daemon/src/patch/manager/entity/mod.rs b/daemon/src/patch/manager/entity/mod.rs +index 2f17abe..f9c4130 100644 +--- a/daemon/src/patch/manager/entity/mod.rs ++++ b/daemon/src/patch/manager/entity/mod.rs +@@ -110,7 +110,7 @@ impl std::cmp::Eq for Patch {} + + impl std::cmp::PartialOrd for Patch { + fn partial_cmp(&self, other: &Self) -> Option { +- self.entity_name.partial_cmp(&other.entity_name) ++ Some(self.entity_name.cmp(&other.entity_name)) + } + } + impl std::cmp::Ord for Patch { +diff --git a/upatch/upatch-build/src/upatch/args/matcher.rs b/upatch/upatch-build/src/upatch/args/matcher.rs +index 11bdbf0..6e82837 100644 +--- a/upatch/upatch-build/src/upatch/args/matcher.rs ++++ b/upatch/upatch-build/src/upatch/args/matcher.rs +@@ -1,6 +1,7 @@ + use clap::{clap_app, crate_description, crate_name, crate_version, AppSettings, ArgMatches}; + +-const DEFAULT_WORK_DIR: &str = "~/.upatch"; ++const DEFAULT_WORK_DIR: &str = "/var/run/syscare"; ++const DEFAULT_BUILD_ROOT: &str = "~/.upatch"; + const DEFAULT_BUILD_PATCH_CMD: &str = ""; + const DEFAULT_COMPILERS: &str = "gcc"; + const DEFAULT_OUTPUT_DIR: &str = "~/.upatch"; +@@ -21,7 +22,8 @@ impl ArgMatcher { + AppSettings::UnifiedHelpMessage, + ]) + (@arg name: short("n") long("name") +takes_value value_name("NAME") "Specify output name") +- (@arg work_dir: short("w") long("work-dir") +takes_value value_name("WORK_DIR") default_value(DEFAULT_WORK_DIR) "Specify working directory") ++ (@arg work_dir: long("work-dir") +takes_value value_name("WORK_DIR") default_value(DEFAULT_WORK_DIR) "Specify working directory") ++ (@arg build_root: long("build-root") +takes_value value_name("BUILD_ROOT") default_value(DEFAULT_BUILD_ROOT) "Specify build temporary directory") + (@arg source_dir: short("s") long("source-dir") +required +takes_value value_name("SOURCE_DIR") "Specify source directory") + (@arg build_source_cmd: short("b") long("build-source-cmd") +required +takes_value value_name("BUILD_SOURCE_CMD") "Specify build source command") + (@arg build_patch_cmd: long("build-patch-cmd") +takes_value value_name("BUILD_PATCH_CMD") default_value(DEFAULT_BUILD_PATCH_CMD) +hide_default_value "Specify build patched source command [default: ]") +diff --git a/upatch/upatch-build/src/upatch/args/mod.rs b/upatch/upatch-build/src/upatch/args/mod.rs +index c08f071..53c4c2a 100644 +--- a/upatch/upatch-build/src/upatch/args/mod.rs ++++ b/upatch/upatch-build/src/upatch/args/mod.rs +@@ -21,6 +21,9 @@ pub struct Arguments { + /// Specify work directory + pub work_dir: PathBuf, + ++ /// Specify build temporary directory ++ pub build_root: PathBuf, ++ + /// Specify source directory + pub source_dir: PathBuf, + +@@ -66,6 +69,7 @@ impl Parser<'_> for Arguments { + true => ArgParserImpl::parse_arg(matches, "name")?, + }, + work_dir: ArgParserImpl::parse_arg(matches, "work_dir")?, ++ build_root: ArgParserImpl::parse_arg(matches, "build_root")?, + source_dir: ArgParserImpl::parse_arg(matches, "source_dir")?, + build_source_cmd: ArgParserImpl::parse_arg(matches, "build_source_cmd")?, + build_patch_cmd: ArgParserImpl::parse_arg(matches, "build_patch_cmd")?, +@@ -95,13 +99,21 @@ impl Arguments { + } + + fn check(mut self) -> anyhow::Result { +- if !self.work_dir.is_dir() { ++ if !self.build_root.is_dir() { + bail!( +- "Working directory \"{}\" should be a directory", ++ "Work directory \"{}\" should be a directory", + self.work_dir.display() + ); + } +- self.work_dir = real_arg(self.work_dir)?.join("upatch"); ++ self.build_root = real_arg(&self.build_root)?; ++ ++ if !self.build_root.is_dir() { ++ bail!( ++ "Build root directory \"{}\" should be a directory", ++ self.build_root.display() ++ ); ++ } ++ self.build_root = real_arg(&self.build_root)?.join("upatch"); + + if !self.source_dir.is_dir() { + bail!( +diff --git a/upatch/upatch-build/src/upatch/build.rs b/upatch/upatch-build/src/upatch/build.rs +index 044e719..ac4bedb 100644 +--- a/upatch/upatch-build/src/upatch/build.rs ++++ b/upatch/upatch-build/src/upatch/build.rs +@@ -11,17 +11,19 @@ use crate::tool::*; + use super::note; + use super::resolve; + use super::Arguments; ++use super::BuildRoot; + use super::Error; + use super::LinkMessages; + use super::Project; + use super::Result; + use super::Tool; +-use super::WorkDir; + use super::{Compiler, CompilerHackGuard}; + ++const UPATCHD_SOCKET_NAME: &str = "upatchd.sock"; ++ + pub struct UpatchBuild { + args: Arguments, +- work_dir: WorkDir, ++ build_root: BuildRoot, + compiler: Compiler, + tool: Tool, + dwarf: Dwarf, +@@ -35,7 +37,7 @@ impl UpatchBuild { + fn new() -> Result { + Ok(Self { + args: Arguments::new()?, +- work_dir: WorkDir::new(), ++ build_root: BuildRoot::new(), + compiler: Compiler::new(), + tool: Tool::new(), + dwarf: Dwarf::new(), +@@ -54,7 +56,7 @@ impl UpatchBuild { + } + + fn build_main(mut self) -> Result<()> { +- self.work_dir.create_dir(&self.args.work_dir)?; ++ self.build_root.create_dir(&self.args.build_root)?; + self.init_logger()?; + + // find upatch-diff +@@ -70,18 +72,19 @@ impl UpatchBuild { + self.compiler.analyze(&self.args.compiler)?; + if !self.args.skip_compiler_check { + self.compiler +- .check_version(self.work_dir.cache_dir(), &self.args.debuginfo)?; ++ .check_version(self.build_root.cache_dir(), &self.args.debuginfo)?; + } + + // hack compiler +- info!("Hacking compiler"); +- let compiler_hacker = CompilerHackGuard::new(self.compiler.clone())?; ++ info!("Hacking compilers"); ++ let socket_file = self.args.work_dir.join(UPATCHD_SOCKET_NAME); ++ let compiler_hacker = CompilerHackGuard::new(&self.compiler, socket_file)?; + let project_name = self.args.source_dir.file_name().unwrap(); + + // build source + info!("Building original {:?}", project_name); + project.build( +- self.work_dir.source_dir(), ++ self.build_root.source_dir(), + self.args.build_source_cmd.clone(), + )?; + +@@ -92,12 +95,13 @@ impl UpatchBuild { + + // collect source link message and object message + self.source_link_messages = +- LinkMessages::from(&self.args.elf_path, self.work_dir.source_dir())?; +- self.source_obj = self.correlate_obj(&self.args.source_dir, self.work_dir.source_dir())?; ++ LinkMessages::from(&self.args.elf_path, self.build_root.source_dir())?; ++ self.source_obj = ++ self.correlate_obj(&self.args.source_dir, self.build_root.source_dir())?; + if self.source_obj.is_empty() { + return Err(Error::Build(format!( + "no valid object in {:?}", +- self.work_dir.source_dir() ++ self.build_root.source_dir() + ))); + } + +@@ -106,21 +110,24 @@ impl UpatchBuild { + + // build patched + info!("Building patched {:?}", project_name); +- project.build(self.work_dir.patch_dir(), self.args.build_patch_cmd.clone())?; ++ project.build( ++ self.build_root.patch_dir(), ++ self.args.build_patch_cmd.clone(), ++ )?; + + // collect patched link message and object message + self.patch_link_messages = +- LinkMessages::from(&self.args.elf_path, self.work_dir.patch_dir())?; +- self.patch_obj = self.correlate_obj(&self.args.source_dir, self.work_dir.patch_dir())?; ++ LinkMessages::from(&self.args.elf_path, self.build_root.patch_dir())?; ++ self.patch_obj = self.correlate_obj(&self.args.source_dir, self.build_root.patch_dir())?; + if self.patch_obj.is_empty() { + return Err(Error::Build(format!( + "no valid object in {:?}", +- self.work_dir.patch_dir() ++ self.build_root.patch_dir() + ))); + } + + // unhack compiler +- info!("Unhacking compiler"); ++ info!("Unhacking compilers"); + drop(compiler_hacker); + + // detecting changed objects +@@ -153,7 +160,7 @@ impl UpatchBuild { + }; + + logger.set_print_level(log_level); +- logger.set_log_file(LevelFilter::Trace, self.work_dir.log_file())?; ++ logger.set_log_file(LevelFilter::Trace, self.build_root.log_file())?; + Logger::init_logger(logger); + + Ok(()) +@@ -228,7 +235,7 @@ impl UpatchBuild { + patch_path, + &output, + &debug_info, +- self.work_dir.log_file(), ++ self.build_root.log_file(), + self.args.verbose, + )?, + None => { +@@ -312,11 +319,15 @@ impl UpatchBuild { + }; + + let binary_name = file_name(&self.args.elf_path[i])?; +- let diff_dir = self.work_dir.output_dir().to_path_buf().join(&binary_name); ++ let diff_dir = self ++ .build_root ++ .output_dir() ++ .to_path_buf() ++ .join(&binary_name); + fs::create_dir(&diff_dir)?; + + let new_debug_info = self +- .work_dir ++ .build_root + .debuginfo_dir() + .join(file_name(&self.args.debuginfo[i])?); + debug!( +diff --git a/upatch/upatch-build/src/upatch/workdir.rs b/upatch/upatch-build/src/upatch/build_root.rs +similarity index 89% +rename from upatch/upatch-build/src/upatch/workdir.rs +rename to upatch/upatch-build/src/upatch/build_root.rs +index 7d4a8fa..c6edcc5 100644 +--- a/upatch/upatch-build/src/upatch/workdir.rs ++++ b/upatch/upatch-build/src/upatch/build_root.rs +@@ -4,7 +4,7 @@ use std::path::{Path, PathBuf}; + use super::Result; + use crate::tool::*; + +-pub struct WorkDir { ++pub struct BuildRoot { + cache_dir: PathBuf, + source_dir: PathBuf, + patch_dir: PathBuf, +@@ -13,7 +13,7 @@ pub struct WorkDir { + log_file: PathBuf, + } + +-impl WorkDir { ++impl BuildRoot { + pub fn new() -> Self { + Self { + cache_dir: PathBuf::new(), +@@ -25,8 +25,8 @@ impl WorkDir { + } + } + +- pub fn create_dir>(&mut self, work_dir: P) -> Result<()> { +- self.cache_dir = work_dir.as_ref().to_path_buf(); ++ pub fn create_dir>(&mut self, build_root: P) -> Result<()> { ++ self.cache_dir = build_root.as_ref().to_path_buf(); + self.source_dir = self.cache_dir.join("source"); + self.patch_dir = self.cache_dir.join("patch"); + self.debuginfo_dir = self.cache_dir.join("debug_info"); +@@ -71,7 +71,7 @@ impl WorkDir { + } + } + +-impl Default for WorkDir { ++impl Default for BuildRoot { + fn default() -> Self { + Self::new() + } +diff --git a/upatch/upatch-build/src/upatch/compiler.rs b/upatch/upatch-build/src/upatch/compiler.rs +index 5baaa65..2f9df9f 100644 +--- a/upatch/upatch-build/src/upatch/compiler.rs ++++ b/upatch/upatch-build/src/upatch/compiler.rs +@@ -1,4 +1,3 @@ +-use std::cmp; + use std::collections::HashSet; + use std::ffi::{OsStr, OsString}; + use std::fs::File; +@@ -16,24 +15,19 @@ use crate::rpc::*; + use super::Error; + use super::Result; + +-const UPATCHD_SOCKET: &str = "/var/run/upatchd.sock"; +- + #[derive(Clone)] + pub struct Compiler { + compiler: Vec, + assembler: Vec, + linker: Vec, +- upatch_proxy: UpatchProxy, + } + + impl Compiler { + pub fn new() -> Self { +- let remote = RpcRemote::new(UPATCHD_SOCKET); + Self { + compiler: Vec::new(), + assembler: Vec::new(), + linker: Vec::new(), +- upatch_proxy: UpatchProxy::new(Rc::new(remote)), + } + } + +@@ -94,14 +88,6 @@ impl Compiler { + Ok(()) + } + +- pub fn hack(&self) -> Result<()> { +- self.hijacker_register(self.compiler.len() + self.assembler.len()) +- } +- +- pub fn unhack(&self) -> Result<()> { +- self.hijacker_unregister(self.compiler.len() + self.assembler.len()) +- } +- + pub fn check_version(&self, cache_dir: P, debug_infoes: I) -> Result<()> + where + P: AsRef, +@@ -188,89 +174,76 @@ impl Compiler { + } + } + +-impl Compiler { +- fn hijacker_register(&self, num: usize) -> Result<()> { +- for i in 0..cmp::min(num, self.compiler.len()) { +- trace!("hack {}", self.compiler[i].display()); +- if let Err(e) = self.upatch_proxy.enable_hijack(self.compiler[i].clone()) { +- trace!("hack {:?} error {}, try to rollback", self.compiler[i], e); +- self.hijacker_unregister(i)?; +- return Err(Error::Mod(format!( +- "hack {} error {}", +- self.compiler[i].display(), +- e +- ))); ++pub struct CompilerHackGuard<'a> { ++ inner: &'a Compiler, ++ upatch_proxy: UpatchProxy, ++} ++ ++impl<'a> CompilerHackGuard<'a> { ++ pub fn new>(compiler: &'a Compiler, socket_file: P) -> Result { ++ let remote = RpcRemote::new(socket_file); ++ let instance = Self { ++ inner: compiler, ++ upatch_proxy: UpatchProxy::new(Rc::new(remote)), ++ }; ++ instance.hack()?; ++ ++ Ok(instance) ++ } ++} ++ ++impl CompilerHackGuard<'_> { ++ pub fn hack(&self) -> Result<()> { ++ let mut hack_list = Vec::new(); ++ hack_list.extend(&self.inner.compiler); ++ hack_list.extend(&self.inner.assembler); ++ ++ let mut finished_list = Vec::new(); ++ let mut need_rollback = false; ++ ++ for exec_path in hack_list { ++ trace!("Hacking \"{}\"...", exec_path.display()); ++ if let Err(e) = self.upatch_proxy.enable_hijack(exec_path.to_owned()) { ++ error!("Failed to hack \"{}\", {}", exec_path.display(), e); ++ need_rollback = true; ++ break; + } ++ finished_list.push(exec_path); + } +- for i in self.compiler.len()..num { +- let i = i - self.compiler.len(); +- trace!("hack {}", self.assembler[i].display()); +- if let Err(e) = self.upatch_proxy.enable_hijack(self.assembler[i].clone()) { +- trace!( +- "hack {} error {}, try to rollback", +- self.assembler[i].display(), +- e +- ); +- self.hijacker_unregister(i)?; +- return Err(Error::Mod(format!( +- "hack {} error {}", +- self.assembler[i].display(), +- e +- ))); ++ ++ if need_rollback { ++ trace!("Rolling back..."); ++ for exec_path in finished_list { ++ trace!("Unhacking \"{}\"...", exec_path.display()); ++ self.upatch_proxy.disable_hijack(exec_path.to_owned()).ok(); + } ++ return Err(Error::Mod(String::from("Failed to hack compilers"))); + } ++ + Ok(()) + } + +- fn hijacker_unregister(&self, num: usize) -> Result<()> { +- for i in (self.compiler.len()..num).rev() { +- let i = i - self.compiler.len(); +- trace!("unhack {}", self.assembler[i].display()); +- if let Err(e) = self.upatch_proxy.disable_hijack(self.assembler[i].clone()) { +- trace!("unhack {} error {}", self.assembler[i].display(), e); +- return Err(Error::Mod(format!( +- "unhack {} error {}", +- self.assembler[i].display(), +- e +- ))); +- } +- } +- +- for i in (0..cmp::min(num, self.compiler.len())).rev() { +- trace!("unhack {}", self.compiler[i].display()); +- if let Err(e) = self.upatch_proxy.disable_hijack(self.compiler[i].clone()) { +- trace!("unhack {} error {}", self.compiler[i].display(), e); +- return Err(Error::Mod(format!( +- "unhack {} error {}", +- self.compiler[i].display(), +- e +- ))); ++ pub fn unhack(&self) -> Result<()> { ++ let mut hack_list = Vec::new(); ++ hack_list.extend(&self.inner.compiler); ++ hack_list.extend(&self.inner.assembler); ++ hack_list.reverse(); ++ ++ for exec_path in hack_list { ++ trace!("Unhacking \"{}\"...", exec_path.display()); ++ if let Err(e) = self.upatch_proxy.disable_hijack(exec_path.to_owned()) { ++ error!("Failed to unhack \"{}\", {}", exec_path.display(), e); ++ return Err(Error::Mod(String::from("Failed to unhack compilers"))); + } + } + Ok(()) + } + } + +-pub struct CompilerHackGuard { +- compiler: Compiler, +-} +- +-impl CompilerHackGuard { +- pub fn new(compiler: Compiler) -> Result { +- compiler.hack()?; +- Ok(CompilerHackGuard { compiler }) +- } +-} +-impl Drop for CompilerHackGuard { ++impl Drop for CompilerHackGuard<'_> { + fn drop(&mut self) { +- if let Err(e) = self.compiler.unhack() { ++ if let Err(e) = self.unhack() { + trace!("{}", e); + } + } + } +- +-impl Default for Compiler { +- fn default() -> Self { +- Self::new() +- } +-} +diff --git a/upatch/upatch-build/src/upatch/mod.rs b/upatch/upatch-build/src/upatch/mod.rs +index a359aa2..88c5f1c 100644 +--- a/upatch/upatch-build/src/upatch/mod.rs ++++ b/upatch/upatch-build/src/upatch/mod.rs +@@ -1,5 +1,6 @@ + mod args; + mod build; ++mod build_root; + mod compiler; + mod error; + mod link_message; +@@ -7,10 +8,10 @@ mod note; + mod project; + mod resolve; + mod tools; +-mod workdir; + + pub use args::*; + pub use build::*; ++pub use build_root::*; + pub use compiler::*; + pub use error::*; + pub use link_message::*; +@@ -18,4 +19,3 @@ pub use note::*; + pub use project::*; + pub use resolve::*; + pub use tools::*; +-pub use workdir::*; +diff --git a/upatch/upatch-daemon/src/args/matcher.rs b/upatch/upatch-daemon/src/args/matcher.rs +index 0badaf6..e938e6e 100644 +--- a/upatch/upatch-daemon/src/args/matcher.rs ++++ b/upatch/upatch-daemon/src/args/matcher.rs +@@ -1,7 +1,5 @@ + use clap::{clap_app, crate_description, crate_name, crate_version, AppSettings, ArgMatches}; + +-const DEFAULT_PID_FILE: &str = "/var/run/upatchd.pid"; +-const DEFAULT_SOCKET_FILE: &str = "/var/run/upatchd.sock"; + const DEFAULT_WORK_DIR: &str = "/var/run/syscare"; + const DEFAULT_CONFIG_DIR: &str = "/etc/syscare"; + const DEFAULT_LOG_DIR: &str = "/var/log/syscare"; +@@ -22,9 +20,7 @@ impl ArgMatcher { + AppSettings::UnifiedHelpMessage, + ]) + (@arg daemon: short("d") long("daemon") "Run as a daemon") +- (@arg pid_file: long("pid-file") +takes_value value_name("PID_FILE") default_value(DEFAULT_PID_FILE) "Path for daemon pid file") +- (@arg socket_file: long("socket-file") +takes_value value_name("SOCKET_FILE") default_value(DEFAULT_SOCKET_FILE) "Path for daemon unix socket") +- (@arg config_file: long("config-dir") +takes_value value_name("CONFIG_DIR") default_value(DEFAULT_CONFIG_DIR) "Daemon config directory") ++ (@arg config_dir: long("config-dir") +takes_value value_name("CONFIG_DIR") default_value(DEFAULT_CONFIG_DIR) "Daemon config directory") + (@arg work_dir: long("work-dir") +takes_value value_name("WORK_DIR") default_value(DEFAULT_WORK_DIR) "Daemon working directory") + (@arg log_dir: long("log-dir") +takes_value value_name("LOG_DIR") default_value(DEFAULT_LOG_DIR) "Daemon logging directory") + (@arg log_level: short("l") long("log-level") +takes_value value_name("LOG_LEVEL") default_value(DEFAULT_LOG_LEVEL) "Set the logging level (\"trace\"|\"debug\"|\"info\"|\"warn\"|\"error\")") +diff --git a/upatch/upatch-daemon/src/args/mod.rs b/upatch/upatch-daemon/src/args/mod.rs +index 318470e..bd6cb3c 100644 +--- a/upatch/upatch-daemon/src/args/mod.rs ++++ b/upatch/upatch-daemon/src/args/mod.rs +@@ -17,12 +17,6 @@ pub struct Arguments { + /// Run as a daemon + pub daemon: bool, + +- /// Path for daemon pid file +- pub pid_file: PathBuf, +- +- /// Path for daemon unix socket +- pub socket_file: PathBuf, +- + /// Daemon config directory + pub config_dir: PathBuf, + +@@ -43,8 +37,6 @@ impl Parser<'_> for Arguments { + { + Ok(Self { + daemon: ArgParserImpl::is_present(matches, "daemon"), +- pid_file: ArgParserImpl::parse_arg(matches, "pid_file")?, +- socket_file: ArgParserImpl::parse_arg(matches, "socket_file")?, + config_dir: ArgParserImpl::parse_arg(matches, "config_dir")?, + work_dir: ArgParserImpl::parse_arg(matches, "work_dir")?, + log_dir: ArgParserImpl::parse_arg(matches, "log_dir")?, +@@ -62,8 +54,6 @@ impl Arguments { + } + + fn normalize_pathes(mut self) -> Result { +- self.pid_file = fs::normalize(&self.pid_file)?; +- self.socket_file = fs::normalize(&self.socket_file)?; + self.config_dir = fs::normalize(&self.config_dir)?; + self.work_dir = fs::normalize(self.work_dir)?; + self.log_dir = fs::normalize(&self.log_dir)?; +diff --git a/upatch/upatch-daemon/src/main.rs b/upatch/upatch-daemon/src/main.rs +index 80c292f..a112c99 100644 +--- a/upatch/upatch-daemon/src/main.rs ++++ b/upatch/upatch-daemon/src/main.rs +@@ -1,5 +1,5 @@ + use std::{ +- fs, ++ fs::{self, Permissions}, + os::unix::fs::PermissionsExt, + path::Path, + process, +@@ -31,8 +31,14 @@ use rpc::{Skeleton, SkeletonImpl}; + const CONFIG_FILE_NAME: &str = "upatchd.yaml"; + + const DAEMON_VERSION: &str = env!("CARGO_PKG_VERSION"); +-const DAEMON_UMASK: u32 = 0o027; +-const DAEMON_PARK_TIMEOUT: u64 = 100; ++const DAEMON_UMASK: u32 = 0o077; ++const DAEMON_PARK_TIME: u64 = 100; ++ ++const PID_FILE_NAME: &str = "upatchd.pid"; ++const SOCKET_FILE_NAME: &str = "upatchd.sock"; ++ ++const WORK_DIR_PERMISSION: u32 = 0o755; ++const SOCKET_FILE_PERMISSION: u32 = 0o666; + + struct Daemon { + args: Arguments, +@@ -72,7 +78,13 @@ impl Daemon { + self.prepare_directory(&self.args.config_dir)?; + + self.prepare_directory(&self.args.work_dir)?; ++ fs::set_permissions( ++ &self.args.work_dir, ++ Permissions::from_mode(WORK_DIR_PERMISSION), ++ )?; ++ + self.prepare_directory(&self.args.log_dir)?; ++ + Ok(()) + } + +@@ -81,10 +93,11 @@ impl Daemon { + return Ok(()); + } + ++ let pid_file = self.args.work_dir.join(PID_FILE_NAME); + Daemonize::new() +- .pid_file(&self.args.pid_file) +- .working_directory(&self.args.work_dir) + .umask(DAEMON_UMASK) ++ .working_directory(&self.args.work_dir) ++ .pid_file(pid_file) + .start() + .context("Daemonize failed") + } +@@ -119,9 +132,7 @@ impl Daemon { + } + + fn start_rpc_server(&self, io_handler: IoHandler) -> Result { +- const SOCKET_FILE_PERMISSION: u32 = 0o666; +- +- let socket_file = self.args.socket_file.as_path(); ++ let socket_file = self.args.work_dir.join(SOCKET_FILE_NAME); + let builder = ServerBuilder::new(io_handler).set_client_buffer_size(1); + let server = builder.start( + socket_file +@@ -129,10 +140,7 @@ impl Daemon { + .context("Failed to convert socket path to string")?, + )?; + +- let mut perm = socket_file.metadata()?.permissions(); +- perm.set_mode(SOCKET_FILE_PERMISSION); +- +- fs::set_permissions(socket_file, perm)?; ++ fs::set_permissions(socket_file, Permissions::from_mode(SOCKET_FILE_PERMISSION))?; + + Ok(server) + } +@@ -142,7 +150,7 @@ impl Daemon { + instance.initialize_logger()?; + + info!("============================"); +- info!("Syscare Builder Daemon - v{}", DAEMON_VERSION); ++ info!("Upatch Daemon - v{}", DAEMON_VERSION); + info!("============================"); + info!("Preparing environment..."); + instance.prepare_environment()?; +@@ -167,7 +175,7 @@ impl Daemon { + + info!("Daemon is running..."); + while !instance.term_flag.load(Ordering::Relaxed) { +- std::thread::park_timeout(Duration::from_millis(DAEMON_PARK_TIMEOUT)); ++ std::thread::park_timeout(Duration::from_millis(DAEMON_PARK_TIME)); + } + + info!("Shutting down..."); +-- +2.33.0 + diff --git a/0015-upatch-fix-memory-leak.patch b/0015-upatch-fix-memory-leak.patch new file mode 100644 index 0000000..d49415f --- /dev/null +++ b/0015-upatch-fix-memory-leak.patch @@ -0,0 +1,363 @@ +From 4bac002ec33f3593ef03ff01494b524234c40484 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Tue, 26 Dec 2023 13:07:53 +0800 +Subject: [PATCH 15/15] upatch: fix memory leak + +Signed-off-by: renoseven +--- + upatch/upatch-manage/upatch-patch.c | 4 +- + upatch/upatch-tool/upatch-meta.c | 8 ++- + upatch/upatch-tool/upatch-resolve.c | 63 +++++++--------- + upatch/upatch-tool/upatch-resolve.h | 3 +- + upatch/upatch-tool/upatch-tool-lib.c | 104 +++++++++++++++++++++------ + 5 files changed, 117 insertions(+), 65 deletions(-) + +diff --git a/upatch/upatch-manage/upatch-patch.c b/upatch/upatch-manage/upatch-patch.c +index 762641c..4763778 100644 +--- a/upatch/upatch-manage/upatch-patch.c ++++ b/upatch/upatch-manage/upatch-patch.c +@@ -590,8 +590,8 @@ static int upatch_apply_patches(struct upatch_process *proc, + + if (!found) { + ret = -1; +- log_debug("can't found inode %lu in pid %d\n", +- uelf->relf->info.inode, proc->pid); ++ log_debug("Cannot find inode %lu in pid %d, file is not loaded\n", ++ uelf->relf->info.inode, proc->pid); + goto out; + } + +diff --git a/upatch/upatch-tool/upatch-meta.c b/upatch/upatch-tool/upatch-meta.c +index c625115..2bd39b4 100644 +--- a/upatch/upatch-tool/upatch-meta.c ++++ b/upatch/upatch-tool/upatch-meta.c +@@ -197,9 +197,11 @@ static int patch_deactive_in_cover(struct upatch_meta_patch *patch) + static int list_add_symbol(struct list_head *head, struct upatch_meta_symbol *sym) + { + struct upatch_meta_symbol *newsym = (struct upatch_meta_symbol *)malloc(sizeof(struct upatch_meta_symbol)); +- if (newsym == NULL) ++ if (newsym == NULL) { + return ENOMEM; ++ } + memset(newsym, 0, sizeof(struct upatch_meta_symbol)); ++ + strncpy(newsym->name, sym->name, sizeof(newsym->name)); + newsym->offset = sym->offset; + INIT_LIST_HEAD(&newsym->self); +@@ -212,9 +214,11 @@ static int list_add_symbol(struct list_head *head, struct upatch_meta_symbol *sy + static int list_add_symbol_for_patch(struct upatch_meta_patch *patch, struct list_head *head, struct upatch_meta_symbol *sym) + { + struct upatch_meta_symbol *newsym = (struct upatch_meta_symbol *)malloc(sizeof(struct upatch_meta_symbol)); +- if (newsym == NULL) ++ if (newsym == NULL) { + return ENOMEM; ++ } + memset(newsym, 0, sizeof(struct upatch_meta_symbol)); ++ + strncpy(newsym->name, sym->name, sizeof(newsym->name)); + newsym->offset = sym->offset; + INIT_LIST_HEAD(&newsym->self); +diff --git a/upatch/upatch-tool/upatch-resolve.c b/upatch/upatch-tool/upatch-resolve.c +index aeb655c..e9d75e0 100644 +--- a/upatch/upatch-tool/upatch-resolve.c ++++ b/upatch/upatch-tool/upatch-resolve.c +@@ -42,79 +42,66 @@ out: + static int list_add_symbol(struct list_head *head, patch_symbols_t *sym) + { + patch_symbols_t *newsym = (patch_symbols_t *)malloc(sizeof(patch_symbols_t)); +- if (newsym == NULL) ++ if (newsym == NULL) { + return ENOMEM; ++ } + + memset(newsym, 0, sizeof(patch_symbols_t)); + strncpy(newsym->name, sym->name, sizeof(newsym->name)); + newsym->offset = sym->offset; + INIT_LIST_HEAD(&newsym->self); + list_add(&newsym->self, head); ++ + return 0; + } + +-struct list_head* patch_symbols_resolve(const char *target_elf, const char *patch_file) { +- struct upatch_elf uelf; +- struct running_elf relf; +- GElf_Shdr *upatch_shdr = NULL; +- struct upatch_patch_func *upatch_funcs = NULL; +- GElf_Off min_addr; // binary base +- int num; +- struct list_head *head = malloc(sizeof(struct list_head)); ++struct list_head* patch_symbols_resolve(struct upatch_elf *uelf, struct running_elf *relf) { ++ struct list_head *head = NULL; + +- INIT_LIST_HEAD(head); +- +- int ret = upatch_init(&uelf, patch_file); +- if (ret < 0) { +- log_warn("upatch-resolve: upatch_init failed\n"); +- goto out; +- } +- +- ret = binary_init(&relf, target_elf); +- if (ret < 0) { +- log_warn("upatch-resolve: binary_init failed %d \n", ret); +- goto out; +- } +- +- if (check_build_id(&uelf.info, &relf.info) == false) { ++ if (check_build_id(&uelf->info, &relf->info) == false) { + log_error("upatch-resolve: Build id mismatched!\n"); + goto out; + } + +- uelf.relf = &relf; +- upatch_shdr = &uelf.info.shdrs[uelf.index.upatch_funcs]; +- upatch_funcs = uelf.info.patch_buff + upatch_shdr->sh_offset; +- min_addr = calculate_load_address(uelf.relf, false); ++ GElf_Shdr *upatch_shdr = &uelf->info.shdrs[uelf->index.upatch_funcs]; ++ GElf_Off min_addr = calculate_load_address(uelf->relf, false); + if (min_addr == (GElf_Off)-1) { + goto out; + } + +- num = upatch_shdr->sh_size / sizeof(*upatch_funcs); ++ struct upatch_patch_func *upatch_funcs = uelf->info.patch_buff + upatch_shdr->sh_offset; ++ int num = upatch_shdr->sh_size / sizeof(*upatch_funcs); + + log_debug("upatch-resolve: sh_size %lu, sizeof %lu \n", upatch_shdr->sh_size, sizeof(*upatch_funcs)); + log_debug("upatch-resolve: elf base addr is 0x%lx, num is %d\n", min_addr, num); + ++ head = malloc(sizeof(struct list_head)); ++ INIT_LIST_HEAD(head); ++ + for (int i = 0; i < num; i++) { +- patch_symbols_t *sym = malloc(sizeof(patch_symbols_t)); +- sprintf(sym->name, "sym_%d", i); +- sym->offset = upatch_funcs[i].old_addr - min_addr;; +- log_debug("+upatch-resolve: sym->offset addr is 0x%lx\n", sym->offset); +- list_add_symbol(head, sym); ++ patch_symbols_t sym; ++ ++ sprintf(sym.name, "sym_%d", i); ++ sym.offset = upatch_funcs[i].old_addr - min_addr; ++ log_debug("upatch-resolve: sym->offset addr is 0x%lx\n", sym.offset); ++ ++ list_add_symbol(head, &sym); // This would copy the symbol + } + + return head; ++ + out: +- free(head); ++ if (head != NULL) { ++ free(head); ++ } + return NULL; + } + + void patch_symbols_free(struct list_head *symbols) { + patch_symbols_t *sym, *next; +- +- if (!symbols) +- return; + list_for_each_entry_safe (sym, next, symbols, self) { + list_del(&sym->self); + free(sym); + } ++ free(symbols); + } +diff --git a/upatch/upatch-tool/upatch-resolve.h b/upatch/upatch-tool/upatch-resolve.h +index 7d0bb47..7c06345 100644 +--- a/upatch/upatch-tool/upatch-resolve.h ++++ b/upatch/upatch-tool/upatch-resolve.h +@@ -2,8 +2,9 @@ + #define __UPATCH_RESOLVE_H_ + + #include "list.h" ++#include "upatch-elf.h" + +-struct list_head* patch_symbols_resolve(const char *target_elf, const char *patch_file); ++struct list_head* patch_symbols_resolve(struct upatch_elf *uelf, struct running_elf *relf); + void patch_symbols_free(struct list_head *symbols); + + #endif +diff --git a/upatch/upatch-tool/upatch-tool-lib.c b/upatch/upatch-tool/upatch-tool-lib.c +index 4e5bda1..3731abe 100644 +--- a/upatch/upatch-tool/upatch-tool-lib.c ++++ b/upatch/upatch-tool/upatch-tool-lib.c +@@ -14,21 +14,43 @@ + + #include "log.h" + #include "list.h" ++#include "upatch-elf.h" + #include "upatch-meta.h" + #include "upatch-resolve.h" + #include "upatch-ioctl.h" + + int upatch_check(const char *target_elf, const char *patch_file, char *err_msg, size_t max_len) + { +- struct list_head *patch_syms = patch_symbols_resolve(target_elf, patch_file); ++ int ret = 0; ++ struct list_head *patch_syms = NULL; ++ struct list_head *collision_list = NULL; ++ ++ struct upatch_elf uelf; ++ ret = upatch_init(&uelf, patch_file); ++ if (ret < 0) { ++ snprintf(err_msg, max_len, "Failed to read patch"); ++ goto out; ++ } ++ ++ struct running_elf relf; ++ ret = binary_init(&relf, target_elf); ++ if (ret < 0) { ++ snprintf(err_msg, max_len, "Failed to read target elf"); ++ goto out; ++ } ++ uelf.relf = &relf; ++ ++ patch_syms = patch_symbols_resolve(&uelf, &relf); + if (patch_syms == NULL) { + snprintf(err_msg, max_len, "Patch format error"); +- return ENOEXEC; ++ ret = ENOEXEC; ++ goto out; + } + +- struct list_head *collision_list = meta_get_symbol_collision(target_elf, patch_syms); ++ collision_list = meta_get_symbol_collision(target_elf, patch_syms); + if (collision_list == NULL) { +- return 0; ++ ret = 0; ++ goto out; + } + + int offset = snprintf(err_msg, max_len, "Patch is conflicted with "); +@@ -39,50 +61,78 @@ int upatch_check(const char *target_elf, const char *patch_file, char *err_msg, + offset = snprintf(err_msg, max_len, "\"%s\" ", collision->uuid); + } + +- patch_symbols_free(patch_syms); +- meta_put_symbol_collision(collision_list); ++out: ++ if (patch_syms != NULL) { ++ patch_symbols_free(patch_syms); ++ } ++ if (collision_list != NULL) { ++ meta_put_symbol_collision(collision_list); ++ } ++ binary_close(&relf); ++ upatch_close(&uelf); + +- return EEXIST; ++ return ret; + } + + int upatch_load(const char *uuid, const char *target, const char *patch, bool force) + { ++ int ret = 0; ++ struct list_head *patch_syms = NULL; ++ patch_entity_t *patch_entity = NULL; ++ struct list_head *collision_syms = NULL; ++ + // Pointer check + if (uuid == NULL || target == NULL || patch == NULL) { + return EINVAL; + } + log_normal("Loading patch {%s} (\"%s\") for \"%s\"\n", uuid, patch, target); + ++ struct upatch_elf uelf; ++ ret = upatch_init(&uelf, patch); ++ if (ret < 0) { ++ log_warn("Failed to read patch\n"); ++ goto out; ++ } ++ ++ struct running_elf relf; ++ ret = binary_init(&relf, target); ++ if (ret < 0) { ++ log_warn("Failed to read target elf\n"); ++ goto out; ++ } ++ uelf.relf = &relf; ++ + // Fails if patch is already exist + if (meta_get_patch_status(uuid) != UPATCH_PATCH_STATUS_NOT_APPLIED) { + log_warn("{%s}: Patch status is invalid\n", uuid); +- return EPERM; ++ ret = EPERM; ++ goto out; + } + + // Resolve patch symbols +- struct list_head *patch_syms = patch_symbols_resolve(target, patch); ++ patch_syms = patch_symbols_resolve(&uelf, &relf); + if (patch_syms == NULL) { + log_warn("{%s}: Patch format error\n", uuid); +- return ENOEXEC; ++ ret = ENOEXEC; ++ goto out; + } + + // Check patch symbol collision + if (!force) { +- struct list_head *collision_syms = meta_get_symbol_collision(target, patch_syms); ++ collision_syms = meta_get_symbol_collision(target, patch_syms); + if (collision_syms != NULL) { + log_warn("{%s}: Patch symbol conflicted\n", uuid); +- patch_symbols_free(patch_syms); +- meta_put_symbol_collision(collision_syms); +- return EEXIST; ++ ret = EEXIST; ++ goto out; + } + } + + // Alloc memory for patch +- patch_entity_t *patch_entity = calloc(1, sizeof(patch_entity_t)); ++ patch_entity = calloc(1, sizeof(patch_entity_t)); + if (patch_entity == NULL) { + log_warn("{%s}: Failed to alloc memory\n", uuid); +- patch_symbols_free(patch_syms); +- return ENOMEM; ++ ret = ENOMEM; ++ goto out; + } + + strncpy(patch_entity->target_path, target, strnlen(target, PATH_MAX)); +@@ -91,17 +141,27 @@ int upatch_load(const char *uuid, const char *target, const char *patch, bool fo + log_normal("patch: %s, patch_path: %s\n", patch, patch_entity->patch_path); + patch_entity->symbols = patch_syms; + +- int ret = meta_create_patch(uuid, patch_entity); ++ ret = meta_create_patch(uuid, patch_entity); + if (ret != 0) { + log_warn("{%s}: Failed to create patch entity\n", uuid); +- free(patch_entity); +- patch_symbols_free(patch_syms); +- return ret; ++ goto out; + } + +- free(patch_entity); + meta_set_patch_status(uuid, UPATCH_PATCH_STATUS_DEACTIVED); + ++out: ++ if (collision_syms != NULL) { ++ meta_put_symbol_collision(collision_syms); ++ } ++ if (patch_syms != NULL) { ++ patch_symbols_free(patch_syms); ++ } ++ if (patch_entity != NULL) { ++ free(patch_entity); ++ } ++ binary_close(&relf); ++ upatch_close(&uelf); ++ + return ret; + } + +-- +2.33.0 + diff --git a/syscare.spec b/syscare.spec index 25e2258..0351abf 100644 --- a/syscare.spec +++ b/syscare.spec @@ -12,11 +12,28 @@ ############################################ Name: syscare Version: 1.2.0 -Release: 6 +Release: 10 Summary: System hot-fix service License: MulanPSL-2.0 and GPL-2.0-only URL: https://gitee.com/openeuler/syscare Source0: %{name}-%{version}.tar.gz + +Patch0001: 0001-builder-fix-enabling-multiple-kpatch-may-lead-soft-l.patch +Patch0002: 0002-upatch-fix-upatch-manage-detach-failure-issue.patch +Patch0003: 0003-upatch-remove-upatch-manage-log-file.patch +Patch0004: 0004-upatch-remove-redudant-log-output.patch +Patch0005: 0005-upatch-manage-close-dup-fd.patch +Patch0006: 0006-daemon-check-patch-before-patch-restoration.patch +Patch0007: 0007-upatch-elf-verification.patch +Patch0008: 0008-upatch-check-build-id.patch +Patch0009: 0009-README-add-example-for-kernel-module-patch-build.patch +Patch0010: 0010-daemon-fix-check-build-id-logic.patch +Patch0011: 0011-upatch-diff-fix-a-nullptr-issue.patch +Patch0012: 0012-daemon-fix-rust-1.60-compile-issue.patch +Patch0013: 0013-upatchd-create-config-dir-at-startup.patch +Patch0014: 0014-syscare-move-files-to-working-directory.patch +Patch0015: 0015-upatch-fix-memory-leak.patch + BuildRequires: cmake >= 3.14 make BuildRequires: rust >= 1.51 cargo >= 1.51 BuildRequires: gcc gcc-c++ @@ -177,6 +194,15 @@ depmod > /dev/null 2>&1 ################ Change log ################ ############################################ %changelog +* Tue Dec 26 2023 ningyu - 1.2.0-10 +- fix memory leak +* Fri Dec 22 2023 ningyu - 1.2.0-9 +- Add Suggests for syscare-build +- Remove log directory +* Tue Dec 12 2023 renoseven - 1.2.0-8 +- Builder: fix 'enabling multiple kpatch may lead soft-lockup' issue +* Wed Nov 29 2023 renoseven - 1.2.0-7 +- Fix aarch64 compile issue * Tue Nov 28 2023 renoseven - 1.2.0-6 - Enable debuginfo for rust code - Sync arguments with old version -- Gitee