[PATCH v8 0/8] Add support for memory sealing
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Mon Feb 17 16:56:31 GMT 2025
On 14/02/25 17:19, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> Memory sealing is an opt-in security feature that requires the new GNU
>> property GNU_PROPERTY_MEMORY_SEAL, defined in Linux ABI [3] and
>> supported on binutils 2.44 [4]. A GNU property is preferable over a
>> new dynamic section tag (like the one proposed for DT_GNU_FLAGS_1) so
>> it can be applied to ET_EXEC (for instance on static binaries).
>>
>> The GNU_PROPERTY_MEMORY_SEAL enforcement depends on whether the kernel
>> supports the mseal syscall and how glibc is configured. On the default
>> configuration that aims to support older kernel releases, the memory
>> sealing attribute is taken as a hint. If glibc is configured with a
>> minimum kernel of 6.10, where mseal is implied to be supported,
>> sealing is enforced.
>
> As discussed, I think we need a feature by which the main program (and
> perhaps any initially loaded shared object) can opt out of memory
> sealing for the whole process. Otherwise, we have to build an entire
> separate glibc merely for building a dynamically linked CRIU. At least
> the Fedora build of CRIU uses GNUTLS, and statically linking that is
> really not something we'd like to do with our current distribution build
> system.
>
> I would prefer if we rolled this feature out gradually, and apply
> sealing only if all objects say they are compatible. We don't have to
> fail dlopen when loading an incompatible object, we can just continue
> and expect the application to provide decent diagnostics for any
> mprotect failures.
After some discussion with Andrei to better understand CRIU requirements,
I think changing the memory seal semantic from what I had proposed this
in patchset should make enablement easier.
Instead of always seal any dependency (including LD_PRELOAD and audit
modules) if they contains the GNU_PROPERTY_MEMORY_SEAL attribute, only
seal if the binary also has the attribute.
For the case the binary has the attribute, memory sealing for dependencies
(DT_NEEDED, LD_PRELOAD, audit modules) and dlopen with RTLD_NODELETE will
happen iff the modules also has the GNU_PROPERTY_MEMORY_SEAL attribute.
So for CRIU, it just a matter to be built with -Wl,-z,nomemory-seal (for
the case bfd adds the attribute by default). This design does not fit
the Firefox case, where it wants on FF binary and some dependencies to
not be sealed; but FF loader hack was also intended to be temporary
(specially now that we support DT_RELR).
For dlopen I think we keep this as-is, since it requires both the object
to be built with memory seal and be opened with RTLD_NODELETE.
>
> The sealing range area is separate from that, but I still think it would
> be useful.
>
The OpenBSD added a PT_OPENBSD_MUTABLE program header to instruct loader
(and kernel, since sealing is done by default) for a bss area that should
not be immutable, along with a special section (".openbsd.mutable"). At
least with current approach, it is not really backward compatible (since
old loader will just ignore it), and it only works to ET_DYN.
We can for current approach extend GNU_PROPERTY_MEMORY_SEAL where if it
has a size larger than 0 it represents the range. It will require some work
on static linker, and add special segment to add a segment similar to what
OpenBSD did, and it will have all the subtle complexities of RELRO (like
page alignment, padding, etc.). I think this scheme should be backward
compatible, since GNU_PROPERTY_MEMORY_SEAL is defined to currently had
zero-size.
However, from OpenBSD experience it has only used this *once* in his whole
code-base (on some malloc metadata that is initialized and later made
read-only), which makes me believe that this is a somewhat useful but at
some time with limited read world cases.
More information about the Libc-alpha
mailing list