The branch, v4-18-stable has been updated via 7ee4d12e5c3 VERSION: Disable GIT_SNAPSHOT for the 4.18.7 release. via 68195cebe73 WHATSNEW: Add release notes for Samba 4.18.7. via c4fd0850c5e smbd: Fix BZ15481 via 7de498a38d9 tests: Add reproducer for BZ15481 via 7b57cfb1a93 s4:kdc: Add correct Asserted Identity SID in response to an S4U2Self request via d96cd43df01 s4:kdc: Avoid copying data if not needed via f1b7a21a7f6 s4:kdc: Don't pass a NULL pointer into krb5_pac_add_buffer() via f869013c616 s3: smbd: Ensure we remove any pending aio values for named pipes on forced shutdown. via db1fbcc0263 s3: torture: Add a new SMB2 test: SMB2-PIPE-READ-ASYNC-DISCONNECT via 721513a219d s3: smbd: named pipe writes are async. Use the same logic as for named pipe transacts to avoid crashes on shutdown. via b3a881f89ae s3: smbd: named pipe reads are async. Use the same logic as for named pipe transacts to avoid crashes on shutdown. via 4baff9de6b2 s3: smbd: Add some DEVELOPER-only code to panic if the destructor for an aio_lnk is called and the associated fsp doesn't exist. via 82d6f8a6ce3 nsswitch/wb_common.c: fix socket fd and memory leaks of global state via 3d8e8ed1594 nsswitch/wb_common.c: don't operate on a stale wb_global_ctx.key via 5b9b8b31582 nsswitch/wb_common.c: winbind_destructor can always use get_wb_global_ctx() via 0ebaac2afe9 nsswitch/wb_common.c: fix build without HAVE_PTHREAD via cb71db6827f nsswitch: add test for pthread_key_delete missuse (bug 15464) via 5cf6870718c libsmb: Fix test for smbc_getxattr via 0d8e5ba4f51 libsmb: fix regression on smbc_getxattr and fix doc via 69fd70b83df mdssvc: better support for search with mdfind from Macs via 14380eb832d vfs_aio_pthread: use SMB_VFS_NEXT_OPENAT() in aio_pthread_openat_fn() via fd1111c2f48 s3: smbd: Sanitize any "server" and "share" components of SMB1 DFS paths to remove UNIX separators. via b80fdc0b0b3 s3: torture: Add test to show an SMB1 DFS path of "\x//\/" crashes smbd. via 5fac5b7b2fd ctdb-common: Set immediate mode for pcap capture via 2b5512712e5 ctdb-common: Replace pcap_open_live() by lower level calls via 550972627b7 ctdb-common: Improve error handling via 794ce23b350 s4-rpc_server/drsupai: Avoid looping with Azure AD Connect by not incrementing temp_highest_usn for the NC root via 50bba4925e0 s4-rpc_server/drsuapi: Ensure logs show DN for replicated objects, not (null) via 9d3b0af9db7 s4-rpc_server/drsuapi: Update getnc_state to be != NULL via cb83e9dbad8 s4-rpc_server/drsuapi: Rename ncRoot -> untrusted_ncRoot to avoid misuse via 21628e1f536 s4-rpc_server/drsuapi: Avoid modification to ncRoot input variable in GetNCChanges via 7da93e9a92f s4-rpc_server/drsuapi: Fix indentation in GetNCChanges() via e43ea61cdd2 s4-rpc_server/drsuapi: Only keep and invalidate replication cycle state for normal replication via dba337929d6 s4-torture/drs: Add test showing that if present in the set the NC root leads and tmp_highest_usn moves via 1fa63e6de9d s4-torture/drs: Add test demonstrating that a GetNCChanges REPL_OBJ will not reset the replication cookie via 69eac697606 s4-torture/drs: Add a test matching Azure AD Connect REPL_OBJ behaviour via 473cb476cdf s4-torture/drs: Use addCleanup() in getchanges.py for OU handling via c6801832cb3 s4-torture/drs: Create temp OU with a unique name per test via 4b30611733e s4-torture/drs: Save the server dnsname on the DcConnection object via 958ae0038d6 s4-rpc_server/drsuapi: Remove rudundant check for valid and non-NULL ncRoot_dn via 2eae9fa2183 s4-dsdb: Improve logging for drs_ObjectIdentifier_to_dn_and_nc_root() via e8fdc72b22e s4-rpc_server/drsuapi: Improve debug message for drs_ObjectIdentifier_to_dn_and_nc_root() failure via 251e3cd8c8d s4-rpc_server/drsuapi: Improve debugging of invalid DNs via 2fe39b167ac s4-rpc_server/drsuapi: Add tmp_highest_usn tracking to replication log via 0a044e409de s3: smbd: Ensure init_smb1_request() zeros out what the incoming pointer points to. via 0605946d20f s3: torture: Add SMB1-NEGOTIATE-TCON that shows the SMB1 server crashes on the uninitialized req->session. via d2c16aada79 s3: smbd: init_smb1_request() isn't being passed zero'ed memory from any codepath. via fec8cda70bc VERSION: Bump version up to Samba 4.18.7... from 2613f2b288c VERSION: Disable GIT_SNAPSHOT for the 4.18.6 release.
https://git.samba.org/?p=samba.git;a=shortlog;h=v4-18-stable - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: VERSION | 2 +- WHATSNEW.txt | 79 +++++- ctdb/common/system_socket.c | 42 ++- ctdb/wscript | 1 + nsswitch/b15464-testcase.c | 77 ++++++ nsswitch/wb_common.c | 152 ++++++++--- nsswitch/wscript_build | 5 + python/samba/tests/libsmb-basic.py | 27 ++ selftest/knownfail.d/getncchanges | 2 + source3/include/libsmbclient.h | 2 +- source3/libsmb/libsmb_xattr.c | 4 +- source3/modules/vfs_aio_pthread.c | 28 +- source3/rpc_server/mdssvc/mdssvc.c | 8 +- ...torture_s3.sh => test_smbtorture_nocrash_s3.sh} | 12 + source3/selftest/tests.py | 47 ++++ source3/smbd/close.c | 8 + source3/smbd/filename.c | 12 +- source3/smbd/smb2_aio.c | 24 ++ source3/smbd/smb2_process.c | 7 +- source3/smbd/smb2_read.c | 13 + source3/smbd/smb2_reply.c | 31 +++ source3/smbd/smb2_write.c | 13 + source3/torture/proto.h | 2 + source3/torture/test_smb1_dfs.c | 56 ++++ source3/torture/test_smb2.c | 117 ++++++++ source3/torture/torture.c | 48 ++++ source4/dsdb/common/dsdb_dn.c | 12 + source4/kdc/pac-glue.c | 26 +- source4/kdc/wdc-samba4.c | 22 -- source4/rpc_server/drsuapi/dcesrv_drsuapi.h | 2 +- source4/rpc_server/drsuapi/getncchanges.c | 293 +++++++++++++++------ source4/torture/drs/python/getnc_exop.py | 25 +- source4/torture/drs/python/getncchanges.py | 218 ++++++++++++++- source4/torture/libsmbclient/libsmbclient.c | 25 +- testprogs/blackbox/b15464-testcase.sh | 21 ++ 35 files changed, 1260 insertions(+), 203 deletions(-) create mode 100644 nsswitch/b15464-testcase.c copy source3/script/tests/{test_smbtorture_s3.sh => test_smbtorture_nocrash_s3.sh} (62%) create mode 100755 testprogs/blackbox/b15464-testcase.sh Changeset truncated at 500 lines: diff --git a/VERSION b/VERSION index 665cbe2cc9f..305add2b815 100644 --- a/VERSION +++ b/VERSION @@ -25,7 +25,7 @@ ######################################################## SAMBA_VERSION_MAJOR=4 SAMBA_VERSION_MINOR=18 -SAMBA_VERSION_RELEASE=6 +SAMBA_VERSION_RELEASE=7 ######################################################## # If a official release has a serious bug # diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 1bb83f6ba4c..fd11954058e 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,3 +1,79 @@ + ============================== + Release Notes for Samba 4.18.7 + September 27, 2023 + ============================== + + +This is the latest stable release of the Samba 4.18 release series. + + +Changes since 4.18.6 +-------------------- + +o Jeremy Allison <j...@samba.org> + * BUG 15419: Weird filename can cause assert to fail in + openat_pathref_fsp_nosymlink(). + * BUG 15423: use-after-free in aio_del_req_from_fsp during smbd shutdown + after failed IPC FSCTL_PIPE_TRANSCEIVE. + * BUG 15432: TREE_CONNECT without SETUP causes smbd to use uninitialized + pointer. + +o Andrew Bartlett <abart...@samba.org> + * BUG 15401: Avoid infinite loop in initial user sync with Azure AD Connect. + * BUG 15407: Samba replication logs show (null) DN. + +o Ralph Boehme <s...@samba.org> + * BUG 15463: macOS mdfind returns only 50 results. + +o Remi Collet <rcol...@redhat.com> + * BUG 14808: smbc_getxattr() return value is incorrect. + +o Volker Lendecke <v...@samba.org> + * BUG 15481: GETREALFILENAME_CACHE can modify incoming new filename with + previous cache entry value. + +o Stefan Metzmacher <me...@samba.org> + * BUG 15464: libnss_winbind causes memory corruption since samba-4.18, + impacts sendmail, zabbix, potentially more. + +o MikeLiu <mike...@qnap.com> + * BUG 15453: File doesn't show when user doesn't have permission if + aio_pthread is loaded. + +o Martin Schwenke <mschwe...@ddn.com> + * BUG 15451: ctdb_killtcp fails to work with --enable-pcap and libpcap ≥ + 1.9.1. + +o Joseph Sutton <josephsut...@catalyst.net.nz> + * BUG 15476: The KDC in 4.18 (and older) is not able to accept tickets with + empty claims pac blobs (from Samba 4.19 or Windows). + * BUG 15477: The heimdal KDC doesn't detect s4u2self correctly when fast is + in use. + + +####################################### +Reporting bugs & Development Discussion +####################################### + +Please discuss this release on the samba-technical mailing list or by +joining the #samba-technical:matrix.org matrix room, or +#samba-technical IRC channel on irc.libera.chat. + +If you do report problems then please try to send high quality +feedback. If you don't provide vital information to help us track down +the problem then you will probably be ignored. All bug reports should +be filed under the Samba 4.1 and newer product in the project's Bugzilla +database (https://bugzilla.samba.org/). + + +====================================================================== +== Our Code, Our Bugs, Our Responsibility. +== The Samba Team +====================================================================== + + +Release notes for older releases follow: +---------------------------------------- ============================== Release Notes for Samba 4.18.6 August 16, 2023 @@ -76,8 +152,7 @@ database (https://bugzilla.samba.org/). ====================================================================== -Release notes for older releases follow: ----------------------------------------- +---------------------------------------------------------------------- ============================== Release Notes for Samba 4.18.5 July 19, 2023 diff --git a/ctdb/common/system_socket.c b/ctdb/common/system_socket.c index 06dc558eb22..273b9c3400e 100644 --- a/ctdb/common/system_socket.c +++ b/ctdb/common/system_socket.c @@ -980,15 +980,45 @@ int ctdb_sys_open_capture_socket(const char *iface, void **private_data) int pcap_packet_type; const char *t = NULL; int fd; + int ret; - pt = pcap_open_live(iface, 100, 0, 0, errbuf); + pt = pcap_create(iface, errbuf); if (pt == NULL) { DBG_ERR("Failed to open pcap capture device %s (%s)\n", iface, errbuf); return -1; } - *((pcap_t **)private_data) = pt; + /* + * pcap isn't very clear about defaults... + */ + ret = pcap_set_snaplen(pt, 100); + if (ret < 0) { + DBG_ERR("Failed to set snaplen for pcap capture\n"); + goto fail; + } + ret = pcap_set_promisc(pt, 0); + if (ret < 0) { + DBG_ERR("Failed to unset promiscuous mode for pcap capture\n"); + goto fail; + } + ret = pcap_set_timeout(pt, 0); + if (ret < 0) { + DBG_ERR("Failed to set timeout for pcap capture\n"); + goto fail; + } +#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE + ret = pcap_set_immediate_mode(pt, 1); + if (ret < 0) { + DBG_ERR("Failed to set immediate mode for pcap capture\n"); + goto fail; + } +#endif + ret = pcap_activate(pt); + if (ret < 0) { + DBG_ERR("Failed to activate pcap capture\n"); + goto fail; + } pcap_packet_type = pcap_datalink(pt); switch (pcap_packet_type) { @@ -1005,8 +1035,7 @@ int ctdb_sys_open_capture_socket(const char *iface, void **private_data) #endif /* DLT_LINUX_SLL2 */ default: DBG_ERR("Unknown pcap packet type %d\n", pcap_packet_type); - pcap_close(pt); - return -1; + goto fail; } fd = pcap_get_selectable_fd(pt); @@ -1014,7 +1043,12 @@ int ctdb_sys_open_capture_socket(const char *iface, void **private_data) t, fd); + *((pcap_t **)private_data) = pt; return fd; + +fail: + pcap_close(pt); + return -1; } int ctdb_sys_close_capture_socket(void *private_data) diff --git a/ctdb/wscript b/ctdb/wscript index 88e42439f5a..a7b04541014 100644 --- a/ctdb/wscript +++ b/ctdb/wscript @@ -221,6 +221,7 @@ def configure(conf): if not conf.CHECK_FUNCS_IN('pcap_open_live', 'pcap', headers='pcap.h'): Logs.error('Need libpcap') sys.exit(1) + conf.CHECK_FUNCS_IN('pcap_set_immediate_mode', 'pcap', headers='pcap.h') if not conf.CHECK_FUNCS_IN('backtrace backtrace_symbols', 'execinfo', checklibc=True, headers='execinfo.h'): 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/wb_common.c b/nsswitch/wb_common.c index d569e761ebe..b7f84435a4e 100644 --- a/nsswitch/wb_common.c +++ b/nsswitch/wb_common.c @@ -26,6 +26,7 @@ #include "replace.h" #include "system/select.h" #include "winbind_client.h" +#include "lib/util/dlinklist.h" #include <assert.h> #ifdef HAVE_PTHREAD_H @@ -37,74 +38,113 @@ static __thread char client_name[32]; /* Global context */ struct winbindd_context { + struct winbindd_context *prev, *next; int winbindd_fd; /* winbind file descriptor */ bool is_privileged; /* using the privileged socket? */ pid_t our_pid; /* calling process pid */ + bool autofree; /* this is a thread global context */ }; static struct wb_global_ctx { - bool initialized; #ifdef HAVE_PTHREAD pthread_once_t control; pthread_key_t key; + bool key_initialized; +#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP +#define WB_GLOBAL_MUTEX_INITIALIZER PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP #else - bool dummy; +#define WB_GLOBAL_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER #endif +#define WB_GLOBAL_LIST_LOCK do { \ + int __pret = pthread_mutex_lock(&wb_global_ctx.list_mutex); \ + assert(__pret == 0); \ +} while(0) +#define WB_GLOBAL_LIST_UNLOCK do { \ + int __pret = pthread_mutex_unlock(&wb_global_ctx.list_mutex); \ + assert(__pret == 0); \ +} while(0) + pthread_mutex_t list_mutex; +#else /* => not HAVE_PTHREAD */ +#define WB_GLOBAL_LIST_LOCK do { } while(0) +#define WB_GLOBAL_LIST_UNLOCK do { } while(0) +#endif /* not HAVE_PTHREAD */ + struct winbindd_context *list; } wb_global_ctx = { #ifdef HAVE_PTHREAD .control = PTHREAD_ONCE_INIT, + .list_mutex = WB_GLOBAL_MUTEX_INITIALIZER, #endif + .list = NULL, }; static void winbind_close_sock(struct winbindd_context *ctx); +static void winbind_ctx_free_locked(struct winbindd_context *ctx); +static void winbind_cleanup_list(void); #ifdef HAVE_PTHREAD static void wb_thread_ctx_initialize(void); -static void wb_atfork_child(void) +static void wb_atfork_prepare(void) { - struct winbindd_context *ctx = NULL; - int ret; + WB_GLOBAL_LIST_LOCK; +} - ctx = (struct winbindd_context *)pthread_getspecific(wb_global_ctx.key); - if (ctx == NULL) { - return; - } +static void wb_atfork_parent(void) +{ + WB_GLOBAL_LIST_UNLOCK; +} - ret = pthread_setspecific(wb_global_ctx.key, NULL); - assert(ret == 0); +static void wb_atfork_child(void) +{ + wb_global_ctx.list_mutex = (pthread_mutex_t)WB_GLOBAL_MUTEX_INITIALIZER; - winbind_close_sock(ctx); - free(ctx); + if (wb_global_ctx.key_initialized) { + int ret; - ret = pthread_key_delete(wb_global_ctx.key); - assert(ret == 0); + /* + * After a fork the child still believes + * it is the same thread as in the parent. + * So pthread_getspecific() would return the + * value of the thread that called fork(). + * + * But we don't want that behavior, so + * we just clear the reference and let + * winbind_cleanup_list() below 'autofree' + * the parent threads global context. + */ + ret = pthread_setspecific(wb_global_ctx.key, NULL); + assert(ret == 0); + } - wb_global_ctx.control = (pthread_once_t)PTHREAD_ONCE_INIT; + /* + * But we need to close/cleanup the global state + * of the parents threads. + */ + winbind_cleanup_list(); } static void wb_thread_ctx_destructor(void *p) { struct winbindd_context *ctx = (struct winbindd_context *)p; - winbind_close_sock(ctx); - free(ctx); + winbindd_ctx_free(ctx); } static void wb_thread_ctx_initialize(void) { int ret; - ret = pthread_atfork(NULL, - NULL, + ret = pthread_atfork(wb_atfork_prepare, + wb_atfork_parent, wb_atfork_child); assert(ret == 0); ret = pthread_key_create(&wb_global_ctx.key, wb_thread_ctx_destructor); assert(ret == 0); + + wb_global_ctx.key_initialized = true; } -#endif static struct winbindd_context *get_wb_thread_ctx(void) { @@ -129,9 +169,14 @@ static struct winbindd_context *get_wb_thread_ctx(void) *ctx = (struct winbindd_context) { .winbindd_fd = -1, .is_privileged = false, - .our_pid = 0 + .our_pid = 0, + .autofree = true, }; + WB_GLOBAL_LIST_LOCK; + DLIST_ADD_END(wb_global_ctx.list, ctx); + WB_GLOBAL_LIST_UNLOCK; + ret = pthread_setspecific(wb_global_ctx.key, ctx); if (ret != 0) { free(ctx); @@ -139,6 +184,7 @@ static struct winbindd_context *get_wb_thread_ctx(void) } return ctx; } +#endif /* HAVE_PTHREAD */ static struct winbindd_context *get_wb_global_ctx(void) { @@ -147,7 +193,8 @@ static struct winbindd_context *get_wb_global_ctx(void) static struct winbindd_context _ctx = { .winbindd_fd = -1, .is_privileged = false, - .our_pid = 0 + .our_pid = 0, + .autofree = false, }; #endif @@ -155,9 +202,11 @@ static struct winbindd_context *get_wb_global_ctx(void) ctx = get_wb_thread_ctx(); #else ctx = &_ctx; + if (ctx->prev == NULL && ctx->next == NULL) { + DLIST_ADD_END(wb_global_ctx.list, ctx); + } #endif - wb_global_ctx.initialized = true; return ctx; } @@ -231,6 +280,30 @@ static void winbind_close_sock(struct winbindd_context *ctx) } } +static void winbind_ctx_free_locked(struct winbindd_context *ctx) +{ + winbind_close_sock(ctx); + DLIST_REMOVE(wb_global_ctx.list, ctx); + free(ctx); +} + +static void winbind_cleanup_list(void) +{ + struct winbindd_context *ctx = NULL, *next = NULL; + + WB_GLOBAL_LIST_LOCK; + for (ctx = wb_global_ctx.list; ctx != NULL; ctx = next) { + next = ctx->next; + + if (ctx->autofree) { + winbind_ctx_free_locked(ctx); + } else { + winbind_close_sock(ctx); + } + } + WB_GLOBAL_LIST_UNLOCK; +} + /* Destructor for global context to ensure fd is closed */ -- Samba Shared Repository