summaryrefslogtreecommitdiff
path: root/src/basic/util.h
diff options
context:
space:
mode:
authorSam Morris <sam@robots.org.uk>2019-01-09 10:15:53 +0000
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2019-01-10 11:08:42 +0100
commitb26c90411343d74b15deb24bd87077848e316dab (patch)
tree4379707a38479aae6e472b146692c18ed470dd97 /src/basic/util.h
parenta1b939dfc74f1f6ac8e8ad41912ac322b5e2438c (diff)
downloadsystemd-b26c90411343d74b15deb24bd87077848e316dab.tar.gz
nss: prevent PROTECT_ERRNO from squashing changes to *errnop
glibc passes in &errno for errnop, which means PROTECT_ERRNO ends up squashing our intentional changes to *errnop. Fixes #11321.
Diffstat (limited to 'src/basic/util.h')
-rw-r--r--src/basic/util.h23
1 files changed, 22 insertions, 1 deletions
diff --git a/src/basic/util.h b/src/basic/util.h
index f009d37d4c..77ef1d9892 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -174,12 +174,33 @@ static inline void *mempset(void *s, int c, size_t n) {
}
static inline void _reset_errno_(int *saved_errno) {
- errno = *saved_errno;
+ if (*saved_errno >= 0)
+ errno = *saved_errno;
}
#define PROTECT_ERRNO \
_cleanup_(_reset_errno_) _unused_ int _saved_errno_ = errno
+/*
+ * NSS modules should indicate errors by assigning to the passed-in *errnop
+ * rather than errno directly; however in dynamically-linked programs, errnop
+ * == &errno, so PROTECT_ERRNO has to be disabled in order for assigning to
+ * *errnop to be effective.
+ */
+#define DISARM_PROTECT_ERRNO(r) \
+ ({ \
+ _reset_errno_(&_saved_errno_); \
+ _saved_errno_ = -1; \
+ abs(r); \
+ })
+
+#define DISARM_PROTECT_ERRNO_INNER(r) \
+ ({ \
+ _reset_errno_(_saved_errno_p); \
+ *_saved_errno_p = -1; \
+ abs(r); \
+ })
+
static inline int negative_errno(void) {
/* This helper should be used to shut up gcc if you know 'errno' is
* negative. Instead of "return -errno;", use "return negative_errno();"