Skip to content

Commit

Permalink
net/sysctl: c/r ipv4/ping_group_range value
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Snorch committed Feb 3, 2025
1 parent 7f35e46 commit f38e588
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 1 deletion.
103 changes: 102 additions & 1 deletion criu/net.c
Original file line number Diff line number Diff line change
Expand Up @@ -2128,6 +2128,79 @@ static inline int dump_nftables(struct cr_imgset *fds)
}
#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;
Expand All @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions images/netdev.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

0 comments on commit f38e588

Please sign in to comment.