Skip to content

Commit

Permalink
unix: sysctl -- Preserve max_dgram_qlen value
Browse files Browse the repository at this point in the history
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 <gorcunov@gmail.com>
Signed-off-by: Alexander Mikhalitsyn <alexander@mihalicyn.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
  • Loading branch information
cyrillos authored and avagin committed Feb 4, 2020
1 parent 1d23dc4 commit ebe3b52
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 1 deletion.
104 changes: 103 additions & 1 deletion criu/net.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,19 @@ char *devconfs6[] = {
#define MAX_CONF_OPT_PATH IFNAMSIZ+60
#define MAX_STR_CONF_LEN 200

static const char *unix_conf_entries[] = {
"max_dgram_qlen",
};

/*
* MAX_CONF_UNIX_PATH = (sizeof(CONF_UNIX_FMT) - strlen("%s"))
* + MAX_CONF_UNIX_OPT_PATH
*/
#define CONF_UNIX_BASE "net/unix"
#define CONF_UNIX_FMT CONF_UNIX_BASE"/%s"
#define MAX_CONF_UNIX_OPT_PATH 32
#define MAX_CONF_UNIX_PATH (sizeof(CONF_UNIX_FMT) + MAX_CONF_UNIX_OPT_PATH - 2)

static int net_conf_op(char *tgt, SysctlEntry **conf, int n, int op, char *proto,
struct sysctl_req *req, char (*path)[MAX_CONF_OPT_PATH], int size,
char **devconfs, SysctlEntry **def_conf)
Expand Down Expand Up @@ -339,6 +352,72 @@ static int ipv6_conf_op(char *tgt, SysctlEntry **conf, int n, int op, SysctlEntr
devconfs6, def_conf);
}

static int unix_conf_op(SysctlEntry ***rconf, size_t *n, int op)
{
int i, ret = -1, flags = 0;
char path[ARRAY_SIZE(unix_conf_entries)][MAX_CONF_UNIX_PATH] = { };
struct sysctl_req req[ARRAY_SIZE(unix_conf_entries)] = { };
SysctlEntry **conf = *rconf;

if (*n != ARRAY_SIZE(unix_conf_entries)) {
pr_err("unix: Unexpected entries in config (%zu %zu)\n",
*n, ARRAY_SIZE(unix_conf_entries));
return -EINVAL;
}

if (opts.weak_sysctls || op == CTL_READ)
flags = CTL_FLAGS_OPTIONAL;

for (i = 0; i < *n; i++) {
snprintf(path[i], MAX_CONF_UNIX_PATH, CONF_UNIX_FMT,
unix_conf_entries[i]);
req[i].name = path[i];
req[i].flags = flags;

switch (conf[i]->type) {
case SYSCTL_TYPE__CTL_32:
req[i].type = CTL_32;
req[i].arg = &conf[i]->iarg;
break;
default:
pr_err("unix: Unknown config type %d\n",
conf[i]->type);
return -1;
}
}

ret = sysctl_op(req, *n, op, CLONE_NEWNET);
if (ret < 0) {
pr_err("unix: Failed to %s %s/<confs>\n",
(op == CTL_READ) ? "read" : "write",
CONF_UNIX_BASE);
return -1;
}

if (op == CTL_READ) {
bool has_entries = false;

for (i = 0; i < *n; i++) {
if (req[i].flags & CTL_FLAGS_HAS) {
conf[i]->has_iarg = true;
if (!has_entries)
has_entries = true;
}
}

/*
* Zap the whole section of data.
* Unix conf is optional.
*/
if (!has_entries) {
*n = 0;
*rconf = NULL;
}
}

return 0;
}

/*
* I case if some entry is missing in
* the kernel, simply write DEVCONFS_UNUSED
Expand Down Expand Up @@ -1824,6 +1903,8 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
int ret = -1;
int i;
NetnsEntry netns = NETNS_ENTRY__INIT;
SysctlEntry *unix_confs = NULL;
size_t sizex = ARRAY_SIZE(unix_conf_entries);
SysctlEntry *def_confs4 = NULL, *all_confs4 = NULL;
int size4 = ARRAY_SIZE(devconfs4);
SysctlEntry *def_confs6 = NULL, *all_confs6 = NULL;
Expand All @@ -1840,7 +1921,8 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
o_buf = buf = xmalloc(
i * (sizeof(NetnsId*) + sizeof(NetnsId)) +
size4 * (sizeof(SysctlEntry*) + sizeof(SysctlEntry)) * 2 +
size6 * (sizeof(SysctlEntry*) + sizeof(SysctlEntry)) * 2
size6 * (sizeof(SysctlEntry*) + sizeof(SysctlEntry)) * 2 +
sizex * (sizeof(SysctlEntry*) + sizeof(SysctlEntry))
);
if (!buf)
goto out;
Expand Down Expand Up @@ -1896,6 +1978,16 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
}
}

netns.n_unix_conf = sizex;
netns.unix_conf = xptr_pull_s(&buf, sizex * sizeof(SysctlEntry*));
unix_confs = xptr_pull_s(&buf, sizex * sizeof(SysctlEntry));

for (i = 0; i < sizex; i++) {
sysctl_entry__init(&unix_confs[i]);
netns.unix_conf[i] = &unix_confs[i];
netns.unix_conf[i]->type = SYSCTL_TYPE__CTL_32;
}

ret = ipv4_conf_op("default", netns.def_conf4, size4, CTL_READ, NULL);
if (ret < 0)
goto err_free;
Expand All @@ -1910,6 +2002,10 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
if (ret < 0)
goto err_free;

ret = unix_conf_op(&netns.unix_conf, &netns.n_unix_conf, 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 @@ -2122,6 +2218,12 @@ static int restore_netns_conf(struct ns_id *ns)
ret = ipv6_conf_op("default", (netns)->def_conf6, (netns)->n_def_conf6, CTL_WRITE, NULL);
}

if ((netns)->unix_conf) {
ret = unix_conf_op(&(netns)->unix_conf, &(netns)->n_unix_conf, 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 @@ -71,4 +71,5 @@ message netns_entry {

repeated netns_id nsids = 7;
optional string ext_key = 8;
repeated sysctl_entry unix_conf = 9;
}

0 comments on commit ebe3b52

Please sign in to comment.