diff options
author | Sam Morris <sam@robots.org.uk> | 2019-01-09 10:15:53 +0000 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2019-01-10 11:08:42 +0100 |
commit | b26c90411343d74b15deb24bd87077848e316dab (patch) | |
tree | 4379707a38479aae6e472b146692c18ed470dd97 /src/basic/util.h | |
parent | a1b939dfc74f1f6ac8e8ad41912ac322b5e2438c (diff) | |
download | systemd-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.h | 23 |
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();" |