Download raw body.
lang/polyml: fix (stupid because needless) W^X violation
On Tue, 15 Jul 2025, Matthias Kilian wrote:
> Hi,
>
> on my build machine, i've kern.wxabort=1 in /etc/sysctl.conf. Since
> the import of polyml, the build always failed for me:
I'm not sure how to move forward, but is the ports system expected to work
with this being set?
If I understand correctly it would prevent run-time testing of the
enforcement of W^X policy which is what Poly/ML is trying to do.
See the comment in osmem.h (in particular the last sentence):
// Various Unix systems have restrictions on pages having both write and
// execute permissions. To get round this we either have to use the MAP_JIT
// flag on Mac OS or map a dummy file as two separate areas in SELInux and
// OpenBSD. We can only test this at run-time.
>
> dmesg(8) says why:
> polyimport(65144): mmap W^X violation
>
> A backtrace points to OSMem::Initialise():
...snip...
>
> I don't even want to know why they do all those mmap(2) checks at
> runtime (see the code touched by the diff).
They first test for W^X enforcement. If you read further down in the code
they explicitly mention that they check for ENOTSUP which is what OpenBSD
says it returns if the requested access is not allowed (as per mmap(2) ).
However with kern.wxabort you've forced the run-time check to abort
instead.
Then, if the code is running on MacOS it tries to add MAP_JIT to allow for
the PolyML JIT style code to work their, as per MacOS mmap(2) docs. And
finally if we've detected at runtime that neither works then the code uses
a backup method which sacrifices speed for safety as is required on
platforms that have implemented and enforce W^X policy.
>
> However, I've verified that the diff below fixes the problem for
> us... Uglyness intentional, because ML is a torture ;-)
>
> ok (with a revision bump)?
I don't think this patch is the way I'd go.
Maybe better to just have a small #ifdef at the start of the function that
does something like this (untested though):
#ifdef __OpenBSD__
// hard-code to avoid runtime testing of W^X which would trigger
// aborts if kern.wxabort=1
wxFix = WXFixDualArea;
return true;
#endif
But then this goes back to my question about what should be the policy for
doing runtime checks of W^X in the ports system?
Should ports not even try to do a runtime check in the first place?
>
> Ciao,
> Kili
>
> Index: patches/patch-libpolyml_osmemunix_cpp
> ===================================================================
> RCS file: patches/patch-libpolyml_osmemunix_cpp
> diff -N patches/patch-libpolyml_osmemunix_cpp
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-libpolyml_osmemunix_cpp 15 Jul 2025 20:11:40 -0000
> @@ -0,0 +1,26 @@
> +Index: libpolyml/osmemunix.cpp
> +--- libpolyml/osmemunix.cpp.orig
> ++++ libpolyml/osmemunix.cpp
> +@@ -163,8 +163,10 @@ bool OSMem::Initialise(enum _MemUsage usage)
> + wxFix = WXFixNone;
> + else
> + {
> ++ void* test;
> ++#ifndef __OpenBSD__
> + // Can we allocate memory with write+execute?
> +- void* test = mmap(0, pageSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
> ++ test = mmap(0, pageSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
> + if (test != MAP_FAILED)
> + wxFix = WXFixNone;
> + #ifdef MAP_JIT
> +@@ -179,6 +181,10 @@ bool OSMem::Initialise(enum _MemUsage usage)
> + {
> + if (errno != ENOTSUP && errno != EACCES) // Fails with ENOTSUPP on OpenBSD and EACCES in SELinux.
> + return false;
> ++#else
> ++ if (1)
> ++ {
> ++#endif
> + // Check that read-write works.
> + test = mmap(0, pageSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
> + if (test == MAP_FAILED)
>
>
>
lang/polyml: fix (stupid because needless) W^X violation