}
static inline void _reset_errno_(int *saved_errno) {
- if (*saved_errno >= 0)
- errno = *saved_errno;
+ 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();"
} else {
hn = gethostname_malloc();
if (!hn) {
- *errnop = DISARM_PROTECT_ERRNO(ENOMEM);
+ *errnop = ENOMEM;
*h_errnop = NO_RECOVERY;
return NSS_STATUS_TRYAGAIN;
}
l = strlen(canonical);
ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * (n_addresses > 0 ? n_addresses : 2);
if (buflen < ms) {
- *errnop = DISARM_PROTECT_ERRNO(ERANGE);
+ *errnop = ERANGE;
*h_errnop = NETDB_INTERNAL;
return NSS_STATUS_TRYAGAIN;
}
uint32_t local_address_ipv4,
struct hostent *result,
char *buffer, size_t buflen,
- int *errnop, int *h_errnop, int* _saved_errno_p,
+ int *errnop, int *h_errnop,
int32_t *ttlp,
char **canonp) {
assert(buffer);
assert(errnop);
assert(h_errnop);
- assert(_saved_errno_p);
alen = FAMILY_ADDRESS_SIZE(af);
(c > 0 ? c+1 : 2) * sizeof(char*);
if (buflen < ms) {
- *errnop = DISARM_PROTECT_ERRNO_INNER(ERANGE);
+ *errnop = ERANGE;
*h_errnop = NETDB_INTERNAL;
return NSS_STATUS_TRYAGAIN;
}
af = AF_INET;
if (!IN_SET(af, AF_INET, AF_INET6)) {
- *errnop = DISARM_PROTECT_ERRNO(EAFNOSUPPORT);
+ *errnop = EAFNOSUPPORT;
*h_errnop = NO_DATA;
return NSS_STATUS_UNAVAIL;
}
} else {
hn = gethostname_malloc();
if (!hn) {
- *errnop = DISARM_PROTECT_ERRNO(ENOMEM);
+ *errnop = ENOMEM;
*h_errnop = NO_RECOVERY;
return NSS_STATUS_TRYAGAIN;
}
local_address_ipv4,
host,
buffer, buflen,
- errnop, h_errnop, &_saved_errno_,
+ errnop, h_errnop,
ttlp,
canonp);
}
assert(h_errnop);
if (!IN_SET(af, AF_INET, AF_INET6)) {
- *errnop = DISARM_PROTECT_ERRNO(EAFNOSUPPORT);
+ *errnop = EAFNOSUPPORT;
*h_errnop = NO_DATA;
return NSS_STATUS_UNAVAIL;
}
if (len != FAMILY_ADDRESS_SIZE(af)) {
- *errnop = DISARM_PROTECT_ERRNO(EINVAL);
+ *errnop = EINVAL;
*h_errnop = NO_RECOVERY;
return NSS_STATUS_UNAVAIL;
}
if (!canonical || additional_from_hostname) {
hn = gethostname_malloc();
if (!hn) {
- *errnop = DISARM_PROTECT_ERRNO(ENOMEM);
+ *errnop = ENOMEM;
*h_errnop = NO_RECOVERY;
return NSS_STATUS_TRYAGAIN;
}
local_address_ipv4,
host,
buffer, buflen,
- errnop, h_errnop, &_saved_errno_,
+ errnop, h_errnop,
ttlp,
NULL);
}
l = strlen(name);
ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c;
if (buflen < ms) {
- *errnop = DISARM_PROTECT_ERRNO(ERANGE);
+ *errnop = ERANGE;
*h_errnop = NETDB_INTERNAL;
return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
fail:
- *errnop = DISARM_PROTECT_ERRNO(r);
+ *errnop = -r;
*h_errnop = NO_DATA;
return NSS_STATUS_UNAVAIL;
}
ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*);
if (buflen < ms) {
- *errnop = DISARM_PROTECT_ERRNO(ERANGE);
+ *errnop = ERANGE;
*h_errnop = NETDB_INTERNAL;
return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
fail:
- *errnop = DISARM_PROTECT_ERRNO(r);
+ *errnop = -r;
*h_errnop = NO_DATA;
return NSS_STATUS_UNAVAIL;
}
l = strlen(name);
if (buflen < l+1) {
- *errnop = DISARM_PROTECT_ERRNO(ERANGE);
+ *errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
fail:
- *errnop = DISARM_PROTECT_ERRNO(r);
+ *errnop = -r;
return NSS_STATUS_UNAVAIL;
}
return NSS_STATUS_NOTFOUND;
if (snprintf(buffer, buflen, "vu-%s-" UID_FMT, machine, (uid_t) mapped) >= (int) buflen) {
- *errnop = DISARM_PROTECT_ERRNO(ERANGE);
+ *errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
fail:
- *errnop = DISARM_PROTECT_ERRNO(r);
+ *errnop = -r;
return NSS_STATUS_UNAVAIL;
}
l = sizeof(char*) + strlen(name) + 1;
if (buflen < l) {
- *errnop = DISARM_PROTECT_ERRNO(ERANGE);
+ *errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
fail:
- *errnop = DISARM_PROTECT_ERRNO(r);
+ *errnop = -r;
return NSS_STATUS_UNAVAIL;
}
return NSS_STATUS_NOTFOUND;
if (buflen < sizeof(char*) + 1) {
- *errnop = DISARM_PROTECT_ERRNO(ERANGE);
+ *errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
memzero(buffer, sizeof(char*));
if (snprintf(buffer + sizeof(char*), buflen - sizeof(char*), "vg-%s-" GID_FMT, machine, (gid_t) mapped) >= (int) buflen) {
- *errnop = DISARM_PROTECT_ERRNO(ERANGE);
+ *errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
fail:
- *errnop = DISARM_PROTECT_ERRNO(r);
+ *errnop = -r;
return NSS_STATUS_UNAVAIL;
}
l = strlen(canonical);
ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c;
if (buflen < ms) {
- *errnop = DISARM_PROTECT_ERRNO(ERANGE);
+ *errnop = ERANGE;
*h_errnop = NETDB_INTERNAL;
return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
fail:
- *errnop = DISARM_PROTECT_ERRNO(r);
+ *errnop = -r;
*h_errnop = NO_RECOVERY;
return ret;
ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*);
if (buflen < ms) {
- *errnop = DISARM_PROTECT_ERRNO(ERANGE);
+ *errnop = ERANGE;
*h_errnop = NETDB_INTERNAL;
return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
fail:
- *errnop = DISARM_PROTECT_ERRNO(r);
+ *errnop = -r;
*h_errnop = NO_RECOVERY;
return ret;
assert(h_errnop);
if (!IN_SET(af, AF_INET, AF_INET6)) {
- *errnop = DISARM_PROTECT_ERRNO(EAFNOSUPPORT);
+ *errnop = EAFNOSUPPORT;
*h_errnop = NO_DATA;
return NSS_STATUS_UNAVAIL;
}
if (len != FAMILY_ADDRESS_SIZE(af)) {
- *errnop = DISARM_PROTECT_ERRNO(EINVAL);
+ *errnop = EINVAL;
*h_errnop = NO_RECOVERY;
return NSS_STATUS_UNAVAIL;
}
c * sizeof(char*); /* pointers to aliases, plus trailing NULL */
if (buflen < ms) {
- *errnop = DISARM_PROTECT_ERRNO(ERANGE);
+ *errnop = ERANGE;
*h_errnop = NETDB_INTERNAL;
return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
fail:
- *errnop = DISARM_PROTECT_ERRNO(r);
+ *errnop = -r;
*h_errnop = NO_RECOVERY;
return ret;
l = strlen(name);
if (buflen < l+1) {
- *errnop = DISARM_PROTECT_ERRNO(ERANGE);
+ *errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
fail:
- *errnop = DISARM_PROTECT_ERRNO(r);
+ *errnop = -r;
return NSS_STATUS_UNAVAIL;
}
l = strlen(translated) + 1;
if (buflen < l) {
- *errnop = DISARM_PROTECT_ERRNO(ERANGE);
+ *errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
fail:
- *errnop = DISARM_PROTECT_ERRNO(r);
+ *errnop = -r;
return NSS_STATUS_UNAVAIL;
}
l = sizeof(char*) + strlen(name) + 1;
if (buflen < l) {
- *errnop = DISARM_PROTECT_ERRNO(ERANGE);
+ *errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
fail:
- *errnop = DISARM_PROTECT_ERRNO(r);
+ *errnop = -r;
return NSS_STATUS_UNAVAIL;
}
l = sizeof(char*) + strlen(translated) + 1;
if (buflen < l) {
- *errnop = DISARM_PROTECT_ERRNO(ERANGE);
+ *errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
fail:
- *errnop = DISARM_PROTECT_ERRNO(r);
+ *errnop = -r;
return NSS_STATUS_UNAVAIL;
}
{
PROTECT_ERRNO;
- errno = 42;
+ errno = -42;
assert_se(unlink_noerrno(name) >= 0);
- assert_se(errno == 42);
+ assert_se(errno == -42);
assert_se(unlink_noerrno(name) < 0);
- assert_se(errno == 42);
+ assert_se(errno == -42);
}
}
assert_se(errno == 12);
}
-static void test_protect_errno_disarmed(void) {
- log_info("/* %s */", __func__);
-
- errno = 12;
- /**
- * Simulate dynamically-linked glibc calling the NSS module with errnop
- * and &errno being the same.
- */
- int *errnop = &errno;
-
- {
- PROTECT_ERRNO;
-
- *errnop = DISARM_PROTECT_ERRNO(25);
- }
-
- assert_se(errno == 25);
- assert_se(*errnop == 25);
-}
-
-static void test_protect_errno_disarmed_inner(void) {
- log_info("/* %s */", __func__);
-
- errno = 12;
- int *errnop = &errno;
-
- {
- PROTECT_ERRNO;
-
- int *_saved_errno_p = &_saved_errno_;
- *errnop = DISARM_PROTECT_ERRNO_INNER(25);
- }
-
- assert_se(errno == 25);
- assert_se(*errnop == 25);
-}
-
-static void test_protect_errno_disarmed_static(void) {
- log_info("/* %s */", __func__);
-
- errno = 12;
- /*
- * "In statically linked programs, the main application and NSS
- * modules do not share the same thread-local variable errno,
- * which is the reason why there is an explicit errnop function
- * argument."
- */
- int errno2 = 15;
- int *errnop = &errno2;
-
- {
- PROTECT_ERRNO;
-
- errno = 13;
- *errnop = DISARM_PROTECT_ERRNO(25);
- assert_se(errno == 12);
-
- errno = 14;
- }
-
- assert_se(errno == 14);
- assert_se(*errnop == 25);
-}
-
static void test_in_set(void) {
log_info("/* %s */", __func__);
test_div_round_up();
test_u64log2();
test_protect_errno();
- test_protect_errno_disarmed();
- test_protect_errno_disarmed_inner();
- test_protect_errno_disarmed_static();
test_in_set();
test_log2i();
test_eqzero();