From 05b31f387d3a3c3e9b6b5005a76b0fe7527a9fd1 Mon Sep 17 00:00:00 2001 From: Carlos O'Donell Date: Nov 30 2017 06:36:39 +0000 Subject: [PATCH 1/2] nss: Fix invalid enum nss_status return values. The upstream glibc test nss/bug17079 covers several cases where the NSS infrastructure passes invalid pointers to NSS plugins. The plugins should return correct results for the invalid values e.g. ERANGE, but it should do so by setting *errnop to the error and returning NSS_STATUS_TRYAGAIN. This commit fixes the group, netgroup, passwd and service handling code to correctly return ERANGE in *errnop and NSS_TATUS_TRYAGAIN in the case of invalid buffer (NULL) or zero sized buffer length. This fixes the nss/bug17079 regression test when run in a test configuration with sss enabled for any of the above mentioned services. Upstream glibc bug: Bug 22530 - FAIL: nss/bug17079 due to _nss_sss_getpwuid_r https://sourceware.org/bugzilla/show_bug.cgi?id=22530 Signed-off-by: Carlos O'Donell --- diff --git a/src/sss_client/nss_group.c b/src/sss_client/nss_group.c index 42fba62..c5073dd 100644 --- a/src/sss_client/nss_group.c +++ b/src/sss_client/nss_group.c @@ -522,7 +522,10 @@ enum nss_status _nss_sss_getgrgid_r(gid_t gid, struct group *result, int ret; /* Caught once glibc passing in buffer == 0x0 */ - if (!buffer || !buflen) return ERANGE; + if (!buffer || !buflen) { + *errnop = ERANGE; + return NSS_STATUS_SUCCESS; + } ret = sss_nss_mc_getgrgid(gid, result, buffer, buflen); switch (ret) { @@ -655,7 +658,10 @@ static enum nss_status internal_getgrent_r(struct group *result, int ret; /* Caught once glibc passing in buffer == 0x0 */ - if (!buffer || !buflen) return ERANGE; + if (!buffer || !buflen) { + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } /* if there are leftovers return the next one */ if (sss_nss_getgrent_data.data != NULL && diff --git a/src/sss_client/nss_netgroup.c b/src/sss_client/nss_netgroup.c index 8594fc4..3a1834a 100644 --- a/src/sss_client/nss_netgroup.c +++ b/src/sss_client/nss_netgroup.c @@ -231,7 +231,10 @@ static enum nss_status internal_getnetgrent_r(struct __netgrent *result, int ret; /* Caught once glibc passing in buffer == 0x0 */ - if (!buffer || !buflen) return ERANGE; + if (!buffer || !buflen) { + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } /* If we're already processing result data, continue to * return it. diff --git a/src/sss_client/nss_passwd.c b/src/sss_client/nss_passwd.c index 61e2a56..5b1c2ce 100644 --- a/src/sss_client/nss_passwd.c +++ b/src/sss_client/nss_passwd.c @@ -251,7 +251,10 @@ enum nss_status _nss_sss_getpwuid_r(uid_t uid, struct passwd *result, int ret; /* Caught once glibc passing in buffer == 0x0 */ - if (!buffer || !buflen) return ERANGE; + if (!buffer || !buflen) { + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } ret = sss_nss_mc_getpwuid(uid, result, buffer, buflen); switch (ret) { @@ -376,7 +379,10 @@ static enum nss_status internal_getpwent_r(struct passwd *result, int ret; /* Caught once glibc passing in buffer == 0x0 */ - if (!buffer || !buflen) return ERANGE; + if (!buffer || !buflen) { + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } /* if there are leftovers return the next one */ if (sss_nss_getpwent_data.data != NULL && diff --git a/src/sss_client/nss_services.c b/src/sss_client/nss_services.c index 64e0b43..161dad9 100644 --- a/src/sss_client/nss_services.c +++ b/src/sss_client/nss_services.c @@ -177,7 +177,10 @@ _nss_sss_getservbyname_r(const char *name, int ret; /* Caught once glibc passing in buffer == 0x0 */ - if (!buffer || !buflen) return ERANGE; + if (!buffer || !buflen) { + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } ret = sss_strnlen(name, SSS_NAME_MAX, &name_len); if (ret != 0) { @@ -278,7 +281,10 @@ _nss_sss_getservbyport_r(int port, const char *protocol, int ret; /* Caught once glibc passing in buffer == 0x0 */ - if (!buffer || !buflen) return ERANGE; + if (!buffer || !buflen) { + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } if (protocol) { ret = sss_strnlen(protocol, SSS_NAME_MAX, &proto_len); @@ -411,7 +417,10 @@ static enum nss_status internal_getservent_r(struct servent *result, int ret; /* Caught once glibc passing in buffer == 0x0 */ - if (!buffer || !buflen) return ERANGE; + if (!buffer || !buflen) { + *errnop = ERANGE; + return NSS_STATUS_TRYAGAIN; + } /* if there are leftovers return the next one */ if (sss_nss_getservent_data.data != NULL && From 85b53657642145b674fe83b20089ca5b51432d8f Mon Sep 17 00:00:00 2001 From: Carlos O'Donell Date: Nov 30 2017 18:07:42 +0000 Subject: [PATCH 2/2] nss: Fix invalid enum nss_status return values. Use NSS_STATUS_TRYAGAIN in _nss_sss_getgrgid_r when passed an invalid buffer or buffer size. Signed-off-by: Carlos O'Donell --- diff --git a/src/sss_client/nss_group.c b/src/sss_client/nss_group.c index c5073dd..054f30e 100644 --- a/src/sss_client/nss_group.c +++ b/src/sss_client/nss_group.c @@ -524,7 +524,7 @@ enum nss_status _nss_sss_getgrgid_r(gid_t gid, struct group *result, /* Caught once glibc passing in buffer == 0x0 */ if (!buffer || !buflen) { *errnop = ERANGE; - return NSS_STATUS_SUCCESS; + return NSS_STATUS_TRYAGAIN; } ret = sss_nss_mc_getgrgid(gid, result, buffer, buflen);