From aac4dbb17f3e19a2fbeefb38b3319827d3bf820e Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Wed, 13 May 2020 13:13:43 +0200 Subject: [PATCH] NSS client: preserve errno during _nss_sss_end* calls glibc does not expect that errno is changed by some of the calls provided by nss modules. This caused at least issues when _nss_sss_endpwent() is called in compat mode. According to https://pubs.opengroup.org/onlinepubs/9699919799/functions/endpwent.html endpwent() should only set errno in the case of an error. Since there is no other way to report an error we will set errno in the case of an error but preserve it otherwise. This should cause no issues because glibc is taking precautions as well tracked by https://sourceware.org/bugzilla/show_bug.cgi?id=25976. To be on the safe side the other _nss_sss_end* calls will show the same behavior. Resolves: https://github.com/SSSD/sssd/issues/5153 Reviewed-by: Alexey Tikhonov --- src/sss_client/nss_group.c | 3 +++ src/sss_client/nss_hosts.c | 4 +++- src/sss_client/nss_ipnetworks.c | 4 +++- src/sss_client/nss_netgroup.c | 3 +++ src/sss_client/nss_passwd.c | 3 +++ src/sss_client/nss_services.c | 3 +++ 6 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/sss_client/nss_group.c b/src/sss_client/nss_group.c index 5ab2bdf78..4a201bf09 100644 --- a/src/sss_client/nss_group.c +++ b/src/sss_client/nss_group.c @@ -735,6 +735,7 @@ enum nss_status _nss_sss_endgrent(void) { enum nss_status nret; int errnop; + int saved_errno = errno; sss_nss_lock(); @@ -745,6 +746,8 @@ enum nss_status _nss_sss_endgrent(void) NULL, NULL, NULL, &errnop); if (nret != NSS_STATUS_SUCCESS) { errno = errnop; + } else { + errno = saved_errno; } sss_nss_unlock(); diff --git a/src/sss_client/nss_hosts.c b/src/sss_client/nss_hosts.c index 5e279468b..aa2676286 100644 --- a/src/sss_client/nss_hosts.c +++ b/src/sss_client/nss_hosts.c @@ -565,6 +565,7 @@ _nss_sss_endhostent(void) { enum nss_status nret; int errnop; + int saved_errno = errno; sss_nss_lock(); @@ -575,9 +576,10 @@ _nss_sss_endhostent(void) NULL, NULL, NULL, &errnop); if (nret != NSS_STATUS_SUCCESS) { errno = errnop; + } else { + errno = saved_errno; } sss_nss_unlock(); - return nret; } diff --git a/src/sss_client/nss_ipnetworks.c b/src/sss_client/nss_ipnetworks.c index 15fee6039..08070499d 100644 --- a/src/sss_client/nss_ipnetworks.c +++ b/src/sss_client/nss_ipnetworks.c @@ -510,6 +510,7 @@ _nss_sss_endnetent(void) { enum nss_status nret; int errnop; + int saved_errno = errno; sss_nss_lock(); @@ -520,10 +521,11 @@ _nss_sss_endnetent(void) NULL, NULL, NULL, &errnop); if (nret != NSS_STATUS_SUCCESS) { errno = errnop; + } else { + errno = saved_errno; } sss_nss_unlock(); - return nret; } diff --git a/src/sss_client/nss_netgroup.c b/src/sss_client/nss_netgroup.c index 3a1834a31..2fc88f8ae 100644 --- a/src/sss_client/nss_netgroup.c +++ b/src/sss_client/nss_netgroup.c @@ -309,6 +309,7 @@ enum nss_status _nss_sss_endnetgrent(struct __netgrent *result) { enum nss_status nret; int errnop; + int saved_errno = errno; sss_nss_lock(); @@ -319,6 +320,8 @@ enum nss_status _nss_sss_endnetgrent(struct __netgrent *result) NULL, NULL, NULL, &errnop); if (nret != NSS_STATUS_SUCCESS) { errno = errnop; + } else { + errno = saved_errno; } sss_nss_unlock(); diff --git a/src/sss_client/nss_passwd.c b/src/sss_client/nss_passwd.c index 96368bd6e..c386dd370 100644 --- a/src/sss_client/nss_passwd.c +++ b/src/sss_client/nss_passwd.c @@ -455,6 +455,7 @@ enum nss_status _nss_sss_endpwent(void) { enum nss_status nret; int errnop; + int saved_errno = errno; sss_nss_lock(); @@ -465,6 +466,8 @@ enum nss_status _nss_sss_endpwent(void) NULL, NULL, NULL, &errnop); if (nret != NSS_STATUS_SUCCESS) { errno = errnop; + } else { + errno = saved_errno; } sss_nss_unlock(); diff --git a/src/sss_client/nss_services.c b/src/sss_client/nss_services.c index 13cb4c3ab..f8c2092cb 100644 --- a/src/sss_client/nss_services.c +++ b/src/sss_client/nss_services.c @@ -484,6 +484,7 @@ _nss_sss_endservent(void) { enum nss_status nret; int errnop; + int saved_errno = errno; sss_nss_lock(); @@ -494,6 +495,8 @@ _nss_sss_endservent(void) NULL, NULL, NULL, &errnop); if (nret != NSS_STATUS_SUCCESS) { errno = errnop; + } else { + errno = saved_errno; } sss_nss_unlock(); -- 2.21.3