Skip to content

Commit b89168b

Browse files
authored
Merge pull request #877 from giuseppe/fuzzing-idmapped-options
tests: add fuzzing for idmapped mounts option
2 parents c8980b5 + 8fca8bf commit b89168b

File tree

5 files changed

+119
-81
lines changed

5 files changed

+119
-81
lines changed

src/libcrun/linux.c

Lines changed: 90 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,92 @@ get_bind_mount (const char *src, libcrun_error_t *err)
430430
return get_and_reset (&open_tree_fd);
431431
}
432432

433+
int
434+
parse_idmapped_mount_option (runtime_spec_schema_config_schema *def, bool is_uids, char *option, char **out, size_t *len, libcrun_error_t *err)
435+
{
436+
size_t written = 0, allocated = 256;
437+
cleanup_free char *mappings = NULL;
438+
const char *it;
439+
440+
mappings = xmalloc (allocated);
441+
442+
for (it = option; *it;)
443+
{
444+
bool relative = false;
445+
long value[3];
446+
size_t i;
447+
448+
if (*it == '\0')
449+
break;
450+
451+
if (*it == '#')
452+
it++;
453+
454+
if (*it == '@')
455+
{
456+
relative = true;
457+
it++;
458+
}
459+
460+
/* read a triplet: file system id - host id - size. */
461+
for (i = 0; i < 3; i++)
462+
{
463+
char *endptr = NULL;
464+
465+
if (i > 0 && *it == '-')
466+
it++;
467+
468+
if (*it == '\0')
469+
return crun_make_error (err, errno, "invalid mapping specified `%s`", option);
470+
471+
errno = 0;
472+
value[i] = strtol (it, &endptr, 10);
473+
if (errno || endptr == it)
474+
return crun_make_error (err, errno, "invalid mapping specified `%s`", option);
475+
476+
it = endptr;
477+
}
478+
479+
if (relative)
480+
{
481+
runtime_spec_schema_defs_id_mapping **mappings;
482+
size_t mappings_len;
483+
484+
if (def == NULL
485+
|| def->linux == NULL
486+
|| (is_uids && def->linux->uid_mappings_len == 0)
487+
|| (! is_uids && def->linux->gid_mappings_len == 0))
488+
return crun_make_error (err, 0, "specified a relative mapping without user namespace mappings");
489+
490+
mappings_len = (is_uids ? def->linux->uid_mappings_len : def->linux->gid_mappings_len);
491+
mappings = is_uids ? def->linux->uid_mappings : def->linux->gid_mappings;
492+
493+
for (i = 0; i < mappings_len; i++)
494+
if (value[0] >= mappings[i]->container_id && value[0] < mappings[i]->container_id + mappings[i]->size)
495+
break;
496+
497+
if (i == mappings_len)
498+
return crun_make_error (err, 0, "could not find a user namespace mapping for the relative mapping `%s`", option);
499+
500+
value[1] += mappings[i]->host_id - mappings[i]->container_id;
501+
}
502+
if (written > allocated - 64)
503+
{
504+
allocated += 256;
505+
mappings = xrealloc (mappings, allocated);
506+
}
507+
written += sprintf (mappings + written, "%ld %ld %ld\n", value[0], value[1], value[2]);
508+
}
509+
*(mappings + written) = '\0';
510+
511+
*len = written;
512+
513+
*out = mappings;
514+
mappings = NULL;
515+
516+
return 0;
517+
}
518+
433519
static pid_t
434520
create_userns_for_idmapped_mount (runtime_spec_schema_config_schema *def, const char *options, libcrun_error_t *err)
435521
{
@@ -453,7 +539,6 @@ create_userns_for_idmapped_mount (runtime_spec_schema_config_schema *def, const
453539
for (option = strtok_r (dup_options, ";", &saveptr); option; option = strtok_r (NULL, ";", &saveptr))
454540
{
455541
cleanup_free char *mappings = NULL;
456-
char *ids, *it, *it_mappings;
457542
bool is_uids = false;
458543
char proc_file[64];
459544
size_t len = 0;
@@ -469,85 +554,11 @@ create_userns_for_idmapped_mount (runtime_spec_schema_config_schema *def, const
469554
else
470555
return crun_make_error (err, 0, "invalid option `%s` specified", option);
471556

472-
ids = option + 5 /* strlen ("uids=") and strlen ("gids=") */;
473-
474-
for (it = ids; *it; it++)
475-
{
476-
/* Account for the maximum length. */
477-
if (*it == '-')
478-
len += 10 /* strlen ("4294967295") */ + 1;
479-
len++;
480-
}
481-
482-
it_mappings = mappings = xmalloc (len + 1);
483-
484-
for (it = ids; *it;)
485-
{
486-
bool relative = false;
487-
long value[3];
488-
size_t i;
489-
490-
*it_mappings = *it;
491-
492-
if (*it == '\0')
493-
break;
494-
495-
if (*it == '#')
496-
it++;
497-
498-
if (*it == '@')
499-
{
500-
relative = true;
501-
it++;
502-
}
503-
504-
/* read a triplet: file system id - host id - size. */
505-
for (i = 0; i < 3; i++)
506-
{
507-
char *endptr = NULL;
508-
509-
if (i > 0 && *it == '-')
510-
it++;
511-
512-
if (*it == '\0')
513-
return crun_make_error (err, errno, "invalid mapping specified `%s`", option);
514-
515-
errno = 0;
516-
value[i] = strtol (it, &endptr, 10);
517-
if (errno || endptr == it)
518-
return crun_make_error (err, errno, "invalid mapping specified `%s`", option);
519-
520-
it = endptr;
521-
}
522-
523-
if (relative)
524-
{
525-
runtime_spec_schema_defs_id_mapping **mappings;
526-
size_t mappings_len;
527-
528-
if (def->linux == NULL
529-
|| (is_uids && def->linux->uid_mappings_len == 0)
530-
|| (! is_uids && def->linux->gid_mappings_len == 0))
531-
return crun_make_error (err, 0, "specified a relative mapping without user namespace mappings");
532-
533-
mappings_len = (is_uids ? def->linux->uid_mappings_len : def->linux->gid_mappings_len);
534-
mappings = is_uids ? def->linux->uid_mappings : def->linux->gid_mappings;
535-
536-
for (i = 0; i < mappings_len; i++)
537-
if (value[0] >= mappings[i]->container_id && value[0] < mappings[i]->container_id + mappings[i]->size)
538-
break;
539-
540-
if (i == mappings_len)
541-
return crun_make_error (err, 0, "could not find a user namespace mapping for the relative mapping `%s`", option);
542-
543-
value[1] += mappings[i]->host_id - mappings[i]->container_id;
544-
}
545-
546-
it_mappings += sprintf (it_mappings, "%ld %ld %ld\n", value[0], value[1], value[2]);
547-
}
548-
*it_mappings = '\0';
557+
ret = parse_idmapped_mount_option (def, is_uids, option + 5 /* strlen ("uids="), strlen ("gids=")*/, &mappings, &len, err);
558+
if (UNLIKELY (ret < 0))
559+
return ret;
549560

550-
ret = write_file (proc_file, mappings, it_mappings - mappings, err);
561+
ret = write_file (proc_file, mappings, len, err);
551562
if (UNLIKELY (ret < 0))
552563
return ret;
553564
}

src/libcrun/linux.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,6 @@ int libcrun_create_dev (libcrun_container_t *container, int devfd,
9191
struct device_s *device, bool binds,
9292
bool ensure_parent_dir, libcrun_error_t *err);
9393

94+
int parse_idmapped_mount_option (runtime_spec_schema_config_schema *def, bool is_uids, char *option, char **out, size_t *len, libcrun_error_t *err);
95+
9496
#endif

tests/fuzzing/Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ RUN git clone https://github.com/giuseppe/containers-fuzzing-corpus /testcases
88

99
COPY run-tests.sh /usr/local/bin
1010

11+
WORKDIR /crun
12+
1113
ENTRYPOINT /usr/local/bin/run-tests.sh

tests/fuzzing/run-tests.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@ TIMEOUT=${TIMEOUT:=10}
66
RUN_TIME=${RUN_TIME:=600}
77
VERBOSITY=${VERBOSITY:=}
88

9-
N_TESTS=7
9+
N_TESTS=8
1010

1111
SINGLE_RUN_TIME=$(( RUN_TIME / N_TESTS ))
1212

1313
CORPUS=${CORPUS:=/testcases}
1414

15-
cd /crun
1615
git clean -fdx
1716
./autogen.sh
1817
./configure --enable-embedded-yajl HFUZZ_CC_UBSAN=1 HFUZZ_CC_ASAN=1 CC=hfuzz-clang CPPFLAGS="-D FUZZER" CFLAGS="-ggdb3 -fsanitize-coverage=trace-pc-guard,trace-cmp,trace-div,indirect-calls"
@@ -37,3 +36,4 @@ run_test 3 $CORPUS/signals
3736
run_test 4 $CORPUS/paths
3837
run_test 5 random-data
3938
run_test 6 $CORPUS/annotations
39+
run_test 7 $CORPUS/idmapped-mounts-option

tests/tests_libcrun_fuzzer.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <libcrun/cgroup-utils.h>
2323
#include <libcrun/cgroup-internal.h>
2424
#include <libcrun/utils.h>
25+
#include <libcrun/linux.h>
2526
#include <libcrun/status.h>
2627
#include <libcrun/seccomp.h>
2728
#include <libcrun/ebpf.h>
@@ -283,6 +284,23 @@ test_parse_sd_array (uint8_t *buf, size_t len)
283284
return 0;
284285
}
285286

287+
static int
288+
test_parse_idmapped_mounts (uint8_t *buf, size_t len)
289+
{
290+
cleanup_free char *data = NULL;
291+
cleanup_free char *out = NULL;
292+
libcrun_error_t err = NULL;
293+
294+
data = make_nul_terminated (buf, len);
295+
if (data == NULL)
296+
return 0;
297+
298+
if (parse_idmapped_mount_option (NULL, buf[0] & 1, data, &out, &len, &err) < 0)
299+
crun_error_release (&err);
300+
301+
return 0;
302+
}
303+
286304
static int
287305
run_one_container (uint8_t *buf, size_t len, bool detach)
288306
{
@@ -381,6 +399,11 @@ run_one_test (int mode, uint8_t *buf, size_t len)
381399
test_parse_sd_array (buf, len);
382400
break;
383401

402+
case 7:
403+
/* expects idmapped mounts annotation. */
404+
test_parse_idmapped_mounts (buf, len);
405+
break;
406+
384407
/* ALL mode. */
385408
case -1:
386409
for (i = 0; i <= 5; i++)

0 commit comments

Comments
 (0)