Commit 62ee701c authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Pavel Emelyanov

Use /proc/pid/smaps for VMA parsing v2

This allows us to detect nonlinear mappings.
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 32e07745
......@@ -82,7 +82,7 @@ static int collect_mappings(pid_t pid, struct list_head *vma_area_list)
pr_info("Collecting mappings (pid: %d)\n", pid);
pr_info("----------------------------------------\n");
ret = parse_maps(pid, vma_area_list, true);
ret = parse_smaps(pid, vma_area_list, true);
if (ret < 0)
goto err;
......
......@@ -965,7 +965,7 @@ static int sigreturn_restore(pid_t pid, struct list_head *tgt_vmas, int nr_vmas)
restore_task_vma_len = 0;
restore_thread_vma_len = 0;
ret = parse_maps(pid, &self_vma_list, false);
ret = parse_smaps(pid, &self_vma_list, false);
close_pid_proc();
if (ret < 0)
goto err;
......
......@@ -95,7 +95,7 @@ struct proc_mountinfo {
extern int parse_mountinfo(pid_t pid, struct proc_mountinfo *mi, int nr_elems);
extern int parse_pid_stat(pid_t pid, struct proc_pid_stat *s);
extern int parse_pid_stat_small(pid_t pid, struct proc_pid_stat_small *s);
extern int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files);
extern int parse_smaps(pid_t pid, struct list_head *vma_area_list, bool use_map_files);
extern int parse_pid_status(pid_t pid, struct proc_status_creds *);
#endif /* PROC_PARSE_H__ */
......@@ -281,4 +281,9 @@ int copy_file(int fd_in, int fd_out, size_t bytes);
bool is_anon_inode(struct statfs *statfs);
int is_anon_link_type(int lfd, char *type);
#define is_hex_digit(c) \
(((c) >= '0' && (c) <= '9') || \
((c) >= 'a' && (c) <= 'f') || \
((c) >= 'A' && (c) <= 'F'))
#endif /* UTIL_H_ */
......@@ -25,7 +25,25 @@ static char *buf = __buf.buf;
#define BUF_SIZE sizeof(__buf.buf)
int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
/* check the @line starts with "%lx-%lx" format */
static bool is_vma_range_fmt(char *line)
{
while (*line && is_hex_digit(*line))
line++;
if (*line++ != '-')
return false;
while (*line && is_hex_digit(*line))
line++;
if (*line++ != ' ')
return false;
return true;
}
int parse_smaps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
{
struct vma_area *vma_area = NULL;
u64 start, end, pgoff;
......@@ -35,10 +53,10 @@ int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
int ret = -1, nr = 0;
DIR *map_files_dir = NULL;
FILE *maps = NULL;
FILE *smaps = NULL;
maps = fopen_proc(pid, "maps");
if (!maps)
smaps = fopen_proc(pid, "smaps");
if (!smaps)
goto err;
if (use_map_files) {
......@@ -47,10 +65,28 @@ int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
goto err;
}
while (fgets(buf, BUF_SIZE, maps)) {
while (fgets(buf, BUF_SIZE, smaps)) {
int num;
char file_path[6];
if (!is_vma_range_fmt(buf)) {
if (!strncmp(buf, "Nonlinear", 9)) {
BUG_ON(!vma_area);
pr_err("Nonlinear mapping found %016lx-%016lx\n",
vma_area->vma.start, vma_area->vma.end);
/*
* VMA is already on list and will be
* freed later as list get destroyed.
*/
vma_area = NULL;
goto err;
} else
continue;
}
vma_area = alloc_vma_area();
if (!vma_area)
goto err;
memset(file_path, 0, 6);
num = sscanf(buf, "%lx-%lx %c%c%c%c %lx %02x:%02x %lu %5s",
......@@ -61,10 +97,6 @@ int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
goto err;
}
vma_area = alloc_vma_area();
if (!vma_area)
goto err;
if (map_files_dir) {
char path[32];
......@@ -177,8 +209,8 @@ int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
ret = nr;
err:
if (maps)
fclose(maps);
if (smaps)
fclose(smaps);
if (map_files_dir)
closedir(map_files_dir);
......
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