Skip to content

Commit 99ec620

Browse files
bsach64avagin
authored andcommitted
criu: Support C/R of pidfds
Process file descriptors (pidfds) were introduced to provide a stable handle on a process. They solve the problem of pid recycling. For a detailed explanation, see https://lwn.net/Articles/801319/ and http://www.corsix.org/content/what-is-a-pidfd Before Linux 6.9, anonymous inodes were used for the implementation of pidfds. So, we detect them in a fashion similiar to other fd types that use anonymous inodes by calling `readlink()`. After 6.9, pidfs (a file system for pidfds) was introduced. In 6.9 `S_ISREG()` returned true for pidfds, but this again changed with 6.10. (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/pidfs.c?h=v6.11-rc2#n285) After this change, pidfs inodes have no file type in st_mode in userspace. We use `PID_FS_MAGIC` to detect pidfds for kernel >= 6.9 Hence, check for pidfds occurs before the check for regular files. For pidfds that refer to dead processes, we lose the pid of the process as the Pid and NSpid fields in /proc/<pid>/fdinfo/<pidfd> change to -1. So, we create a temporary process for each unique inode and open pidfds that refer to this process. After all pidfds have been opened we kill this temporary process. This commit does not include support for pidfds that point to a specific thread, i.e pidfds opened with `PIDFD_THREAD` flag. Fixes: #2258 Signed-off-by: Bhavik Sachdev <[email protected]>
1 parent a1db762 commit 99ec620

File tree

12 files changed

+361
-1
lines changed

12 files changed

+361
-1
lines changed

criu/Makefile.crtools

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ obj-$(CONFIG_COMPAT) += vdso-compat.o
101101
CFLAGS_REMOVE_vdso-compat.o += $(CFLAGS-ASAN) $(CFLAGS-GCOV)
102102
obj-y += pidfd-store.o
103103
obj-y += hugetlb.o
104+
obj-y += pidfd.o
104105

105106
PROTOBUF_GEN := scripts/protobuf-gen.sh
106107

criu/cr-restore.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
#include "timens.h"
8080
#include "bpfmap.h"
8181
#include "apparmor.h"
82+
#include "pidfd.h"
8283

8384
#include "parasite-syscall.h"
8485
#include "files-reg.h"
@@ -280,7 +281,7 @@ static struct collect_image_info *cinfos_files[] = {
280281
&unix_sk_cinfo, &fifo_cinfo, &pipe_cinfo, &nsfile_cinfo, &packet_sk_cinfo,
281282
&netlink_sk_cinfo, &eventfd_cinfo, &epoll_cinfo, &epoll_tfd_cinfo, &signalfd_cinfo,
282283
&tunfile_cinfo, &timerfd_cinfo, &inotify_cinfo, &inotify_mark_cinfo, &fanotify_cinfo,
283-
&fanotify_mark_cinfo, &ext_file_cinfo, &memfd_cinfo,
284+
&fanotify_mark_cinfo, &ext_file_cinfo, &memfd_cinfo, &pidfd_cinfo
284285
};
285286

286287
/* These images are required to restore namespaces */

criu/files.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include "kerndat.h"
5050
#include "fdstore.h"
5151
#include "bpfmap.h"
52+
#include "pidfd.h"
5253

5354
#include "protobuf.h"
5455
#include "util.h"
@@ -544,6 +545,8 @@ static int dump_one_file(struct pid *pid, int fd, int lfd, struct fd_opts *opts,
544545
ops = &signalfd_dump_ops;
545546
else if (is_timerfd_link(link))
546547
ops = &timerfd_dump_ops;
548+
else if (is_pidfd_link(link))
549+
ops = &pidfd_dump_ops;
547550
#ifdef CONFIG_HAS_LIBBPF
548551
else if (is_bpfmap_link(link))
549552
ops = &bpfmap_dump_ops;
@@ -554,6 +557,11 @@ static int dump_one_file(struct pid *pid, int fd, int lfd, struct fd_opts *opts,
554557
return do_dump_gen_file(&p, lfd, ops, e);
555558
}
556559

560+
if (p.fs_type == PID_FS_MAGIC) {
561+
ops = &pidfd_dump_ops;
562+
return do_dump_gen_file(&p, lfd, ops, e);
563+
}
564+
557565
if (S_ISREG(p.stat.st_mode) || S_ISDIR(p.stat.st_mode) || S_ISLNK(p.stat.st_mode)) {
558566
if (fill_fdlink(lfd, &p, &link))
559567
return -1;
@@ -1778,6 +1786,9 @@ static int collect_one_file(void *o, ProtobufCMessage *base, struct cr_img *i)
17781786
case FD_TYPES__MEMFD:
17791787
ret = collect_one_file_entry(fe, fe->memfd->id, &fe->memfd->base, &memfd_cinfo);
17801788
break;
1789+
case FD_TYPES__PIDFD:
1790+
ret = collect_one_file_entry(fe, fe->pidfd->id, &fe->pidfd->base, &pidfd_cinfo);
1791+
break;
17811792
#ifdef CONFIG_HAS_LIBBPF
17821793
case FD_TYPES__BPFMAP:
17831794
ret = collect_one_file_entry(fe, fe->bpf->id, &fe->bpf->base, &bpfmap_cinfo);
@@ -1800,5 +1811,11 @@ int prepare_files(void)
18001811
{
18011812
init_fdesc_hash();
18021813
init_sk_info_hash();
1814+
1815+
if (init_dead_pidfd_hash()) {
1816+
pr_err("Could not initialise hash map for dead pidfds\n");
1817+
return -1;
1818+
}
1819+
18031820
return collect_image(&files_cinfo);
18041821
}

criu/image-desc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ struct cr_fd_desc_tmpl imgset_template[CR_FD_MAX] = {
107107
FD_ENTRY_F(BPFMAP_FILE, "bpfmap-file", O_NOBUF),
108108
FD_ENTRY_F(BPFMAP_DATA, "bpfmap-data", O_NOBUF),
109109
FD_ENTRY(APPARMOR, "apparmor"),
110+
FD_ENTRY(PIDFD, "pidfd"),
110111

111112
[CR_FD_STATS] = {
112113
.fmt = "stats-%s",

criu/include/fs-magic.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,8 @@
5757
#define OVERLAYFS_SUPER_MAGIC 0x794c7630
5858
#endif
5959

60+
#ifndef PID_FS_MAGIC
61+
#define PID_FS_MAGIC 0x50494446
62+
#endif
63+
6064
#endif /* __CR_FS_MAGIC_H__ */

criu/include/image-desc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ enum {
113113
CR_FD_PIPES,
114114
CR_FD_TTY_FILES,
115115
CR_FD_MEMFD_FILE,
116+
CR_FD_PIDFD,
116117

117118
CR_FD_AUTOFS,
118119

criu/include/magic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
#define BPFMAP_FILE_MAGIC 0x57506142 /* Alapayevsk */
101101
#define BPFMAP_DATA_MAGIC 0x64324033 /* Arkhangelsk */
102102
#define APPARMOR_MAGIC 0x59423047 /* Nikolskoye */
103+
#define PIDFD_MAGIC 0x54435556 /* Ufa */
103104

104105
#define IFADDR_MAGIC RAW_IMAGE_MAGIC
105106
#define ROUTE_MAGIC RAW_IMAGE_MAGIC

criu/include/pidfd.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef __CR_PIDFD_H__
2+
#define __CR_PIDFD_H__
3+
4+
#include "files.h"
5+
#include "pidfd.pb-c.h"
6+
7+
extern const struct fdtype_ops pidfd_dump_ops;
8+
extern struct collect_image_info pidfd_cinfo;
9+
extern int is_pidfd_link(char *link);
10+
extern int init_dead_pidfd_hash(void);
11+
struct pidfd_dump_info {
12+
PidfdEntry pidfe;
13+
pid_t pid;
14+
};
15+
16+
#endif /* __CR_PIDFD_H__ */

criu/include/protobuf-desc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ enum {
7070
PB_BPFMAP_FILE,
7171
PB_BPFMAP_DATA,
7272
PB_APPARMOR,
73+
PB_PIDFD,
7374

7475
/* PB_AUTOGEN_STOP */
7576

0 commit comments

Comments
 (0)