# Livepatch the process in userspace If there is a problem when the process is running, we stop the process and observe the debugging log, and then update the code to try to reproduce the problem. But when you stop this process, it means that the current environment may change. So in this case livepatch can be used [LivePatch repo](https://github.com/RoyWFHuang/userspace_livepatch) ## Theory When a program be loaded to memory, it will be loaded by elf format into the VMA. Loader will also link the dynamci lib to support it. ![擷取選取區域_001](https://hackmd.io/_uploads/HkLCPnje1l.jpg) Use ==/proc/<PID>/maps== to get the map ``` $ cat /proc/$(pidof testlive)/maps 55869ea92000-55869ea93000 r--p 00000000 00:2d 281 /home/roy/src-code/github/roy/00.project/livepatch/testlive 55869ea93000-55869ea94000 r-xp 00001000 00:2d 281 /home/roy/src-code/github/roy/00.project/livepatch/testlive 55869ea94000-55869ea95000 r--p 00002000 00:2d 281 /home/roy/src-code/github/roy/00.project/livepatch/testlive 55869ea95000-55869ea96000 r--p 00002000 00:2d 281 /home/roy/src-code/github/roy/00.project/livepatch/testlive 55869ea96000-55869ea97000 rw-p 00003000 00:2d 281 /home/roy/src-code/github/roy/00.project/livepatch/testlive 55869f60d000-55869f62e000 rw-p 00000000 00:00 0 [heap] 7f5a33ea2000-7f5a33ea5000 rw-p 00000000 00:00 0 7f5a33ea5000-7f5a33ecd000 r--p 00000000 08:01 3862 /usr/lib/x86_64-linux-gnu/libc.so.6 7f5a33ecd000-7f5a34062000 r-xp 00028000 08:01 3862 /usr/lib/x86_64-linux-gnu/libc.so.6 7f5a34062000-7f5a340ba000 r--p 001bd000 08:01 3862 /usr/lib/x86_64-linux-gnu/libc.so.6 7f5a340ba000-7f5a340bb000 ---p 00215000 08:01 3862 /usr/lib/x86_64-linux-gnu/libc.so.6 7f5a340bb000-7f5a340bf000 r--p 00215000 08:01 3862 /usr/lib/x86_64-linux-gnu/libc.so.6 7f5a340bf000-7f5a340c1000 rw-p 00219000 08:01 3862 /usr/lib/x86_64-linux-gnu/libc.so.6 7f5a340c1000-7f5a340ce000 rw-p 00000000 00:00 0 7f5a340d3000-7f5a340d8000 rwxp 00000000 00:00 0 7f5a340d8000-7f5a340da000 rw-p 00000000 00:00 0 7f5a340da000-7f5a340dc000 r--p 00000000 08:01 3859 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 7f5a340dc000-7f5a34106000 r-xp 00002000 08:01 3859 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 7f5a34106000-7f5a34111000 r--p 0002c000 08:01 3859 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 7f5a34112000-7f5a34114000 r--p 00037000 08:01 3859 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 7f5a34114000-7f5a34116000 rw-p 00039000 08:01 3859 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 7ffff3c6f000-7ffff3c90000 rw-p 00000000 00:00 0 [stack] 7ffff3d41000-7ffff3d45000 r--p 00000000 00:00 0 [vvar] 7ffff3d45000-7ffff3d47000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall] ``` We can execute a process to hack it and load the fix function into the target process ![image](https://hackmd.io/_uploads/r1_oF2slkl.png) Then use modify the target process. Let call ==bug_func== be replaced by ==fix_func== ![擷取選取區域_003](https://hackmd.io/_uploads/Hy3McnsgJl.jpg) ## How to work As we know, the gdb can hack the runtime program. We can use the gdb to set paramater value, jump to the sepcific instruction. So how does the gdb make it? The answer is [ptrace](https://man7.org/linux/man-pages/man2/ptrace.2.html) So we can use the ptrace to control how the process executes. Like ==PTRACE_ATTACH== to attach the process, ==PTRACE_PEEKDATA==/==PTRACE_POKEDATA== to get and set data into the target process VMA. Now, We have the method to control it, and we also need a library to help to get elf section. ==Bfd library== is a good tool for us. Using this, we get the symbol table, the function address, and the most importart is getting ==.got==/==.got.plt==/==.rela.plt== these section to help the fix_func to redirect the instruction in ==.plt== section. :::info Q: Why do we need to redirect it ? A: When we build the so file, this file only has the patch function, so the linker does not know "actual" address of the shared library in the target process. So the .plt section will be filled with "0". If we do not redirect it, the shared library be executed with the "0" insturction, this will make system fail. ::: ## executing ![擷取選取區域_004](https://hackmd.io/_uploads/BJomDaolkl.jpg) the target program is ```c #include <stdio.h> #include <time.h> #include <limits.h> #include <unistd.h> #include <sys/mman.h> int func_J(int a, int b) { char *str_P = "I'm wrong function...QQ"; printf("in %s\n", str_P); sleep(3); printf("exit %s\n", str_P); return (a+b); } int main () { while(1) { int a = func_J(1, 2); sleep(3); printf("In main get calculating result: %d\n", a); if (12 == a) { printf("=== You fix it !!! (%d)\n ===", a); break; } else { printf("=== No, this is not the right answer....(%d) ===\n", a); } } } ``` the patch file is ```c #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <stddef.h> #include <dlfcn.h> int func1(int a, int b) { printf("in fixup\n"); sleep(2); printf("exit fixup\n"); return (a*10+b); } ``` How to build it: ![image](https://hackmd.io/_uploads/S136w6oxke.png) ## Ref You can use ==readelf --relocs== to get the relocation section ``` $ readelf --relocs libfoo.a Relocation section '.rela.dyn' at offset 0x488 contains 7 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000003e10 000000000008 R_X86_64_RELATIVE 1130 000000003e18 000000000008 R_X86_64_RELATIVE 10f0 000000004028 000000000008 R_X86_64_RELATIVE 4028 000000003fe0 000100000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTM[...] + 0 000000003fe8 000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0 000000003ff0 000400000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCl[...] + 0 000000003ff8 000600000006 R_X86_64_GLOB_DAT 0000000000000000 __cxa_finalize@GLIBC_2.2.5 + 0 Relocation section '.rela.plt' at offset 0x530 contains 2 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000004018 000200000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0 000000004020 000500000007 R_X86_64_JUMP_SLO 0000000000000000 sleep@GLIBC_2.2.5 + ``` for this example we need to relocate ==printf== and ==sleep== function to actual address.