2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-22 01:51:51 +00:00

net/sysctl: c/r ipv4/ping_group_range value

It is per net namespace, we need it to allow creation of unprivileged
ICMP sockets.

Note: in case this sysctl was disabled after unprivileged ICMP
socket was created we still need to somehow handle it on restore.

Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This commit is contained in:
Pavel Tikhomirov 2025-01-16 11:00:28 +08:00 committed by Pavel Tikhomirov
parent 7f35e46e9d
commit f38e58836a
2 changed files with 103 additions and 1 deletions

View File

@ -2128,6 +2128,79 @@ nft_ctx_free_out:
}
#endif
static const char *ipv4_sysctl_entries[] = {
"ping_group_range",
};
#define IPV4_SYSCTL_BASE "net/ipv4"
#define IPV4_SYSCTL_FMT IPV4_SYSCTL_BASE"/%s"
#define MAX_IPV4_SYSCTL_OPT 32
#define MAX_IPV4_SYSCTL_PATH (sizeof(IPV4_SYSCTL_FMT) + MAX_IPV4_SYSCTL_OPT - 2)
#define MAX_STR_IPV4_SYSCTL_LEN 200
static int ipv4_sysctls_op(SysctlEntry ***rsysctl, size_t *pn, int op)
{
int i, ret = -1, flags = 0;
char path[ARRAY_SIZE(ipv4_sysctl_entries)][MAX_IPV4_SYSCTL_PATH] = {};
struct sysctl_req req[ARRAY_SIZE(ipv4_sysctl_entries)] = {};
SysctlEntry **sysctl = *rsysctl;
size_t n = *pn;
if (n != ARRAY_SIZE(ipv4_sysctl_entries)) {
pr_err("unix: Unexpected entries in sysctlig (%zu %zu)\n", n, ARRAY_SIZE(ipv4_sysctl_entries));
return -EINVAL;
}
if (opts.weak_sysctls || op == CTL_READ)
flags = CTL_FLAGS_OPTIONAL;
for (i = 0; i < n; i++) {
snprintf(path[i], MAX_IPV4_SYSCTL_PATH, IPV4_SYSCTL_FMT, ipv4_sysctl_entries[i]);
req[i].name = path[i];
req[i].flags = flags;
switch (sysctl[i]->type) {
case SYSCTL_TYPE__CTL_STR:
req[i].type = CTL_STR(MAX_STR_IPV4_SYSCTL_LEN);
/* skip write if have no value */
if (op == CTL_WRITE && !sysctl[i]->sarg)
continue;
req[i].arg = sysctl[i]->sarg;
break;
default:
pr_err("ipv4: Unknown sysctl type %d\n", sysctl[i]->type);
return -1;
}
}
ret = sysctl_op(req, n, op, CLONE_NEWNET);
if (ret < 0) {
pr_err("unix: Failed to %s %s/<sysctls>\n", (op == CTL_READ) ? "read" : "write", IPV4_SYSCTL_BASE);
return -1;
}
if (op == CTL_READ) {
bool has_entries = false;
for (i = 0; i < n; i++) {
if (req[i].flags & CTL_FLAGS_HAS) {
sysctl[i]->has_iarg = true;
if (!has_entries)
has_entries = true;
}
}
if (!has_entries) {
*pn = 0;
*rsysctl = NULL;
}
}
return 0;
}
static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
{
void *buf, *o_buf;
@ -2142,6 +2215,9 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
int size6 = ARRAY_SIZE(devconfs6);
char def_stable_secret[MAX_STR_CONF_LEN + 1] = {};
char all_stable_secret[MAX_STR_CONF_LEN + 1] = {};
SysctlEntry *ipv4_sysctls = NULL;
size_t ipv4_sysctl_size = ARRAY_SIZE(ipv4_sysctl_entries);
char ping_group_range[MAX_STR_IPV4_SYSCTL_LEN + 1] = {};
NetnsId *ids;
struct netns_id *p;
@ -2157,7 +2233,7 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
* arrays and then finally save them into images.
*/
o_buf = buf = xmalloc(i * (sizeof(NetnsId *) + sizeof(NetnsId)) +
(size4 * 2 + size6 * 2 + sizex) *
(2 * size4 + 2 * size6 + sizex + ipv4_sysctl_size) *
(sizeof(SysctlEntry *) + sizeof(SysctlEntry)));
if (!buf)
goto out;
@ -2223,6 +2299,21 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
netns.unix_conf[i]->type = SYSCTL_TYPE__CTL_32;
}
netns.n_ipv4_sysctl = ipv4_sysctl_size;
netns.ipv4_sysctl = xptr_pull_s(&buf, ipv4_sysctl_size * sizeof(SysctlEntry *));
ipv4_sysctls = xptr_pull_s(&buf, ipv4_sysctl_size * sizeof(SysctlEntry));
for (i = 0; i < ipv4_sysctl_size; i++) {
sysctl_entry__init(&ipv4_sysctls[i]);
netns.ipv4_sysctl[i] = &ipv4_sysctls[i];
if (!strcmp(ipv4_sysctl_entries[i], "ping_group_range")) {
netns.ipv4_sysctl[i]->type = SYSCTL_TYPE__CTL_STR;
netns.ipv4_sysctl[i]->sarg = ping_group_range;
} else {
/* Need to handle this case when we have more sysctls */
BUG();
}
}
ret = ipv4_conf_op("default", netns.def_conf4, size4, CTL_READ, NULL);
if (ret < 0)
goto err_free;
@ -2241,6 +2332,10 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
if (ret < 0)
goto err_free;
ret = ipv4_sysctls_op(&netns.ipv4_sysctl, &netns.n_ipv4_sysctl, CTL_READ);
if (ret < 0)
goto err_free;
ret = pb_write_one(img_from_set(fds, CR_FD_NETNS), &netns, PB_NETNS);
err_free:
xfree(o_buf);
@ -2593,6 +2688,12 @@ static int restore_netns_conf(struct ns_id *ns)
goto out;
}
if ((netns)->ipv4_sysctl) {
ret = ipv4_sysctls_op(&(netns)->ipv4_sysctl, &(netns)->n_ipv4_sysctl, CTL_WRITE);
if (ret)
goto out;
}
ns->net.netns = netns;
out:
return ret;

View File

@ -74,4 +74,5 @@ message netns_entry {
repeated netns_id nsids = 7;
optional string ext_key = 8;
repeated sysctl_entry unix_conf = 9;
repeated sysctl_entry ipv4_sysctl = 10;
}