The branch, master has been updated
       via  40bd0a9 nsswitch: Run nsswitch thread test
       via  b5ea794 nsswitch: add test for parallel NSS & libwbclient calls
       via  988182c nsswitch: protect access to wb_global_ctx by a mutex
       via  e82b3ac nsswitch: make wb_global_ctx private add add get/put 
functions to access global context
       via  2cfb58d nsswitch: use goto to have only one function return
       via  8d14714 s3: winbind: Remove fstring from wb_acct_info struct
      from  1b2de44 vfs_fruit: let fruit_open_meta() with O_CREAT return a 
fake-fd

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 40bd0a930b2990a6c4e10a5e0db27608cff198c8
Author: Volker Lendecke <v...@samba.org>
Date:   Fri Oct 5 16:27:48 2018 +0200

    nsswitch: Run nsswitch thread test
    
    Signed-off-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>
    
    Autobuild-User(master): Jeremy Allison <j...@samba.org>
    Autobuild-Date(master): Thu Nov  1 05:06:23 CET 2018 on sn-devel-144

commit b5ea7946f844ff6b9337fea57fd002b716595703
Author: Ralph Wuerthner <ralph.wuerth...@de.ibm.com>
Date:   Fri Oct 5 13:53:30 2018 +0200

    nsswitch: add test for parallel NSS & libwbclient calls
    
    Signed-off-by: Ralph Wuerthner <ralph.wuerth...@de.ibm.com>
    Reviewed-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>

commit 988182c3b8dab6511c75622e3484c9ef71e6d0db
Author: Ralph Wuerthner <ralph.wuerth...@de.ibm.com>
Date:   Tue Oct 2 13:41:00 2018 +0200

    nsswitch: protect access to wb_global_ctx by a mutex
    
    This change will make libwbclient thread safe for all API calls not using a
    context. Especially there are no more conflicts with threads using nsswitch
    and libwbclient in parallel.
    
    Signed-off-by: Ralph Wuerthner <ralph.wuerth...@de.ibm.com>
    Reviewed-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>

commit e82b3ac0ae5b50993db3c85d77dd317f957beb7e
Author: Ralph Wuerthner <ralph.wuerth...@de.ibm.com>
Date:   Tue Oct 2 13:35:16 2018 +0200

    nsswitch: make wb_global_ctx private add add get/put functions to access 
global context
    
    Signed-off-by: Ralph Wuerthner <ralph.wuerth...@de.ibm.com>
    Reviewed-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>

commit 2cfb58d7535e63c5ef9f3970ebaa189741b715cb
Author: Ralph Wuerthner <ralph.wuerth...@de.ibm.com>
Date:   Tue Oct 2 10:58:12 2018 +0200

    nsswitch: use goto to have only one function return
    
    Signed-off-by: Ralph Wuerthner <ralph.wuerth...@de.ibm.com>
    Reviewed-by: Volker Lendecke <v...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>

commit 8d14714cc5e4c2b439e973faf602afb2fc1e7488
Author: Samuel Cabrero <scabr...@suse.de>
Date:   Tue Oct 30 18:47:16 2018 +0100

    s3: winbind: Remove fstring from wb_acct_info struct
    
    The group enumeration backend functions try to allocate an array of
    wb_acct_info structs with a number of elements equal to the number of
    groups. In domains with a large number of groups this allocation may
    fail due to the size of the chunk.
    
    Found while trying to enumerate the groups in a domain with more than
    700k groups.
    
    Signed-off-by: Samuel Cabrero <scabr...@suse.de>
    Reviewed-by: Jeremy Allison <j...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

-----------------------------------------------------------------------

Summary of changes:
 nsswitch/stress-nss-libwbclient.c                | 156 +++++++++++++++++++++++
 nsswitch/wb_common.c                             |  66 ++++++++--
 nsswitch/wscript_build                           |   7 +
 source3/script/tests/test_libwbclient_threads.sh |  17 +++
 source3/selftest/tests.py                        |   7 +
 source3/winbindd/winbindd.h                      |   4 +-
 source3/winbindd/winbindd_ads.c                  |   8 +-
 source3/winbindd/winbindd_cache.c                |   8 +-
 source3/winbindd/winbindd_rpc.c                  |  16 ++-
 9 files changed, 263 insertions(+), 26 deletions(-)
 create mode 100644 nsswitch/stress-nss-libwbclient.c
 create mode 100755 source3/script/tests/test_libwbclient_threads.sh


Changeset truncated at 500 lines:

diff --git a/nsswitch/stress-nss-libwbclient.c 
b/nsswitch/stress-nss-libwbclient.c
new file mode 100644
index 0000000..cf85ff3
--- /dev/null
+++ b/nsswitch/stress-nss-libwbclient.c
@@ -0,0 +1,156 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Stress test for parallel NSS & libwbclient calls.
+
+   Copyright (C) Ralph Wuerthner 2018
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <pthread.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <wbclient.h>
+
+#define RUNTIME 10
+
+struct thread_state {
+       const char *username;
+       time_t timeout;
+       pthread_mutex_t lock;
+       bool fail;
+       int nss_loop_count;
+       int wbc_loop_count;
+};
+
+static void *query_nss_thread(void *ptr)
+{
+       struct thread_state *state = ptr;
+       char buf[1024];
+       int rc;
+       struct passwd pwd, *result;
+
+       while (time(NULL) < state->timeout) {
+               rc = getpwnam_r(state->username,
+                               &pwd,
+                               buf,
+                               sizeof(buf),
+                               &result);
+               if (rc != 0 || result == NULL) {
+                       pthread_mutex_lock(&state->lock);
+                       state->fail = true;
+                       pthread_mutex_unlock(&state->lock);
+                       fprintf(stderr,
+                               "getpwnam_r failed with rc='%s' result=%p\n",
+                               strerror(rc),
+                               result);
+                       break;
+               }
+               state->nss_loop_count++;
+               pthread_mutex_lock(&state->lock);
+               if (state->fail) {
+                       pthread_mutex_unlock(&state->lock);
+                       break;
+               }
+               pthread_mutex_unlock(&state->lock);
+       }
+       return NULL;
+}
+
+static void *query_wbc_thread(void *ptr)
+{
+       struct thread_state *state = ptr;
+       struct passwd *ppwd;
+       wbcErr wbc_status;
+
+       while (time(NULL) < state->timeout) {
+               wbc_status = wbcGetpwnam(state->username, &ppwd);
+               if (!WBC_ERROR_IS_OK(wbc_status)) {
+                       pthread_mutex_lock(&state->lock);
+                       state->fail = true;
+                       pthread_mutex_unlock(&state->lock);
+                       fprintf(stderr,
+                               "wbcGetpwnam failed with %s\n",
+                               wbcErrorString(wbc_status));
+                       break;
+               }
+               wbcFreeMemory(ppwd);
+               state->wbc_loop_count++;
+               pthread_mutex_lock(&state->lock);
+               if (state->fail) {
+                       pthread_mutex_unlock(&state->lock);
+                       break;
+               }
+               pthread_mutex_unlock(&state->lock);
+       }
+       return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+       int rc, n;
+       struct thread_state state;
+       pthread_t threads[2];
+
+       if (argc < 2 ) {
+               fprintf(stderr,"%s: missing domain user\n", argv[0]);
+               return 1;
+       }
+
+       state.username = argv[1];
+       state.timeout = time(NULL) + RUNTIME;
+       pthread_mutex_init(&state.lock, NULL);
+       state.fail = false;
+       state.nss_loop_count = 0;
+       state.wbc_loop_count = 0;
+
+       printf("query domain user '%s'\n", state.username);
+
+       /* create query threads */
+       rc = pthread_create(&threads[0], NULL, query_nss_thread, &state);
+       if (rc != 0) {
+               fprintf(stderr,
+                       "creating NSS thread failed: %s\n",
+                       strerror(rc));
+               exit(1);
+       }
+       rc = pthread_create(&threads[1], NULL, query_wbc_thread, &state);
+       if (rc != 0) {
+               fprintf(stderr,
+                       "creating libwbclient thread failed: %s\n",
+                       strerror(rc));
+               exit(1);
+       }
+
+       /* wait for query threads to terminate */
+       for (n = 0; n < 2; n++) {
+               pthread_join(threads[n], NULL);
+       }
+
+       fprintf(state.fail ? stderr: stdout,
+               "test %s with %i NSS and %i libwbclient calls\n",
+               state.fail ? "failed" : "passed",
+               state.nss_loop_count,
+               state.wbc_loop_count);
+
+       return state.fail;
+}
diff --git a/nsswitch/wb_common.c b/nsswitch/wb_common.c
index 42b341b..59370aa 100644
--- a/nsswitch/wb_common.c
+++ b/nsswitch/wb_common.c
@@ -27,6 +27,10 @@
 #include "system/select.h"
 #include "winbind_client.h"
 
+#if HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
 /* Global context */
 
 struct winbindd_context {
@@ -35,11 +39,31 @@ struct winbindd_context {
        pid_t our_pid;          /* calling process pid */
 };
 
-static struct winbindd_context wb_global_ctx = {
-       .winbindd_fd = -1,
-       .is_privileged = false,
-       .our_pid = 0
-};
+#if HAVE_PTHREAD
+static pthread_mutex_t wb_global_ctx_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+static struct winbindd_context *get_wb_global_ctx(void)
+{
+       static struct winbindd_context wb_global_ctx = {
+               .winbindd_fd = -1,
+               .is_privileged = false,
+               .our_pid = 0
+       };
+
+#if HAVE_PTHREAD
+       pthread_mutex_lock(&wb_global_ctx_mutex);
+#endif
+       return &wb_global_ctx;
+}
+
+static void put_wb_global_ctx(void)
+{
+#if HAVE_PTHREAD
+       pthread_mutex_unlock(&wb_global_ctx_mutex);
+#endif
+       return;
+}
 
 /* Free a response structure */
 
@@ -93,7 +117,11 @@ __attribute__((destructor))
 #endif
 static void winbind_destructor(void)
 {
-       winbind_close_sock(&wb_global_ctx);
+       struct winbindd_context *ctx;
+
+       ctx = get_wb_global_ctx();
+       winbind_close_sock(ctx);
+       put_wb_global_ctx();
 }
 
 #define CONNECT_TIMEOUT 30
@@ -725,16 +753,23 @@ NSS_STATUS winbindd_request_response(struct 
winbindd_context *ctx,
                                     struct winbindd_response *response)
 {
        NSS_STATUS status = NSS_STATUS_UNAVAIL;
+       bool release_global_ctx = false;
 
        if (ctx == NULL) {
-               ctx = &wb_global_ctx;
+               ctx = get_wb_global_ctx();
+               release_global_ctx = true;
        }
 
        status = winbindd_send_request(ctx, req_type, 0, request);
-       if (status != NSS_STATUS_SUCCESS)
-               return (status);
+       if (status != NSS_STATUS_SUCCESS) {
+               goto out;
+       }
        status = winbindd_get_response(ctx, response);
 
+out:
+       if (release_global_ctx) {
+               put_wb_global_ctx();
+       }
        return status;
 }
 
@@ -744,16 +779,23 @@ NSS_STATUS winbindd_priv_request_response(struct 
winbindd_context *ctx,
                                          struct winbindd_response *response)
 {
        NSS_STATUS status = NSS_STATUS_UNAVAIL;
+       bool release_global_ctx = false;
 
        if (ctx == NULL) {
-               ctx = &wb_global_ctx;
+               ctx = get_wb_global_ctx();
+               release_global_ctx = true;
        }
 
        status = winbindd_send_request(ctx, req_type, 1, request);
-       if (status != NSS_STATUS_SUCCESS)
-               return (status);
+       if (status != NSS_STATUS_SUCCESS) {
+               goto out;
+       }
        status = winbindd_get_response(ctx, response);
 
+out:
+       if (release_global_ctx) {
+               put_wb_global_ctx();
+       }
        return status;
 }
 
diff --git a/nsswitch/wscript_build b/nsswitch/wscript_build
index ff98372..6acc4a1 100644
--- a/nsswitch/wscript_build
+++ b/nsswitch/wscript_build
@@ -17,6 +17,13 @@ bld.SAMBA_BINARY('nsstest',
                  install=False
                 )
 
+if bld.CONFIG_SET('HAVE_PTHREAD'):
+    bld.SAMBA_BINARY('stress-nss-libwbclient',
+                    source='stress-nss-libwbclient.c',
+                    deps='wbclient',
+                    install=False
+                    )
+
 # The nss_wrapper code relies strictly on the linux implementation and
 # name, so compile but do not install a copy under this name.
 bld.SAMBA_LIBRARY('nss_wrapper_winbind',
diff --git a/source3/script/tests/test_libwbclient_threads.sh 
b/source3/script/tests/test_libwbclient_threads.sh
new file mode 100755
index 0000000..1f8d041
--- /dev/null
+++ b/source3/script/tests/test_libwbclient_threads.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+if [ $# -lt 2 ] ; then
+cat <<EOF
+Usage: test_libwbclient_threads.sh DOMAIN USERNAME
+EOF
+exit 1;
+fi
+
+DOMAIN="$1"
+USERNAME="$2"
+shift 2
+
+incdir=`dirname $0`/../../../testprogs/blackbox
+. $incdir/subunit.sh
+
+testit "libwbclient-threads" "$BINDIR/stress-nss-libwbclient" 
"$DOMAIN/$USERNAME"
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index f31007f..08395c1 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -385,6 +385,13 @@ if with_pthreadpool and have_ldwrap:
     plantestsuite("samba3.pthreadpool_cmocka", "none",
                   [os.path.join(bindir(), "pthreadpooltest_cmocka")])
 
+if with_pthreadpool:
+    plantestsuite("samba3.libwbclient_threads",
+                  "nt4_member",
+                  [os.path.join(samba3srcdir,
+                                "script/tests/test_libwbclient_threads.sh"),
+                   "$DOMAIN", "$DC_USERNAME"])
+
 plantestsuite("samba3.async_req", "nt4_dc",
               [os.path.join(samba3srcdir, "script/tests/test_async_req.sh")])
 
diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h
index 5737176..6d4b92f 100644
--- a/source3/winbindd/winbindd.h
+++ b/source3/winbindd/winbindd.h
@@ -189,8 +189,8 @@ struct winbindd_domain {
 };
 
 struct wb_acct_info {
-       fstring acct_name; /* account name */
-       fstring acct_desc; /* account name */
+       const char *acct_name; /* account name */
+       const char *acct_desc; /* account name */
        uint32_t rid; /* domain-relative RID */
 };
 
diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c
index 76d6a30..abc044d 100644
--- a/source3/winbindd/winbindd_ads.c
+++ b/source3/winbindd/winbindd_ads.c
@@ -500,8 +500,8 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain 
*domain,
                struct dom_sid sid;
                uint32_t rid;
 
-               name = ads_pull_username(ads, mem_ctx, msg);
-               gecos = ads_pull_string(ads, mem_ctx, msg, "name");
+               name = ads_pull_username(ads, (*info), msg);
+               gecos = ads_pull_string(ads, (*info), msg, "name");
                if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
                        DEBUG(1,("No sid for %s !?\n", name));
                        continue;
@@ -512,8 +512,8 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain 
*domain,
                        continue;
                }
 
-               fstrcpy((*info)[i].acct_name, name);
-               fstrcpy((*info)[i].acct_desc, gecos);
+               (*info)[i].acct_name = name;
+               (*info)[i].acct_desc = gecos;
                (*info)[i].rid = rid;
                i++;
        }
diff --git a/source3/winbindd/winbindd_cache.c 
b/source3/winbindd/winbindd_cache.c
index 7d98d61..2e2a04d 100644
--- a/source3/winbindd/winbindd_cache.c
+++ b/source3/winbindd/winbindd_cache.c
@@ -1565,8 +1565,8 @@ do_fetch_cache:
                smb_panic_fn("enum_dom_groups out of memory");
        }
        for (i=0; i<(*num_entries); i++) {
-               fstrcpy((*info)[i].acct_name, centry_string(centry, mem_ctx));
-               fstrcpy((*info)[i].acct_desc, centry_string(centry, mem_ctx));
+               (*info)[i].acct_name = centry_string(centry, (*info));
+               (*info)[i].acct_desc = centry_string(centry, (*info));
                (*info)[i].rid = centry_uint32(centry);
        }
 
@@ -1660,8 +1660,8 @@ do_fetch_cache:
                smb_panic_fn("enum_dom_groups out of memory");
        }
        for (i=0; i<(*num_entries); i++) {
-               fstrcpy((*info)[i].acct_name, centry_string(centry, mem_ctx));
-               fstrcpy((*info)[i].acct_desc, centry_string(centry, mem_ctx));
+               (*info)[i].acct_name = centry_string(centry, (*info));
+               (*info)[i].acct_desc = centry_string(centry, (*info));
                (*info)[i].rid = centry_uint32(centry);
        }
 
diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c
index f50fb8f..6f7cb07 100644
--- a/source3/winbindd/winbindd_rpc.c
+++ b/source3/winbindd/winbindd_rpc.c
@@ -155,9 +155,13 @@ NTSTATUS rpc_enum_dom_groups(TALLOC_CTX *mem_ctx,
                for (g = 0; g < count; g++) {
                        struct wb_acct_info *i = &info[num_info + g];
 
-                       fstrcpy(i->acct_name,
+                       i->acct_name = talloc_strdup(info,
                                sam_array->entries[g].name.string);
-                       fstrcpy(i->acct_desc, "");
+                       if (i->acct_name == NULL) {
+                               TALLOC_FREE(info);
+                               return NT_STATUS_NO_MEMORY;
+                       }
+                       i->acct_desc = NULL;
                        i->rid = sam_array->entries[g].idx;
                }
 
@@ -217,9 +221,13 @@ NTSTATUS rpc_enum_local_groups(TALLOC_CTX *mem_ctx,
                for (g = 0; g < count; g++) {
                        struct wb_acct_info *i = &info[num_info + g];
 
-                       fstrcpy(i->acct_name,
+                       i->acct_name = talloc_strdup(info,
                                sam_array->entries[g].name.string);
-                       fstrcpy(i->acct_desc, "");
+                       if (i->acct_name == NULL) {
+                               TALLOC_FREE(info);
+                               return NT_STATUS_NO_MEMORY;
+                       }
+                       i->acct_desc = NULL;
                        i->rid = sam_array->entries[g].idx;
                }
 


-- 
Samba Shared Repository

Reply via email to