Skip to content

Commit ebe3b52

Browse files
cyrillosavagin
authored andcommitted
unix: sysctl -- Preserve max_dgram_qlen value
The /proc/sys/net/unix/max_dgram_qlen is a per-net variable and we already noticed that systemd inside a container may change its value (for example it sets it to 512 by now instead of kernel's default value 10), thus we need keep it inside image and restore then. Signed-off-by: Cyrill Gorcunov <[email protected]> Signed-off-by: Alexander Mikhalitsyn <[email protected]> Signed-off-by: Alexander Mikhalitsyn <[email protected]>
1 parent 1d23dc4 commit ebe3b52

File tree

2 files changed

+104
-1
lines changed

2 files changed

+104
-1
lines changed

criu/net.c

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,19 @@ char *devconfs6[] = {
210210
#define MAX_CONF_OPT_PATH IFNAMSIZ+60
211211
#define MAX_STR_CONF_LEN 200
212212

213+
static const char *unix_conf_entries[] = {
214+
"max_dgram_qlen",
215+
};
216+
217+
/*
218+
* MAX_CONF_UNIX_PATH = (sizeof(CONF_UNIX_FMT) - strlen("%s"))
219+
* + MAX_CONF_UNIX_OPT_PATH
220+
*/
221+
#define CONF_UNIX_BASE "net/unix"
222+
#define CONF_UNIX_FMT CONF_UNIX_BASE"/%s"
223+
#define MAX_CONF_UNIX_OPT_PATH 32
224+
#define MAX_CONF_UNIX_PATH (sizeof(CONF_UNIX_FMT) + MAX_CONF_UNIX_OPT_PATH - 2)
225+
213226
static int net_conf_op(char *tgt, SysctlEntry **conf, int n, int op, char *proto,
214227
struct sysctl_req *req, char (*path)[MAX_CONF_OPT_PATH], int size,
215228
char **devconfs, SysctlEntry **def_conf)
@@ -339,6 +352,72 @@ static int ipv6_conf_op(char *tgt, SysctlEntry **conf, int n, int op, SysctlEntr
339352
devconfs6, def_conf);
340353
}
341354

355+
static int unix_conf_op(SysctlEntry ***rconf, size_t *n, int op)
356+
{
357+
int i, ret = -1, flags = 0;
358+
char path[ARRAY_SIZE(unix_conf_entries)][MAX_CONF_UNIX_PATH] = { };
359+
struct sysctl_req req[ARRAY_SIZE(unix_conf_entries)] = { };
360+
SysctlEntry **conf = *rconf;
361+
362+
if (*n != ARRAY_SIZE(unix_conf_entries)) {
363+
pr_err("unix: Unexpected entries in config (%zu %zu)\n",
364+
*n, ARRAY_SIZE(unix_conf_entries));
365+
return -EINVAL;
366+
}
367+
368+
if (opts.weak_sysctls || op == CTL_READ)
369+
flags = CTL_FLAGS_OPTIONAL;
370+
371+
for (i = 0; i < *n; i++) {
372+
snprintf(path[i], MAX_CONF_UNIX_PATH, CONF_UNIX_FMT,
373+
unix_conf_entries[i]);
374+
req[i].name = path[i];
375+
req[i].flags = flags;
376+
377+
switch (conf[i]->type) {
378+
case SYSCTL_TYPE__CTL_32:
379+
req[i].type = CTL_32;
380+
req[i].arg = &conf[i]->iarg;
381+
break;
382+
default:
383+
pr_err("unix: Unknown config type %d\n",
384+
conf[i]->type);
385+
return -1;
386+
}
387+
}
388+
389+
ret = sysctl_op(req, *n, op, CLONE_NEWNET);
390+
if (ret < 0) {
391+
pr_err("unix: Failed to %s %s/<confs>\n",
392+
(op == CTL_READ) ? "read" : "write",
393+
CONF_UNIX_BASE);
394+
return -1;
395+
}
396+
397+
if (op == CTL_READ) {
398+
bool has_entries = false;
399+
400+
for (i = 0; i < *n; i++) {
401+
if (req[i].flags & CTL_FLAGS_HAS) {
402+
conf[i]->has_iarg = true;
403+
if (!has_entries)
404+
has_entries = true;
405+
}
406+
}
407+
408+
/*
409+
* Zap the whole section of data.
410+
* Unix conf is optional.
411+
*/
412+
if (!has_entries) {
413+
*n = 0;
414+
*rconf = NULL;
415+
}
416+
}
417+
418+
return 0;
419+
}
420+
342421
/*
343422
* I case if some entry is missing in
344423
* the kernel, simply write DEVCONFS_UNUSED
@@ -1824,6 +1903,8 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
18241903
int ret = -1;
18251904
int i;
18261905
NetnsEntry netns = NETNS_ENTRY__INIT;
1906+
SysctlEntry *unix_confs = NULL;
1907+
size_t sizex = ARRAY_SIZE(unix_conf_entries);
18271908
SysctlEntry *def_confs4 = NULL, *all_confs4 = NULL;
18281909
int size4 = ARRAY_SIZE(devconfs4);
18291910
SysctlEntry *def_confs6 = NULL, *all_confs6 = NULL;
@@ -1840,7 +1921,8 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
18401921
o_buf = buf = xmalloc(
18411922
i * (sizeof(NetnsId*) + sizeof(NetnsId)) +
18421923
size4 * (sizeof(SysctlEntry*) + sizeof(SysctlEntry)) * 2 +
1843-
size6 * (sizeof(SysctlEntry*) + sizeof(SysctlEntry)) * 2
1924+
size6 * (sizeof(SysctlEntry*) + sizeof(SysctlEntry)) * 2 +
1925+
sizex * (sizeof(SysctlEntry*) + sizeof(SysctlEntry))
18441926
);
18451927
if (!buf)
18461928
goto out;
@@ -1896,6 +1978,16 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
18961978
}
18971979
}
18981980

1981+
netns.n_unix_conf = sizex;
1982+
netns.unix_conf = xptr_pull_s(&buf, sizex * sizeof(SysctlEntry*));
1983+
unix_confs = xptr_pull_s(&buf, sizex * sizeof(SysctlEntry));
1984+
1985+
for (i = 0; i < sizex; i++) {
1986+
sysctl_entry__init(&unix_confs[i]);
1987+
netns.unix_conf[i] = &unix_confs[i];
1988+
netns.unix_conf[i]->type = SYSCTL_TYPE__CTL_32;
1989+
}
1990+
18991991
ret = ipv4_conf_op("default", netns.def_conf4, size4, CTL_READ, NULL);
19001992
if (ret < 0)
19011993
goto err_free;
@@ -1910,6 +2002,10 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
19102002
if (ret < 0)
19112003
goto err_free;
19122004

2005+
ret = unix_conf_op(&netns.unix_conf, &netns.n_unix_conf, CTL_READ);
2006+
if (ret < 0)
2007+
goto err_free;
2008+
19132009
ret = pb_write_one(img_from_set(fds, CR_FD_NETNS), &netns, PB_NETNS);
19142010
err_free:
19152011
xfree(o_buf);
@@ -2122,6 +2218,12 @@ static int restore_netns_conf(struct ns_id *ns)
21222218
ret = ipv6_conf_op("default", (netns)->def_conf6, (netns)->n_def_conf6, CTL_WRITE, NULL);
21232219
}
21242220

2221+
if ((netns)->unix_conf) {
2222+
ret = unix_conf_op(&(netns)->unix_conf, &(netns)->n_unix_conf, CTL_WRITE);
2223+
if (ret)
2224+
goto out;
2225+
}
2226+
21252227
ns->net.netns = netns;
21262228
out:
21272229
return ret;

images/netdev.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,5 @@ message netns_entry {
7171

7272
repeated netns_id nsids = 7;
7373
optional string ext_key = 8;
74+
repeated sysctl_entry unix_conf = 9;
7475
}

0 commit comments

Comments
 (0)