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

net: Fix TOCTOU race condition in unix_conf_op

The unix_conf_op function reads the size of the sysctl entry array
twice. gcc thinks that it can lead to a time-of-check to time-of-use
(TOCTOU) race condition if the array size changes between the two reads.

Fixes #2398

Signed-off-by: Andrei Vagin <avagin@gmail.com>
This commit is contained in:
Andrei Vagin 2024-05-25 05:11:21 +00:00 committed by Andrei Vagin
parent 457bc6a8ff
commit cc88b1e1ff
2 changed files with 9 additions and 8 deletions

View File

@ -359,22 +359,23 @@ static int ipv6_conf_op(char *tgt, SysctlEntry **conf, int n, int op, SysctlEntr
return net_conf_op(tgt, conf, n, op, "ipv6", req, path, ARRAY_SIZE(devconfs6), devconfs6, def_conf); return net_conf_op(tgt, conf, n, op, "ipv6", req, path, ARRAY_SIZE(devconfs6), devconfs6, def_conf);
} }
static int unix_conf_op(SysctlEntry ***rconf, size_t *n, int op) static int unix_conf_op(SysctlEntry ***rconf, size_t *pn, int op)
{ {
int i, ret = -1, flags = 0; int i, ret = -1, flags = 0;
char path[ARRAY_SIZE(unix_conf_entries)][MAX_CONF_UNIX_PATH] = {}; char path[ARRAY_SIZE(unix_conf_entries)][MAX_CONF_UNIX_PATH] = {};
struct sysctl_req req[ARRAY_SIZE(unix_conf_entries)] = {}; struct sysctl_req req[ARRAY_SIZE(unix_conf_entries)] = {};
SysctlEntry **conf = *rconf; SysctlEntry **conf = *rconf;
size_t n = *pn;
if (*n != ARRAY_SIZE(unix_conf_entries)) { if (n != ARRAY_SIZE(unix_conf_entries)) {
pr_err("unix: Unexpected entries in config (%zu %zu)\n", *n, ARRAY_SIZE(unix_conf_entries)); pr_err("unix: Unexpected entries in config (%zu %zu)\n", n, ARRAY_SIZE(unix_conf_entries));
return -EINVAL; return -EINVAL;
} }
if (opts.weak_sysctls || op == CTL_READ) if (opts.weak_sysctls || op == CTL_READ)
flags = CTL_FLAGS_OPTIONAL; flags = CTL_FLAGS_OPTIONAL;
for (i = 0; i < *n; i++) { for (i = 0; i < n; i++) {
snprintf(path[i], MAX_CONF_UNIX_PATH, CONF_UNIX_FMT, unix_conf_entries[i]); snprintf(path[i], MAX_CONF_UNIX_PATH, CONF_UNIX_FMT, unix_conf_entries[i]);
req[i].name = path[i]; req[i].name = path[i];
req[i].flags = flags; req[i].flags = flags;
@ -390,7 +391,7 @@ static int unix_conf_op(SysctlEntry ***rconf, size_t *n, int op)
} }
} }
ret = sysctl_op(req, *n, op, CLONE_NEWNET); ret = sysctl_op(req, n, op, CLONE_NEWNET);
if (ret < 0) { if (ret < 0) {
pr_err("unix: Failed to %s %s/<confs>\n", (op == CTL_READ) ? "read" : "write", CONF_UNIX_BASE); pr_err("unix: Failed to %s %s/<confs>\n", (op == CTL_READ) ? "read" : "write", CONF_UNIX_BASE);
return -1; return -1;
@ -399,7 +400,7 @@ static int unix_conf_op(SysctlEntry ***rconf, size_t *n, int op)
if (op == CTL_READ) { if (op == CTL_READ) {
bool has_entries = false; bool has_entries = false;
for (i = 0; i < *n; i++) { for (i = 0; i < n; i++) {
if (req[i].flags & CTL_FLAGS_HAS) { if (req[i].flags & CTL_FLAGS_HAS) {
conf[i]->has_iarg = true; conf[i]->has_iarg = true;
if (!has_entries) if (!has_entries)
@ -412,7 +413,7 @@ static int unix_conf_op(SysctlEntry ***rconf, size_t *n, int op)
* Unix conf is optional. * Unix conf is optional.
*/ */
if (!has_entries) { if (!has_entries) {
*n = 0; *pn = 0;
*rconf = NULL; *rconf = NULL;
} }
} }

View File

@ -1,4 +1,4 @@
FROM ubuntu:focal FROM ubuntu:24.04
COPY scripts/ci/apt-install /bin/apt-install COPY scripts/ci/apt-install /bin/apt-install