Commit 33b5b417 authored by Dmitry Safonov's avatar Dmitry Safonov Committed by Andrei Vagin

vdso: Don't drop original VVAR VMA on dump

I think, it's better if we still restore the original vvar
as some code may expect vma to be there or may dereference
pointer there.
E.g., if we checkpointed task while it was on vdso page,
it'll dereference pointer to vvar. Better keep it in vmas.

So, the original code deleted it becase it was proxy_vvar_marked,
which I think is misnaming problem.
Having two vvar addresses named rt_ and orig_ describes what to
do with them on dump.
Signed-off-by: 's avatarDmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 3b8071ba
......@@ -49,8 +49,9 @@ struct parasite_vma_entry
struct parasite_vdso_vma_entry {
unsigned long start;
unsigned long len;
unsigned long proxy_vdso_addr;
unsigned long proxy_vvar_addr;
unsigned long orig_vdso_addr;
unsigned long orig_vvar_addr;
unsigned long rt_vvar_addr;
int is_marked;
bool try_fill_symtable;
bool is_vdso;
......
......@@ -554,13 +554,15 @@ static int parasite_check_vdso_mark(struct parasite_vdso_vma_entry *args)
pr_err("vdso: Mark version mismatch!\n");
return -EINVAL;
}
args->is_marked = 1;
args->proxy_vdso_addr = m->orig_vdso_addr;
args->proxy_vvar_addr = m->orig_vvar_addr;
args->is_marked = 1;
args->orig_vdso_addr = m->orig_vdso_addr;
args->orig_vvar_addr = m->orig_vvar_addr;
args->rt_vvar_addr = m->rt_vvar_addr;
} else {
args->is_marked = 0;
args->proxy_vdso_addr = VDSO_BAD_ADDR;
args->proxy_vvar_addr = VVAR_BAD_ADDR;
args->is_marked = 0;
args->orig_vdso_addr = VDSO_BAD_ADDR;
args->orig_vvar_addr = VVAR_BAD_ADDR;
args->rt_vvar_addr = VVAR_BAD_ADDR;
if (args->try_fill_symtable) {
struct vdso_symtable t;
......
......@@ -118,10 +118,11 @@ static bool not_vvar_or_vdso(struct vma_area *vma)
int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
struct vm_area_list *vma_area_list)
{
unsigned long proxy_vdso_addr = VDSO_BAD_ADDR;
unsigned long proxy_vvar_addr = VVAR_BAD_ADDR;
struct vma_area *proxy_vdso_marked = NULL;
struct vma_area *proxy_vvar_marked = NULL;
unsigned long orig_vdso_addr = VDSO_BAD_ADDR;
unsigned long orig_vvar_addr = VVAR_BAD_ADDR;
unsigned long rt_vvar_addr = VVAR_BAD_ADDR;
struct vma_area *rt_vdso_marked = NULL;
struct vma_area *rt_vvar_marked = NULL;
struct parasite_vdso_vma_entry *args;
int fd = -1, exit_code = -1;
enum vdso_check_t vcheck;
......@@ -152,10 +153,10 @@ int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
BUILD_BUG_ON(!(VDSO_PROT & VVAR_PROT));
if ((vma->e->prot & VVAR_PROT) == VVAR_PROT) {
if (proxy_vvar_addr != VVAR_BAD_ADDR &&
proxy_vvar_addr == vma->e->start) {
BUG_ON(proxy_vvar_marked);
proxy_vvar_marked = vma;
if (rt_vvar_addr != VVAR_BAD_ADDR &&
rt_vvar_addr == vma->e->start) {
BUG_ON(rt_vvar_marked);
rt_vvar_marked = vma;
continue;
}
}
......@@ -188,13 +189,14 @@ int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
* area status.
*/
if (unlikely(args->is_marked)) {
if (proxy_vdso_marked) {
if (rt_vdso_marked) {
pr_err("Ow! Second vdso mark detected!\n");
goto err;
}
proxy_vdso_marked = vma;
proxy_vdso_addr = args->proxy_vdso_addr;
proxy_vvar_addr = args->proxy_vvar_addr;
rt_vdso_marked = vma;
orig_vdso_addr = args->orig_vdso_addr;
orig_vvar_addr = args->orig_vvar_addr;
rt_vvar_addr = args->rt_vvar_addr;
continue;
}
......@@ -225,38 +227,38 @@ int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
* There is marked vdso, it means such vdso is autogenerated
* and must be dropped from vma list.
*/
if (proxy_vdso_marked) {
pr_debug("vdso: Found marked at %lx (proxy vDSO at %lx VVAR at %lx)\n",
(long)proxy_vdso_marked->e->start,
(long)proxy_vdso_addr, (long)proxy_vvar_addr);
if (rt_vdso_marked) {
pr_debug("vdso: Found marked at %lx (orig vDSO at %lx VVAR at %lx)\n",
(long)rt_vdso_marked->e->start,
(long)orig_vdso_addr, (long)orig_vvar_addr);
/*
* Don't forget to restore the proxy vdso/vvar status, since
* it's unknown to the kernel.
*/
list_for_each_entry(vma, &vma_area_list->h, list) {
if (vma->e->start == proxy_vdso_addr) {
if (vma->e->start == orig_vdso_addr) {
vma->e->status |= VMA_AREA_REGULAR | VMA_AREA_VDSO;
pr_debug("vdso: Restore proxy vDSO status at %lx\n",
pr_debug("vdso: Restore orig vDSO status at %lx\n",
(long)vma->e->start);
} else if (vma->e->start == proxy_vvar_addr) {
} else if (vma->e->start == orig_vvar_addr) {
vma->e->status |= VMA_AREA_REGULAR | VMA_AREA_VVAR;
pr_debug("vdso: Restore proxy VVAR status at %lx\n",
pr_debug("vdso: Restore orig VVAR status at %lx\n",
(long)vma->e->start);
}
}
pr_debug("vdso: Droppping marked vdso at %lx\n",
(long)proxy_vdso_marked->e->start);
list_del(&proxy_vdso_marked->list);
xfree(proxy_vdso_marked);
(long)rt_vdso_marked->e->start);
list_del(&rt_vdso_marked->list);
xfree(rt_vdso_marked);
vma_area_list->nr--;
if (proxy_vvar_marked) {
if (rt_vvar_marked) {
pr_debug("vdso: Droppping marked vvar at %lx\n",
(long)proxy_vvar_marked->e->start);
list_del(&proxy_vvar_marked->list);
xfree(proxy_vvar_marked);
(long)rt_vvar_marked->e->start);
list_del(&rt_vvar_marked->list);
xfree(rt_vvar_marked);
vma_area_list->nr--;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment