Changes

Jump to navigation Jump to search
m
Line 138: Line 138:  
No additional actions here. The process will be restored and will continue execution from the abort handler (not within the rseq CS!).
 
No additional actions here. The process will be restored and will continue execution from the abort handler (not within the rseq CS!).
   −
=== inside CS: <code>flags</code> is <code>RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL</code> ===
+
=== Executing non-abortable critical section ===
   −
Rare case, but we support it too. If the rseq CS has <code>RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL</code> flag it means that its technically
+
This is a relatively rare case, but it is fully supported by CRIU. When an RSEQ critical section is marked with the <code>RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL</code> flag, it is effectively non-abortable.
non-abortable. So, from the first glance, it seems like we can just not do anything special: save rseq structure address, not fix up IP.
+
At first glance, this might suggest that no special handling is required as the RSEQ structure could simply be saved, and the instruction pointer left unchanged. However, this assumption is incorrect.
This is incorrect.
     −
The kernel will clean up <code>(struct rseq).rseq_cs</code> pointer once we jump into the parasite on the dump:
+
During checkpoint, when CRIU transfers execution to the parasite, the kernel clears the <code>(struct rseq).rseq_cs</code> pointer if it determines that execution is no longer within an rseq critical section:
 
<pre>
 
<pre>
 
static int rseq_ip_fixup(struct pt_regs *regs)
 
static int rseq_ip_fixup(struct pt_regs *regs)
Line 159: Line 158:  
</pre>
 
</pre>
   −
and after the restore process will continue the rseq CS execution from the same place (it's okay) but from the kernel point of view,
+
As a result, after restore, the process resumes execution at the correct instruction pointer within the critical section, but from the kernel's perspective it is no longer executing inside an RSEQ critical section. This discrepancy is problematic, because the kernel relies on the <code>(struct rseq).rseq_cs</code> field to determine rseq execution context.
the process will continue this execution as not being within the rseq CS (that's bad!). Because the kernel determines execution context from the <code>(struct rseq).rseq_cs</code> field.
     −
==== Dump ====
+
==== Checkpoint ====
We need to determine where the <code>struct rseq</code> is and dump its address length and signature.
  −
To achieve that we use special ptrace handle <code>PTRACE_GET_RSEQ_CONFIGURATION</code> (refer to the <code>dump_thread_rseq</code> function).
     −
We save IP as it was (not doing fixup), but we have to save <code>(struct rseq).rseq_cs</code> field into the CRIU image.
+
CRIU locates the <code>struct rseq</code> instance and records its address, length, and signature using the <code>PTRACE_GET_RSEQ_CONFIGURATION</code> ptrace request.
 +
The instruction pointer is saved without modification, but the <code>(struct rseq).rseq_cs</code> field is also recorded in the CRIU image.
    
==== Restore ====
 
==== Restore ====
We need to take data about the <code>struct rseq</code> from the image (see images/rseq.proto) and register it from the parasite context using the <code>rseq</code> syscall (take a look on <code>restore_rseq</code> in criu/pie/restorer.c)
     −
We need to restore <code>(struct rseq).rseq_cs</code> memory externaly using ptrace <code>POKEAREA</code> (see <code>restore_rseq_cs</code>).
+
During restore, CRIU re-registers the <code>struct rseq</code> from the checkpoint image (<code>images/rseq.proto<code>) using the <code>rseq</code> system call from the restorer context (see <code>restore_rseq</code> in <code>criu/pie/restorer.c</code>). In addition, CRIU explicitly restores the <code>(struct rseq).rseq_cs</code> field using <code>PTRACE_POKEAREA</code> (see <code>restore_rseq_cs</code>) to reestablish the correct <code>rseq</code> execution context in the kernel.
    
== TODO ==
 
== TODO ==
554

edits

Navigation menu