Add UPDATE_INETSK hook for inet address rewrite

We need to support restoring processes on different nodes or subnets
where the original socket IPs may no longer be valid. This change
introduces a new plugin hook, CR_PLUGIN_HOOK__UPDATE_INETSK, and wires
it into both the plugin API and the legacy descriptor autogen so that
existing plugins remain compatible.

The hook is invoked from collect_one_inetsk() before address validation,
port reservation, or bind()/connect(). A plugin may rewrite the IPv4 or
IPv6 src/dst address fields in InetSkEntry in‑place and return 0.
Returning -ENOTSUP skips to the next plugin; any other negative value
aborts the restore for that socket. Only the IP addresses may change —
family, ports, ifname and length constraints remain enforced.

This mechanism is mainly intended for cross‑node or Kubernetes‑style
scenarios where the final IP is only known after the target network
namespace is created and configured. Pre‑editing image files would be
awkward or infeasible otherwise.

Note: for established TCP connections, external coordination or preserving
the original 4‑tuple is still required. This hook only adjusts addresses
and does not modify TCP state.

Signed-off-by: Rowan-Ye <rowenye1@gmail.com>
This commit is contained in:
Rowan-Ye 2025-12-05 20:46:37 +08:00
parent 90300748ef
commit e68f7685a0
3 changed files with 12 additions and 0 deletions

View file

@ -66,6 +66,8 @@ enum {
CR_PLUGIN_HOOK__DUMP_DEVICES_LATE = 14,
CR_PLUGIN_HOOK__UPDATE_INETSK = 15,
CR_PLUGIN_HOOK__MAX
};
@ -87,6 +89,7 @@ DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__CHECKPOINT_DEVICES, int pid);
DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__POST_FORKING, void);
DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__RESTORE_INIT, void);
DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__DUMP_DEVICES_LATE, int id);
DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__UPDATE_INETSK, uint32_t family, uint32_t state, uint32_t src_ip, uint32_t dst_ip);
enum {
CR_PLUGIN_STAGE__DUMP,
@ -162,5 +165,6 @@ typedef int(cr_plugin_update_vma_map_t)(const char *path, const uint64_t addr, c
uint64_t *new_pgoff, int *plugin_fd);
typedef int(cr_plugin_resume_devices_late_t)(int pid);
typedef int(cr_plugin_post_forking_t)(void);
typedef int(cr_plugin_update_inetsk_t)(uint32_t family, uint32_t state, uint32_t src_ip, uint32_t dst_ip);
#endif /* __CRIU_PLUGIN_H__ */

View file

@ -62,6 +62,7 @@ static cr_plugin_desc_t *cr_gen_plugin_desc(void *h, char *path)
__assign_hook(POST_FORKING, "cr_plugin_post_forking");
__assign_hook(RESTORE_INIT, "cr_plugin_restore_init");
__assign_hook(DUMP_DEVICES_LATE, "cr_plugin_dump_devices_late");
__assign_hook(UPDATE_INETSK, "cr_plugin_update_inetsk");
#undef __assign_hook

View file

@ -35,6 +35,7 @@
#include "protobuf.h"
#include "util.h"
#include "namespaces.h"
#include "plugin.h"
#include "images/inventory.pb-c.h"
@ -707,8 +708,14 @@ static inline int tcp_connection(InetSkEntry *ie)
static int collect_one_inetsk(void *o, ProtobufCMessage *base, struct cr_img *i)
{
struct inet_sk_info *ii = o;
int ret;
ii->ie = pb_msg(base, InetSkEntry);
ret = run_plugins(UPDATE_INETSK, ii->ie->family, ii->ie->state, ii->ie->src_addr, ii->ie->dst_addr);
if (ret < 0 && ret != -ENOTSUP)
return -1;
if (tcp_connection(ii->ie))
tcp_locked_conn_add(ii);