diff --git a/criu/cr-check.c b/criu/cr-check.c index f57e8eb4e..8b21a7b0d 100644 --- a/criu/cr-check.c +++ b/criu/cr-check.c @@ -1084,6 +1084,17 @@ static int check_ns_pid(void) return 0; } +static int check_ns_get_userns(void) +{ + if (kerndat_has_ns_get_userns() < 0) + return -1; + + if (!kdat.has_ns_get_userns) + return -1; + + return 0; +} + static int (*chk_feature)(void); /* @@ -1192,6 +1203,7 @@ int cr_check(void) ret |= check_uffd_noncoop(); ret |= check_sk_netns(); ret |= check_ns_pid(); + ret |= check_ns_get_userns(); } /* @@ -1274,6 +1286,7 @@ static struct feature_list feature_list[] = { { "nsid", check_nsid }, { "link_nsid", check_link_nsid}, { "ns_pid", check_ns_pid}, + { "ns_get_userns", check_ns_get_userns }, { NULL, NULL }, }; diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h index c00c6d220..541b5efff 100644 --- a/criu/include/kerndat.h +++ b/criu/include/kerndat.h @@ -67,6 +67,7 @@ struct kerndat_s { bool has_nsid; bool has_link_nsid; bool has_nspid; + bool has_ns_get_userns; }; extern struct kerndat_s kdat; @@ -90,5 +91,6 @@ extern int kerndat_fs_virtualized(unsigned int which, u32 kdev); extern int kerndat_tcp_repair(); extern int kerndat_uffd(void); extern int kerndat_has_nspid(void); +extern int kerndat_has_ns_get_userns(void); #endif /* __CR_KERNDAT_H__ */ diff --git a/criu/kerndat.c b/criu/kerndat.c index 700a5a5e4..55c60111f 100644 --- a/criu/kerndat.c +++ b/criu/kerndat.c @@ -669,6 +669,26 @@ err: return ret; } +int kerndat_has_ns_get_userns(void) +{ + int pid_fd, user_fd; + + pid_fd = open("/proc/self/ns/pid", O_RDONLY); + if (pid_fd < 0) { + perror("Can't open pid ns"); + return -1; + } + + user_fd = ioctl(pid_fd, NS_GET_USERNS); + if (user_fd >= 0) { + kdat.has_ns_get_userns = true; + close(user_fd); + } + + close(pid_fd); + return 0; +} + #define KERNDAT_CACHE_FILE KDAT_RUNDIR"/criu.kdat" #define KERNDAT_CACHE_FILE_TMP KDAT_RUNDIR"/.criu.kdat" @@ -926,12 +946,10 @@ int kerndat_init(void) /* Depends on kerndat_vdso_fill_symtable() */ if (!ret) ret = kerndat_vdso_preserves_hint(); - if (!ret) - ret = kerndat_socket_netns(); - if (!ret) - ret = kerndat_nsid(); if (!ret) ret = kerndat_has_nspid(); + if (!ret) + ret = kerndat_has_ns_get_userns(); kerndat_lsm(); kerndat_mmap_min_addr();