From f1c89d50e140d92214eab3dfeb58570784d62fa8 Mon Sep 17 00:00:00 2001 From: Avril Date: Mon, 15 Apr 2024 16:50:57 +0100 Subject: [PATCH] Added IFUNC resolver for `memfd_secret()`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fortune for memfd_secret-shim's current commit: Curse − 凶 --- src/ifunc.h | 18 ++++++++++++++++-- src/memfd_secret.c | 19 +++++++++++++++---- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/ifunc.h b/src/ifunc.h index 732671a..4a2e379 100644 --- a/src/ifunc.h +++ b/src/ifunc.h @@ -2,10 +2,24 @@ #define _IT_IFUNC_H //! ifunc helpers +#if !IFUNC_PREFIX +#define IFUNC_PREFIX _ifun__ +#endif + +#define _IFUNC_STR_(X) #X +#define _IFUNC_STR(X) _IFUNC_STR_(X) + +#define _IFUNC_PREFIX_S _IFUNC_STR(IFUNC_PREFIX) + +#define _IFUNC_PASTE_(X,Y) X##Y +#define _IFUNC_PASTE(X,Y) _IFUNC_PASTE_(X,Y) + +#define _IFUNC_PREFIX(X) _IFUNC_PASTE(IFUNC_PREFIX, X) + #define IFUNC_NAME(name, ver) _impl__ ## name ## __ ## ver #define IFUNC_IMPL(name, ver) __attribute__((copy(name))) IFUNC_NAME(name, ver) -#define IFUNC_RESOLVER_A(attr, name) __attribute__((returns_nonnull)) (* __attribute__(attr) _ifun__ ## name (void)) // When the ifunc resolver wants to return a function pointer that has attributes on it, the attribute inner list (e.g. `(returns_nonnull, const, nonnull)') can be provided as the first argument +#define IFUNC_RESOLVER_A(attr, name) __attribute__((returns_nonnull)) (* __attribute__(attr) _IFUNC_PREFIX(name) /*_ifun__ ## name*/ (void)) // When the ifunc resolver wants to return a function pointer that has attributes on it, the attribute inner list (e.g. `(returns_nonnull, const, nonnull)') can be provided as the first argument #define IFUNC_RESOLVER(name) IFUNC_RESOLVER_A((copy(name)), name) -#define IFUNC_DEF(name, params) name params __attribute__((__ifunc__("_ifun__" #name))) +#define IFUNC_DEF(name, params) name params __attribute__((__ifunc__(_IFUNC_PREFIX_S #name))) #endif /* _IT_IFUNC_H */ diff --git a/src/memfd_secret.c b/src/memfd_secret.c index 520759d..3c5320a 100644 --- a/src/memfd_secret.c +++ b/src/memfd_secret.c @@ -25,7 +25,8 @@ __attribute__((gnu_inline)) static inline int _has_memfd_secret_raw() { - int fd = _memfd_secret(FD_CLOEXEC); + // Attempt syscall + int fd = _memfd_secret_raw(FD_CLOEXEC); // If failure to create new fd was caused by `ENOSYS`, it is not available. if(fd < 0 && errno == ENOSYS) @@ -52,9 +53,12 @@ int _has_memfd_secret() { return ok; } +int IFUNC_DEF(memfd_secret, (unsigned int)); + /// Set as IFUNC target for systems with `memfd_secret()` support enabled. -__attribute__((visibility("hidden"))) //XXX: `hidden` is the "can only be accessed outside .so from returned internal function pointer", right? and `internal` is "can *never* be accessed outside of .so"? (TODO: Check. Idk if this is the other way around.) -int memfd_secret_$enabled(unsigned int flags) +__attribute__((visibility("hidden"))) +int IFUNC_IMPL(memfd_secret, $enabled) (unsigned int flags) + { return _memfd_secret_raw(flags); } @@ -63,7 +67,7 @@ int memfd_secret_$enabled(unsigned int flags) /// /// The call is forwarded to `memfd_create()` instead. __attribute__((visibility("hidden"))) -int memfd_secret_$disabled(unsigned int flags) +int IFUNC_IMPL(memfd_secret, $disabled) (unsigned int flags) { if( FD_CLOEXEC != MEMFD_CLOEXEC ) { // NOTE: This is a constant expression, and this code will be removed if they are equal. //TODO: Translate mask `flags`, from `FD_CLOEXEC` (if it is set) -> `MEMFD_CLOEXEC`. @@ -71,5 +75,12 @@ int memfd_secret_$disabled(unsigned int flags) return memfd_create("memfd_secret@?", flags); } +int IFUNC_RESOLVER(memfd_secret) (unsigned int flags) +{ + return _has_memfd_secret() + ? &IFUNC_NAME(memfd_secret, $enabled) + : &IFUNC_NAME(memfd_secret, $disabled); +} + //TODO: IFUNC resolver for `memfd_secret()` (Above two targets^^) //TODO: Use `ifunc.h`'s macros for defining the ifunc instead of manually, it de-clutters shit and removed repetition.