[CRIU] [PATCH 3/5] vdso: Proxify vDSO code on restore
Pavel Emelyanov
xemul at parallels.com
Mon May 20 07:54:56 EDT 2013
On 05/16/2013 07:33 PM, Cyrill Gorcunov wrote:
>
> When tasks are restored in a kernel which version differ from the one
> they were being dumped on, the vDSO content may has been changed thus
> any call to vDSO service routine will lead to SIGBUS in a better case
> or in wrong results without notice in a worst one.
>
> So to work this situation out we need a that named vDSO proxy, where
> any call to original vDSO service routine shall be redirected to
> a valid runtime vDSO supplied by the kernel we're restoring on.
>
> In terms of ugly ascii gprahics it might be represented as following.
>
> Original vDSO in image
> ======================
>
> +---------------------------+
> | __vdso_getcpu |
> | ... |
> | function body here |
> +---------------------------+
> | __vdso_time |
> | ... |
> | function body here |
> +---------------------------+
> ...
>
> Run-time proxified calls
> ========================
>
> Mapped from image and then patched
>
> +---------------------------+
> | __vdso_getcpu |
> | redirect +----+
> | int3 | |
> +---------------------------+ |
> | __vdso_time | |
> | redirect +-+ |
> | int3 | | |
> +---------------------------+ | |
> ... | |
> | | New memory area with valid vDSO content
> | | +---------------------------+
> | | | __vdso_getcpu |
> | +->| ... |
> | | function body here |
> | +---------------------------+
> | | __vdso_time |
> +---->| ... |
> | function body here |
> +---------------------------+
> ...
>
> To achieve this we
>
> 1) Read vDSO from memory the kernel provides us and remember
> its structure and functions addresses.
>
> 2) Analyze VMAs read from images, if vdso is met -- remember where
> this area is premaped.
>
> 3) Once the vdso page data read from disk -- parse it and fill symbols
> table, we will use it to patch the vdso calls. Then mark it with
> special vdso signature. Thus on next dump session it might be
> recognized as vdso area.
>
> 4) When we start unmapping self vmas, if runtime vdso met (from [1])
> we remap it at some new place.
>
> 5) Patch old vDSO entry points to redirect calls to new vDSO entries.
>
> 6) Mark new vDSO with special sign thus in future patch the dumper will
> find that the second vDSO should be omitted from writting on disk.
>
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
> cr-restore.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
> include/restorer.h | 12 ++++++++
> pie/restorer.c | 54 ++++++++++++++++++++++++++++++++++
> 3 files changed, 148 insertions(+), 3 deletions(-)
>
> @@ -263,6 +268,18 @@ static int map_private_vma(pid_t pid, struct vma_area *vma, void *tgt_addr,
> if (vma_entry_is(&vma->vma, VMA_FILE_PRIVATE))
> close(vma->vma.fd);
>
> + if (vma_entry_is(&vma->vma, VMA_AREA_VDSO)) {
> + if (vdso_proxy.proxify) {
> + pr_err("Got second vDSO area while only one expected\n");
> + return -1;
> + }
> +
> + vdso_proxy.sym_dumpee.vma_start = vma->vma.start;
> + vdso_proxy.sym_dumpee.vma_end = vma->vma.end;
> + vdso_proxy.premmaped_at = (unsigned long)addr;
> + vdso_proxy.proxify = true;
> + }
> +
> return 0;
> }
So you _always_ put VDSO proxy. I thought we've decided not to do it if
symbols offsets match.
More information about the CRIU
mailing list