CTSRD-CHERI / cheribsd-ports

FreeBSD ports tree adapted for CheriBSD.
https://CheriBSD.org
Other
5 stars 11 forks source link

configure AC_FUNC_MMAP does not detect mmap #122

Closed ivmai closed 6 months ago

ivmai commented 8 months ago

Not sure I'm reporting the issue in the proper space but I found that AC_FUNC_MMAP in configure does reports that mmap() is not working. Host: GCC farm cfarm240 (Morello CheriBSD/arm64) autoreconf: v2.71

How to reproduce:

configure.ac content:

AC_INIT
AC_FUNC_MMAP
AC_OUTPUT

type: autoreconf -i && ./configure

output (see "checking for working mmap..." line):

checking build system type... aarch64-unknown-freebsd14.0
checking host system type... aarch64-unknown-freebsd14.0
checking for gcc... no
checking for cc... cc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether the compiler supports GNU C... yes
checking whether cc accepts -g... yes
checking for cc option to enable C11 features... none needed
checking for stdio.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for strings.h... yes
checking for sys/stat.h... yes
checking for sys/types.h... yes
checking for unistd.h... yes
checking for sys/param.h... yes
checking for getpagesize... yes
checking for working mmap... no
configure: creating ./config.status
brooksdavis commented 6 months ago

More of a CheriBSD issue than a cheribsd-ports issue, but I'll address it here.

TL;DR: in order to preserve provenance and intentionality we greatly restrict the use of MAP_FIXED. You can likely just define ac_cv_func_mmap_fixed_mapped=yes when running configure to skip this test (we probably didn't notice this because the cheribsd_ports system already does this).

The generated test tries something we've deliberately broken to avoid races and confusing runtime behavior. Specifically, the failing part of the code does approximately:

char *data2 = mmap (0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0L);
munmap (data2, pagesize);
assert(data2 == mmap (data2, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0L));

On CheriBSD 22.12 this will attempt to perform a MAP_FIXED mapping using a tagged capability to a location with no existing mapping (despite the comment in the test implying there is one). We reject this because in the general case another thread could trigger an mmap between the munmap and the mmap allocating this address space and then you've got an aliasing violation. On 22.11 one could work around this by changing the second mmap to:

assert(data2 == mmap ((void*)(uintptr_t)(ptraddr_t)data2, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0L));

This strips the provenance from the pointer (it will be untagged and metadata will be cleared) and works because we allow mappings at arbitrary addresses so long as nothing is there as a compatibility measure.

On CheriBSD 23.11 this will fail for a slightly different reason. Because we have enabled heap temporal safety, after the munmap, a quarantined vm entry remains until such a time as a relocation pass picks that one to revoke and invalidates all references. Thus the mapping fails because the code is attempting to make a fixed mapping (implicitly exclusive as above) on top of an existing mapping. Should revocation have happened between munmap and mmap we'd reject the mmap without the cast above because the capability would have metadata, but not tag and we thing it's better to fail consistently in that case rather than sometimes succeeding depending on activity in other threads.

In the end, I think the test is testing something people might care about, but I doubt it affects most mmap consumers or platforms so maybe it shouldn't be in the main test. (It's perhaps worth noting that the test doesn't test what the comments say it does due to the munmap...)

Hopefully that longwinded writeup is somewhat informative.

brooksdavis commented 6 months ago

This will be fixed in autoconf 2.72e (https://lists.gnu.org/r/autoconf/2023-12/msg00026.html). The workaround is to set ac_cv_func_mmap_fixed_mapped=yes in the environment.

ivmai commented 6 months ago

Thank you for the detailed explanation and the fix!

ivmai commented 5 months ago

I confirm autoconf 2.72e solves the issue.