net/sysctl: make ipv4/ping_group_range work in user namespaces

We dump sysctls from criu user namespace, but restore from restored user
namespace. So group id values should be mapped to the restored user
namespace gid space to restore correctly.

Signed-off-by: Andrei Vagin <avagin@google.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This commit is contained in:
Pavel Tikhomirov 2025-06-08 14:07:13 +08:00 committed by Andrei Vagin
parent 45d09ae17e
commit 87bd09a0d1
2 changed files with 45 additions and 1 deletions

View file

@ -2203,6 +2203,42 @@ static int ipv4_sysctls_op(SysctlEntry ***rsysctl, size_t *pn, int op)
return 0;
}
static int ipv4_sysctls_ping_group_range_map_gid(SysctlEntry *ent, size_t size)
{
int start, end, ustart, uend, ret;
if (sscanf(ent->sarg, "%d %d", &start, &end) != 2) {
pr_err("Failed to parse ping_group_range: %s\n", ent->sarg);
return -1;
}
/*
* The default is "1 0", which means no group
* is allowed to create ICMP Echo sockets.
*/
if (start == 1 && end == 0) {
pr_debug("The ping_group_range is set to default, skipping it.\n");
ent->sarg = NULL;
return 0;
}
if (!(root_ns_mask & CLONE_NEWUSER))
return 0;
ustart = userns_gid(start);
uend = userns_gid(end);
pr_debug("Mapping ping_group_range %d %d to userns -> %d %d\n",
start, end, ustart, uend);
ret = snprintf(ent->sarg, size, "%d\t%d\n", ustart, uend);
if (ret < 0 || ret >= size) {
pr_err("Failed to map ping_group_range: %d\t%d\n", ustart, uend);
return -1;
}
return 0;
}
static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
{
void *buf, *o_buf;
@ -2220,6 +2256,7 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
SysctlEntry *ipv4_sysctls = NULL;
size_t ipv4_sysctl_size = ARRAY_SIZE(ipv4_sysctl_entries);
char ping_group_range[MAX_STR_IPV4_SYSCTL_LEN + 1] = {};
int ping_group_range_id = -1;
NetnsId *ids;
struct netns_id *p;
@ -2310,6 +2347,7 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
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;
ping_group_range_id = i;
} else {
/* Need to handle this case when we have more sysctls */
BUG();
@ -2338,6 +2376,12 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
if (ret < 0)
goto err_free;
BUG_ON(ping_group_range_id == -1);
ret = ipv4_sysctls_ping_group_range_map_gid(netns.ipv4_sysctl[ping_group_range_id],
MAX_STR_IPV4_SYSCTL_LEN + 1);
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);

View file

@ -1,4 +1,4 @@
{
'flavor': 'ns',
'flavor': 'ns uns',
'flags': 'suid'
}