From c3c996ccebd3753a91b9b6843c1565a3b78ccabf 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 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 --- 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_ */