Skip to content

Commit c3c996c

Browse files
committed
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
1 parent b411742 commit c3c996c

File tree

2 files changed

+11
-0
lines changed

2 files changed

+11
-0
lines changed

libselinux/src/init.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ void set_selinuxmnt(const char *mnt)
146146
static void init_lib(void) __attribute__ ((constructor));
147147
static void init_lib(void)
148148
{
149+
SELINUX_PROTECT_ERRNO;
149150
selinux_page_size = sysconf(_SC_PAGE_SIZE);
150151
init_selinuxmnt();
151152
#ifndef ANDROID

libselinux/src/selinux_internal.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <selinux/selinux.h>
55
#include <pthread.h>
6+
#include <errno.h>
67

78

89
extern int require_seusers ;
@@ -131,4 +132,13 @@ void *reallocarray(void *ptr, size_t nmemb, size_t size);
131132
#define IGNORE_DEPRECATED_DECLARATION_END
132133
#endif
133134

135+
static inline void selinux_reset_errno(int *saved_errno) {
136+
if (*saved_errno < 0)
137+
return;
138+
139+
errno = *saved_errno;
140+
}
141+
142+
#define SELINUX_PROTECT_ERRNO __attribute__((__cleanup__(selinux_reset_errno))) \
143+
__attribute__((__unused__)) int __selinux_saved_errno = errno
134144
#endif /* SELINUX_INTERNAL_H_ */

0 commit comments

Comments
 (0)