The branch, master has been updated via 6020d05 Bump version to 1.1.10 via d8e591b tests: Add tests for gethostbyname2_r, IPv4 and IPv6 via 14e90a8 nwrap: Account for ending NULL pointer when checking the buffer length via 0d0c018 nwrap: Forward ERANGE error to caller in gethostbyname[2]_r via 7149d57 nwrap: Filter by family in gethostbyname2_r via 0df9940 tests: Check that gethostbyname_r() zeros return values via ba1d362 nwrap: Check paramters and make sure return values are zeored via 0f30d31 nwrap: Zero the result in case we return with an error via 36c5192 nwrap: Use SAFE_FREE() in nwrap_files_gethostbyname2_r() via a3ff3c2 nwrap: Use calloc() to allocate addr_list vector via 008913f nwrap: Add missing check for gethostbyname2_r() via 5788a92 nwrap: Fix build if system doesn't provide gethostbyname2 from d24aec9 Bump version to 1.1.9
https://git.samba.org/?p=nss_wrapper.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 6020d05c6ab9b885741670ebd6a0f2ebf99052cf Author: Andreas Schneider <a...@samba.org> Date: Thu Mar 19 10:08:16 2020 +0100 Bump version to 1.1.10 The library version is set to 0.3.0 because gethostbyname2_r() is provided now. This wasn't exported due to a missing configure check for it. Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Alexander Bokovoy <a...@samba.org> Reviewed-by: Samuel Cabrero <scabr...@suse.de> commit d8e591be8211c48ffbc034ccd2c22c63c7f2b8fb Author: Samuel Cabrero <scabr...@suse.de> Date: Wed Mar 18 13:19:28 2020 +0100 tests: Add tests for gethostbyname2_r, IPv4 and IPv6 Signed-off-by: Samuel Cabrero <scabr...@suse.de> Reviewed-by: Andreas Schneider <a...@samba.org> Reviewed-by: Alexander Bokovoy <a...@samba.org> commit 14e90a84f6e2566a87e641821802428b355b1b62 Author: Samuel Cabrero <scabr...@suse.de> Date: Wed Mar 18 13:43:23 2020 +0100 nwrap: Account for ending NULL pointer when checking the buffer length The hostent->h_addr_list ends with a NULL pointer, take it into account when checking the provided buffer length. Signed-off-by: Samuel Cabrero <scabr...@suse.de> Reviewed-by: Andreas Schneider <a...@samba.org> Reviewed-by: Alexander Bokovoy <a...@samba.org> commit 0d0c0188616cb0772c4cd2eb1b4da8a39171a3fa Author: Samuel Cabrero <scabr...@suse.de> Date: Wed Mar 18 13:18:49 2020 +0100 nwrap: Forward ERANGE error to caller in gethostbyname[2]_r Signed-off-by: Samuel Cabrero <scabr...@suse.de> Reviewed-by: Andreas Schneider <a...@samba.org> Reviewed-by: Alexander Bokovoy <a...@samba.org> commit 7149d5786903eee72f5e776568b0287dc18c1be8 Author: Samuel Cabrero <scabr...@suse.de> Date: Wed Mar 18 13:18:17 2020 +0100 nwrap: Filter by family in gethostbyname2_r Signed-off-by: Samuel Cabrero <scabr...@suse.de> Reviewed-by: Andreas Schneider <a...@samba.org> Reviewed-by: Alexander Bokovoy <a...@samba.org> commit 0df994033be3e728910355480f3453497507d570 Author: Andreas Schneider <a...@samba.org> Date: Thu Mar 19 09:53:30 2020 +0100 tests: Check that gethostbyname_r() zeros return values Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Alexander Bokovoy <a...@samba.org> Reviewed-by: Samuel Cabrero <scabr...@suse.de> commit ba1d362c0bad254cf5de1015a1d90df5397f1aa6 Author: Andreas Schneider <a...@samba.org> Date: Thu Mar 19 09:16:24 2020 +0100 nwrap: Check paramters and make sure return values are zeored Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Alexander Bokovoy <a...@samba.org> Reviewed-by: Samuel Cabrero <scabr...@suse.de> commit 0f30d319d5200f36d53014c42d1a45468ab4041c Author: Andreas Schneider <a...@samba.org> Date: Thu Mar 19 09:45:09 2020 +0100 nwrap: Zero the result in case we return with an error This fixes a crash bug in OpenLDAP libraries which do not check the return value of gethostbyname_r(). Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Alexander Bokovoy <a...@samba.org> Reviewed-by: Samuel Cabrero <scabr...@suse.de> commit 36c51922f16d8e0c4308b7372799d2f83937b76b Author: Andreas Schneider <a...@samba.org> Date: Thu Mar 19 09:39:16 2020 +0100 nwrap: Use SAFE_FREE() in nwrap_files_gethostbyname2_r() Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Alexander Bokovoy <a...@samba.org> Reviewed-by: Samuel Cabrero <scabr...@suse.de> commit a3ff3c2b430f8c5f8e82539cd54d388e109c0f8b Author: Andreas Schneider <a...@samba.org> Date: Tue Mar 17 20:13:19 2020 +0100 nwrap: Use calloc() to allocate addr_list vector Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Alexander Bokovoy <a...@samba.org> Reviewed-by: Samuel Cabrero <scabr...@suse.de> commit 008913fb8a4968023fd94a8c7aed3d5de75ac2e4 Author: Andreas Schneider <a...@samba.org> Date: Tue Mar 17 18:07:44 2020 +0100 nwrap: Add missing check for gethostbyname2_r() Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Alexander Bokovoy <a...@samba.org> Reviewed-by: Samuel Cabrero <scabr...@suse.de> commit 5788a920629e3114f457809febfd2d1229467f0f Author: Andreas Schneider <a...@samba.org> Date: Mon Mar 16 17:43:20 2020 +0100 nwrap: Fix build if system doesn't provide gethostbyname2 Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Alexander Bokovoy <a...@samba.org> Reviewed-by: Samuel Cabrero <scabr...@suse.de> ----------------------------------------------------------------------- Summary of changes: CHANGELOG | 4 ++ CMakeLists.txt | 6 +- ConfigureChecks.cmake | 1 + config.h.cmake | 3 + src/nss_wrapper.c | 69 ++++++++++++++++++--- tests/test_gethostby_name_addr.c | 127 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 197 insertions(+), 13 deletions(-) Changeset truncated at 500 lines: diff --git a/CHANGELOG b/CHANGELOG index 5e76d70..e649ee8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,10 @@ ChangeLog ========== +version 1.1.10 (released 2020-03-19) + * Fixed crash bug in OpenLDAP libraries with gethostbyname_r() + * Code cleanup in gethostbyname(2)(_r) functions + version 1.1.9 (released 2020-03-16) * Fixed log spam when loading modules diff --git a/CMakeLists.txt b/CMakeLists.txt index c520d16..64e3412 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules") include(DefineCMakeDefaults) include(DefineCompilerFlags) -project(nss_wrapper VERSION 1.1.9 LANGUAGES C) +project(nss_wrapper VERSION 1.1.10 LANGUAGES C) # global needed variables set(APPLICATION_NAME ${PROJECT_NAME}) @@ -24,8 +24,8 @@ set(APPLICATION_NAME ${PROJECT_NAME}) # If the source code was changed, but there were no interface changes: # Increment PATCH. set(LIBRARY_VERSION_MAJOR 0) -set(LIBRARY_VERSION_MINOR 2) -set(LIBRARY_VERSION_PATCH 8) +set(LIBRARY_VERSION_MINOR 3) +set(LIBRARY_VERSION_PATCH 0) set(LIBRARY_VERSION "${LIBRARY_VERSION_MAJOR}.${LIBRARY_VERSION_MINOR}.${LIBRARY_VERSION_PATCH}") set(LIBRARY_SOVERSION ${LIBRARY_VERSION_MAJOR}) diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index 2947a8e..30510d8 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -77,6 +77,7 @@ check_function_exists(gethostbyaddr_r HAVE_GETHOSTBYADDR_R) check_function_exists(gethostbyname_r HAVE_GETHOSTBYNAME_R) check_function_exists(gethostbyname2 HAVE_GETHOSTBYNAME2) +check_function_exists(gethostbyname2_r HAVE_GETHOSTBYNAME2_R) check_function_exists(getprogname HAVE_GETPROGNAME) check_function_exists(getexecname HAVE_GETEXECNAME) diff --git a/config.h.cmake b/config.h.cmake index de0b5df..41b2531 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -59,6 +59,9 @@ /* Define to 1 if you have the `gethostbyname2' function. */ #cmakedefine HAVE_GETHOSTBYNAME2 1 +/* Define to 1 if you have the `gethostbyname2_r' function. */ +#cmakedefine HAVE_GETHOSTBYNAME2_R 1 + #cmakedefine HAVE_GETPROGNAME 1 #cmakedefine HAVE_GETEXECNAME 1 diff --git a/src/nss_wrapper.c b/src/nss_wrapper.c index d6639eb..d90264c 100644 --- a/src/nss_wrapper.c +++ b/src/nss_wrapper.c @@ -351,6 +351,15 @@ struct nwrap_libc_fns { struct hostent *(*_libc_gethostbyname)(const char *name); #ifdef HAVE_GETHOSTBYNAME2 /* GNU extension */ struct hostent *(*_libc_gethostbyname2)(const char *name, int af); +#endif +#ifdef HAVE_GETHOSTBYNAME2_R /* GNU extension */ + int (*_libc_gethostbyname2_r)(const char *name, + int af, + struct hostent *ret, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop); #endif struct hostent *(*_libc_gethostbyaddr)(const void *addr, socklen_t len, int type); @@ -512,8 +521,10 @@ static struct hostent *nwrap_files_gethostbyaddr(struct nwrap_backend *b, socklen_t len, int type); static struct hostent *nwrap_files_gethostbyname(struct nwrap_backend *b, const char *name); +#ifdef HAVE_GETHOSTBYNAME2 static struct hostent *nwrap_files_gethostbyname2(struct nwrap_backend *b, const char *name, int af); +#endif /* HAVE_GETHOSTBYNAME2 */ static int nwrap_files_gethostbyname2_r(struct nwrap_backend *b, const char *name, int af, struct hostent *hedst, @@ -589,7 +600,9 @@ struct nwrap_ops nwrap_files_ops = { .nw_endgrent = nwrap_files_endgrent, .nw_gethostbyaddr = nwrap_files_gethostbyaddr, .nw_gethostbyname = nwrap_files_gethostbyname, +#ifdef HAVE_GETHOSTBYNAME2 .nw_gethostbyname2 = nwrap_files_gethostbyname2, +#endif /* HAVE_GETHOSTBYNAME2 */ .nw_gethostbyname2_r = nwrap_files_gethostbyname2_r, }; @@ -1372,6 +1385,27 @@ static struct hostent *libc_gethostbyname2(const char *name, int af) } #endif +#ifdef HAVE_GETHOSTBYNAME2_R /* GNU extension */ +static int libc_gethostbyname2_r(const char *name, + int af, + struct hostent *ret, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop) +{ + nwrap_load_lib_function(NWRAP_LIBNSL, gethostbyname2_r); + + return nwrap_main_global->libc->fns->_libc_gethostbyname2_r(name, + af, + ret, + buf, + buflen, + result, + h_errnop); +} +#endif + static struct hostent *libc_gethostbyaddr(const void *addr, socklen_t len, int type) @@ -3587,6 +3621,12 @@ static int nwrap_files_internal_gethostbyname(const char *name, int af, bool he_found = false; bool ok; + /* + * We need to make sure we have zeroed return pointer for consumers + * which don't check return values, e.g. OpenLDAP. + */ + ZERO_STRUCTP(result); + ok = nwrap_files_cache_reload(nwrap_he_global.cache); if (!ok) { NWRAP_LOG(NWRAP_LOG_ERROR, "error loading hosts file"); @@ -3677,7 +3717,7 @@ static int nwrap_files_gethostbyname2_r(struct nwrap_backend *b, char *buf, size_t buflen, struct hostent **hedstp) { - struct nwrap_vector *addr_list = malloc(sizeof(struct nwrap_vector)); + struct nwrap_vector *addr_list = NULL; union { char *ptr; char **list; @@ -3687,6 +3727,14 @@ static int nwrap_files_gethostbyname2_r(struct nwrap_backend *b, (void) b; /* unused */ (void) af; /* unused */ + if (name == NULL || hedst == NULL || buf == NULL || buflen == 0) { + errno = EINVAL; + return -1; + } + *hedstp = NULL; + buf[0] = '\0'; + + addr_list = calloc(1, sizeof(struct nwrap_vector)); if (addr_list == NULL) { NWRAP_LOG(NWRAP_LOG_ERROR, "Unable to allocate memory for address list"); @@ -3694,20 +3742,17 @@ static int nwrap_files_gethostbyname2_r(struct nwrap_backend *b, return -1; } - ZERO_STRUCTP(addr_list); - - rc = nwrap_files_internal_gethostbyname(name, AF_UNSPEC, hedst, + rc = nwrap_files_internal_gethostbyname(name, af, hedst, addr_list); if (rc == -1) { - if (addr_list->items != NULL) { - free(addr_list->items); - } + SAFE_FREE(addr_list->items); SAFE_FREE(addr_list); errno = ENOENT; return -1; } - if (buflen < (addr_list->count * sizeof(void *))) { + /* +1 i for ending NULL pointer */ + if (buflen < ((addr_list->count + 1) * sizeof(void *))) { SAFE_FREE(addr_list->items); SAFE_FREE(addr_list); return ERANGE; @@ -3718,8 +3763,8 @@ static int nwrap_files_gethostbyname2_r(struct nwrap_backend *b, * +1 is for ending NULL pointer. */ memcpy(buf, addr_list->items, (addr_list->count + 1) * sizeof(void *)); - free(addr_list->items); - free(addr_list); + SAFE_FREE(addr_list->items); + SAFE_FREE(addr_list); g.ptr = buf; hedst->h_addr_list = g.list; @@ -3742,6 +3787,8 @@ static int nwrap_gethostbyname_r(const char *name, buf, buflen, result); if (rc == 0) { return 0; + } else if (rc == ERANGE) { + return ERANGE; } } *h_errnop = h_errno; @@ -3781,6 +3828,8 @@ static int nwrap_gethostbyname2_r(const char *name, int af, buf, buflen, result); if (rc == 0) { return 0; + } else if (rc == ERANGE) { + return ERANGE; } } *h_errnop = h_errno; diff --git a/tests/test_gethostby_name_addr.c b/tests/test_gethostby_name_addr.c index cb55c06..e8939f6 100644 --- a/tests/test_gethostby_name_addr.c +++ b/tests/test_gethostby_name_addr.c @@ -247,6 +247,128 @@ static void test_nwrap_gethostbyname_r(void **state) assert_string_equal(ip, "127.0.0.11"); } + +static void test_nwrap_gethostbyname_r_null(void **state) +{ + char buf[2]; + struct hostent hb, *he; + int herr = 0; + int rc; + + (void) state; /* unused */ + + buf[0] = 'A'; + buf[1] = '\0'; + + /* Check that the returned buffer is zeroed */ + rc = gethostbyname_r("wurst", + &hb, + buf, sizeof(buf), + &he, + &herr); + assert_int_equal(rc, ENOENT); + assert_null(he); + assert_null(hb.h_name); + assert_null(hb.h_addr_list); + assert_string_equal(buf, ""); +} +#endif + +#ifdef HAVE_GETHOSTBYNAME2_R +static void test_nwrap_gethostbyname2_r_v4(void **state) +{ + char *buf = NULL; + size_t buflen = 2; + char ip[INET_ADDRSTRLEN]; + struct hostent hb, *he; + const char *a; + int herr = 0; + int rc; + + (void) state; /* unused */ + + for (rc = ERANGE, buflen = 2; rc == ERANGE; buflen *= 2) { + if (buf != NULL) { + free(buf); + } + buf = calloc(1, buflen); + assert_non_null(buf); + + rc = gethostbyname2_r("magrathea.galaxy.site", AF_INET, + &hb, + buf, buflen, + &he, + &herr); + } + + assert_int_equal(rc, 0); + assert_int_equal(herr, 0); + assert_non_null(he); + assert_non_null(he->h_name); + assert_non_null(he->h_addr_list); + + assert_string_equal(he->h_name, "magrathea.galaxy.site"); + assert_int_equal(he->h_addrtype, AF_INET); + + assert_non_null(he->h_addr_list[0]); + a = inet_ntop(AF_INET, he->h_addr_list[0], ip, sizeof(ip)); + assert_non_null(a); + assert_string_equal(a, "127.0.0.11"); + + assert_non_null(he->h_addr_list[1]); + a = inet_ntop(AF_INET, he->h_addr_list[1], ip, sizeof(ip)); + assert_non_null(a); + assert_string_equal(a, "127.0.0.12"); + + assert_null(he->h_addr_list[2]); + + free(buf); +} + +static void test_nwrap_gethostbyname2_r_v6(void **state) +{ + char *buf = NULL; + size_t buflen = 2; + char ip[INET6_ADDRSTRLEN]; + struct hostent hb, *he; + const char *a; + int herr = 0; + int rc; + + (void) state; /* unused */ + + for (rc = ERANGE, buflen = 2; rc == ERANGE; buflen *= 2) { + if (buf != NULL) { + free(buf); + } + buf = calloc(1, buflen); + assert_non_null(buf); + + rc = gethostbyname2_r("magrathea.galaxy.site", AF_INET6, + &hb, + buf, buflen, + &he, + &herr); + } + + assert_int_equal(rc, 0); + assert_int_equal(herr, 0); + assert_non_null(he); + assert_non_null(he->h_name); + assert_non_null(he->h_addr_list); + + assert_string_equal(he->h_name, "magrathea.galaxy.site"); + assert_int_equal(he->h_addrtype, AF_INET6); + + assert_non_null(he->h_addr_list[0]); + a = inet_ntop(AF_INET6, he->h_addr_list[0], ip, sizeof(ip)); + assert_non_null(a); + assert_string_equal(a, "::29a"); + + assert_null(he->h_addr_list[1]); + + free(buf); +} #endif #ifdef HAVE_GETHOSTBYADDR_R @@ -293,6 +415,11 @@ int main(void) { cmocka_unit_test(test_nwrap_gethostbyaddr), #ifdef HAVE_GETHOSTBYNAME_R cmocka_unit_test(test_nwrap_gethostbyname_r), + cmocka_unit_test(test_nwrap_gethostbyname_r_null), +#endif +#ifdef HAVE_GETHOSTBYNAME2_R + cmocka_unit_test(test_nwrap_gethostbyname2_r_v4), + cmocka_unit_test(test_nwrap_gethostbyname2_r_v6), #endif #ifdef HAVE_GETHOSTBYADDR_R cmocka_unit_test(test_nwrap_gethostbyaddr_r), -- NSS Wrapper Repository