Commit 0ae2bad0 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

mm: mark a vma as stack, if a value of sp is in it

/proc/PID/maps can contains not up to date information about a stack vma.
A kernel marks a VMA as stack, if thread_struct->usersp is in it,
but usersp is updated, when a process calls a syscall.

This problem is occured, when we try to dump/restore a process in a loop.
When a restorer resumes a process, a restorer vma will be marked as stack.

A thread stack should not be marked as stack, because its vma is mapped
w/o MAP_GROWSDOWN.
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Acked-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 0e0da2de
......@@ -833,7 +833,8 @@ err:
static int dump_task_core_all(pid_t pid, const struct proc_pid_stat *stat,
const struct parasite_dump_misc *misc, const struct parasite_ctl *ctl,
const struct cr_fdset *cr_fdset)
const struct cr_fdset *cr_fdset,
struct list_head *vma_area_list)
{
int fd_core = fdset_fd(cr_fdset, CR_FD_CORE);
CoreEntry *core;
......@@ -859,6 +860,8 @@ static int dump_task_core_all(pid_t pid, const struct proc_pid_stat *stat,
if (ret)
goto err_free;
mark_stack_vma(core->thread_info->gpregs->sp, vma_area_list);
ret = get_task_futex_robust_list(pid, core->thread_core);
if (ret)
goto err_free;
......@@ -1423,7 +1426,8 @@ static int dump_one_task(struct pstree_item *item)
goto err_cure;
}
ret = dump_task_core_all(pid, &pps_buf, &misc, parasite_ctl, cr_fdset);
ret = dump_task_core_all(pid, &pps_buf, &misc,
parasite_ctl, cr_fdset, &vma_area_list);
if (ret) {
pr_err("Dump core (pid: %d) failed with %d\n", pid, ret);
goto err_cure;
......
......@@ -1208,6 +1208,9 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core, struct list_head *tgt_v
if (ret < 0)
goto err;
/* required to unmap stack _with_ guard page */
mark_stack_vma((long) &self_vma_list, &self_vma_list);
self_vmas_len = round_up((ret + 1) * sizeof(VmaEntry), PAGE_SIZE);
vmas_len = round_up((nr_vmas + 1) * sizeof(VmaEntry), PAGE_SIZE);
......
......@@ -165,6 +165,8 @@ extern void pr_vma(unsigned int loglevel, const struct vma_area *vma_area);
p__; \
})
extern void mark_stack_vma(unsigned long sp, struct list_head *vma_area_list);
extern int move_img_fd(int *img_fd, int want_fd);
extern int close_safe(int *fd);
......
......@@ -144,10 +144,7 @@ int parse_smaps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
goto err;
}
if (strstr(buf, "[stack")) {
vma_area->vma.status |= VMA_AREA_REGULAR | VMA_AREA_STACK;
vma_area->vma.flags |= MAP_GROWSDOWN;
} else if (strstr(buf, "[vsyscall]")) {
if (strstr(buf, "[vsyscall]")) {
vma_area->vma.status |= VMA_AREA_VSYSCALL;
} else if (strstr(buf, "[vdso]")) {
vma_area->vma.status |= VMA_AREA_REGULAR | VMA_AREA_VDSO;
......
......@@ -36,6 +36,20 @@
#include "crtools.h"
/* /proc/PID/maps can contain not up to date information about stack */
void mark_stack_vma(unsigned long sp, struct list_head *vma_area_list)
{
struct vma_area *vma_area;
list_for_each_entry(vma_area, vma_area_list, list) {
if (in_vma_area(vma_area, sp)) {
vma_area->vma.status |= VMA_AREA_STACK;
vma_area->vma.flags |= MAP_GROWSDOWN;
return;
}
}
BUG();
}
void pr_vma(unsigned int loglevel, const struct vma_area *vma_area)
{
if (!vma_area)
......
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