diff --git a/nsswitch/b15464-testcase.c b/nsswitch/b15464-testcase.c new file mode 100644 index 00000000000..decb474a81e --- /dev/null +++ b/nsswitch/b15464-testcase.c @@ -0,0 +1,77 @@ +#include "replace.h" +#include "system/wait.h" +#include "system/threads.h" +#include <assert.h> + +int main(int argc, const char *argv[]) +{ + pid_t pid; + int wstatus; + pthread_key_t k1; + pthread_key_t k2; + pthread_key_t k3; + char *val = NULL; + const char *nss_winbind = (argc >= 2 ? argv[1] : "bin/plugins/libnss_winbind.so.2"); + void *nss_winbind_handle = NULL; + union { + int (*fn)(void); + void *symbol; + } nss_winbind_endpwent = { .symbol = NULL, }; + + /* + * load and invoke something simple like + * _nss_winbind_endpwent in order to + * get the libnss_winbind internal going + */ + nss_winbind_handle = dlopen(nss_winbind, RTLD_NOW); + printf("%d: nss_winbind[%s] nss_winbind_handle[%p]\n", + getpid(), nss_winbind, nss_winbind_handle); + assert(nss_winbind_handle != NULL); + + nss_winbind_endpwent.symbol = dlsym(nss_winbind_handle, + "_nss_winbind_endpwent"); + printf("%d: nss_winbind_handle[%p] _nss_winbind_endpwent[%p]\n", + getpid(), nss_winbind_handle, nss_winbind_endpwent.symbol); + assert(nss_winbind_endpwent.symbol != NULL); + (void)nss_winbind_endpwent.fn(); + + val = malloc(1); + assert(val != NULL); + + pthread_key_create(&k1, NULL); + pthread_setspecific(k1, val); + printf("%d: k1=%d\n", getpid(), k1); + + pid = fork(); + if (pid) { + free(val); + wait(&wstatus); + return WEXITSTATUS(wstatus); + } + + pthread_key_create(&k2, NULL); + pthread_setspecific(k2, val); + + printf("%d: Hello after fork, k1=%d, k2=%d\n", getpid(), k1, k2); + + pid = fork(); + + if (pid) { + free(val); + wait(&wstatus); + return WEXITSTATUS(wstatus); + } + + pthread_key_create(&k3, NULL); + pthread_setspecific(k3, val); + + printf("%d: Hello after fork2, k1=%d, k2=%d, k3=%d\n", getpid(), k1, k2, k3); + + if (k1 == k2 || k2 == k3) { + printf("%d: FAIL inconsistent keys\n", getpid()); + return 1; + } + + printf("%d: OK consistent keys\n", getpid()); + return 0; +} diff --git a/nsswitch/wscript_build b/nsswitch/wscript_build index 3247b6c2b7c..4e62bb4c946 100644 --- a/nsswitch/wscript_build +++ b/nsswitch/wscript_build @@ -15,6 +15,11 @@ if bld.CONFIG_SET('HAVE_PTHREAD'): deps='wbclient pthread', for_selftest=True ) + bld.SAMBA_BINARY('b15464-testcase', + source='b15464-testcase.c', + deps='replace pthread dl', + for_selftest=True + ) # The nss_wrapper code relies strictly on the linux implementation and # name, so compile but do not install a copy under this name. diff --git a/selftest/knownfail.d/b15464_testcase b/selftest/knownfail.d/b15464_testcase new file mode 100644 index 00000000000..94dd7db7c2a --- /dev/null +++ b/selftest/knownfail.d/b15464_testcase @@ -0,0 +1 @@ +^b15464_testcase.run.b15464-testcase diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 9d77c49ed48..fa51f7fdcbd 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -67,6 +67,8 @@ except KeyError: samba4bindir = bindir() config_h = os.path.join(samba4bindir, "default/include/config.h") +bbdir = os.path.join(srcdir(), "testprogs/blackbox") + # check available features config_hash = dict() f = open(config_h, 'r') @@ -958,6 +960,10 @@ if with_pthreadpool: [os.path.join(samba3srcdir, "script/tests/test_libwbclient_threads.sh"), "$DOMAIN", "$DC_USERNAME"]) + plantestsuite("b15464_testcase", "none", + [os.path.join(bbdir, "b15464-testcase.sh"), + binpath("b15464-testcase"), + binpath("plugins/libnss_winbind.so.2")]) plantestsuite("samba3.test_nfs4_acl", "none", [os.path.join(bindir(), "test_nfs4_acls"), diff --git a/testprogs/blackbox/b15464-testcase.sh b/testprogs/blackbox/b15464-testcase.sh new file mode 100755 index 00000000000..b0c88260d4c --- /dev/null +++ b/testprogs/blackbox/b15464-testcase.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# Blackbox wrapper for bug 15464 +# Copyright (C) 2023 Stefan Metzmacher + +if [ $# -lt 2 ]; then + cat <<EOF +Usage: b15464-testcase.sh B15464_TESTCASE LIBNSS_WINBIND +EOF + exit 1 +fi + +b15464_testcase=$1 +libnss_winbind=$2 +shift 2 +failed=0 + +. $(dirname $0)/subunit.sh + +testit "run b15464-testcase" $VALGRIND $b15464_testcase $libnss_winbind || failed=$(expr $failed + 1) + +testok $0 $failed