Changes

Jump to navigation Jump to search
2,181 bytes added ,  20:11, 16 December 2014
no edit summary
Line 1: Line 1:  
== Overview ==
 
== Overview ==
 +
Parasite code is a binary blob of code built in [http://en.wikipedia.org/wiki/Position-independent_code PIE] format for execution inside another process address space. The main and only purpose of the parasite code is to execute CRIU service routines inside dumpee tasks address space.
   −
Parasite code is a binary blob of code built in [http://en.wikipedia.org/wiki/Position-independent_code PIE] format for execution inside another process address space. As result in a sake of simplicity parasite code utilize native system calls only.
+
== Using the parasite ==
   −
=== Running the parasite ===
+
All architecture independent code calling for parasite service routines is sitting in <code>parasite-syscall.c</code> file. When we need to run parasite code inside some dumpee task we:
 +
 +
# Move task into that named seized state with <code>ptrace(PTRACE_SEIZE, …)</code> helper (thus task get stopped but does not notice that someone outside is trying to manipulate it).
 +
# Inject and execute mmap syscall inside dumpee address space with help of <code>ptrace</code> system call, because we need to allocate a shared memory area which will be used for parasite stack and parameters exchange between CRIU and dumpee.
 +
# Open local copy of shared memory space from ''/proc/$PID/map_files/'', where '''$PID''' is process identificator of a dumpee.
   −
Injection of a parasite code may be splitted into two phases
+
All these actions are gathered in <code>parasite_infect_seized()</code> helper. Once parasite is prepared and placed into dumpee address space, CRIU can call for parasite service routines.
   −
# preparation of a victim task
+
There are two modes the parasite can operate in:
# injection itself
     −
During preparation stage we move a victim into that named ''seized'' state with help of '''prctl''' system call (in this state the victim does not recognize that it is being manipulated by someone). Once seized we substitute current code at '''IP''' (instruction pointer) with '''mmap''' system call allocating a shared memory space needed to carry a parasite blob.
+
# Trap mode
 +
# Daemon mode
   −
Parasite code injection itself is pretty simple: because we have a shared memory slab allocated inside a victim space we can scan <code>/proc/$pid/map_files/</code> directory and open this slab inside CRIU address space. Once opened we simply copy parasite code there with '''memcpy'''.
+
In trap mode parasite simply executes one command and yields cpu trap instruction which CRIU intercepts. This is like one command at a time mode.
   −
At this moment we can run parasite code adjusting '''IP''' of the victim and call '''prctl''' again. After that parasite is spinning listening the socket for commands from outside world.
+
In daemon mode (as name implies) parasite behaves like a unix daemon - it opens a unix socket and start listening for commands on it. Once command received it get handled and daemon returns result back via socket packet, then it continue listening for the next command and etc. All currently known commands are assembled as <code>PARASITE_CMD_…</code> enum in <code>parasite.h</code> header.
   −
=== Parasite internal structure ===
+
== Parasite internal structure ==
   −
Internally parasite code is represented as two blocks
+
Internally parasite might be represented as following blocks
   −
# a bootstrap written in assembly language
+
[[File:Parasite-layout.svg|thumb|upright=1|center]]
# a daemon written in C language
     −
[[File:Parasite-structure.svg|thumb|upright=4|center]]
+
Parasite bootstrap code written in assembly language, which is specific for every architecture (x86, arm, arm64), in turn parasite daemon is common for all architectures and written in C language. We consider only x86 architecture here but other architectures have the similar approach.
   −
==== Parasite bootstrap ====
+
While all blocks on the image above are self descriptive the sigframe (signal frame) block requires some comments. Its main purpose is to handle <code>rt_sigreturn()</code> system call which we use to restore victim’s execution context (registers and etc). It should be prepared by caller setting up original registers values and etc the victim has at the moment of parasite injection.
   −
Parasite bootstrap lives in <code>parasite-head.S</code> file and simply prepares the own stack (nipping off a few bytes) and literally calls for body execution. Once main body execution is complete we simply call the cpu trap thus CRIU can intercept this moment and cure the victim restoring its original code contents.
+
=== Parasite bootstrap ===
   −
==== Parasite daemon ====
+
Parasite bootstrap lives in <code>parasite-head.S</code> file and simply adjusts own stack and literally call the daemon entry point. Right after the call there is trapping instruction placed which triggers the notification to a caller that parasite has finished its work if been running in trap mode. When parasite is running in daemon mode the notifications are a bit more complex and will be considered later.
   −
Parasite daemon lives in <code>pie/parasite.c</code> file and as file extension implies is written in pure C language. The entry point is <code>parasite_service</code>, which simply opens unix socket and reads the command to service.
+
=== Parasite daemon ===
 +
 
 +
Parasite daemon code lives in <code>pie/parasite.c</code> file. Its entry point is <code>parasite_daemon()</code>. Upon enter it opens command socket which is used to communicate with the caller. Once socket is opened the daemon comes to sleep waiting for command to appear.
 +
 
 +
[[File:Parasite-daemon.svg|thumb|upright=3|center]]
 +
 
 +
Because the whole parasite memory block is a shared memory slab data exchange between CRIU and dumpee is regular read/write operations into arguments area while commands are sent as network packets.
 +
 
 +
== Curing dumpee from parasite code ==
 +
 
 +
Once everything is done and we no longer need parasite we are removing it from the dumpee address space in several steps:
 +
 
 +
# CRIU start tracing the syscalls parasite is executing with help of <code>ptrace</code>
 +
# Send <code>PARASITE_CMD_FINI</code> to parasite via control socket
 +
# Parasite receives it, then closes control socket and executes <code>rt_sigreturn()</code> system call
 +
# CRIU intercept exit from this syscall and unmaps parasite memory area, thus victim become into the state it was before parasite injection
    
[[Category: Under the hood]]
 
[[Category: Under the hood]]

Navigation menu