This page describes what this context is and why we need one.
What is it?
The restorer context is the last stage of the restore process. It differs from the regular CRIU's (process) context like the parasite code does -- it doesn't have any libraries, it is PIE-compiled and can olny work on fixed amount of memory. In this context CRIU restores
- memory
- timers
- credentials
- threads
Why separate context?
The reasoning for this is simple -- when CRIU comes to the state when it needs to restore process' memory, it should unmap all the old mappings and map the new ones. But since CRIU process would do this operation on itself, once the old code is unmapped CRIU will seg-fault right on the exit from the munmap()
system call. Also this code should be get over-mmaped by the mapping is restores. So we need some code that would do this. And this other code should "sit" in two address spaces simultaneously -- in the CRIU's one and in the target one.
The switch to this context is done in several steps.
First, we collect the data needed by the restorer code and puts all it into one sequential memory area. Then, knowing the data size and the restorer code size, we find the appropriate hole in the intersection of CRIU's and target mappings. Then we mmap() this region, mremap() the data into it, put the restorer blob nearby, fix the pointers (see below) and call assember's "jump" instruction to get there.
Now what "fix the pointers" mean. When we collected data for CRIU we addressed the objects in this are using pointers valid in CRIU address space. When we will jump into restorer code pointers in there should "know" where the respective objects are. So knowing where from the restorer counts pointers and the structure of the restorer data, we alter them respectively.