Adapt patches to patches merged upstream

Fix running on aarch64

Resolves: RHEL-58354

Signed-off-by: Adrian Reber <areber@redhat.com>
This commit is contained in:
Adrian Reber 2025-02-04 09:41:06 +01:00
parent d866d1994f
commit 4d542e727d
No known key found for this signature in database
GPG Key ID: 82C9378ED3C4906A
6 changed files with 1070 additions and 211 deletions

128
2549.patch Normal file
View File

@ -0,0 +1,128 @@
From 0a17c4160580d9bc7092ba9eb7db86952921d221 Mon Sep 17 00:00:00 2001
From: Adrian Reber <areber@redhat.com>
Date: Thu, 16 Jan 2025 07:52:42 +0000
Subject: [PATCH 1/2] util: added cleanup_file attribute.
Signed-off-by: Adrian Reber <areber@redhat.com>
---
criu/include/util.h | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/criu/include/util.h b/criu/include/util.h
index ae293a68c8..4793f7f20e 100644
--- a/criu/include/util.h
+++ b/criu/include/util.h
@@ -406,6 +406,14 @@ static inline void cleanup_freep(void *p)
free(*pp);
}
+#define cleanup_file __attribute__((cleanup(cleanup_filep)))
+static inline void cleanup_filep(FILE **f)
+{
+ FILE *file = *f;
+ if (file)
+ (void)fclose(file);
+}
+
extern int run_command(char *buf, size_t buf_size, int (*child_fn)(void *), void *args);
/*
From 1ed4109958644fbe1cbadf7c72472c82a12834b0 Mon Sep 17 00:00:00 2001
From: Adrian Reber <areber@redhat.com>
Date: Tue, 17 Dec 2024 08:52:46 +0100
Subject: [PATCH 2/2] net: redirect nftables stdout and stderr to CRIU's log
file
When using the nftables network locking backend and restoring a process
a second time the network locking has already been deleted by the first
restore. The second restore will print out to the console text like:
Error: Could not process rule: No such file or directory
delete table inet CRIU-202621
With this change CRIU's log FD is used by libnftables stdout and stderr.
Signed-off-by: Adrian Reber <areber@redhat.com>
---
criu/net.c | 43 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/criu/net.c b/criu/net.c
index eee3311087..efd52db327 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -3066,9 +3066,43 @@ static int iptables_restore(bool ipv6, char *buf, int size)
return ret;
}
+#if defined(CONFIG_HAS_NFTABLES_LIB_API_0) || defined(CONFIG_HAS_NFTABLES_LIB_API_1)
+static inline FILE *redirect_nftables_output(struct nft_ctx *nft)
+{
+ FILE *fp;
+ int fd;
+
+ fd = dup(log_get_fd());
+ if (fd < 0) {
+ pr_perror("dup() to redirect nftables output failed");
+ return NULL;
+ }
+
+ fp = fdopen(fd, "w");
+ if (!fp) {
+ pr_perror("fdopen() to redirect nftables output failed");
+ return NULL;
+ }
+
+ /**
+ * Without setvbuf() the output from libnftables will be
+ * somewhere in the log file, probably at the end.
+ * With setvbuf() potential output will be at the correct
+ * position.
+ */
+ setvbuf(fp, NULL, _IONBF, 0);
+
+ nft_ctx_set_output(nft, fp);
+ nft_ctx_set_error(nft, fp);
+
+ return fp;
+}
+#endif
+
static inline int nftables_lock_network_internal(void)
{
#if defined(CONFIG_HAS_NFTABLES_LIB_API_0) || defined(CONFIG_HAS_NFTABLES_LIB_API_1)
+ cleanup_file FILE *fp = NULL;
struct nft_ctx *nft;
int ret = 0;
char table[32];
@@ -3081,6 +3115,10 @@ static inline int nftables_lock_network_internal(void)
if (!nft)
return -1;
+ fp = redirect_nftables_output(nft);
+ if (!fp)
+ goto out;
+
snprintf(buf, sizeof(buf), "create table %s", table);
if (NFT_RUN_CMD(nft, buf))
goto err2;
@@ -3168,6 +3206,7 @@ static inline int nftables_network_unlock(void)
{
#if defined(CONFIG_HAS_NFTABLES_LIB_API_0) || defined(CONFIG_HAS_NFTABLES_LIB_API_1)
int ret = 0;
+ cleanup_file FILE *fp = NULL;
struct nft_ctx *nft;
char table[32];
char buf[128];
@@ -3179,6 +3218,10 @@ static inline int nftables_network_unlock(void)
if (!nft)
return -1;
+ fp = redirect_nftables_output(nft);
+ if (!fp)
+ return -1;
+
snprintf(buf, sizeof(buf), "delete table %s", table);
if (NFT_RUN_CMD(nft, buf))
ret = -1;

473
2550.patch Normal file
View File

@ -0,0 +1,473 @@
From 9a2b7d6b3baa2b3183489ed9cebece039f9f488f Mon Sep 17 00:00:00 2001
From: Adrian Reber <areber@redhat.com>
Date: Thu, 23 Jan 2025 09:26:15 +0000
Subject: [PATCH 1/2] criu: use libuuid for criu_run_id generation
criu_run_id will be used in upcoming changes to create and remove
network rules for network locking. Instead of trying to come up with
a way to create unique IDs, just use an existing library.
libuuid should be installed on most systems as it is indirectly required
by systemd (via libmount).
Signed-off-by: Adrian Reber <areber@redhat.com>
---
.cirrus.yml | 2 +-
.github/workflows/check-commits.yml | 2 +-
compel/include/uapi/infect-util.h | 11 ++++++++++-
compel/src/lib/infect-util.c | 2 +-
compel/src/lib/infect.c | 2 +-
criu/Makefile.packages | 4 +++-
criu/fdstore.c | 2 +-
criu/files.c | 2 +-
criu/include/util.h | 4 +++-
criu/pidfd-store.c | 2 +-
criu/unittest/mock.c | 4 +++-
criu/util.c | 17 +++++++----------
scripts/build/Dockerfile.alpine | 3 ++-
scripts/build/Dockerfile.amd-rocm | 1 +
scripts/build/Dockerfile.archlinux | 1 +
scripts/build/Dockerfile.hotspot-alpine | 1 +
scripts/build/Dockerfile.hotspot-ubuntu | 1 +
scripts/build/Dockerfile.linux32.tmpl | 1 +
scripts/build/Dockerfile.openj9-ubuntu | 1 +
.../build/Dockerfile.riscv64-stable-cross.tmpl | 1 +
scripts/build/Dockerfile.stable-cross.tmpl | 1 +
scripts/build/Dockerfile.tmpl | 1 +
scripts/build/Dockerfile.unstable-cross.tmpl | 1 +
scripts/ci/prepare-for-fedora-rawhide.sh | 1 +
scripts/ci/run-ci-tests.sh | 2 +-
scripts/ci/vagrant.sh | 2 +-
26 files changed, 48 insertions(+), 24 deletions(-)
diff --git a/compel/include/uapi/infect-util.h b/compel/include/uapi/infect-util.h
index ace6f6b6b1..658df9393d 100644
--- a/compel/include/uapi/infect-util.h
+++ b/compel/include/uapi/infect-util.h
@@ -3,11 +3,20 @@
#include "common/compiler.h"
+/**
+ * The length of the hash is based on what libuuid provides.
+ * According to the manpage this is:
+ *
+ * The uuid_unparse() function converts the supplied UUID uu from the binary
+ * representation into a 36-byte string (plus trailing '\0')
+ */
+#define RUN_ID_HASH_LENGTH 37
+
/*
* compel_run_id is a unique value of the current run. It can be used to
* generate resource ID-s to avoid conflicts with other processes.
*/
-extern uint64_t compel_run_id;
+extern char compel_run_id[RUN_ID_HASH_LENGTH];
struct parasite_ctl;
extern int __must_check compel_util_send_fd(struct parasite_ctl *ctl, int fd);
diff --git a/compel/src/lib/infect-util.c b/compel/src/lib/infect-util.c
index 00a7c83f7d..dc57e28f7c 100644
--- a/compel/src/lib/infect-util.c
+++ b/compel/src/lib/infect-util.c
@@ -7,7 +7,7 @@
#include "infect-rpc.h"
#include "infect-util.h"
-uint64_t compel_run_id;
+char compel_run_id[RUN_ID_HASH_LENGTH];
int compel_util_send_fd(struct parasite_ctl *ctl, int fd)
{
diff --git a/compel/src/lib/infect.c b/compel/src/lib/infect.c
index 1e3ffb9670..caf54e03fd 100644
--- a/compel/src/lib/infect.c
+++ b/compel/src/lib/infect.c
@@ -427,7 +427,7 @@ static int gen_parasite_saddr(struct sockaddr_un *saddr, int key)
int sun_len;
saddr->sun_family = AF_UNIX;
- snprintf(saddr->sun_path, UNIX_PATH_MAX, "X/crtools-pr-%d-%" PRIx64, key, compel_run_id);
+ snprintf(saddr->sun_path, UNIX_PATH_MAX, "X/crtools-pr-%d-%s", key, compel_run_id);
sun_len = SUN_LEN(saddr);
*saddr->sun_path = '\0';
diff --git a/criu/Makefile.packages b/criu/Makefile.packages
index 7f6113c8f1..3e2e6efd18 100644
--- a/criu/Makefile.packages
+++ b/criu/Makefile.packages
@@ -6,6 +6,7 @@ REQ-RPM-PKG-NAMES += protobuf-devel
REQ-RPM-PKG-NAMES += protobuf-python
REQ-RPM-PKG-NAMES += libnl3-devel
REQ-RPM-PKG-NAMES += libcap-devel
+REQ-RPM-PKG-NAMES += libuuid-devel
REQ-RPM-PKG-TEST-NAMES += libaio-devel
@@ -16,6 +17,7 @@ REQ-DEB-PKG-NAMES += protobuf-compiler
REQ-DEB-PKG-NAMES += $(PYTHON)-protobuf
REQ-DEB-PKG-NAMES += libnl-3-dev
REQ-DEB-PKG-NAMES += libcap-dev
+REQ-DEB-PKG-NAMES += uuid-dev
REQ-DEB-PKG-TEST-NAMES += $(PYTHON)-yaml
REQ-DEB-PKG-TEST-NAMES += libaio-dev
@@ -25,7 +27,7 @@ REQ-DEB-PKG-TEST-NAMES += libaio-dev
REQ-RPM-PKG-TEST-NAMES += $(PYTHON)-PyYAML
-export LIBS += -lprotobuf-c -ldl -lnl-3 -lsoccr -Lsoccr/ -lnet
+export LIBS += -lprotobuf-c -ldl -lnl-3 -lsoccr -Lsoccr/ -lnet -luuid
check-packages-failed:
$(warning Can not find some of the required libraries)
diff --git a/criu/fdstore.c b/criu/fdstore.c
index d615ad15d0..6ac639c553 100644
--- a/criu/fdstore.c
+++ b/criu/fdstore.c
@@ -58,7 +58,7 @@ int fdstore_init(void)
}
addr.sun_family = AF_UNIX;
- addrlen = snprintf(addr.sun_path, sizeof(addr.sun_path), "X/criu-fdstore-%" PRIx64 "-%" PRIx64, st.st_ino,
+ addrlen = snprintf(addr.sun_path, sizeof(addr.sun_path), "X/criu-fdstore-%" PRIx64 "-%s", st.st_ino,
criu_run_id);
addrlen += sizeof(addr.sun_family);
diff --git a/criu/files.c b/criu/files.c
index 31e705bcc5..f16ec32a23 100644
--- a/criu/files.c
+++ b/criu/files.c
@@ -978,7 +978,7 @@ static int receive_fd(struct fdinfo_list_entry *fle);
static void transport_name_gen(struct sockaddr_un *addr, int *len, int pid)
{
addr->sun_family = AF_UNIX;
- snprintf(addr->sun_path, UNIX_PATH_MAX, "x/crtools-fd-%d-%" PRIx64, pid, criu_run_id);
+ snprintf(addr->sun_path, UNIX_PATH_MAX, "x/crtools-fd-%d-%s", pid, criu_run_id);
*len = SUN_LEN(addr);
*addr->sun_path = '\0';
}
diff --git a/criu/include/util.h b/criu/include/util.h
index 4793f7f20e..194e94deeb 100644
--- a/criu/include/util.h
+++ b/criu/include/util.h
@@ -21,6 +21,8 @@
#include "log.h"
#include "common/err.h"
+#include "compel/infect-util.h"
+
#define PREF_SHIFT_OP(pref, op, size) ((size)op(pref##BYTES_SHIFT))
#define KBYTES_SHIFT 10
#define MBYTES_SHIFT 20
@@ -420,7 +422,7 @@ extern int run_command(char *buf, size_t buf_size, int (*child_fn)(void *), void
* criu_run_id is a unique value of the current run. It can be used to
* generate resource ID-s to avoid conflicts with other CRIU processes.
*/
-extern uint64_t criu_run_id;
+extern char criu_run_id[RUN_ID_HASH_LENGTH];
extern void util_init(void);
extern char *resolve_mountpoint(char *path);
diff --git a/criu/pidfd-store.c b/criu/pidfd-store.c
index 9fdc74cb74..110f7802a2 100644
--- a/criu/pidfd-store.c
+++ b/criu/pidfd-store.c
@@ -99,7 +99,7 @@ int init_pidfd_store_sk(pid_t pid, int sk)
goto err;
}
- addrlen = snprintf(addr.sun_path, sizeof(addr.sun_path), "X/criu-pidfd-store-%d-%d-%" PRIx64, pid, sk,
+ addrlen = snprintf(addr.sun_path, sizeof(addr.sun_path), "X/criu-pidfd-store-%d-%d-%s", pid, sk,
criu_run_id);
addrlen += sizeof(addr.sun_family);
diff --git a/criu/unittest/mock.c b/criu/unittest/mock.c
index e517720e42..b2d5072787 100644
--- a/criu/unittest/mock.c
+++ b/criu/unittest/mock.c
@@ -5,6 +5,8 @@
#include <stdint.h>
#include <stdlib.h>
+#include "compel/infect-util.h"
+
int add_external(char *key)
{
return 0;
@@ -141,4 +143,4 @@ int check_mount_v2(void)
return 0;
}
-uint64_t compel_run_id;
+char compel_run_id[RUN_ID_HASH_LENGTH];
diff --git a/criu/util.c b/criu/util.c
index d2bc9a8657..58c18e20be 100644
--- a/criu/util.c
+++ b/criu/util.c
@@ -28,6 +28,7 @@
#include <ftw.h>
#include <time.h>
#include <libgen.h>
+#include <uuid/uuid.h>
#include "linux/mount.h"
@@ -2026,20 +2027,16 @@ int run_command(char *buf, size_t buf_size, int (*child_fn)(void *), void *args)
return fret;
}
-uint64_t criu_run_id;
+char criu_run_id[RUN_ID_HASH_LENGTH];
void util_init(void)
{
- struct stat statbuf;
+ uuid_t uuid;
- criu_run_id = getpid();
- if (!stat("/proc/self/ns/pid", &statbuf))
- criu_run_id |= (uint64_t)statbuf.st_ino << 32;
- else if (errno != ENOENT)
- pr_perror("Can't stat /proc/self/ns/pid - CRIU run id might not be unique");
-
- compel_run_id = criu_run_id;
- pr_info("CRIU run id = %#" PRIx64 "\n", criu_run_id);
+ uuid_generate(uuid);
+ uuid_unparse(uuid, criu_run_id);
+ pr_info("CRIU run id = %s\n", criu_run_id);
+ memcpy(compel_run_id, criu_run_id, sizeof(criu_run_id));
}
/*
diff --git a/scripts/build/Dockerfile.alpine b/scripts/build/Dockerfile.alpine
index 329d7791de..d843793ea2 100644
--- a/scripts/build/Dockerfile.alpine
+++ b/scripts/build/Dockerfile.alpine
@@ -24,7 +24,8 @@ RUN apk update && apk add \
sudo \
libcap-utils \
libdrm-dev \
- util-linux
+ util-linux \
+ util-linux-dev
COPY . /criu
WORKDIR /criu
diff --git a/scripts/build/Dockerfile.amd-rocm b/scripts/build/Dockerfile.amd-rocm
index c466a73d2d..ed66ae4fec 100644
--- a/scripts/build/Dockerfile.amd-rocm
+++ b/scripts/build/Dockerfile.amd-rocm
@@ -56,6 +56,7 @@ RUN apt-get clean -qqy && apt-get update -qqy && apt-get install -qqy --no-insta
python-protobuf \
python3-minimal \
python-ipaddress \
+ uuid-dev \
curl \
wget \
vim \
diff --git a/scripts/build/Dockerfile.archlinux b/scripts/build/Dockerfile.archlinux
index 4056514891..9d11194bb0 100644
--- a/scripts/build/Dockerfile.archlinux
+++ b/scripts/build/Dockerfile.archlinux
@@ -35,6 +35,7 @@ RUN pacman -Syu --noconfirm \
python-junit-xml \
python-importlib-metadata \
libdrm \
+ util-linux-libs \
diffutils
COPY . /criu
diff --git a/scripts/build/Dockerfile.hotspot-alpine b/scripts/build/Dockerfile.hotspot-alpine
index cb9332fd0c..6caf9d0b1b 100644
--- a/scripts/build/Dockerfile.hotspot-alpine
+++ b/scripts/build/Dockerfile.hotspot-alpine
@@ -19,6 +19,7 @@ RUN apk update && apk add \
maven \
ip6tables \
iptables \
+ util-linux-dev \
bash
COPY . /criu
diff --git a/scripts/build/Dockerfile.hotspot-ubuntu b/scripts/build/Dockerfile.hotspot-ubuntu
index 0318f650f3..67de916acb 100644
--- a/scripts/build/Dockerfile.hotspot-ubuntu
+++ b/scripts/build/Dockerfile.hotspot-ubuntu
@@ -22,6 +22,7 @@ RUN apt-install protobuf-c-compiler \
pkg-config \
iptables \
gcc \
+ uuid-dev \
maven
COPY . /criu
diff --git a/scripts/build/Dockerfile.linux32.tmpl b/scripts/build/Dockerfile.linux32.tmpl
index 13e9926424..d218e06414 100644
--- a/scripts/build/Dockerfile.linux32.tmpl
+++ b/scripts/build/Dockerfile.linux32.tmpl
@@ -21,6 +21,7 @@ RUN apt-install \
pkg-config \
protobuf-c-compiler \
protobuf-compiler \
+ uuid-dev \
python3-minimal
COPY . /criu
diff --git a/scripts/ci/prepare-for-fedora-rawhide.sh b/scripts/ci/prepare-for-fedora-rawhide.sh
index 09085c403b..42252c93c9 100755
--- a/scripts/ci/prepare-for-fedora-rawhide.sh
+++ b/scripts/ci/prepare-for-fedora-rawhide.sh
@@ -36,6 +36,7 @@ dnf install -y \
e2fsprogs \
rubygem-asciidoctor \
libdrm-devel \
+ libuuid-devel \
kmod
# /tmp is no longer 755 in the rawhide container image and breaks CI - fix it
From c39bce3cf17782784d1a14cf40a4cedd059059fa Mon Sep 17 00:00:00 2001
From: Adrian Reber <areber@redhat.com>
Date: Thu, 23 Jan 2025 17:42:45 +0000
Subject: [PATCH 2/2] net: remember the name of the lock chain (nftables)
Using libnftables the chain to lock the network is composed of
("CRIU-%d", real_pid). This leads to around 40 zdtm tests failing
with errors like this:
Error: No such file or directory; did you mean table 'CRIU-62' in family inet?
delete table inet CRIU-86
The reason is that as soon as a process is running in a namespace the
real PID can be anything and only the PID in the namespace is restored
correctly. Relying on the real PID does not work for the chain name.
Using the PID of the innermost namespace would lead to the chain be
called 'CRIU-1' most of the time which is also not really unique.
With this commit the change is now named using the already existing CRIU
run ID. To be able to correctly restore the process and delete the
locking table, the CRIU run id during checkpointing is now stored in the
inventory as dump_criu_run_id.
Signed-off-by: Adrian Reber <areber@redhat.com>
---
criu/image.c | 30 ++++++++++++++++++++++++++++++
criu/include/util.h | 2 ++
criu/netfilter.c | 20 +++++++++++++++++++-
images/inventory.proto | 4 ++++
4 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/criu/image.c b/criu/image.c
index 9589167fb1..f3747d6ff5 100644
--- a/criu/image.c
+++ b/criu/image.c
@@ -25,6 +25,7 @@ bool img_common_magic = true;
TaskKobjIdsEntry *root_ids;
u32 root_cg_set;
Lsmtype image_lsm;
+char dump_criu_run_id[RUN_ID_HASH_LENGTH];
int check_img_inventory(bool restore)
{
@@ -120,6 +121,24 @@ int check_img_inventory(bool restore)
} else {
opts.network_lock_method = he->network_lock_method;
}
+
+ /**
+ * This contains the criu_run_id during dumping of the process.
+ * For things like removing network locking (nftables) this
+ * information is needed to identify the name of the network
+ * locking table.
+ */
+ if (he->dump_criu_run_id) {
+ strncpy(dump_criu_run_id, he->dump_criu_run_id, sizeof(dump_criu_run_id) - 1);
+ pr_info("Dump CRIU run id = %s\n", dump_criu_run_id);
+ } else {
+ /**
+ * If restoring from an old image this is a marker
+ * that no dump_criu_run_id exists.
+ */
+ dump_criu_run_id[0] = NO_DUMP_CRIU_RUN_ID;
+ }
+
}
ret = 0;
@@ -367,6 +386,17 @@ int prepare_inventory(InventoryEntry *he)
he->has_network_lock_method = true;
he->network_lock_method = opts.network_lock_method;
+ /**
+ * This contains the criu_run_id during dumping of the process.
+ * For things like removing network locking (nftables) this
+ * information is needed to identify the name of the network
+ * locking table.
+ */
+ he->dump_criu_run_id = xstrdup(criu_run_id);
+
+ if (!he->dump_criu_run_id)
+ return -1;
+
return 0;
}
diff --git a/criu/include/util.h b/criu/include/util.h
index 194e94deeb..55ad5b63cf 100644
--- a/criu/include/util.h
+++ b/criu/include/util.h
@@ -424,6 +424,8 @@ extern int run_command(char *buf, size_t buf_size, int (*child_fn)(void *), void
*/
extern char criu_run_id[RUN_ID_HASH_LENGTH];
extern void util_init(void);
+#define NO_DUMP_CRIU_RUN_ID 0x7f
+extern char dump_criu_run_id[RUN_ID_HASH_LENGTH];
extern char *resolve_mountpoint(char *path);
diff --git a/criu/netfilter.c b/criu/netfilter.c
index 9e78dc4b03..e2c82764f2 100644
--- a/criu/netfilter.c
+++ b/criu/netfilter.c
@@ -299,7 +299,25 @@ int nftables_lock_connection(struct inet_sk_desc *sk)
int nftables_get_table(char *table, int n)
{
- if (snprintf(table, n, "inet CRIU-%d", root_item->pid->real) < 0) {
+ int ret;
+
+ switch(dump_criu_run_id[0]) {
+ case 0:
+ /* This is not a restore.*/
+ ret = snprintf(table, n, "inet CRIU-%s", criu_run_id);
+ break;
+ case NO_DUMP_CRIU_RUN_ID:
+ /**
+ * This is a restore from an older image with no
+ * dump_criu_run_id available. Let's use the old ID.
+ */
+ ret = snprintf(table, n, "inet CRIU-%d", root_item->pid->real);
+ break;
+ default:
+ ret = snprintf(table, n, "inet CRIU-%s", dump_criu_run_id);
+ }
+
+ if (ret < 0) {
pr_err("Cannot generate CRIU's nftables table name\n");
return -1;
}
diff --git a/images/inventory.proto b/images/inventory.proto
index 7f655031bc..1e18815bb9 100644
--- a/images/inventory.proto
+++ b/images/inventory.proto
@@ -29,4 +29,8 @@ message inventory_entry {
optional uint32 pre_dump_mode = 9;
optional bool tcp_close = 10;
optional uint32 network_lock_method = 11;
+ // Remember the criu_run_id when CRIU dumped the process.
+ // This is currently used to delete the correct nftables
+ // network locking rule.
+ optional string dump_criu_run_id = 13;
}

452
2570.patch Normal file
View File

@ -0,0 +1,452 @@
From ed2468f0a3c1c3c3b40b41047ffd97ce32346a4e Mon Sep 17 00:00:00 2001
From: Adrian Reber <areber@redhat.com>
Date: Wed, 22 Jan 2025 14:35:26 +0100
Subject: [PATCH] vdso: switch from DT_HASH to DT_GNU_HASH (aarch64)
Trying to run latest CRIU on CentOS Stream 10 or Ubuntu 24.04 (aarch64)
fails like this:
# criu/criu check -v4
[...]
(00.096460) vdso: Parsing at ffffb2e2a000 ffffb2e2c000
(00.096539) vdso: PT_LOAD p_vaddr: 0
(00.096567) vdso: DT_STRTAB: 1d0
(00.096592) vdso: DT_SYMTAB: 128
(00.096616) vdso: DT_STRSZ: 8a
(00.096640) vdso: DT_SYMENT: 18
(00.096663) Error (criu/pie-util-vdso.c:193): vdso: Not all dynamic entries are present
(00.096688) Error (criu/vdso.c:627): vdso: Failed to fill self vdso symtable
(00.096713) Error (criu/kerndat.c:1906): kerndat_vdso_fill_symtable failed when initializing kerndat.
(00.096812) Found mmap_min_addr 0x10000
(00.096881) files stat: fs/nr_open 1073741816
(00.096908) Error (criu/crtools.c:267): Could not initialize kernel features detection.
This seems to be related to the kernel (6.12.0-41.el10.aarch64). The
Ubuntu user-space is running in a container on the same kernel.
Looking at the kernel this seems to be related to:
commit 48f6430505c0b0498ee9020ce3cf9558b1caaaeb
Author: Fangrui Song <i@maskray.me>
Date: Thu Jul 18 10:34:23 2024 -0700
arm64/vdso: Remove --hash-style=sysv
glibc added support for .gnu.hash in 2006 and .hash has been obsoleted
for more than one decade in many Linux distributions. Using
--hash-style=sysv might imply unaddressed issues and confuse readers.
Just drop the option and rely on the linker default, which is likely
"both", or "gnu" when the distribution really wants to eliminate sysv
hash overhead.
Similar to commit 6b7e26547fad ("x86/vdso: Emit a GNU hash").
The commit basically does:
-ldflags-y := -shared -soname=linux-vdso.so.1 --hash-style=sysv \
+ldflags-y := -shared -soname=linux-vdso.so.1 \
Which results in only a GNU hash being added to the ELF header. This
change has been merged with 6.11.
Looking at the referenced x86 commit:
commit 6b7e26547fad7ace3dcb27a5babd2317fb9d1e12
Author: Andy Lutomirski <luto@amacapital.net>
Date: Thu Aug 6 14:45:45 2015 -0700
x86/vdso: Emit a GNU hash
Some dynamic loaders may be slightly faster if a GNU hash is
available. Strangely, this seems to have no effect at all on
the vdso size.
This is unlikely to have any measurable effect on the time it
takes to resolve vdso symbols (since there are so few of them).
In some contexts, it can be a win for a different reason: if
every DSO has a GNU hash section, then libc can avoid
calculating SysV hashes at all. Both musl and glibc appear to
have this optimization.
It's plausible that this breaks some ancient glibc version. If
so, then, depending on what glibc versions break, we could
either require COMPAT_VDSO for them or consider reverting.
Which is also a really simple change:
-VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) \
+VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=both) \
The big difference here is that for x86 both hash sections are
generated. For aarch64 only the newer GNU hash is generated. That is why
we only see this error on kernel >= 6.11 and aarch64.
Changing from DT_HASH to DT_GNU_HASH seems to work on aarch64. The test
suite runs without any errors.
Unfortunately I am not aware of all implication of this change and if a
successful test suite run means that it still works.
Looking at the kernel I see following hash styles for the VDSO:
aarch64: not specified (only GNU hash style)
arm: --hash-style=sysv
loongarch: --hash-style=sysv
mips: --hash-style=sysv
powerpc: --hash-style=both
riscv: --hash-style=both
s390: --hash-style=both
x86: --hash-style=both
Only aarch64 on kernels >= 6.11 is a problem right now, because all
other platforms provide the old style hashing.
Signed-off-by: Adrian Reber <areber@redhat.com>
Co-developed-by: Dmitry Safonov <dima@arista.com>
Co-authored-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
---
criu/pie/util-vdso.c | 245 ++++++++++++++++++++++++++++++++++---------
1 file changed, 198 insertions(+), 47 deletions(-)
diff --git a/criu/pie/util-vdso.c b/criu/pie/util-vdso.c
index f1e3239ff5..9819335d81 100644
--- a/criu/pie/util-vdso.c
+++ b/criu/pie/util-vdso.c
@@ -5,6 +5,7 @@
#include <fcntl.h>
#include <errno.h>
#include <stdint.h>
+#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -48,10 +49,25 @@ static bool __ptr_struct_oob(uintptr_t ptr, size_t struct_size, uintptr_t start,
return __ptr_oob(ptr, start, size) || __ptr_struct_end_oob(ptr, struct_size, start, size);
}
+/* Local strlen implementation */
+static size_t __strlen(const char *str)
+{
+ const char *ptr;
+
+ if (!str)
+ return 0;
+
+ ptr = str;
+ while (*ptr != '\0')
+ ptr++;
+
+ return ptr - str;
+}
+
/*
* Elf hash, see format specification.
*/
-static unsigned long elf_hash(const unsigned char *name)
+static unsigned long elf_sysv_hash(const unsigned char *name)
{
unsigned long h = 0, g;
@@ -65,6 +81,15 @@ static unsigned long elf_hash(const unsigned char *name)
return h;
}
+/* * The GNU hash format. Taken from glibc. */
+static unsigned long elf_gnu_hash(const unsigned char *name)
+{
+ unsigned long h = 5381;
+ for (unsigned char c = *name; c != '\0'; c = *++name)
+ h = h * 33 + c;
+ return h;
+}
+
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define BORD ELFDATA2MSB /* 0x02 */
#else
@@ -149,11 +174,14 @@ static int parse_elf_phdr(uintptr_t mem, size_t size, Phdr_t **dynamic, Phdr_t *
* Output parameters are:
* @dyn_strtab - address of the symbol table
* @dyn_symtab - address of the string table section
- * @dyn_hash - address of the symbol hash table
+ * @dyn_hash - address of the symbol hash table
+ * @use_gnu_hash - the format of hash DT_HASH or DT_GNU_HASH
*/
-static int parse_elf_dynamic(uintptr_t mem, size_t size, Phdr_t *dynamic, Dyn_t **dyn_strtab, Dyn_t **dyn_symtab,
- Dyn_t **dyn_hash)
+static int parse_elf_dynamic(uintptr_t mem, size_t size, Phdr_t *dynamic,
+ Dyn_t **dyn_strtab, Dyn_t **dyn_symtab,
+ Dyn_t **dyn_hash, bool *use_gnu_hash)
{
+ Dyn_t *dyn_gnu_hash = NULL, *dyn_sysv_hash = NULL;
Dyn_t *dyn_syment = NULL;
Dyn_t *dyn_strsz = NULL;
uintptr_t addr;
@@ -184,16 +212,52 @@ static int parse_elf_dynamic(uintptr_t mem, size_t size, Phdr_t *dynamic, Dyn_t
dyn_syment = d;
pr_debug("DT_SYMENT: %lx\n", (unsigned long)d->d_un.d_val);
} else if (d->d_tag == DT_HASH) {
- *dyn_hash = d;
+ dyn_sysv_hash = d;
pr_debug("DT_HASH: %lx\n", (unsigned long)d->d_un.d_ptr);
+ } else if (d->d_tag == DT_GNU_HASH) {
+ /*
+ * This is complicated.
+ *
+ * Looking at the Linux kernel source, the following can be seen
+ * regarding which hashing style the VDSO uses on each arch:
+ *
+ * aarch64: not specified (depends on linker, can be
+ * only GNU hash style)
+ * arm: --hash-style=sysv
+ * loongarch: --hash-style=sysv
+ * mips: --hash-style=sysv
+ * powerpc: --hash-style=both
+ * riscv: --hash-style=both
+ * s390: --hash-style=both
+ * x86: --hash-style=both
+ *
+ * Some architectures are using both hash-styles, that
+ * is the easiest for CRIU. Some architectures are only
+ * using the old style (sysv), that is what CRIU supports.
+ *
+ * Starting with Linux 6.11, aarch64 unfortunately decided
+ * to switch from '--hash-style=sysv' to ''. Specifying
+ * nothing unfortunately may mean GNU hash style only and not
+ * 'both' (depending on the linker).
+ */
+ dyn_gnu_hash = d;
+ pr_debug("DT_GNU_HASH: %lx\n", (unsigned long)d->d_un.d_ptr);
}
}
- if (!*dyn_strtab || !*dyn_symtab || !dyn_strsz || !dyn_syment || !*dyn_hash) {
+ if (!*dyn_strtab || !*dyn_symtab || !dyn_strsz || !dyn_syment ||
+ (!dyn_gnu_hash && !dyn_sysv_hash)) {
pr_err("Not all dynamic entries are present\n");
return -EINVAL;
}
+ /*
+ * Prefer DT_HASH over DT_GNU_HASH as it's been more tested and
+ * as a result more stable.
+ */
+ *use_gnu_hash = !dyn_sysv_hash;
+ *dyn_hash = dyn_sysv_hash ?: dyn_gnu_hash;
+
return 0;
err_oob:
@@ -208,60 +272,141 @@ typedef unsigned long Hash_t;
typedef Word_t Hash_t;
#endif
-static void parse_elf_symbols(uintptr_t mem, size_t size, Phdr_t *load, struct vdso_symtable *t,
- uintptr_t dynsymbol_names, Hash_t *hash, Dyn_t *dyn_symtab)
+static bool elf_symbol_match(uintptr_t mem, size_t size,
+ uintptr_t dynsymbol_names, Sym_t *sym,
+ const char *symbol, const size_t vdso_symbol_length)
{
- ARCH_VDSO_SYMBOLS_LIST
-
- const char *vdso_symbols[VDSO_SYMBOL_MAX] = { ARCH_VDSO_SYMBOLS };
- const size_t vdso_symbol_length = sizeof(t->symbols[0].name) - 1;
+ uintptr_t addr = (uintptr_t)sym;
+ char *name;
- Hash_t nbucket, nchain;
- Hash_t *bucket, *chain;
+ if (__ptr_struct_oob(addr, sizeof(Sym_t), mem, size))
+ return false;
- unsigned int i, j, k;
- uintptr_t addr;
+ if (ELF_ST_TYPE(sym->st_info) != STT_FUNC && ELF_ST_BIND(sym->st_info) != STB_GLOBAL)
+ return false;
- nbucket = hash[0];
- nchain = hash[1];
- bucket = &hash[2];
- chain = &hash[nbucket + 2];
+ addr = dynsymbol_names + sym->st_name;
+ if (__ptr_struct_oob(addr, vdso_symbol_length, mem, size))
+ return false;
+ name = (void *)addr;
- pr_debug("nbucket %lx nchain %lx bucket %lx chain %lx\n", (long)nbucket, (long)nchain, (unsigned long)bucket,
- (unsigned long)chain);
+ return !std_strncmp(name, symbol, vdso_symbol_length);
+}
- for (i = 0; i < VDSO_SYMBOL_MAX; i++) {
- const char *symbol = vdso_symbols[i];
- k = elf_hash((const unsigned char *)symbol);
- for (j = bucket[k % nbucket]; j < nchain && j != STN_UNDEF; j = chain[j]) {
- Sym_t *sym;
- char *name;
+static unsigned long elf_symbol_lookup(uintptr_t mem, size_t size,
+ const char *symbol, uint32_t symbol_hash, unsigned int sym_off,
+ uintptr_t dynsymbol_names, Dyn_t *dyn_symtab, Phdr_t *load,
+ Hash_t nbucket, Hash_t nchain, Hash_t *bucket, Hash_t *chain,
+ const size_t vdso_symbol_length, bool use_gnu_hash)
+{
+ unsigned int j;
+ uintptr_t addr;
- addr = mem + dyn_symtab->d_un.d_ptr - load->p_vaddr;
+ j = bucket[symbol_hash % nbucket];
+ if (j == STN_UNDEF)
+ return 0;
+
+ addr = mem + dyn_symtab->d_un.d_ptr - load->p_vaddr;
+
+ if (use_gnu_hash) {
+ uint32_t *h = bucket + nbucket + (j - sym_off);
+ uint32_t hash_val;
+
+ symbol_hash |= 1;
+ do {
+ Sym_t *sym = (void *)addr + sizeof(Sym_t) * j;
+
+ hash_val = *h++;
+ if ((hash_val | 1) == symbol_hash &&
+ elf_symbol_match(mem, size, dynsymbol_names, sym,
+ symbol, vdso_symbol_length))
+ return sym->st_value;
+ j++;
+ } while (!(hash_val & 1));
+ } else {
+ for (; j < nchain && j != STN_UNDEF; j = chain[j]) {
+ Sym_t *sym = (void *)addr + sizeof(Sym_t) * j;
+
+ if (elf_symbol_match(mem, size, dynsymbol_names, sym,
+ symbol, vdso_symbol_length))
+ return sym->st_value;
+ }
+ }
+ return 0;
+}
- addr += sizeof(Sym_t) * j;
- if (__ptr_struct_oob(addr, sizeof(Sym_t), mem, size))
- continue;
- sym = (void *)addr;
+static int parse_elf_symbols(uintptr_t mem, size_t size, Phdr_t *load,
+ struct vdso_symtable *t, uintptr_t dynsymbol_names,
+ Hash_t *hash, Dyn_t *dyn_symtab, bool use_gnu_hash)
+{
+ ARCH_VDSO_SYMBOLS_LIST
- if (ELF_ST_TYPE(sym->st_info) != STT_FUNC && ELF_ST_BIND(sym->st_info) != STB_GLOBAL)
- continue;
+ const char *vdso_symbols[VDSO_SYMBOL_MAX] = { ARCH_VDSO_SYMBOLS };
+ const size_t vdso_symbol_length = sizeof(t->symbols[0].name) - 1;
- addr = dynsymbol_names + sym->st_name;
- if (__ptr_struct_oob(addr, vdso_symbol_length, mem, size))
- continue;
- name = (void *)addr;
+ Hash_t *bucket = NULL;
+ Hash_t *chain = NULL;
+ Hash_t nbucket = 0;
+ Hash_t nchain = 0;
+
+ unsigned int sym_off = 0;
+ unsigned int i = 0;
+
+ unsigned long (*elf_hash)(const unsigned char *);
+
+ if (use_gnu_hash) {
+ uint32_t *gnu_hash = (uint32_t *)hash;
+ uint32_t bloom_sz;
+ size_t *bloom;
+
+ nbucket = gnu_hash[0];
+ sym_off = gnu_hash[1];
+ bloom_sz = gnu_hash[2];
+ bloom = (size_t *)&gnu_hash[4];
+ bucket = (Hash_t *)(&bloom[bloom_sz]);
+ elf_hash = &elf_gnu_hash;
+ pr_debug("nbucket %lx sym_off %lx bloom_sz %lx bloom %lx bucket %lx\n",
+ (unsigned long)nbucket, (unsigned long)sym_off,
+ (unsigned long)bloom_sz, (unsigned long)bloom,
+ (unsigned long)bucket);
+ } else {
+ nbucket = hash[0];
+ nchain = hash[1];
+ bucket = &hash[2];
+ chain = &hash[nbucket + 2];
+ elf_hash = &elf_sysv_hash;
+ pr_debug("nbucket %lx nchain %lx bucket %lx chain %lx\n",
+ (unsigned long)nbucket, (unsigned long)nchain,
+ (unsigned long)bucket, (unsigned long)chain);
+ }
- if (std_strncmp(name, symbol, vdso_symbol_length))
- continue;
- /* XXX: provide strncpy() implementation for PIE */
- memcpy(t->symbols[i].name, name, vdso_symbol_length);
- t->symbols[i].offset = (unsigned long)sym->st_value - load->p_vaddr;
- break;
+ for (i = 0; i < VDSO_SYMBOL_MAX; i++) {
+ const char *symbol = vdso_symbols[i];
+ unsigned long addr, symbol_hash;
+ const size_t symbol_length = __strlen(symbol);
+
+ symbol_hash = elf_hash((const unsigned char *)symbol);
+ addr = elf_symbol_lookup(mem, size, symbol, symbol_hash,
+ sym_off, dynsymbol_names, dyn_symtab, load,
+ nbucket, nchain, bucket, chain,
+ vdso_symbol_length, use_gnu_hash);
+ pr_debug("symbol %s at address %lx\n", symbol, addr);
+ if (!addr)
+ continue;
+
+ /* XXX: provide strncpy() implementation for PIE */
+ if (symbol_length > vdso_symbol_length) {
+ pr_err("strlen(%s) %zd, only %zd bytes available\n",
+ symbol, symbol_length, vdso_symbol_length);
+ return -EINVAL;
}
+ memcpy(t->symbols[i].name, symbol, symbol_length);
+ t->symbols[i].offset = addr - load->p_vaddr;
}
+
+ return 0;
}
int vdso_fill_symtable(uintptr_t mem, size_t size, struct vdso_symtable *t)
@@ -271,6 +416,7 @@ int vdso_fill_symtable(uintptr_t mem, size_t size, struct vdso_symtable *t)
Dyn_t *dyn_symtab = NULL;
Dyn_t *dyn_hash = NULL;
Hash_t *hash = NULL;
+ bool use_gnu_hash;
uintptr_t dynsymbol_names;
uintptr_t addr;
@@ -296,7 +442,8 @@ int vdso_fill_symtable(uintptr_t mem, size_t size, struct vdso_symtable *t)
* needed. Note that we're interested in a small set of tags.
*/
- ret = parse_elf_dynamic(mem, size, dynamic, &dyn_strtab, &dyn_symtab, &dyn_hash);
+ ret = parse_elf_dynamic(mem, size, dynamic, &dyn_strtab, &dyn_symtab,
+ &dyn_hash, &use_gnu_hash);
if (ret < 0)
return ret;
@@ -310,7 +457,11 @@ int vdso_fill_symtable(uintptr_t mem, size_t size, struct vdso_symtable *t)
goto err_oob;
hash = (void *)addr;
- parse_elf_symbols(mem, size, load, t, dynsymbol_names, hash, dyn_symtab);
+ ret = parse_elf_symbols(mem, size, load, t, dynsymbol_names, hash, dyn_symtab,
+ use_gnu_hash);
+
+ if (ret <0)
+ return ret;
return 0;

View File

@ -12,7 +12,7 @@
Name: criu
Version: 3.19
Release: 7%{?dist}
Release: 8%{?dist}
Summary: Tool for Checkpoint/Restore in User-space
License: GPL-2.0-only AND LGPL-2.1-only AND MIT
URL: http://criu.org/
@ -22,14 +22,17 @@ Source0: https://github.com/checkpoint-restore/criu/archive/v%{version}/criu-%{v
Patch0: network.lock.nftables.patch
# Update restartable sequences to latest upstream code
Patch1: https://github.com/checkpoint-restore/criu/commit/089345f77a34d1bc7ef146d650636afcd3cdda21.patch
# Upstream tracked as
# https://github.com/checkpoint-restore/criu/pull/2549
# https://github.com/checkpoint-restore/criu/pull/2550
Patch2: nftables.chain.patch
# Unfortunately crun added code to always force
# iptables backed network locking. This disables
# setting the network locking to iptables via RPC.
Patch3: disable.network.locking.via.rpc.patch
Patch2: disable.network.locking.via.rpc.patch
# net: redirect nftables stdout and stderr to CRIU's log file #2549
Patch3: https://patch-diff.githubusercontent.com/raw/checkpoint-restore/criu/pull/2549.patch
# net: remember the name of the lock chain (nftables) #2550
# based on https://patch-diff.githubusercontent.com/raw/checkpoint-restore/criu/pull/2550.patch
Patch4: 2550.patch
# vdso: switch from DT_HASH to DT_GNU_HASH (aarch64) #2570
Patch5: https://patch-diff.githubusercontent.com/raw/checkpoint-restore/criu/pull/2570.patch
# Add protobuf-c as a dependency.
# We use this patch because the protobuf-c package name
@ -51,6 +54,7 @@ BuildRequires: perl-interpreter
BuildRequires: libselinux-devel
BuildRequires: gnutls-devel
BuildRequires: nftables-devel
BuildRequires: libuuid-devel
# Checkpointing containers with a tmpfs requires tar
Recommends: tar
%if 0%{?fedora}
@ -114,6 +118,8 @@ This script can help to workaround the so called "PID mismatch" problem.
%patch -P 1 -p1
%patch -P 2 -p1
%patch -P 3 -p1
%patch -P 4 -p1
%patch -P 5 -p1
%patch -P 99 -p1
%build
@ -173,6 +179,10 @@ rm -f $RPM_BUILD_ROOT%{_libdir}/libcriu.a
%doc %{_mandir}/man1/criu-ns.1*
%changelog
* Tue Feb 04 2025 Adrian Reber <areber@redhat.com> - 3.19-8
- Adapt patches to patches merged upstream
- Fix running on aarch64
* Tue Dec 10 2024 Adrian Reber <areber@redhat.com> - 3.19-7
- Switch network locking backend default to nftables

View File

@ -1,205 +0,0 @@
diff -ur ../criu-3.19/criu/cr-dump.c criu-3.19/criu/cr-dump.c
--- ../criu-3.19/criu/cr-dump.c 2023-11-28 01:47:16.000000000 +0100
+++ criu-3.19/criu/cr-dump.c 2024-12-17 09:53:58.545908685 +0100
@@ -2182,7 +2182,7 @@
if (collect_pstree_ids())
goto err;
- if (network_lock())
+ if (network_lock(&he))
goto err;
if (rpc_query_external_files())
diff -ur ../criu-3.19/criu/cr-restore.c criu-3.19/criu/cr-restore.c
--- ../criu-3.19/criu/cr-restore.c 2023-11-28 01:47:16.000000000 +0100
+++ criu-3.19/criu/cr-restore.c 2024-12-17 09:29:47.771542239 +0100
@@ -2359,7 +2359,7 @@
* the '--empty-ns net' mode no iptables C/R is done and we
* need to return these rules by hands.
*/
- ret = network_lock_internal();
+ ret = network_lock_internal(NULL);
if (ret)
goto out_kill;
}
diff -ur ../criu-3.19/criu/image.c criu-3.19/criu/image.c
--- ../criu-3.19/criu/image.c 2023-11-28 01:47:16.000000000 +0100
+++ criu-3.19/criu/image.c 2024-12-17 09:56:13.751949657 +0100
@@ -25,6 +25,7 @@
TaskKobjIdsEntry *root_ids;
u32 root_cg_set;
Lsmtype image_lsm;
+char nft_lock_table[32];
int check_img_inventory(bool restore)
{
@@ -99,6 +100,9 @@
} else {
opts.network_lock_method = he->network_lock_method;
}
+
+ if (he->nft_lock_table)
+ strncpy(nft_lock_table, he->nft_lock_table, sizeof(nft_lock_table) - 1);
}
ret = 0;
diff -ur ../criu-3.19/criu/include/net.h criu-3.19/criu/include/net.h
--- ../criu-3.19/criu/include/net.h 2023-11-28 01:47:16.000000000 +0100
+++ criu-3.19/criu/include/net.h 2024-12-17 09:27:40.578168778 +0100
@@ -29,9 +29,10 @@
extern int collect_net_namespaces(bool for_dump);
-extern int network_lock(void);
+#include "images/inventory.pb-c.h"
+extern int network_lock(InventoryEntry *he);
extern void network_unlock(void);
-extern int network_lock_internal(void);
+extern int network_lock_internal(InventoryEntry *he);
extern struct ns_desc net_ns_desc;
diff -ur ../criu-3.19/criu/net.c criu-3.19/criu/net.c
--- ../criu-3.19/criu/net.c 2023-11-28 01:47:16.000000000 +0100
+++ criu-3.19/criu/net.c 2024-12-17 09:53:25.370199544 +0100
@@ -229,6 +229,8 @@
"max_dgram_qlen",
};
+extern char nft_lock_table[32];
+
/*
* MAX_CONF_UNIX_PATH = (sizeof(CONF_UNIX_FMT) - strlen("%s"))
* + MAX_CONF_UNIX_OPT_PATH
@@ -3053,21 +3055,34 @@
return ret;
}
-static inline int nftables_lock_network_internal(void)
+static inline int nftables_lock_network_internal(InventoryEntry *he)
{
#if defined(CONFIG_HAS_NFTABLES_LIB_API_0) || defined(CONFIG_HAS_NFTABLES_LIB_API_1)
struct nft_ctx *nft;
int ret = 0;
char table[32];
char buf[128];
+ FILE *fp;
if (nftables_get_table(table, sizeof(table)))
return -1;
+ if (he) {
+ he->nft_lock_table = strdup(table);
+ }
+
nft = nft_ctx_new(NFT_CTX_DEFAULT);
if (!nft)
return -1;
+ fp = fdopen(log_get_fd(), "w");
+ if (!fp) {
+ pr_perror("fdopen() failed");
+ goto err3;
+ }
+ nft_ctx_set_output(nft, fp);
+ nft_ctx_set_error(nft, fp);
+
snprintf(buf, sizeof(buf), "create table %s", table);
if (NFT_RUN_CMD(nft, buf))
goto err2;
@@ -3094,6 +3109,9 @@
snprintf(buf, sizeof(buf), "delete table %s", table);
NFT_RUN_CMD(nft, buf);
err2:
+ fflush(fp);
+ fclose(fp);
+err3:
ret = -1;
pr_err("Locking network failed using nftables\n");
out:
@@ -3130,7 +3148,7 @@
return ret;
}
-int network_lock_internal(void)
+int network_lock_internal(InventoryEntry *he)
{
int ret = 0, nsret;
@@ -3143,7 +3161,7 @@
if (opts.network_lock_method == NETWORK_LOCK_IPTABLES)
ret = iptables_network_lock_internal();
else if (opts.network_lock_method == NETWORK_LOCK_NFTABLES)
- ret = nftables_lock_network_internal();
+ ret = nftables_lock_network_internal(he);
if (restore_ns(nsret, &net_ns_desc))
ret = -1;
@@ -3158,18 +3176,34 @@
struct nft_ctx *nft;
char table[32];
char buf[128];
+ FILE *fp;
- if (nftables_get_table(table, sizeof(table)))
- return -1;
+ if (nft_lock_table[0] != 0) {
+ strncpy(table, nft_lock_table, sizeof(table));
+ } else {
+ if (nftables_get_table(table, sizeof(table)))
+ return -1;
+ }
nft = nft_ctx_new(NFT_CTX_DEFAULT);
if (!nft)
return -1;
+ fp = fdopen(log_get_fd(), "w");
+ if (!fp) {
+ pr_perror("fdopen() failed");
+ nft_ctx_free(nft);
+ return -1;
+ }
+ nft_ctx_set_output(nft, fp);
+ nft_ctx_set_error(nft, fp);
+
snprintf(buf, sizeof(buf), "delete table %s", table);
if (NFT_RUN_CMD(nft, buf))
ret = -1;
+ fflush(fp);
+ fclose(fp);
nft_ctx_free(nft);
return ret;
#else
@@ -3216,7 +3250,7 @@
return ret;
}
-int network_lock(void)
+int network_lock(InventoryEntry *he)
{
pr_info("Lock network\n");
@@ -3230,10 +3264,10 @@
if (run_scripts(ACT_NET_LOCK))
return -1;
- return network_lock_internal();
+ return network_lock_internal(he);
}
-void network_unlock(void)
+void network_unlock()
{
pr_info("Unlock network\n");
diff -ur ../criu-3.19/images/inventory.proto criu-3.19/images/inventory.proto
--- ../criu-3.19/images/inventory.proto 2023-11-28 01:47:16.000000000 +0100
+++ criu-3.19/images/inventory.proto 2024-12-17 09:21:55.378011178 +0100
@@ -21,4 +21,5 @@
optional uint32 pre_dump_mode = 9;
optional bool tcp_close = 10;
optional uint32 network_lock_method = 11;
+ optional string nft_lock_table = 13;
}

View File

@ -23,6 +23,7 @@
- libnl3-devel
- libcap-devel
- libaio-devel
- libuuid-devel
- nftables-devel
- python3-pyyaml
- python3-protobuf