[LTP] [PATCH] syscalls/mmap21: Add new test for mmap's ENOMEM case

Cyril Hrubis chrubis@suse.cz
Thu Aug 31 14:42:53 CEST 2023


Hi!
> To be more precise in this test and checking for ENOMEM on exact mapping
> when limit is crossed, I could only think of counting the existing
> mappings from /proc/$pid/maps and counting the remaining possible
> mappings. Is there any better approach if we want to test this for exact
> case?

If you want to check that we managed to create exactly the amount of
mappings in this limit, this would be a sensible way to do that.

However beware that this also depends on the overcommit settings. If
kernel is not set to overcommit and if the size of the memory needed to
cross the maximal number of mappings would exceed available memory you
would get ENOMEM before you manage to hit the limit. With overcommit
enabled you can create mappings as long as the kernel has enough memory
to hold the vma structures.

At my system the limit is set to 65530 which on 4k page size would
consume around 300MB, which does not seem to be much, but may still fail
on small embedded boards with disabled overcommit. So either we try to
set the limit to a lower value for the duration of the test, or allow
the mmap() to fail sooner if we find that available memory is close to
or smaller than number of mappings multiplied by page size.

> Signed-off-by: Avinesh Kumar <akumar@suse.de>
> ---
>  testcases/kernel/syscalls/mmap/mmap21.c | 70 +++++++++++++++++++++++++
>  1 file changed, 70 insertions(+)
>  create mode 100644 testcases/kernel/syscalls/mmap/mmap21.c
> 
> diff --git a/testcases/kernel/syscalls/mmap/mmap21.c b/testcases/kernel/syscalls/mmap/mmap21.c
> new file mode 100644
> index 000000000..76002edb3
> --- /dev/null
> +++ b/testcases/kernel/syscalls/mmap/mmap21.c
> @@ -0,0 +1,70 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2023 SUSE LLC Avinesh Kumar <avinesh.kumar@suse.com>
> + */
> +
> +/*\
> + * [Description]
> + *
> + * Verify that, mmap(2) fails with errno ENOMEM when process's
> + * maximum number of mappings would have been exceeded.
> + */
> +
> +#include <stdio.h>
             ^
I do not think that this is needed, or is ti?

> +#include "tst_test.h"
> +
> +#define TEMPFILE "mmapfile"
> +static int fd;
> +static size_t page_sz;
> +static int max_map;
> +
> +static void setup(void)
> +{
> +	page_sz = getpagesize();
> +
> +	fd = SAFE_OPEN(TEMPFILE, O_RDWR | O_CREAT, 0666);

I guess that we can simplify the test by mapping anonymous memory and
get rid of the needs_tmpdir and file creation.

> +	SAFE_FILE_SCANF("/proc/sys/vm/max_map_count", "%d   ", &max_map);
> +	tst_res(TINFO, "max_map_count: %d", max_map);
> +}
> +
> +static void run(void)
> +{
> +	int i;
> +	char *addr[max_map];
> +
> +	for (i = 0; i < max_map; i++) {
> +		TESTPTR(mmap(0, page_sz, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 0));
                             ^
			     Again since this is an address, it is better to be NULL.

> +		if (TST_RET_PTR != MAP_FAILED) {
> +			addr[i] = TST_RET_PTR;
> +		} else {
> +			if (TST_ERR == ENOMEM) {
> +				tst_res(TINFO, "New successful mappings before exhausting the limit: %d", i);
> +				tst_res(TPASS, "mmap() failed with ENOMEM");
> +			} else {
> +				tst_res(TINFO, "New successful mappings before mmap() failed: %d", i);
> +				tst_res(TFAIL | TERRNO, "mmap() failed with unexpected errno");
> +			}
> +			break;
> +		}
> +	}
> +
> +	if (i == max_map)
> +		tst_res(TFAIL, "mmap() crossed max_map_count limit, no of new mmapings: %d", i);
> +
> +	while (--i >= 0)
> +		SAFE_MUNMAP(addr[i], page_sz);
> +}
> +
> +static void cleanup(void)
> +{
> +	if (fd > 0)
> +		SAFE_CLOSE(fd);
> +}
> +
> +static struct tst_test test = {
> +	.setup = setup,
> +	.cleanup = cleanup,
> +	.test_all = run,
> +	.needs_tmpdir = 1
> +};
> -- 
> 2.41.0
> 
> 
> -- 
> Mailing list info: https://lists.linux.it/listinfo/ltp

-- 
Cyril Hrubis
chrubis@suse.cz


More information about the ltp mailing list