mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-30 13:58:34 +00:00
Use openat() helper intensively when opening /proc/pid/X files
This allows us to get rid of open-coded "/proc/pid/X". Based-on-patch-from: Pavel Emelyanov <xemul@parallels.com> Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Acked-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
117
cr-dump.c
117
cr-dump.c
@@ -65,7 +65,7 @@ void free_mappings(struct list_head *vma_area_list)
|
|||||||
INIT_LIST_HEAD(vma_area_list);
|
INIT_LIST_HEAD(vma_area_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int collect_mappings(pid_t pid, struct list_head *vma_area_list)
|
static int collect_mappings(pid_t pid, int pid_dir, struct list_head *vma_area_list)
|
||||||
{
|
{
|
||||||
struct vma_area *vma_area;
|
struct vma_area *vma_area;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
@@ -74,7 +74,7 @@ static int collect_mappings(pid_t pid, struct list_head *vma_area_list)
|
|||||||
pr_info("Collecting mappings (pid: %d)\n", pid);
|
pr_info("Collecting mappings (pid: %d)\n", pid);
|
||||||
pr_info("----------------------------------------\n");
|
pr_info("----------------------------------------\n");
|
||||||
|
|
||||||
ret = parse_maps(pid, vma_area_list, true);
|
ret = parse_maps(pid, pid_dir, vma_area_list, true);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
@@ -93,8 +93,9 @@ err_bogus_mapping:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int dump_one_reg_file(int type, unsigned long fd_name, int lfd,
|
static int dump_one_reg_file(int type, unsigned long fd_name, int lfd,
|
||||||
bool do_close, unsigned long pos, unsigned int flags,
|
bool do_close_lfd, unsigned long pos,
|
||||||
char *id, struct cr_fdset *cr_fdset)
|
unsigned int flags, char *id,
|
||||||
|
struct cr_fdset *cr_fdset)
|
||||||
{
|
{
|
||||||
struct fdinfo_entry e;
|
struct fdinfo_entry e;
|
||||||
char fd_str[128];
|
char fd_str[128];
|
||||||
@@ -112,7 +113,7 @@ static int dump_one_reg_file(int type, unsigned long fd_name, int lfd,
|
|||||||
pr_info("Dumping path for %lx fd via self %d [%s]\n",
|
pr_info("Dumping path for %lx fd via self %d [%s]\n",
|
||||||
fd_name, lfd, big_buffer);
|
fd_name, lfd, big_buffer);
|
||||||
|
|
||||||
if (do_close)
|
if (do_close_lfd)
|
||||||
close(lfd);
|
close(lfd);
|
||||||
|
|
||||||
e.type = type;
|
e.type = type;
|
||||||
@@ -136,14 +137,14 @@ err:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dump_cwd(char *path, struct cr_fdset *cr_fdset)
|
static int dump_cwd(int pid_dir, struct cr_fdset *cr_fdset)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
fd = open(path, O_RDONLY | O_DIRECTORY);
|
fd = open_proc(pid_dir, "cwd");
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
pr_perror("Failed to openat %s\n", path);
|
pr_perror("Failed to openat cwd\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,7 +235,7 @@ err:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dump_one_fd(char *pid_fd_dir, int dir, char *fd_name, unsigned long pos,
|
static int dump_one_fd(pid_t pid, int pid_dir, char *fd_name, unsigned long pos,
|
||||||
unsigned int flags, char *id, struct cr_fdset *cr_fdset)
|
unsigned int flags, char *id, struct cr_fdset *cr_fdset)
|
||||||
{
|
{
|
||||||
struct statfs stfs_buf;
|
struct statfs stfs_buf;
|
||||||
@@ -242,18 +243,18 @@ static int dump_one_fd(char *pid_fd_dir, int dir, char *fd_name, unsigned long p
|
|||||||
int err = -1;
|
int err = -1;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
|
||||||
fd = openat(dir, fd_name, O_RDONLY);
|
fd = open_proc(pid_dir, "fd/%s", fd_name);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
err = try_dump_socket(pid_fd_dir, fd_name, cr_fdset);
|
err = try_dump_socket(pid, fd_name, cr_fdset);
|
||||||
if (err != 1)
|
if (err != 1)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
pr_perror("Failed to openat %s/%d %s\n", pid_fd_dir, dir, fd_name);
|
pr_perror("Failed to openat %d/fd/%s\n", pid, fd_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fstat(fd, &st_buf) < 0) {
|
if (fstat(fd, &st_buf) < 0) {
|
||||||
pr_perror("Can't get stat on %s\n", fd_name);
|
pr_perror("Can't get stat on %d/fd/%s\n", pid, fd_name);
|
||||||
goto out_close;
|
goto out_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,7 +264,7 @@ static int dump_one_fd(char *pid_fd_dir, int dir, char *fd_name, unsigned long p
|
|||||||
/* skip only standard destriptors */
|
/* skip only standard destriptors */
|
||||||
if (atoi(fd_name) < 3) {
|
if (atoi(fd_name) < 3) {
|
||||||
err = 0;
|
err = 0;
|
||||||
pr_info("... Skipping tty ... %s/%s\n", pid_fd_dir, fd_name);
|
pr_info("... Skipping tty ... %d/fd/%s\n", pid, fd_name);
|
||||||
goto out_close;
|
goto out_close;
|
||||||
}
|
}
|
||||||
goto err;
|
goto err;
|
||||||
@@ -294,13 +295,14 @@ out_close:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_fd_params(pid_t pid, char *fd, unsigned long *pos,
|
static int read_fd_params(pid_t pid, int pid_dir, char *fd,
|
||||||
unsigned int *flags, char *id)
|
unsigned long *pos, unsigned int *flags,
|
||||||
|
char *id)
|
||||||
{
|
{
|
||||||
FILE *file;
|
FILE *file;
|
||||||
unsigned int f;
|
unsigned int f;
|
||||||
|
|
||||||
file = fopen_proc("%d/fdinfo/%s", "r", pid, fd);
|
file = fopen_proc(pid_dir, "fdinfo/%s", fd);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
pr_perror("Can't open %d's %s fdinfo\n", pid, fd);
|
pr_perror("Can't open %d's %s fdinfo\n", pid, fd);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -309,15 +311,14 @@ static int read_fd_params(pid_t pid, char *fd, unsigned long *pos,
|
|||||||
fscanf(file, "pos:\t%li\nflags:\t%o\nid:\t%s\n", pos, flags, id);
|
fscanf(file, "pos:\t%li\nflags:\t%o\nid:\t%s\n", pos, flags, id);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
pr_info("%d fdinfo %s: pos: %16lx flags: %16o id %s\n",
|
pr_info("%d fdinfo %s: pos: %16lx flags: %16o id %20s\n",
|
||||||
pid, fd, *pos, *flags, id);
|
pid, fd, *pos, *flags, id);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dump_task_files(pid_t pid, struct cr_fdset *cr_fdset)
|
static int dump_task_files(pid_t pid, int pid_dir, struct cr_fdset *cr_fdset)
|
||||||
{
|
{
|
||||||
char pid_fd_dir[64];
|
|
||||||
struct dirent *de;
|
struct dirent *de;
|
||||||
unsigned long pos;
|
unsigned long pos;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
@@ -328,26 +329,23 @@ static int dump_task_files(pid_t pid, struct cr_fdset *cr_fdset)
|
|||||||
pr_info("Dumping opened files (pid: %d)\n", pid);
|
pr_info("Dumping opened files (pid: %d)\n", pid);
|
||||||
pr_info("----------------------------------------\n");
|
pr_info("----------------------------------------\n");
|
||||||
|
|
||||||
snprintf(pid_fd_dir, sizeof(pid_fd_dir), "/proc/%d/cwd", pid);
|
if (dump_cwd(pid_dir, cr_fdset)) {
|
||||||
if (dump_cwd(pid_fd_dir, cr_fdset)) {
|
pr_perror("Can't dump %d's cwd %s\n", pid);
|
||||||
pr_perror("Can't dump cwd %s\n", pid_fd_dir);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(pid_fd_dir, sizeof(pid_fd_dir), "/proc/%d/fd", pid);
|
fd_dir = opendir_proc(pid_dir, "fd");
|
||||||
fd_dir = opendir(pid_fd_dir);
|
|
||||||
if (!fd_dir) {
|
if (!fd_dir) {
|
||||||
pr_perror("Can't open %s\n", pid_fd_dir);
|
pr_perror("Can't open %d's fd\n", pid);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((de = readdir(fd_dir))) {
|
while ((de = readdir(fd_dir))) {
|
||||||
if (de->d_name[0] == '.')
|
if (de->d_name[0] == '.')
|
||||||
continue;
|
continue;
|
||||||
if (read_fd_params(pid, de->d_name, &pos, &flags, id))
|
if (read_fd_params(pid, pid_dir, de->d_name, &pos, &flags, id))
|
||||||
return -1;
|
return -1;
|
||||||
if (dump_one_fd(pid_fd_dir, dirfd(fd_dir), de->d_name,
|
if (dump_one_fd(pid, pid_dir, de->d_name, pos, flags, id, cr_fdset))
|
||||||
pos, flags, id, cr_fdset))
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,7 +422,7 @@ err:
|
|||||||
#define assign_reg(dst, src, e) dst.e = (__typeof__(dst.e))src.e
|
#define assign_reg(dst, src, e) dst.e = (__typeof__(dst.e))src.e
|
||||||
#define assign_array(dst, src, e) memcpy(&dst.e, &src.e, sizeof(dst.e))
|
#define assign_array(dst, src, e) memcpy(&dst.e, &src.e, sizeof(dst.e))
|
||||||
|
|
||||||
static int get_task_stat(pid_t pid, u8 *comm, u32 *flags,
|
static int get_task_stat(pid_t pid, int pid_dir, u8 *comm, u32 *flags,
|
||||||
u64 *start_code, u64 *end_code,
|
u64 *start_code, u64 *end_code,
|
||||||
u64 *start_data, u64 *end_data,
|
u64 *start_data, u64 *end_data,
|
||||||
u64 *start_stack, u64 *start_brk,
|
u64 *start_stack, u64 *start_brk,
|
||||||
@@ -439,7 +437,7 @@ static int get_task_stat(pid_t pid, u8 *comm, u32 *flags,
|
|||||||
* '0' symbol at argument 20 in format string.
|
* '0' symbol at argument 20 in format string.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
file = fopen_proc("%d/stat", "r", pid);
|
file = fopen_proc(pid_dir, "stat");
|
||||||
if (!file) {
|
if (!file) {
|
||||||
pr_perror("Can't open %d stat\n", pid);
|
pr_perror("Can't open %d stat\n", pid);
|
||||||
goto err;
|
goto err;
|
||||||
@@ -526,7 +524,7 @@ static int get_task_stat(pid_t pid, u8 *comm, u32 *flags,
|
|||||||
* Now signals.
|
* Now signals.
|
||||||
*/
|
*/
|
||||||
fclose(file);
|
fclose(file);
|
||||||
file = fopen_proc("%d/status", "r", pid);
|
file = fopen_proc(pid_dir, "status");
|
||||||
if (!file) {
|
if (!file) {
|
||||||
pr_perror("Can't open %d status\n", pid);
|
pr_perror("Can't open %d status\n", pid);
|
||||||
goto err;
|
goto err;
|
||||||
@@ -550,12 +548,12 @@ err_corrupted:
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_task_personality(pid_t pid, u32 *personality)
|
static int get_task_personality(pid_t pid, int pid_dir, u32 *personality)
|
||||||
{
|
{
|
||||||
FILE *file = NULL;
|
FILE *file = NULL;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
file = fopen_proc("%d/personality", "r", pid);
|
file = fopen_proc(pid_dir, "personality");
|
||||||
if (!file) {
|
if (!file) {
|
||||||
pr_perror("Can't open %d personality\n", pid);
|
pr_perror("Can't open %d personality\n", pid);
|
||||||
goto err;
|
goto err;
|
||||||
@@ -648,7 +646,7 @@ err:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dump_task_core_seized(pid_t pid, struct cr_fdset *cr_fdset)
|
static int dump_task_core_seized(pid_t pid, int pid_dir, struct cr_fdset *cr_fdset)
|
||||||
{
|
{
|
||||||
struct core_entry *core = xzalloc(sizeof(*core));
|
struct core_entry *core = xzalloc(sizeof(*core));
|
||||||
int fd_core = cr_fdset->fds[CR_FD_CORE];
|
int fd_core = cr_fdset->fds[CR_FD_CORE];
|
||||||
@@ -671,13 +669,13 @@ static int dump_task_core_seized(pid_t pid, struct cr_fdset *cr_fdset)
|
|||||||
pr_info("OK\n");
|
pr_info("OK\n");
|
||||||
|
|
||||||
pr_info("Obtainting personality ... ");
|
pr_info("Obtainting personality ... ");
|
||||||
ret = get_task_personality(pid, &core->task_personality);
|
ret = get_task_personality(pid, pid_dir, &core->task_personality);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_free;
|
goto err_free;
|
||||||
pr_info("OK\n");
|
pr_info("OK\n");
|
||||||
|
|
||||||
pr_info("Obtainting task stat ... ");
|
pr_info("Obtainting task stat ... ");
|
||||||
ret = get_task_stat(pid, core->task_comm,
|
ret = get_task_stat(pid, pid_dir, core->task_comm,
|
||||||
&core->task_flags,
|
&core->task_flags,
|
||||||
&core->mm_start_code,
|
&core->mm_start_code,
|
||||||
&core->mm_end_code,
|
&core->mm_end_code,
|
||||||
@@ -715,14 +713,14 @@ err:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_threads(pid_t pid, struct pstree_item *item)
|
static int parse_threads(pid_t pid, int pid_dir, struct pstree_item *item)
|
||||||
{
|
{
|
||||||
struct dirent *de;
|
struct dirent *de;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
u32 *t = NULL;
|
u32 *t = NULL;
|
||||||
int nr = 1;
|
int nr = 1;
|
||||||
|
|
||||||
dir = opendir_proc("%d/task", pid);
|
dir = opendir_proc(pid_dir, "task");
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
pr_perror("Can't open %d/task\n", pid);
|
pr_perror("Can't open %d/task\n", pid);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -753,7 +751,7 @@ static int parse_threads(pid_t pid, struct pstree_item *item)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_children(pid_t pid, struct pstree_item *item)
|
static int parse_children(pid_t pid, int pid_dir, struct pstree_item *item)
|
||||||
{
|
{
|
||||||
FILE *file;
|
FILE *file;
|
||||||
char *tok;
|
char *tok;
|
||||||
@@ -762,8 +760,7 @@ static int parse_children(pid_t pid, struct pstree_item *item)
|
|||||||
|
|
||||||
for (i = 0; i < item->nr_threads; i++) {
|
for (i = 0; i < item->nr_threads; i++) {
|
||||||
|
|
||||||
file = fopen_fmt("/proc/%d/task/%d/children", "r",
|
file = fopen_proc(pid_dir, "task/%d/children", item->threads[i]);
|
||||||
pid, item->threads[i]);
|
|
||||||
if (!file) {
|
if (!file) {
|
||||||
pr_perror("Can't open %d children %d\n",
|
pr_perror("Can't open %d children %d\n",
|
||||||
pid, item->threads[i]);
|
pid, item->threads[i]);
|
||||||
@@ -798,7 +795,7 @@ err:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pstree_item *find_pstree_entry(pid_t pid)
|
static struct pstree_item *find_pstree_entry(pid_t pid, int pid_dir)
|
||||||
{
|
{
|
||||||
struct pstree_item *item;
|
struct pstree_item *item;
|
||||||
|
|
||||||
@@ -806,10 +803,10 @@ static struct pstree_item *find_pstree_entry(pid_t pid)
|
|||||||
if (!item)
|
if (!item)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (parse_threads(pid, item))
|
if (parse_threads(pid, pid_dir, item))
|
||||||
goto err_free;
|
goto err_free;
|
||||||
|
|
||||||
if (parse_children(pid, item))
|
if (parse_children(pid, pid_dir, item))
|
||||||
goto err_free;
|
goto err_free;
|
||||||
|
|
||||||
item->pid = pid;
|
item->pid = pid;
|
||||||
@@ -827,9 +824,14 @@ static int collect_pstree(pid_t pid, struct list_head *pstree_list)
|
|||||||
{
|
{
|
||||||
struct pstree_item *item;
|
struct pstree_item *item;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
|
int pid_dir;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
item = find_pstree_entry(pid);
|
pid_dir = open_pid_proc(pid);
|
||||||
|
if (pid_dir < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
item = find_pstree_entry(pid, pid_dir);
|
||||||
if (!item)
|
if (!item)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
@@ -838,10 +840,12 @@ static int collect_pstree(pid_t pid, struct list_head *pstree_list)
|
|||||||
for (i = 0; i < item->nr_children; i++) {
|
for (i = 0; i < item->nr_children; i++) {
|
||||||
ret = collect_pstree(item->children[i], pstree_list);
|
ret = collect_pstree(item->children[i], pstree_list);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err_close;
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
|
err_close:
|
||||||
|
close(pid_dir);
|
||||||
err:
|
err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1076,13 +1080,20 @@ static int dump_one_task(pid_t pid, struct cr_fdset *cr_fdset)
|
|||||||
{
|
{
|
||||||
LIST_HEAD(vma_area_list);
|
LIST_HEAD(vma_area_list);
|
||||||
struct parasite_ctl *parasite_ctl;
|
struct parasite_ctl *parasite_ctl;
|
||||||
int ret = 0;
|
int ret = -1;
|
||||||
|
int pid_dir;
|
||||||
|
|
||||||
pr_info("========================================\n");
|
pr_info("========================================\n");
|
||||||
pr_info("Dumping task (pid: %d)\n", pid);
|
pr_info("Dumping task (pid: %d)\n", pid);
|
||||||
pr_info("========================================\n");
|
pr_info("========================================\n");
|
||||||
|
|
||||||
ret = collect_mappings(pid, &vma_area_list);
|
pid_dir = open_pid_proc(pid);
|
||||||
|
if (pid_dir < 0) {
|
||||||
|
pr_perror("Can't open %d proc dir\n", pid);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = collect_mappings(pid, pid_dir, &vma_area_list);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("Collect mappings (pid: %d) failed with %d\n", pid, ret);
|
pr_err("Collect mappings (pid: %d) failed with %d\n", pid, ret);
|
||||||
goto err;
|
goto err;
|
||||||
@@ -1095,7 +1106,7 @@ static int dump_one_task(pid_t pid, struct cr_fdset *cr_fdset)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = dump_task_core_seized(pid, cr_fdset);
|
ret = dump_task_core_seized(pid, pid_dir, cr_fdset);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("Dump core (pid: %d) failed with %d\n", pid, ret);
|
pr_err("Dump core (pid: %d) failed with %d\n", pid, ret);
|
||||||
goto err;
|
goto err;
|
||||||
@@ -1131,7 +1142,7 @@ static int dump_one_task(pid_t pid, struct cr_fdset *cr_fdset)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = dump_task_files(pid, cr_fdset);
|
ret = dump_task_files(pid, pid_dir, cr_fdset);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("Dump files (pid: %d) failed with %d\n", pid, ret);
|
pr_err("Dump files (pid: %d) failed with %d\n", pid, ret);
|
||||||
goto err;
|
goto err;
|
||||||
@@ -1185,7 +1196,7 @@ int cr_dump_tasks(pid_t pid, struct cr_options *opts)
|
|||||||
struct cr_fdset *cr_fdset = NULL;
|
struct cr_fdset *cr_fdset = NULL;
|
||||||
struct cr_fdset *cr_fdset_thread = NULL;
|
struct cr_fdset *cr_fdset_thread = NULL;
|
||||||
struct pstree_item *item;
|
struct pstree_item *item;
|
||||||
int i, ret = -1;
|
int i, ret = -1, pid_dir;
|
||||||
|
|
||||||
pr_info("========================================\n");
|
pr_info("========================================\n");
|
||||||
if (!opts->leader_only)
|
if (!opts->leader_only)
|
||||||
|
@@ -1307,6 +1307,7 @@ static void sigreturn_restore(pid_t pstree_pid, pid_t pid)
|
|||||||
struct pstree_entry pstree_entry;
|
struct pstree_entry pstree_entry;
|
||||||
int *fd_core_threads;
|
int *fd_core_threads;
|
||||||
int fd_pstree = -1;
|
int fd_pstree = -1;
|
||||||
|
int pid_dir;
|
||||||
|
|
||||||
pr_info("%d: Restore via sigreturn\n", pid);
|
pr_info("%d: Restore via sigreturn\n", pid);
|
||||||
|
|
||||||
@@ -1316,7 +1317,13 @@ static void sigreturn_restore(pid_t pstree_pid, pid_t pid)
|
|||||||
restore_thread_vma_len = 0;
|
restore_thread_vma_len = 0;
|
||||||
restore_shmem_vma_len = SHMEMS_SIZE;
|
restore_shmem_vma_len = SHMEMS_SIZE;
|
||||||
|
|
||||||
if (parse_maps(getpid(), &self_vma_list, false))
|
pid_dir = open_pid_proc(pid);
|
||||||
|
if (pid_dir < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
ret = parse_maps(getpid(), pid_dir, &self_vma_list, false);
|
||||||
|
close(pid_dir);
|
||||||
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* pr_info_vma_list(&self_vma_list); */
|
/* pr_info_vma_list(&self_vma_list); */
|
||||||
|
@@ -1,10 +1,12 @@
|
|||||||
#ifndef CR_SOCKETS_H__
|
#ifndef CR_SOCKETS_H__
|
||||||
#define CR_SOCKETS_H__
|
#define CR_SOCKETS_H__
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
struct cr_fdset;
|
struct cr_fdset;
|
||||||
extern int try_dump_socket(char *dir_name, char *fd_name, struct cr_fdset *cr_fdset);
|
extern int try_dump_socket(pid_t pid, char *fd_name, struct cr_fdset *cr_fdset);
|
||||||
|
|
||||||
extern int collect_sockets(void);
|
extern int collect_sockets(void);
|
||||||
extern int prepare_sockets(int pid);
|
extern int prepare_sockets(int pid);
|
||||||
|
@@ -165,7 +165,7 @@ extern void printk_vma(struct vma_area *vma_area);
|
|||||||
#define pr_info_siginfo(siginfo) printk_siginfo(siginfo)
|
#define pr_info_siginfo(siginfo) printk_siginfo(siginfo)
|
||||||
|
|
||||||
extern int move_img_fd(int *img_fd, int want_fd);
|
extern int move_img_fd(int *img_fd, int want_fd);
|
||||||
extern int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files);
|
extern int parse_maps(pid_t pid, int pid_dir, struct list_head *vma_area_list, bool use_map_files);
|
||||||
extern int close_safe(int *fd);
|
extern int close_safe(int *fd);
|
||||||
|
|
||||||
extern int reopen_fd_as_safe(int new_fd, int old_fd, bool allow_reuse_fd);
|
extern int reopen_fd_as_safe(int new_fd, int old_fd, bool allow_reuse_fd);
|
||||||
@@ -174,10 +174,10 @@ extern int reopen_fd_as_safe(int new_fd, int old_fd, bool allow_reuse_fd);
|
|||||||
|
|
||||||
extern void hex_dump(void *addr, unsigned long len);
|
extern void hex_dump(void *addr, unsigned long len);
|
||||||
|
|
||||||
extern DIR *opendir_proc(char *fmt, ...);
|
int open_pid_proc(pid_t pid);
|
||||||
extern FILE *fopen_proc(char *fmt, char *mode, ...);
|
int open_proc(int pid_dir_fd, char *fmt, ...);
|
||||||
extern FILE *fopen_fmt(char *fmt, char *mode, ...);
|
DIR *opendir_proc(int pid_dir_fd, char *fmt, ...);
|
||||||
extern int open_fmt(char *fmt, int mode, ...);
|
FILE *fopen_proc(int pid_dir_fd, char *fmt, ...);
|
||||||
|
|
||||||
#define __xalloc(op, size, ...) \
|
#define __xalloc(op, size, ...) \
|
||||||
({ \
|
({ \
|
||||||
|
13
sockets.c
13
sockets.c
@@ -175,13 +175,18 @@ err:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int try_dump_socket(char *dir, char *fd, struct cr_fdset *cr_fdset)
|
int try_dump_socket(pid_t pid, char *fd, struct cr_fdset *cr_fdset)
|
||||||
{
|
{
|
||||||
struct socket_desc *sk;
|
struct socket_desc *sk;
|
||||||
struct statfs fst;
|
struct statfs fst;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
char path[64];
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", dir, fd);
|
/*
|
||||||
|
* Sockets are tricky, we can't open it but can
|
||||||
|
* do stats over and check for sokets magic.
|
||||||
|
*/
|
||||||
|
snprintf(buf, sizeof(buf), "/proc/%d/fd/%s", pid, fd);
|
||||||
if (statfs(buf, &fst)) {
|
if (statfs(buf, &fst)) {
|
||||||
pr_err("Can't statfs %s\n", buf);
|
pr_err("Can't statfs %s\n", buf);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -206,8 +211,10 @@ int try_dump_socket(char *dir, char *fd, struct cr_fdset *cr_fdset)
|
|||||||
return dump_one_unix(sk, fd, cr_fdset);
|
return dump_one_unix(sk, fd, cr_fdset);
|
||||||
default:
|
default:
|
||||||
pr_err("BUG! Unknown socket collected\n");
|
pr_err("BUG! Unknown socket collected\n");
|
||||||
return -1;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int unix_collect_one(struct unix_diag_msg *m, struct rtattr **tb)
|
static int unix_collect_one(struct unix_diag_msg *m, struct rtattr **tb)
|
||||||
|
116
util.c
116
util.c
@@ -180,12 +180,11 @@ int move_img_fd(int *img_fd, int want_fd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
|
int parse_maps(pid_t pid, int pid_dir, struct list_head *vma_area_list, bool use_map_files)
|
||||||
{
|
{
|
||||||
struct vma_area *vma_area = NULL;
|
struct vma_area *vma_area = NULL;
|
||||||
u64 start, end, pgoff;
|
u64 start, end, pgoff;
|
||||||
char big_buffer[1024];
|
char big_buffer[1024];
|
||||||
char path[64];
|
|
||||||
unsigned long ino;
|
unsigned long ino;
|
||||||
char r,w,x,s;
|
char r,w,x,s;
|
||||||
int dev_maj, dev_min;
|
int dev_maj, dev_min;
|
||||||
@@ -194,18 +193,16 @@ int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
|
|||||||
DIR *map_files_dir = NULL;
|
DIR *map_files_dir = NULL;
|
||||||
FILE *maps = NULL;
|
FILE *maps = NULL;
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "/proc/%d/maps", pid);
|
maps = fopen_proc(pid_dir, "maps");
|
||||||
maps = fopen(path, "r");
|
|
||||||
if (!maps) {
|
if (!maps) {
|
||||||
pr_perror("Can't open: %s\n", path);
|
pr_perror("Can't open %d's maps\n", pid);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_map_files) {
|
if (use_map_files) {
|
||||||
snprintf(path, sizeof(path), "/proc/%d/map_files", pid);
|
map_files_dir = opendir_proc(pid_dir, "map_files");
|
||||||
map_files_dir = opendir(path);
|
|
||||||
if (!map_files_dir) {
|
if (!map_files_dir) {
|
||||||
pr_err("Can't open %s, old kernel?\n", path);
|
pr_err("Can't open %d's, old kernel?\n", pid);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -227,6 +224,8 @@ int parse_maps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (map_files_dir) {
|
if (map_files_dir) {
|
||||||
|
char path[32];
|
||||||
|
|
||||||
/* Figure out if it's file mapping */
|
/* Figure out if it's file mapping */
|
||||||
snprintf(path, sizeof(path), "%lx-%lx", start, end);
|
snprintf(path, sizeof(path), "%lx-%lx", start, end);
|
||||||
|
|
||||||
@@ -341,56 +340,6 @@ err_bogus_mapping:
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIR *opendir_proc(char *fmt, ...)
|
|
||||||
{
|
|
||||||
DIR *dir;
|
|
||||||
char path[128];
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
sprintf(path, "/proc/");
|
|
||||||
va_start(args, fmt);
|
|
||||||
vsnprintf(path + 6, sizeof(path) - 6, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
dir = opendir(path);
|
|
||||||
if (!dir)
|
|
||||||
pr_perror("Can't open %s\n", path);
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *fopen_proc(char *fmt, char *mode, ...)
|
|
||||||
{
|
|
||||||
FILE *file;
|
|
||||||
char fname[128];
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
sprintf(fname, "/proc/");
|
|
||||||
va_start(args, mode);
|
|
||||||
vsnprintf(fname + 6, sizeof(fname) - 6, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
file = fopen(fname, mode);
|
|
||||||
if (!file)
|
|
||||||
pr_perror("Can't open %s\n", fname);
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *fopen_fmt(char *fmt, char *mode, ...)
|
|
||||||
{
|
|
||||||
FILE *file;
|
|
||||||
char fname[128];
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
va_start(args, mode);
|
|
||||||
vsnprintf(fname, sizeof(fname), fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
file = fopen(fname, mode);
|
|
||||||
if (!file)
|
|
||||||
pr_perror("Can't open %s\n", fname);
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
int open_image_ro_nocheck(const char *fmt, int pid)
|
int open_image_ro_nocheck(const char *fmt, int pid)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
@@ -424,3 +373,54 @@ int open_image_ro(int type, int pid)
|
|||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int open_pid_proc(pid_t pid)
|
||||||
|
{
|
||||||
|
char path[18];
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
sprintf(path, "/proc/%d", pid);
|
||||||
|
fd = open(path, O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
pr_perror("Can't open %s\n", path);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define do_open_proc(pid_dir_fd, fmt) \
|
||||||
|
({ \
|
||||||
|
char fname[64]; \
|
||||||
|
va_list args; \
|
||||||
|
\
|
||||||
|
va_start(args, fmt); \
|
||||||
|
vsnprintf(fname, sizeof(fname), fmt, args); \
|
||||||
|
va_end(args); \
|
||||||
|
\
|
||||||
|
openat(pid_dir_fd, fname, O_RDONLY); \
|
||||||
|
})
|
||||||
|
|
||||||
|
int open_proc(int pid_dir_fd, char *fmt, ...)
|
||||||
|
{
|
||||||
|
return do_open_proc(pid_dir_fd, fmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
DIR *opendir_proc(int pid_dir_fd, char *fmt, ...)
|
||||||
|
{
|
||||||
|
int dirfd;
|
||||||
|
|
||||||
|
dirfd = do_open_proc(pid_dir_fd, fmt);
|
||||||
|
if (dirfd >= 0)
|
||||||
|
return fdopendir(dirfd);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *fopen_proc(int pid_dir_fd, char *fmt, ...)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = do_open_proc(pid_dir_fd, fmt);
|
||||||
|
if (fd >= 0)
|
||||||
|
return fdopen(fd, "r");
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user