From 1fd585e90088a214054bd0d0ef25244eaca328e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristian=20Rodr=C3=ADguez?= Date: Sat, 28 Sep 2024 14:34:39 -0300 Subject: [PATCH] libselinux: Do not clobber errno of the world MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit libselinux clobbers errno of all consumers (systemd, sshd you name it) because its constructors do not properly save and restore errno. The following program demonstrates it. int main(void) { assert(errno == 0); /* Just a test, it doesn't matter already clobbered */ if(is_selinux_enabled() < 0) { perror("not enabled"); return 1; } } if any function sets errno, it is not switched back to the original value and standards DO NOT require errno to the set to zero before entering main Signed-off-by: Cristian Rodríguez --- libselinux/src/init.c | 1 + libselinux/src/selinux_internal.h | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/libselinux/src/init.c b/libselinux/src/init.c index 542c979b9d..2df515f51f 100644 --- a/libselinux/src/init.c +++ b/libselinux/src/init.c @@ -146,6 +146,7 @@ void set_selinuxmnt(const char *mnt) static void init_lib(void) __attribute__ ((constructor)); static void init_lib(void) { + SELINUX_PROTECT_ERRNO; selinux_page_size = sysconf(_SC_PAGE_SIZE); init_selinuxmnt(); #ifndef ANDROID diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h index 450a42c2dc..e7ade0c3b2 100644 --- a/libselinux/src/selinux_internal.h +++ b/libselinux/src/selinux_internal.h @@ -3,6 +3,7 @@ #include #include +#include extern int require_seusers ; @@ -131,4 +132,13 @@ void *reallocarray(void *ptr, size_t nmemb, size_t size); #define IGNORE_DEPRECATED_DECLARATION_END #endif +static inline void selinux_reset_errno(int *saved_errno) { + if (*saved_errno < 0) + return; + + errno = *saved_errno; +} + +#define SELINUX_PROTECT_ERRNO __attribute__((__cleanup__(selinux_reset_errno))) \ + __attribute__((__unused__)) int __selinux_saved_errno = errno #endif /* SELINUX_INTERNAL_H_ */