nsswitch: add test for pthread_key_delete missuse (bug 15464)
authorStefan Metzmacher <metze@samba.org>
Fri, 8 Sep 2023 11:57:26 +0000 (13:57 +0200)
committerStefan Metzmacher <metze@samba.org>
Thu, 14 Sep 2023 17:56:30 +0000 (17:56 +0000)
This is based on https://bugzilla.samba.org/attachment.cgi?id=18081
written by Krzysztof Piotr Oledzki <ole@ans.pl>

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15464

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
nsswitch/b15464-testcase.c [new file with mode: 0644]
nsswitch/wscript_build
selftest/knownfail.d/b15464_testcase [new file with mode: 0644]
source3/selftest/tests.py
testprogs/blackbox/b15464-testcase.sh [new file with mode: 0755]

diff --git a/nsswitch/b15464-testcase.c b/nsswitch/b15464-testcase.c
new file mode 100644 (file)
index 0000000..decb474
--- /dev/null
@@ -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;
+}
index 3247b6c2b7c3206a8123b8fac8988560d3f2e748..4e62bb4c9461f0119c738ba05c83929dc9a1d00c 100644 (file)
@@ -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 (file)
index 0000000..94dd7db
--- /dev/null
@@ -0,0 +1 @@
+^b15464_testcase.run.b15464-testcase
index 9d77c49ed48c27b8454d062bcade72647533ccee..fa51f7fdcbd64fb5c200e4d445aa6078dd9ce12a 100755 (executable)
@@ -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 (executable)
index 0000000..b0c8826
--- /dev/null
@@ -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