
A Runtime Code Modification Method for Application Programs Kazuhiro Yamato Toyo Abe Miracle Linux Corporation Miracle Linux Corpration [email protected] [email protected] Abstract be fixed at runtime with binary patches. In addition, in- terruption time to apply binary patches should be short This paper proposes a runtime code modification because long interruption degrades the quality of voice method for application programs and an implementa- and video, which are major services of telecom. tion. It enables the bugs and security problems to be In this paper, we call an application program to be fixed fixed at runtime. Such software is notably useful for by RBP (Runtime Binary Patcher) a target. Two major applications used in telecom, which cannot be stopped open source RBPs, livepatch [1] and pannus [2], already because of the need to maintain the required level of sys- exist. However, livepatch potentially interrupts the ex- tem availability. The advantages of the proposed method ecution of a target for a long time. The maintenance of are short interruption of the target application and easy pannus doesn’t seem to be easy. maintenance using trap instructions and utrace. This paper proposes a runtime code modification This paper also shows evaluation results with three con- method for application programs, and, an implemented ditions. The interruption times by the proposed method RBP. It achieves short interruption and easy mainte- were comparable to, or shorter than those by existing nance using the trap instruction and the utrace APIs [3]. similar software, livepatch and pannus. In a certain con- dition, our implementation’s interruption time was three 2 Existing Methods orders of magnitude shorter in comparison. 2.1 ptrace system call and gdb 1 Introduction The ptrace system call provides debug functions, such as reading/writing memory in the target’s virtual Although there have been a number of activities to im- memory space, acquisition/modification of the target’s prove software quality, there is no way to completely registers, and catching signals delivered to the target. prevent bugs and security problems. These are gener- These functions are enough to realize runtime code ally fixed by rebuilding the program with patches to the modification. Actually, we can modify a target’s mem- source code. This fix naturally requires termination and ory with gdb [4], which is one of the most popular de- restarting of the program. The termination of the pro- buggers in the GNU/Linux environment and also a typ- gram not only interrupts the service, but also loses vari- ical application using ptrace. ous data such as variables, file descriptors, and network connections. It is impossible to recover these proper- For example, the gdb command "set variable ties unless a recovery mechanism is built in the program *((unsigned short*)0x8048387)=0x0dff" itself. overwrites 0x0dff (dec instruction on i386) at address 0x8048387 by calling ptrace(PTRACE_ Fixing with a termination is a serious problem especially POKEDATA, pid, addr, data), where pid, addr, for application programs used in telecom, because they and data are the process ID of the target, the address cannot easily be terminated to keep the required level to be overwritten, and the address of data to overwrite, of system availability.1 Therefore, the problems should respectively. 1The CGL (Carrier Grade Linux) specification requires 99.999% However, this approach potentially causes long inter- availability. ruption of target execution when the target has many • 245 • 246 • A Runtime Code Modification Method for Application Programs (a) before (b) after int prot = PROT_READ|PROT_WRITE; int flags = MAP_PRIVATE|MAP_ANONYMOUS; mmap(NULL, size, prot, flags, -1, 0); main() main() asm volatile("int $3"); { { func(); func(); ... ... Figure 2: The code written in the target stack } } func() func()jmp the patch, gives addresses to unresolved symbols, { { and so on. ... ... } } 2. Memory Allocation: allocates memory for the patch in the target. func_fix() 3. Load: loads the patch into the allocated memory. { ... 4. Activation: overwrites an instruction to jump to the Newly Allocated } patch at the top of the target function. Mem ory Figure 1: Function call path before and after applying a 2.2.1 livepatch binary patch livepatch [1] was developed by F. Ukai, and consists threads or the patch is large. gdb frequently stops only of a utility in user space, which is about 900 all threads in a target. As the number of threads in- lines of code. In the preparation stage, livepatch gets creases, interruption time increases, too. The writ- the information about the patches in the ELF file with ing size of PTRACE_POKEDATA is a ‘word,’ which is libbfd. In the memory allocation stage, livepatch first architecture-dependent—four bytes on i386. obtains the stack pointer of the target using PTRACE_ GETREGS Some practical cases will require additional memory to . Then it writes the machine code correspond- apply a binary patch whose size is greater than the orig- ing to the source shown in Figure 2 on the stack. The inal code. ptrace doesn’t provide a direct function code is executed by setting the program counter to the PTRACE_SETREGS to allocate memory. However, livepatch solves this by top address of the stack using , fol- PTRACE_CONT mmap() making a target execute instructions to allocate memory lowed by . The in the code as described in Section 2.2.1. allocates memory in the target, because the target it- self calls the mmap(). The assembler instruction ‘int $3’ generates the SIGTRAP to bring back the control to 2.2 Open Source RBPs livepatch, which is sleeping by wait(NULL) after the PTRACE_CONT. livepatch and pannus are two major open source RBPs. They both fix problems by adding a binary patch in the In the load stage, livepatch writes the patch in the allo- target’s virtual memory space and overwriting the jmp cated memory by repeating PTRACE_POKEDATA. In instruction to the binary patch at the top of the function the activation stage, PTRACE_POKEDATA is also used to be fixed (we call it the target function) as shown in to overwrite the instruction to jump. Figure 1. This means problems are fixed by the func- tion unit. Thus a patch is provided as a function (fixed- function) in an ELF shared library (patch file). The ba- 2.2.2 pannus sic processes of livepatch and pannus are similar and roughly divided into the following four stages. pannus [2] was developed by a group from NTT Cor- poration. It consists of a utility in user space and a ker- 1. Preparation: opens a patch file, obtains the size of nel patch. In the preparation stage, livepatch analyzes a 2008 Linux Symposium, Volume Two • 247 patch file by itself without external libraries and obtains Initialization necessary data. The memory allocation is mainly per- formed by a mmap3() kernel API which is provided Patch file analysis by the kernel patch. Actually it also plays a role in a Target execution file analysis portion of the load stage, because the mmap3() maps Preparation the patch file. The mmap3() is an enhanced version Compatibility check of mmap2(), which is a standard kernel API. It enables Stage other processes to allocate memory for the specified pro- Patch code analysis cess, directly accessing the core kernel structures such as mm_struct, vm_area_struct, and so on. Be- Address resolution cause members of the structures or access rules are often Patch instantiation changed, the maintenance of the patch doesn’t seem to be easy. Allocation request Mem ory In the load stage, the access_process_vm() ker- Allocation Memory allocation nel API is used via the kernel patch to set relocation Stage information in the allocated memory. The API reads/ Allocated address check writes any size of memory in the specified process. Patch loading request In the activation stage, pannus also uses access_ Load Stage process_vm() to overwrite the instruction to jump. Patch loading Note that pannus checks whether the status is safe be- Safety check fore the overwriting. The safety means that the number Activation Stage of threads whose program counters point the region to Activation be overwritten is zero. The program counter is obtained by PTRACE_GETREGS, after the target was stopped by Figure 3: The patching process of kaho PTRACE_ATTATCH. If the status is not ‘safety,’ pannus resumes the target once by PTRACE_DETATCH, and tries to check again. If the result of the second check The Preparation Stage consists of seven steps. Initial- is not also safety, pannus aborts the overwriting. The ization interprets the command line options, which in- probability that this situation happens increases with the clude information about the target and the command call frequency of the target function. file. The command file defines the name of a target, a fixed function, a patch file, and a map file. Patch file analysis opens the patch file and reads ELF infor- 3 Proposed Method and its Implementation mation such as ELF header, section headers, program headers, symbol table, dynamic sections, and versions. 3.1 Patching process Target execution file analysis finds the executable from /proc/<PID>/exe and acquires ELF information. Compatibility check confirms that byte order (endian), We propose a new patching method, which is used in our file class, OS ABI,2 and ABI version of the patch file, project kaho, which means Kernel Aided Hexadecimal which are contained in the ELF header, are identical to code Operator. The patching process of kaho is divided those of the target execution file. Patch code analysis into four stages similarly to livepatch and pannus. They searches for an entry whose st_name member is iden- are shown in Figure 3 with detailed steps. Its implemen- tical to the name of the fixed function from the symbol tation consists of a user-space utility program and a ker- table, and its file position from the st_value.
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages12 Page
-
File Size-