diff --git a/SOURCES/CVE-2021-44142-v4.14.patch b/SOURCES/CVE-2021-44142-v4.14.patch
new file mode 100644
index 0000000..1f76f7c
--- /dev/null
+++ b/SOURCES/CVE-2021-44142-v4.14.patch
@@ -0,0 +1,759 @@
+From 2f7332f6c283fbedbd859c79a3f74ca6e07aad46 Mon Sep 17 00:00:00 2001
+From: Ralph Boehme <slow@samba.org>
+Date: Thu, 13 Jan 2022 16:48:01 +0100
+Subject: [PATCH 1/5] CVE-2021-44142: libadouble: add defines for icon lengths
+
+From https://www.ietf.org/rfc/rfc1740.txt
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=14914
+
+Signed-off-by: Ralph Boehme <slow@samba.org>
+---
+ source3/lib/adouble.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/source3/lib/adouble.h b/source3/lib/adouble.h
+index 90a825c502e0..e3b9263a1f9a 100644
+--- a/source3/lib/adouble.h
++++ b/source3/lib/adouble.h
+@@ -101,6 +101,8 @@ typedef enum {ADOUBLE_META, ADOUBLE_RSRC} adouble_type_t;
+ #define ADEDLEN_MACFILEI        4
+ #define ADEDLEN_PRODOSFILEI     8
+ #define ADEDLEN_MSDOSFILEI      2
++#define ADEDLEN_ICONBW          128
++#define ADEDLEN_ICONCOL         1024
+ #define ADEDLEN_DID             4
+ #define ADEDLEN_PRIVDEV         8
+ #define ADEDLEN_PRIVINO         8
+-- 
+2.34.1
+
+
+From fc20cb8268af1203a331ba142b630d4dfb613478 Mon Sep 17 00:00:00 2001
+From: Ralph Boehme <slow@samba.org>
+Date: Sat, 20 Nov 2021 16:36:42 +0100
+Subject: [PATCH 2/5] CVE-2021-44142: smbd: add Netatalk xattr used by
+ vfs_fruit to the list of private Samba xattrs
+
+This is an internal xattr that should not be user visible.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=14914
+
+Signed-off-by: Ralph Boehme <slow@samba.org>
+[slow@samba.org: conflict due to changed includes in source3/smbd/trans2.c]
+---
+ source3/smbd/trans2.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
+index 70a492a96a8a..a200656b76cf 100644
+--- a/source3/smbd/trans2.c
++++ b/source3/smbd/trans2.c
+@@ -45,6 +45,7 @@
+ #include "smb1_utils.h"
+ #include "libcli/smb/smb2_posix.h"
+ #include "lib/util/string_wrappers.h"
++#include "source3/lib/adouble.h"
+ 
+ #define DIR_ENTRY_SAFETY_MARGIN 4096
+ 
+@@ -218,6 +219,7 @@ bool samba_private_attr_name(const char *unix_ea_name)
+ 		SAMBA_XATTR_DOS_ATTRIB,
+ 		SAMBA_XATTR_MARKER,
+ 		XATTR_NTACL_NAME,
++		AFPINFO_EA_NETATALK,
+ 		NULL
+ 	};
+ 
+-- 
+2.34.1
+
+
+From 73302708170a71afce09ff42640ea4fceff4d08a Mon Sep 17 00:00:00 2001
+From: Ralph Boehme <slow@samba.org>
+Date: Fri, 26 Nov 2021 07:19:32 +0100
+Subject: [PATCH 3/5] CVE-2021-44142: libadouble: harden ad_unpack_xattrs()
+
+This ensures ad_unpack_xattrs() is only called for an ad_type of ADOUBLE_RSRC,
+which is used for parsing ._ AppleDouble sidecar files, and the buffer
+ad->ad_data is AD_XATTR_MAX_HDR_SIZE bytes large which is a prerequisite for all
+buffer out-of-bounds access checks in ad_unpack_xattrs().
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=14914
+
+Signed-off-by: Ralph Boehme <slow@samba.org>
+---
+ source3/lib/adouble.c | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/source3/lib/adouble.c b/source3/lib/adouble.c
+index 0ab9019cfb59..7875dd6f0df8 100644
+--- a/source3/lib/adouble.c
++++ b/source3/lib/adouble.c
+@@ -707,14 +707,27 @@ static bool ad_pack(struct vfs_handle_struct *handle,
+ static bool ad_unpack_xattrs(struct adouble *ad)
+ {
+ 	struct ad_xattr_header *h = &ad->adx_header;
++	size_t bufsize = talloc_get_size(ad->ad_data);
+ 	const char *p = ad->ad_data;
+ 	uint32_t hoff;
+ 	uint32_t i;
+ 
++	if (ad->ad_type != ADOUBLE_RSRC) {
++		return false;
++	}
++
+ 	if (ad_getentrylen(ad, ADEID_FINDERI) <= ADEDLEN_FINDERI) {
+ 		return true;
+ 	}
+ 
++	/*
++	 * Ensure the buffer ad->ad_data was allocated by ad_alloc() for an
++	 * ADOUBLE_RSRC type (._ AppleDouble file on-disk).
++	 */
++	if (bufsize != AD_XATTR_MAX_HDR_SIZE) {
++		return false;
++	}
++
+ 	/* 2 bytes padding */
+ 	hoff = ad_getentryoff(ad, ADEID_FINDERI) + ADEDLEN_FINDERI + 2;
+ 
+@@ -964,9 +977,11 @@ static bool ad_unpack(struct adouble *ad, const size_t nentries,
+ 		ad->ad_eid[eid].ade_len = len;
+ 	}
+ 
+-	ok = ad_unpack_xattrs(ad);
+-	if (!ok) {
+-		return false;
++	if (ad->ad_type == ADOUBLE_RSRC) {
++		ok = ad_unpack_xattrs(ad);
++		if (!ok) {
++			return false;
++		}
+ 	}
+ 
+ 	return true;
+-- 
+2.34.1
+
+
+From 0cfe02ac7ad197ea9fb4b19f296b73e5e7baf0af Mon Sep 17 00:00:00 2001
+From: Ralph Boehme <slow@samba.org>
+Date: Thu, 25 Nov 2021 15:04:03 +0100
+Subject: [PATCH 4/5] CVE-2021-44142: libadouble: add basic cmocka tests
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=14914
+
+Signed-off-by: Ralph Boehme <slow@samba.org>
+[slow@samba.org: conflict due to missing test in selftest/tests.py]
+---
+ selftest/knownfail.d/samba.unittests.adouble |   3 +
+ selftest/tests.py                            |   2 +
+ source3/lib/test_adouble.c                   | 389 +++++++++++++++++++
+ source3/wscript_build                        |   5 +
+ 4 files changed, 399 insertions(+)
+ create mode 100644 selftest/knownfail.d/samba.unittests.adouble
+ create mode 100644 source3/lib/test_adouble.c
+
+diff --git a/selftest/knownfail.d/samba.unittests.adouble b/selftest/knownfail.d/samba.unittests.adouble
+new file mode 100644
+index 000000000000..8b0314f2faec
+--- /dev/null
++++ b/selftest/knownfail.d/samba.unittests.adouble
+@@ -0,0 +1,3 @@
++^samba.unittests.adouble.parse_abouble_finderinfo2\(none\)
++^samba.unittests.adouble.parse_abouble_finderinfo3\(none\)
++^samba.unittests.adouble.parse_abouble_date2\(none\)
+diff --git a/selftest/tests.py b/selftest/tests.py
+index af1e46061852..f4a1056f1dc8 100644
+--- a/selftest/tests.py
++++ b/selftest/tests.py
+@@ -427,3 +427,5 @@ plantestsuite("samba.unittests.test_oLschema2ldif", "none",
+                   [os.path.join(bindir(), "default/source3/test_mdsparser_es")] + [configuration])
+ plantestsuite("samba.unittests.credentials", "none",
+               [os.path.join(bindir(), "default/auth/credentials/test_creds")])
++plantestsuite("samba.unittests.adouble", "none",
++              [os.path.join(bindir(), "test_adouble")])
+diff --git a/source3/lib/test_adouble.c b/source3/lib/test_adouble.c
+new file mode 100644
+index 000000000000..615c22469c91
+--- /dev/null
++++ b/source3/lib/test_adouble.c
+@@ -0,0 +1,389 @@
++/*
++ * Unix SMB/CIFS implementation.
++ *
++ * Copyright (C) 2021 Ralph Boehme <slow@samba.org>
++ *
++ * 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 "adouble.c"
++#include <cmocka.h>
++
++static int setup_talloc_context(void **state)
++{
++	TALLOC_CTX *frame = talloc_stackframe();
++
++	*state = frame;
++	return 0;
++}
++
++static int teardown_talloc_context(void **state)
++{
++	TALLOC_CTX *frame = *state;
++
++	TALLOC_FREE(frame);
++	return 0;
++}
++
++/*
++ * Basic and sane buffer.
++ */
++static uint8_t ad_basic[] = {
++	0x00, 0x05, 0x16, 0x07, /* Magic */
++	0x00, 0x02, 0x00, 0x00, /* Version */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x02,             /* Count */
++	/* adentry 1: FinderInfo */
++	0x00, 0x00, 0x00, 0x09,	/* eid: FinderInfo */
++	0x00, 0x00, 0x00, 0x32,	/* offset */
++	0x00, 0x00, 0x00, 0x20,	/* length */
++	/* adentry 2: Resourcefork */
++	0x00, 0x00, 0x00, 0x02,	/* eid: Resourcefork */
++	0x00, 0x00, 0x00, 0x52,	/* offset */
++	0xff, 0xff, 0xff, 0x00,	/* length */
++	/* FinderInfo data: 32 bytes */
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++};
++
++/*
++ * An empty FinderInfo entry.
++ */
++static uint8_t ad_finderinfo1[] = {
++	0x00, 0x05, 0x16, 0x07, /* Magic */
++	0x00, 0x02, 0x00, 0x00, /* Version */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x02,             /* Count */
++	/* adentry 1: FinderInfo */
++	0x00, 0x00, 0x00, 0x09,	/* eid: FinderInfo */
++	0x00, 0x00, 0x00, 0x52,	/* off: points at end of buffer */
++	0x00, 0x00, 0x00, 0x00,	/* len: 0, so off+len don't exceed bufferlen */
++	/* adentry 2: Resourcefork */
++	0x00, 0x00, 0x00, 0x02,	/* eid: Resourcefork */
++	0x00, 0x00, 0x00, 0x52,	/* offset */
++	0xff, 0xff, 0xff, 0x00,	/* length */
++	/* FinderInfo data: 32 bytes */
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++};
++
++/*
++ * A dangerous FinderInfo with correct length exceeding buffer by one byte.
++ */
++static uint8_t ad_finderinfo2[] = {
++	0x00, 0x05, 0x16, 0x07, /* Magic */
++	0x00, 0x02, 0x00, 0x00, /* Version */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x02,             /* Count */
++	/* adentry 1: FinderInfo */
++	0x00, 0x00, 0x00, 0x09,	/* eid: FinderInfo */
++	0x00, 0x00, 0x00, 0x33,	/* off: points at beginng of data + 1 */
++	0x00, 0x00, 0x00, 0x20,	/* len: 32, so off+len exceeds bufferlen by 1 */
++	/* adentry 2: Resourcefork */
++	0x00, 0x00, 0x00, 0x02,	/* eid: Resourcefork */
++	0x00, 0x00, 0x00, 0x52,	/* offset */
++	0xff, 0xff, 0xff, 0x00,	/* length */
++	/* FinderInfo data: 32 bytes */
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++};
++
++static uint8_t ad_finderinfo3[] = {
++	0x00, 0x05, 0x16, 0x07, /* Magic */
++	0x00, 0x02, 0x00, 0x00, /* Version */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x02,             /* Count */
++	/* adentry 1: FinderInfo */
++	0x00, 0x00, 0x00, 0x09,	/* eid: FinderInfo */
++	0x00, 0x00, 0x00, 0x33,	/* off: points at beginng of data + 1 */
++	0x00, 0x00, 0x00, 0x1f,	/* len: 31, so off+len don't exceed buf */
++	/* adentry 2: Resourcefork */
++	0x00, 0x00, 0x00, 0x02,	/* eid: Resourcefork */
++	0x00, 0x00, 0x00, 0x52,	/* offset */
++	0xff, 0xff, 0xff, 0x00,	/* length */
++	/* FinderInfo data: 32 bytes */
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++};
++
++/*
++ * A dangerous name entry.
++ */
++static uint8_t ad_name[] = {
++	0x00, 0x05, 0x16, 0x07, /* Magic */
++	0x00, 0x02, 0x00, 0x00, /* Version */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x02,             /* Count */
++	/* adentry 1: FinderInfo */
++	0x00, 0x00, 0x00, 0x09,	/* eid: FinderInfo */
++	0x00, 0x00, 0x00, 0x32,	/* offset */
++	0x00, 0x00, 0x00, 0x20,	/* length */
++	/* adentry 2: Name */
++	0x00, 0x00, 0x00, 0x03,	/* eid: Name */
++	0x00, 0x00, 0x00, 0x52,	/* off: points at end of buffer */
++	0x00, 0x00, 0x00, 0x01,	/* len: 1, so off+len exceeds bufferlen */
++	/* FinderInfo data: 32 bytes */
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++};
++
++/*
++ * A empty ADEID_FILEDATESI entry.
++ */
++static uint8_t ad_date1[] = {
++	0x00, 0x05, 0x16, 0x07, /* Magic */
++	0x00, 0x02, 0x00, 0x00, /* Version */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x02,             /* Count */
++	/* adentry 1: FinderInfo */
++	0x00, 0x00, 0x00, 0x09,	/* eid: FinderInfo */
++	0x00, 0x00, 0x00, 0x32,	/* offset */
++	0x00, 0x00, 0x00, 0x20,	/* length */
++	/* adentry 2: Dates */
++	0x00, 0x00, 0x00, 0x08,	/* eid: dates */
++	0x00, 0x00, 0x00, 0x52,	/* off: end of buffer */
++	0x00, 0x00, 0x00, 0x00,	/* len: 0, empty entry, valid */
++	/* FinderInfo data: 32 bytes */
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++};
++
++/*
++ * A dangerous ADEID_FILEDATESI entry, invalid length.
++ */
++static uint8_t ad_date2[] = {
++	0x00, 0x05, 0x16, 0x07, /* Magic */
++	0x00, 0x02, 0x00, 0x00, /* Version */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x00, 0x00, 0x00, /* Filler */
++	0x00, 0x02,             /* Count */
++	/* adentry 1: FinderInfo */
++	0x00, 0x00, 0x00, 0x09,	/* eid: FinderInfo */
++	0x00, 0x00, 0x00, 0x32,	/* offset */
++	0x00, 0x00, 0x00, 0x20,	/* length */
++	/* adentry 2: Dates */
++	0x00, 0x00, 0x00, 0x08,	/* eid: dates */
++	0x00, 0x00, 0x00, 0x43,	/* off: FinderInfo buf but one byte short */
++	0x00, 0x00, 0x00, 0x0f,	/* len: 15, so off+len don't exceed bufferlen */
++	/* FinderInfo data: 32 bytes */
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++	0x00, 0x00, 0x00, 0x00,
++};
++
++static struct adouble *parse_adouble(TALLOC_CTX *mem_ctx,
++				     uint8_t *adbuf,
++				     size_t adsize,
++				     off_t filesize)
++{
++	struct adouble *ad = NULL;
++	bool ok;
++
++	ad = talloc_zero(mem_ctx, struct adouble);
++	ad->ad_data = talloc_zero_size(ad, adsize);
++	assert_non_null(ad);
++
++	memcpy(ad->ad_data, adbuf, adsize);
++
++	ok = ad_unpack(ad, 2, filesize);
++	if (!ok) {
++		return NULL;
++	}
++
++	return ad;
++}
++
++static void parse_abouble_basic(void **state)
++{
++	TALLOC_CTX *frame = *state;
++	struct adouble *ad = NULL;
++	char *p = NULL;
++
++	ad = parse_adouble(frame, ad_basic, sizeof(ad_basic), 0xffffff52);
++	assert_non_null(ad);
++
++	p = ad_get_entry(ad, ADEID_FINDERI);
++	assert_non_null(p);
++
++	return;
++}
++
++static void parse_abouble_finderinfo1(void **state)
++{
++	TALLOC_CTX *frame = *state;
++	struct adouble *ad = NULL;
++	char *p = NULL;
++
++	ad = parse_adouble(frame,
++			   ad_finderinfo1,
++			   sizeof(ad_finderinfo1),
++			   0xffffff52);
++	assert_non_null(ad);
++
++	p = ad_get_entry(ad, ADEID_FINDERI);
++	assert_null(p);
++
++	return;
++}
++
++static void parse_abouble_finderinfo2(void **state)
++{
++	TALLOC_CTX *frame = *state;
++	struct adouble *ad = NULL;
++
++	ad = parse_adouble(frame,
++			   ad_finderinfo2,
++			   sizeof(ad_finderinfo2),
++			   0xffffff52);
++	assert_null(ad);
++
++	return;
++}
++
++static void parse_abouble_finderinfo3(void **state)
++{
++	TALLOC_CTX *frame = *state;
++	struct adouble *ad = NULL;
++
++	ad = parse_adouble(frame,
++			   ad_finderinfo3,
++			   sizeof(ad_finderinfo3),
++			   0xffffff52);
++	assert_null(ad);
++
++	return;
++}
++
++static void parse_abouble_name(void **state)
++{
++	TALLOC_CTX *frame = *state;
++	struct adouble *ad = NULL;
++
++	ad = parse_adouble(frame, ad_name, sizeof(ad_name), 0x52);
++	assert_null(ad);
++
++	return;
++}
++
++static void parse_abouble_date1(void **state)
++{
++	TALLOC_CTX *frame = *state;
++	struct adouble *ad = NULL;
++	char *p = NULL;
++
++	ad = parse_adouble(frame, ad_date1, sizeof(ad_date1), 0x52);
++	assert_non_null(ad);
++
++	p = ad_get_entry(ad, ADEID_FILEDATESI);
++	assert_null(p);
++
++	return;
++}
++
++static void parse_abouble_date2(void **state)
++{
++	TALLOC_CTX *frame = *state;
++	struct adouble *ad = NULL;
++
++	ad = parse_adouble(frame, ad_date2, sizeof(ad_date2), 0x52);
++	assert_null(ad);
++
++	return;
++}
++
++int main(int argc, char *argv[])
++{
++	int rc;
++	const struct CMUnitTest tests[] = {
++		cmocka_unit_test(parse_abouble_basic),
++		cmocka_unit_test(parse_abouble_finderinfo1),
++		cmocka_unit_test(parse_abouble_finderinfo2),
++		cmocka_unit_test(parse_abouble_finderinfo3),
++		cmocka_unit_test(parse_abouble_name),
++		cmocka_unit_test(parse_abouble_date1),
++		cmocka_unit_test(parse_abouble_date2),
++	};
++
++	if (argc == 2) {
++		cmocka_set_test_filter(argv[1]);
++	}
++	cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
++
++	rc = cmocka_run_group_tests(tests,
++				    setup_talloc_context,
++				    teardown_talloc_context);
++
++	return rc;
++}
+diff --git a/source3/wscript_build b/source3/wscript_build
+index a143477a5064..95e589cfc734 100644
+--- a/source3/wscript_build
++++ b/source3/wscript_build
+@@ -1088,6 +1088,11 @@ bld.SAMBA3_SUBSYSTEM('ADOUBLE',
+                     source='lib/adouble.c',
+                     deps='STRING_REPLACE')
+ 
++bld.SAMBA3_BINARY('test_adouble',
++                 source='lib/test_adouble.c',
++                 deps='smbd_base STRING_REPLACE cmocka',
++                 for_selftest=True)
++
+ bld.SAMBA3_SUBSYSTEM('STRING_REPLACE',
+                     source='lib/string_replace.c')
+ 
+-- 
+2.34.1
+
+
+From 793ca8c474a74f82745a266f4a4bf9e20443ad53 Mon Sep 17 00:00:00 2001
+From: Ralph Boehme <slow@samba.org>
+Date: Thu, 13 Jan 2022 17:03:02 +0100
+Subject: [PATCH 5/5] CVE-2021-44142: libadouble: harden parsing code
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=14914
+
+Signed-off-by: Ralph Boehme <slow@samba.org>
+---
+ selftest/knownfail.d/samba.unittests.adouble |   3 -
+ source3/lib/adouble.c                        | 115 ++++++++++++++++---
+ 2 files changed, 101 insertions(+), 17 deletions(-)
+ delete mode 100644 selftest/knownfail.d/samba.unittests.adouble
+
+diff --git a/selftest/knownfail.d/samba.unittests.adouble b/selftest/knownfail.d/samba.unittests.adouble
+deleted file mode 100644
+index 8b0314f2faec..000000000000
+--- a/selftest/knownfail.d/samba.unittests.adouble
++++ /dev/null
+@@ -1,3 +0,0 @@
+-^samba.unittests.adouble.parse_abouble_finderinfo2\(none\)
+-^samba.unittests.adouble.parse_abouble_finderinfo3\(none\)
+-^samba.unittests.adouble.parse_abouble_date2\(none\)
+diff --git a/source3/lib/adouble.c b/source3/lib/adouble.c
+index 7875dd6f0df8..48cc0007c23c 100644
+--- a/source3/lib/adouble.c
++++ b/source3/lib/adouble.c
+@@ -269,6 +269,95 @@ size_t ad_setentryoff(struct adouble *ad, int eid, size_t off)
+ 	return ad->ad_eid[eid].ade_off = off;
+ }
+ 
++/*
++ * All entries besides FinderInfo and resource fork must fit into the
++ * buffer. FinderInfo is special as it may be larger then the default 32 bytes
++ * if it contains marshalled xattrs, which we will fixup that in
++ * ad_convert(). The first 32 bytes however must also be part of the buffer.
++ *
++ * The resource fork is never accessed directly by the ad_data buf.
++ */
++static bool ad_entry_check_size(uint32_t eid,
++				size_t bufsize,
++				uint32_t off,
++				uint32_t got_len)
++{
++	struct {
++		off_t expected_len;
++		bool fixed_size;
++		bool minimum_size;
++	} ad_checks[] = {
++		[ADEID_DFORK] = {-1, false, false}, /* not applicable */
++		[ADEID_RFORK] = {-1, false, false}, /* no limit */
++		[ADEID_NAME] = {ADEDLEN_NAME, false, false},
++		[ADEID_COMMENT] = {ADEDLEN_COMMENT, false, false},
++		[ADEID_ICONBW] = {ADEDLEN_ICONBW, true, false},
++		[ADEID_ICONCOL] = {ADEDLEN_ICONCOL, false, false},
++		[ADEID_FILEI] = {ADEDLEN_FILEI, true, false},
++		[ADEID_FILEDATESI] = {ADEDLEN_FILEDATESI, true, false},
++		[ADEID_FINDERI] = {ADEDLEN_FINDERI, false, true},
++		[ADEID_MACFILEI] = {ADEDLEN_MACFILEI, true, false},
++		[ADEID_PRODOSFILEI] = {ADEDLEN_PRODOSFILEI, true, false},
++		[ADEID_MSDOSFILEI] = {ADEDLEN_MSDOSFILEI, true, false},
++		[ADEID_SHORTNAME] = {ADEDLEN_SHORTNAME, false, false},
++		[ADEID_AFPFILEI] = {ADEDLEN_AFPFILEI, true, false},
++		[ADEID_DID] = {ADEDLEN_DID, true, false},
++		[ADEID_PRIVDEV] = {ADEDLEN_PRIVDEV, true, false},
++		[ADEID_PRIVINO] = {ADEDLEN_PRIVINO, true, false},
++		[ADEID_PRIVSYN] = {ADEDLEN_PRIVSYN, true, false},
++		[ADEID_PRIVID] = {ADEDLEN_PRIVID, true, false},
++	};
++
++	if (eid >= ADEID_MAX) {
++		return false;
++	}
++	if (got_len == 0) {
++		/* Entry present, but empty, allow */
++		return true;
++	}
++	if (ad_checks[eid].expected_len == 0) {
++		/*
++		 * Shouldn't happen: implicitly initialized to zero because
++		 * explicit initializer missing.
++		 */
++		return false;
++	}
++	if (ad_checks[eid].expected_len == -1) {
++		/* Unused or no limit */
++		return true;
++	}
++	if (ad_checks[eid].fixed_size) {
++		if (ad_checks[eid].expected_len != got_len) {
++			/* Wrong size fo fixed size entry. */
++			return false;
++		}
++	} else {
++		if (ad_checks[eid].minimum_size) {
++			if (got_len < ad_checks[eid].expected_len) {
++				/*
++				 * Too small for variable sized entry with
++				 * minimum size.
++				 */
++				return false;
++			}
++		} else {
++			if (got_len > ad_checks[eid].expected_len) {
++				/* Too big for variable sized entry. */
++				return false;
++			}
++		}
++	}
++	if (off + got_len < off) {
++		/* wrap around */
++		return false;
++	}
++	if (off + got_len > bufsize) {
++		/* overflow */
++		return false;
++	}
++	return true;
++}
++
+ /**
+  * Return a pointer to an AppleDouble entry
+  *
+@@ -276,8 +365,15 @@ size_t ad_setentryoff(struct adouble *ad, int eid, size_t off)
+  **/
+ char *ad_get_entry(const struct adouble *ad, int eid)
+ {
++	size_t bufsize = talloc_get_size(ad->ad_data);
+ 	off_t off = ad_getentryoff(ad, eid);
+ 	size_t len = ad_getentrylen(ad, eid);
++	bool valid;
++
++	valid = ad_entry_check_size(eid, bufsize, off, len);
++	if (!valid) {
++		return NULL;
++	}
+ 
+ 	if (off == 0 || len == 0) {
+ 		return NULL;
+@@ -914,20 +1010,11 @@ static bool ad_unpack(struct adouble *ad, const size_t nentries,
+ 			return false;
+ 		}
+ 
+-		/*
+-		 * All entries besides FinderInfo and resource fork
+-		 * must fit into the buffer. FinderInfo is special as
+-		 * it may be larger then the default 32 bytes (if it
+-		 * contains marshalled xattrs), but we will fixup that
+-		 * in ad_convert(). And the resource fork is never
+-		 * accessed directly by the ad_data buf (also see
+-		 * comment above) anyway.
+-		 */
+-		if ((eid != ADEID_RFORK) &&
+-		    (eid != ADEID_FINDERI) &&
+-		    ((off + len) > bufsize)) {
+-			DEBUG(1, ("bogus eid %d: off: %" PRIu32 ", len: %" PRIu32 "\n",
+-				  eid, off, len));
++		ok = ad_entry_check_size(eid, bufsize, off, len);
++		if (!ok) {
++			DBG_ERR("bogus eid [%"PRIu32"] bufsize [%zu] "
++				"off [%"PRIu32"] len [%"PRIu32"]\n",
++				eid, bufsize, off, len);
+ 			return false;
+ 		}
+ 
+-- 
+2.34.1
+
diff --git a/SOURCES/samba-4.14-del-dir-with-dangling-symlinks.patch b/SOURCES/samba-4.14-del-dir-with-dangling-symlinks.patch
new file mode 100644
index 0000000..ca9dd8e
--- /dev/null
+++ b/SOURCES/samba-4.14-del-dir-with-dangling-symlinks.patch
@@ -0,0 +1,1023 @@
+From a0618e0eda69d31d090f776a9217a6a3cf76e5da Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra@samba.org>
+Date: Thu, 21 Oct 2021 16:37:27 -0700
+Subject: [PATCH 1/7] s3: smbd: Add two tests showing the ability to delete a
+ directory containing a dangling symlink over SMB2 depends on "delete veto
+ files" setting.
+
+Add knownfail.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879
+
+Signed-off-by: Jeremy Allison <jra@samba.org>
+Reviewed-by: Ralph Boehme <slow@samba.org>
+(cherry picked from commit 942123b95923f35a32df4196a072a3ed3468396a)
+(cherry picked from commit 359517877d6462ff4398401748f921c8b79357a6)
+---
+ selftest/knownfail.d/rmdir_dangle_symlink     |   1 +
+ selftest/target/Samba3.pm                     |   4 +
+ .../test_delete_veto_files_only_rmdir.sh      | 183 ++++++++++++++++++
+ source3/selftest/tests.py                     |   3 +
+ 4 files changed, 191 insertions(+)
+ create mode 100644 selftest/knownfail.d/rmdir_dangle_symlink
+ create mode 100755 source3/script/tests/test_delete_veto_files_only_rmdir.sh
+
+diff --git a/selftest/knownfail.d/rmdir_dangle_symlink b/selftest/knownfail.d/rmdir_dangle_symlink
+new file mode 100644
+index 00000000000..c775dc5fe15
+--- /dev/null
++++ b/selftest/knownfail.d/rmdir_dangle_symlink
+@@ -0,0 +1 @@
++^samba3.blackbox.test_dangle_rmdir.rmdir can delete directory containing dangling symlink\(fileserver\)
+diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
+index bbff9d74817..588d7779dd4 100755
+--- a/selftest/target/Samba3.pm
++++ b/selftest/target/Samba3.pm
+@@ -1584,6 +1584,10 @@ sub setup_fileserver
+ 	veto files = /veto_name*/
+ 	delete veto files = yes
+ 
++[delete_veto_files_only]
++	path = $veto_sharedir
++	delete veto files = yes
++
+ [homes]
+ 	comment = Home directories
+ 	browseable = No
+diff --git a/source3/script/tests/test_delete_veto_files_only_rmdir.sh b/source3/script/tests/test_delete_veto_files_only_rmdir.sh
+new file mode 100755
+index 00000000000..d2c3b2198f7
+--- /dev/null
++++ b/source3/script/tests/test_delete_veto_files_only_rmdir.sh
+@@ -0,0 +1,183 @@
++#!/bin/sh
++#
++# Check smbclient can (or cannot) delete a directory containing dangling symlinks.
++# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879
++#
++
++if [ $# -lt 6 ]; then
++cat <<EOF
++Usage: $0 SERVER SERVER_IP USERNAME PASSWORD SHAREPATH SMBCLIENT
++EOF
++exit 1;
++fi
++
++SERVER=${1}
++SERVER_IP=${2}
++USERNAME=${3}
++PASSWORD=${4}
++SHAREPATH=${5}
++SMBCLIENT=${6}
++shift 6
++SMBCLIENT="$VALGRIND ${SMBCLIENT}"
++ADDARGS="$@"
++
++incdir=$(dirname "$0")/../../../testprogs/blackbox
++. $incdir/subunit.sh
++
++failed=0
++
++rmdir_path="$SHAREPATH/dir"
++
++#
++# Using the share "[delete_veto_files_only]" we CAN delete
++# a directory containing only a dangling symlink.
++#
++test_dangle_symlink_delete_veto_rmdir()
++{
++    local dangle_symlink_path="$rmdir_path/bad_link"
++    local tmpfile=$PREFIX/smbclient.in.$$
++
++    # Create rmdir directory.
++    mkdir -p "$rmdir_path"
++    # Create dangling symlink underneath.
++    ln -s "nowhere-foo" "$dangle_symlink_path"
++
++    cat > "$tmpfile" <<EOF
++cd dir
++ls
++quit
++EOF
++
++    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/delete_veto_files_only -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
++    eval echo "$cmd"
++    out=$(eval "$cmd")
++    ret=$?
++
++    # Check for smbclient error.
++    if [ $ret != 0 ] ; then
++        echo "Failed accessing share delete_veto_files_only - $ret"
++        echo "$out"
++        return 1
++    fi
++
++    # We should NOT see the dangling symlink file.
++    echo "$out" | grep bad_link
++    ret=$?
++    if [ $ret -eq 0 ] ; then
++       echo "Saw dangling symlink bad_link in share delete_veto_files_only"
++       echo "$out"
++       return 1
++    fi
++
++    # Try and remove the directory, should succeed.
++    cat > "$tmpfile" <<EOF
++rd dir
++quit
++EOF
++
++    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/delete_veto_files_only -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
++    eval echo "$cmd"
++    out=$(eval "$cmd")
++    ret=$?
++
++    # Check for smbclient error.
++    if [ $ret != 0 ] ; then
++        echo "Failed accessing share delete_veto_files_only - $ret"
++        echo "$out"
++        return 1
++    fi
++
++    # We should get no NT_STATUS_ errors.
++    echo "$out" | grep NT_STATUS_
++    ret=$?
++    if [ $ret -eq 0 ] ; then
++       echo "Got error NT_STATUS_ in share delete_veto_files_only"
++       echo "$out"
++       return 1
++    fi
++
++    return 0
++}
++
++#
++# Using the share "[veto_files_nodelete]" we CANNOT delete
++# a directory containing only a dangling symlink.
++#
++test_dangle_symlink_veto_files_nodelete()
++{
++    local dangle_symlink_path="$rmdir_path/bad_link"
++    local tmpfile=$PREFIX/smbclient.in.$$
++
++    # Create rmdir directory.
++    mkdir -p "$rmdir_path"
++    # Create dangling symlink underneath.
++    ln -s "nowhere-foo" "$dangle_symlink_path"
++
++    cat > "$tmpfile" <<EOF
++cd dir
++ls
++quit
++EOF
++
++    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_nodelete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
++    eval echo "$cmd"
++    out=$(eval "$cmd")
++    ret=$?
++
++    # Check for smbclient error.
++    if [ $ret != 0 ] ; then
++        echo "Failed accessing share veto_files_nodelete - $ret"
++        echo "$out"
++        return 1
++    fi
++
++    # We should NOT see the dangling symlink file.
++    echo "$out" | grep bad_link
++    ret=$?
++    if [ $ret -eq 0 ] ; then
++       echo "Saw dangling symlink bad_link in share veto_files_nodelete"
++       echo "$out"
++       return 1
++    fi
++
++    # Try and remove the directory, should fail with DIRECTORY_NOT_EMPTY.
++    cat > "$tmpfile" <<EOF
++rd dir
++quit
++EOF
++
++    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_nodelete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
++    eval echo "$cmd"
++    out=$(eval "$cmd")
++    ret=$?
++
++    # Check for smbclient error.
++    if [ $ret != 0 ] ; then
++        echo "Failed accessing share veto_files_nodelete - $ret"
++        echo "$out"
++        return 1
++    fi
++
++    # We should get NT_STATUS_DIRECTORY_NOT_EMPTY errors.
++    echo "$out" | grep NT_STATUS_DIRECTORY_NOT_EMPTY
++    ret=$?
++    if [ $ret -ne 0 ] ; then
++       echo "Should get NT_STATUS_DIRECTORY_NOT_EMPTY in share veto_files_nodelete"
++       echo "$out"
++       return 1
++    fi
++
++    return 0
++}
++
++
++testit "rmdir can delete directory containing dangling symlink" \
++   test_dangle_symlink_delete_veto_rmdir || failed=$(expr "$failed" + 1)
++
++rm -rf "$rmdir_path"
++
++testit "rmdir cannot delete directory delete_veto_files_no containing dangling symlink" \
++   test_dangle_symlink_veto_files_nodelete || failed=$(expr "$failed" + 1)
++
++rm -rf "$rmdir_path"
++exit "$failed"
+diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
+index 82f32ec4232..330024cf77c 100755
+--- a/source3/selftest/tests.py
++++ b/source3/selftest/tests.py
+@@ -501,6 +501,9 @@ for env in ["fileserver"]:
+     plantestsuite("samba3.blackbox.test_veto_rmdir", env,
+                   [os.path.join(samba3srcdir, "script/tests/test_veto_rmdir.sh"),
+                   '$SERVER', '$SERVER_IP', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/veto', smbclient3])
++    plantestsuite("samba3.blackbox.test_dangle_rmdir", env,
++                  [os.path.join(samba3srcdir, "script/tests/test_delete_veto_files_only_rmdir.sh"),
++                  '$SERVER', '$SERVER_IP', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/veto', smbclient3])
+ 
+     #
+     # tar command tests
+-- 
+2.33.1
+
+
+From 47c98fe40101b60d5b5a34eb8ef02106c1da66c9 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra@samba.org>
+Date: Mon, 25 Oct 2021 12:01:58 -0700
+Subject: [PATCH 2/7] s3: VFS: streams_depot. Allow unlinkat to cope with
+ dangling symlinks.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879
+
+Signed-off-by: Jeremy Allison <jra@samba.org>
+Reviewed-by: Ralph Boehme <slow@samba.org>
+(cherry picked from commit 295d7d026babe3cd5123d0f53adcb16868907f05)
+(backported from commit 7a4173809a87350bc3580240232978042ec2ceca)
+[pfilipen@redhat.com: code in 4.15 uses different variable name]
+---
+ source3/modules/vfs_streams_depot.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c
+index a5e02d5a069..dd6376e5fd0 100644
+--- a/source3/modules/vfs_streams_depot.c
++++ b/source3/modules/vfs_streams_depot.c
+@@ -739,6 +739,16 @@ static int streams_depot_unlink_internal(vfs_handle_struct *handle,
+ 		ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_base);
+ 	} else {
+ 		ret = SMB_VFS_NEXT_STAT(handle, smb_fname_base);
++		if (ret == -1 && (errno == ENOENT || errno == ELOOP)) {
++			if (VALID_STAT(smb_fname->st) &&
++					S_ISLNK(smb_fname->st.st_ex_mode)) {
++				/*
++				 * Original name was a link - Could be
++				 * trying to remove a dangling symlink.
++				 */
++				ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_base);
++			}
++		}
+ 	}
+ 
+ 	if (ret == -1) {
+-- 
+2.33.1
+
+
+From 474a91d03527a15f7655be3866a9e5eaa405118f Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra@samba.org>
+Date: Mon, 25 Oct 2021 12:02:43 -0700
+Subject: [PATCH 3/7] s3: VFS: xattr_tdb. Allow unlinkat to cope with dangling
+ symlinks.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879
+
+Signed-off-by: Jeremy Allison <jra@samba.org>
+Reviewed-by: Ralph Boehme <slow@samba.org>
+(cherry picked from commit f254be19d6501a4f573843af97963e350a9ee2ed)
+(backported from commit 0dba0917fd97e975d1daab5b0828644d026c2bc5)
+[pfilipen@redhat.com: code in 4.15 uses different variable name]
+---
+ source3/modules/vfs_xattr_tdb.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/source3/modules/vfs_xattr_tdb.c b/source3/modules/vfs_xattr_tdb.c
+index d89a1dd0d7d..e06ff9639f1 100644
+--- a/source3/modules/vfs_xattr_tdb.c
++++ b/source3/modules/vfs_xattr_tdb.c
+@@ -639,6 +639,16 @@ static int xattr_tdb_unlinkat(vfs_handle_struct *handle,
+ 		ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_tmp);
+ 	} else {
+ 		ret = SMB_VFS_NEXT_STAT(handle, smb_fname_tmp);
++		if (ret == -1 && (errno == ENOENT || errno == ELOOP)) {
++			if (VALID_STAT(smb_fname->st) &&
++					S_ISLNK(smb_fname->st.st_ex_mode)) {
++				/*
++				 * Original name was a link - Could be
++				 * trying to remove a dangling symlink.
++				 */
++				ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_tmp);
++			}
++		}
+ 	}
+ 	if (ret == -1) {
+ 		goto out;
+-- 
+2.33.1
+
+
+From 298a8dac1160ebba56cd84b7e25908e160b88f85 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra@samba.org>
+Date: Mon, 25 Oct 2021 12:21:37 -0700
+Subject: [PATCH 4/7] s3: smbd: Fix rmdir_internals() to do an early return if
+ lp_delete_veto_files() is not set.
+
+Fix the comments to match what the code actually does. The
+exit at the end of the scan directory loop if we find a client
+visible filename is a change in behavior, but the previous
+behavior (not exist on visible filename, but delete it) was
+a bug and in non-tested code. Now it's testd.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879
+
+Signed-off-by: Jeremy Allison <jra@samba.org>
+Reviewed-by: Ralph Boehme <slow@samba.org>
+(cherry picked from commit a37d16e7c55f85e3f2c9c8614755ea6307092d5f)
+(backported from commit e00fe095e8cf7ab54bc82870b913762d2fdddbad)
+[pfilipen@redhat.com: rmdir_internals() got refactored in 4.15]
+---
+ source3/smbd/close.c | 247 ++++++++++++++++++++++---------------------
+ 1 file changed, 128 insertions(+), 119 deletions(-)
+
+diff --git a/source3/smbd/close.c b/source3/smbd/close.c
+index f05619d1886..0c102b9533b 100644
+--- a/source3/smbd/close.c
++++ b/source3/smbd/close.c
+@@ -938,8 +938,11 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp)
+ {
+ 	connection_struct *conn = fsp->conn;
+ 	struct smb_filename *smb_dname = fsp->fsp_name;
+-	const struct loadparm_substitution *lp_sub =
+-		loadparm_s3_global_substitution();
++	SMB_STRUCT_STAT st;
++	const char *dname = NULL;
++	char *talloced = NULL;
++	long dirpos = 0;
++	struct smb_Dir *dir_hnd = NULL;
+ 	int ret;
+ 
+ 	SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
+@@ -974,143 +977,149 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp)
+ 		return NT_STATUS_OK;
+ 	}
+ 
+-	if(((errno == ENOTEMPTY)||(errno == EEXIST)) && *lp_veto_files(talloc_tos(), lp_sub, SNUM(conn))) {
+-		/*
+-		 * Check to see if the only thing in this directory are
+-		 * vetoed files/directories. If so then delete them and
+-		 * retry. If we fail to delete any of them (and we *don't*
+-		 * do a recursive delete) then fail the rmdir.
+-		 */
+-		SMB_STRUCT_STAT st;
+-		const char *dname = NULL;
+-		char *talloced = NULL;
+-		long dirpos = 0;
+-		struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
+-						  smb_dname, NULL,
+-						  0);
+-
+-		if(dir_hnd == NULL) {
++	if (!((errno == ENOTEMPTY) || (errno == EEXIST))) {
++		DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
++			 "%s\n", smb_fname_str_dbg(smb_dname),
++			 strerror(errno)));
++		return map_nt_error_from_unix(errno);
++	}
++
++	/*
++	 * Here we know the initial directory unlink failed with
++	 * ENOTEMPTY or EEXIST so we know there are objects within.
++	 * If we don't have permission to delete files non
++	 * visible to the client just fail the directory delete.
++	 */
++
++	if (!lp_delete_veto_files(SNUM(conn))) {
++		errno = ENOTEMPTY;
++		goto err;
++	}
++
++	/*
++	 * Check to see if the only thing in this directory are
++	 * files non-visible to the client. If not, fail the delete.
++	 */
++
++	dir_hnd = OpenDir(talloc_tos(), conn, smb_dname, NULL, 0);
++	if (dir_hnd == NULL) {
++		errno = ENOTEMPTY;
++		goto err;
++	}
++
++	while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced)) != NULL) {
++		if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) {
++			TALLOC_FREE(talloced);
++			continue;
++		}
++		if (!is_visible_file(conn,
++					dir_hnd,
++					dname,
++					&st,
++					false)) {
++			TALLOC_FREE(talloced);
++			continue;
++		}
++		if(!IS_VETO_PATH(conn, dname)) {
++			/*
++			 * We found a client visible name.
++			 * We cannot delete this directory.
++			 */
++			DBG_DEBUG("got name %s - "
++				"can't delete directory %s\n",
++				dname,
++				fsp_str_dbg(fsp));
++			TALLOC_FREE(dir_hnd);
++			TALLOC_FREE(talloced);
+ 			errno = ENOTEMPTY;
+ 			goto err;
+ 		}
++		TALLOC_FREE(talloced);
++	}
+ 
+-		while ((dname = ReadDirName(dir_hnd, &dirpos, &st,
+-					    &talloced)) != NULL) {
+-			if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) {
+-				TALLOC_FREE(talloced);
+-				continue;
+-			}
+-			if (!is_visible_file(conn,
+-						dir_hnd,
+-						dname,
+-						&st,
+-						false)) {
+-				TALLOC_FREE(talloced);
+-				continue;
+-			}
+-			if(!IS_VETO_PATH(conn, dname)) {
+-				TALLOC_FREE(dir_hnd);
+-				TALLOC_FREE(talloced);
+-				errno = ENOTEMPTY;
+-				goto err;
+-			}
++	/* Do a recursive delete. */
++	RewindDir(dir_hnd,&dirpos);
++	while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced)) != NULL) {
++		struct smb_filename *smb_dname_full = NULL;
++		char *fullname = NULL;
++		bool do_break = true;
++
++		if (ISDOT(dname) || ISDOTDOT(dname)) {
++			TALLOC_FREE(talloced);
++			continue;
++		}
++		if (!is_visible_file(conn,
++					dir_hnd,
++					dname,
++					&st,
++					false)) {
+ 			TALLOC_FREE(talloced);
++			continue;
+ 		}
+ 
+-		/* We only have veto files/directories.
+-		 * Are we allowed to delete them ? */
++		fullname = talloc_asprintf(ctx,
++				"%s/%s",
++				smb_dname->base_name,
++				dname);
+ 
+-		if(!lp_delete_veto_files(SNUM(conn))) {
+-			TALLOC_FREE(dir_hnd);
+-			errno = ENOTEMPTY;
+-			goto err;
++		if (fullname == NULL) {
++			errno = ENOMEM;
++			goto err_break;
+ 		}
+ 
+-		/* Do a recursive delete. */
+-		RewindDir(dir_hnd,&dirpos);
+-		while ((dname = ReadDirName(dir_hnd, &dirpos, &st,
+-					    &talloced)) != NULL) {
+-			struct smb_filename *smb_dname_full = NULL;
+-			char *fullname = NULL;
+-			bool do_break = true;
+-
+-			if (ISDOT(dname) || ISDOTDOT(dname)) {
+-				TALLOC_FREE(talloced);
+-				continue;
+-			}
+-			if (!is_visible_file(conn,
+-						dir_hnd,
+-						dname,
+-						&st,
+-						false)) {
+-				TALLOC_FREE(talloced);
+-				continue;
+-			}
+-
+-			fullname = talloc_asprintf(ctx,
+-					"%s/%s",
+-					smb_dname->base_name,
+-					dname);
++		smb_dname_full = synthetic_smb_fname(talloc_tos(),
++						fullname,
++						NULL,
++						NULL,
++						smb_dname->twrp,
++						smb_dname->flags);
++		if (smb_dname_full == NULL) {
++			errno = ENOMEM;
++			goto err_break;
++		}
+ 
+-			if(!fullname) {
+-				errno = ENOMEM;
++		if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
++			goto err_break;
++		}
++		if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
++			int retval;
++			if(!recursive_rmdir(ctx, conn,
++					    smb_dname_full)) {
+ 				goto err_break;
+ 			}
+-
+-			smb_dname_full = synthetic_smb_fname(talloc_tos(),
+-							fullname,
+-							NULL,
+-							NULL,
+-							smb_dname->twrp,
+-							smb_dname->flags);
+-			if (smb_dname_full == NULL) {
+-				errno = ENOMEM;
++			retval = SMB_VFS_UNLINKAT(conn,
++					conn->cwd_fsp,
++					smb_dname_full,
++					AT_REMOVEDIR);
++			if(retval != 0) {
+ 				goto err_break;
+ 			}
+-
+-			if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
++		} else {
++			int retval = SMB_VFS_UNLINKAT(conn,
++					conn->cwd_fsp,
++					smb_dname_full,
++					0);
++			if(retval != 0) {
+ 				goto err_break;
+ 			}
+-			if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
+-				int retval;
+-				if(!recursive_rmdir(ctx, conn,
+-						    smb_dname_full)) {
+-					goto err_break;
+-				}
+-				retval = SMB_VFS_UNLINKAT(conn,
+-						conn->cwd_fsp,
+-						smb_dname_full,
+-						AT_REMOVEDIR);
+-				if(retval != 0) {
+-					goto err_break;
+-				}
+-			} else {
+-				int retval = SMB_VFS_UNLINKAT(conn,
+-						conn->cwd_fsp,
+-						smb_dname_full,
+-						0);
+-				if(retval != 0) {
+-					goto err_break;
+-				}
+-			}
++		}
+ 
+-			/* Successful iteration. */
+-			do_break = false;
++		/* Successful iteration. */
++		do_break = false;
+ 
+-		 err_break:
+-			TALLOC_FREE(fullname);
+-			TALLOC_FREE(smb_dname_full);
+-			TALLOC_FREE(talloced);
+-			if (do_break)
+-				break;
+-		}
+-		TALLOC_FREE(dir_hnd);
+-		/* Retry the rmdir */
+-		ret = SMB_VFS_UNLINKAT(conn,
+-				conn->cwd_fsp,
+-				smb_dname,
+-				AT_REMOVEDIR);
++	err_break:
++		TALLOC_FREE(fullname);
++		TALLOC_FREE(smb_dname_full);
++		TALLOC_FREE(talloced);
++		if (do_break)
++			break;
+ 	}
++	TALLOC_FREE(dir_hnd);
++	/* Retry the rmdir */
++	ret = SMB_VFS_UNLINKAT(conn,
++			conn->cwd_fsp,
++			smb_dname,
++			AT_REMOVEDIR);
+ 
+   err:
+ 
+-- 
+2.33.1
+
+
+From a7075aeedd078c68b57556678fa40907cd66cd08 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra@samba.org>
+Date: Mon, 25 Oct 2021 12:32:29 -0700
+Subject: [PATCH 5/7] s3: smbd: Fix logic in rmdir_internals() to cope with
+ dangling symlinks.
+
+Still need to add the same logic in can_delete_directory_fsp()
+before we can delete the knownfail.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879
+
+Signed-off-by: Jeremy Allison <jra@samba.org>
+Reviewed-by: Ralph Boehme <slow@samba.org>
+(cherry picked from commit 26fecad2e66e91a3913d88ee2e0889f266e91d89)
+(backported from commit 4793c4d5307472f0eb72f70f7dbf7324744e3f91)
+[pfilipen@redhat.com: rmdir_internals() got refactored in 4.15]
+---
+ source3/smbd/close.c | 103 ++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 101 insertions(+), 2 deletions(-)
+
+diff --git a/source3/smbd/close.c b/source3/smbd/close.c
+index 0c102b9533b..81811f703b0 100644
+--- a/source3/smbd/close.c
++++ b/source3/smbd/close.c
+@@ -1008,10 +1008,14 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp)
+ 	}
+ 
+ 	while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced)) != NULL) {
++		struct smb_filename *smb_dname_full = NULL;
++		char *fullname = NULL;
++
+ 		if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) {
+ 			TALLOC_FREE(talloced);
+ 			continue;
+ 		}
++
+ 		if (!is_visible_file(conn,
+ 					dir_hnd,
+ 					dname,
+@@ -1020,6 +1024,98 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp)
+ 			TALLOC_FREE(talloced);
+ 			continue;
+ 		}
++
++		fullname = talloc_asprintf(talloc_tos(),
++					   "%s/%s",
++					   smb_dname->base_name,
++					   dname);
++
++		if (fullname == NULL) {
++			TALLOC_FREE(talloced);
++			errno = ENOMEM;
++			goto err;
++		}
++
++		smb_dname_full = synthetic_smb_fname(talloc_tos(),
++						     fullname,
++						     NULL,
++						     NULL,
++						     smb_dname->twrp,
++						     smb_dname->flags);
++		if (smb_dname_full == NULL) {
++			TALLOC_FREE(talloced);
++			TALLOC_FREE(fullname);
++			errno = ENOMEM;
++			goto err;
++		}
++
++		ret = SMB_VFS_LSTAT(conn, smb_dname_full);
++		if (ret != 0) {
++			int saved_errno = errno;
++			TALLOC_FREE(talloced);
++			TALLOC_FREE(fullname);
++			TALLOC_FREE(smb_dname_full);
++			errno = saved_errno;
++			goto err;
++		}
++
++		if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
++			/* Could it be an msdfs link ? */
++			if (lp_host_msdfs() &&
++				lp_msdfs_root(SNUM(conn))) {
++				struct smb_filename *smb_atname;
++				smb_atname = synthetic_smb_fname(talloc_tos(),
++							dname,
++							NULL,
++							&smb_dname_full->st,
++							fsp->fsp_name->twrp,
++							fsp->fsp_name->flags);
++				if (smb_atname == NULL) {
++					TALLOC_FREE(talloced);
++					TALLOC_FREE(fullname);
++					TALLOC_FREE(smb_dname_full);
++					errno = ENOMEM;
++					goto err;
++				}
++				if (is_msdfs_link(conn, smb_atname)) {
++					TALLOC_FREE(talloced);
++					TALLOC_FREE(fullname);
++					TALLOC_FREE(smb_dname_full);
++					TALLOC_FREE(smb_atname);
++					DBG_DEBUG("got msdfs link name %s "
++						"- can't delete directory %s\n",
++						dname,
++						fsp_str_dbg(fsp));
++					errno = ENOTEMPTY;
++					goto err;
++				}
++				TALLOC_FREE(smb_atname);
++			}
++
++			/* Not a DFS link - could it be a dangling symlink ? */
++			ret = SMB_VFS_STAT(conn, smb_dname_full);
++			if (ret == -1 && (errno == ENOENT || errno == ELOOP)) {
++				/*
++				 * Dangling symlink.
++				 * Allow delete as "delete veto files = yes"
++				 */
++				TALLOC_FREE(talloced);
++				TALLOC_FREE(fullname);
++				TALLOC_FREE(smb_dname_full);
++				continue;
++			}
++
++			DBG_DEBUG("got symlink name %s - "
++				"can't delete directory %s\n",
++				dname,
++				fsp_str_dbg(fsp));
++			TALLOC_FREE(talloced);
++			TALLOC_FREE(fullname);
++			TALLOC_FREE(smb_dname_full);
++			errno = ENOTEMPTY;
++			goto err;
++		}
++
+ 		if(!IS_VETO_PATH(conn, dname)) {
+ 			/*
+ 			 * We found a client visible name.
+@@ -1029,12 +1125,15 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp)
+ 				"can't delete directory %s\n",
+ 				dname,
+ 				fsp_str_dbg(fsp));
+-			TALLOC_FREE(dir_hnd);
+ 			TALLOC_FREE(talloced);
++			TALLOC_FREE(fullname);
++			TALLOC_FREE(smb_dname_full);
+ 			errno = ENOTEMPTY;
+ 			goto err;
+ 		}
+ 		TALLOC_FREE(talloced);
++		TALLOC_FREE(fullname);
++		TALLOC_FREE(smb_dname_full);
+ 	}
+ 
+ 	/* Do a recursive delete. */
+@@ -1114,7 +1213,6 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp)
+ 		if (do_break)
+ 			break;
+ 	}
+-	TALLOC_FREE(dir_hnd);
+ 	/* Retry the rmdir */
+ 	ret = SMB_VFS_UNLINKAT(conn,
+ 			conn->cwd_fsp,
+@@ -1123,6 +1221,7 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp)
+ 
+   err:
+ 
++	TALLOC_FREE(dir_hnd);
+ 	if (ret != 0) {
+ 		DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
+ 			 "%s\n", smb_fname_str_dbg(smb_dname),
+-- 
+2.33.1
+
+
+From 843fc3b857cdfd6c7e902acef933d17690815e7e Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra@samba.org>
+Date: Mon, 25 Oct 2021 12:36:57 -0700
+Subject: [PATCH 6/7] s3: smbd: Fix logic in can_delete_directory_fsp() to cope
+ with dangling symlinks.
+
+Remove knownfail.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879
+
+Signed-off-by: Jeremy Allison <jra@samba.org>
+Reviewed-by: Ralph Boehme <slow@samba.org>
+(cherry picked from commit e9ef970eee5eca8ab3720279c54098e91d2dfda9)
+(backported from commit 5023dbc04bfad7cc39e8c4de96f40c82e7a0288e)
+[pfilipen@redhat.com: can_delete_directory_fsp() got refactored in 4.15]
+---
+ selftest/knownfail.d/rmdir_dangle_symlink |  1 -
+ source3/smbd/dir.c                        | 97 +++++++++++++++++++++++
+ 2 files changed, 97 insertions(+), 1 deletion(-)
+ delete mode 100644 selftest/knownfail.d/rmdir_dangle_symlink
+
+diff --git a/selftest/knownfail.d/rmdir_dangle_symlink b/selftest/knownfail.d/rmdir_dangle_symlink
+deleted file mode 100644
+index c775dc5fe15..00000000000
+--- a/selftest/knownfail.d/rmdir_dangle_symlink
++++ /dev/null
+@@ -1 +0,0 @@
+-^samba3.blackbox.test_dangle_rmdir.rmdir can delete directory containing dangling symlink\(fileserver\)
+diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
+index 545c7499f28..96edc8678e5 100644
+--- a/source3/smbd/dir.c
++++ b/source3/smbd/dir.c
+@@ -1876,6 +1876,8 @@ NTSTATUS can_delete_directory_fsp(files_struct *fsp)
+ 	char *talloced = NULL;
+ 	SMB_STRUCT_STAT st;
+ 	struct connection_struct *conn = fsp->conn;
++	struct smb_filename *smb_dname = fsp->fsp_name;
++	int ret;
+ 	struct smb_Dir *dir_hnd = OpenDir(talloc_tos(),
+ 					conn,
+ 					fsp->fsp_name,
+@@ -1887,6 +1889,9 @@ NTSTATUS can_delete_directory_fsp(files_struct *fsp)
+ 	}
+ 
+ 	while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced))) {
++		struct smb_filename *smb_dname_full = NULL;
++		char *fullname = NULL;
++
+ 		if (ISDOT(dname) || (ISDOTDOT(dname))) {
+ 			TALLOC_FREE(talloced);
+ 			continue;
+@@ -1901,6 +1906,98 @@ NTSTATUS can_delete_directory_fsp(files_struct *fsp)
+ 			continue;
+ 		}
+ 
++		fullname = talloc_asprintf(talloc_tos(),
++					   "%s/%s",
++					   smb_dname->base_name,
++					   dname);
++
++		if (fullname == NULL) {
++			TALLOC_FREE(dir_hnd);
++			TALLOC_FREE(talloced);
++			return NT_STATUS_NO_MEMORY;
++		}
++
++		smb_dname_full = synthetic_smb_fname(talloc_tos(),
++						     fullname,
++						     NULL,
++						     NULL,
++						     smb_dname->twrp,
++						     smb_dname->flags);
++		if (smb_dname_full == NULL) {
++			TALLOC_FREE(dir_hnd);
++			TALLOC_FREE(talloced);
++			TALLOC_FREE(fullname);
++			return NT_STATUS_NO_MEMORY;
++		}
++
++		ret = SMB_VFS_LSTAT(conn, smb_dname_full);
++		if (ret != 0) {
++			TALLOC_FREE(dir_hnd);
++			TALLOC_FREE(talloced);
++			TALLOC_FREE(fullname);
++			TALLOC_FREE(smb_dname_full);
++			return map_nt_error_from_unix(errno);
++		}
++
++		if (S_ISLNK(smb_dname_full->st.st_ex_mode)) {
++			/* Could it be an msdfs link ? */
++			if (lp_host_msdfs() &&
++			    lp_msdfs_root(SNUM(conn))) {
++				struct smb_filename *smb_atname;
++				smb_atname = synthetic_smb_fname(talloc_tos(),
++							dname,
++							NULL,
++							&smb_dname_full->st,
++							fsp->fsp_name->twrp,
++							fsp->fsp_name->flags);
++				if (smb_atname == NULL) {
++					TALLOC_FREE(dir_hnd);
++					TALLOC_FREE(talloced);
++					TALLOC_FREE(fullname);
++					TALLOC_FREE(smb_dname_full);
++					return NT_STATUS_NO_MEMORY;
++				}
++				if (is_msdfs_link(conn, smb_atname)) {
++					TALLOC_FREE(dir_hnd);
++					TALLOC_FREE(talloced);
++					TALLOC_FREE(fullname);
++					TALLOC_FREE(smb_dname_full);
++					TALLOC_FREE(smb_atname);
++					DBG_DEBUG("got msdfs link name %s "
++						"- can't delete directory %s\n",
++						dname,
++						fsp_str_dbg(fsp));
++					return NT_STATUS_DIRECTORY_NOT_EMPTY;
++				}
++				TALLOC_FREE(smb_atname);
++			}
++
++			/* Not a DFS link - could it be a dangling symlink ? */
++			ret = SMB_VFS_STAT(conn, smb_dname_full);
++			if (ret == -1 && (errno == ENOENT || errno == ELOOP)) {
++				/*
++				 * Dangling symlink.
++				 * Allow if "delete veto files = yes"
++				 */
++				if (lp_delete_veto_files(SNUM(conn))) {
++					TALLOC_FREE(talloced);
++					TALLOC_FREE(fullname);
++					TALLOC_FREE(smb_dname_full);
++					continue;
++				}
++			}
++
++			DBG_DEBUG("got symlink name %s - "
++				"can't delete directory %s\n",
++				dname,
++				fsp_str_dbg(fsp));
++			TALLOC_FREE(dir_hnd);
++			TALLOC_FREE(talloced);
++			TALLOC_FREE(fullname);
++			TALLOC_FREE(smb_dname_full);
++			return NT_STATUS_DIRECTORY_NOT_EMPTY;
++		}
++
+ 		DEBUG(10,("got name %s - can't delete\n",
+ 			 dname ));
+ 		status = NT_STATUS_DIRECTORY_NOT_EMPTY;
+-- 
+2.33.1
+
+
+From 7189ea825d8c9e4777dba737227ead602ad9b651 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra@samba.org>
+Date: Mon, 25 Oct 2021 12:42:02 -0700
+Subject: [PATCH 7/7] s3: docs-xml: Clarify the "delete veto files" paramter.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879
+
+Signed-off-by: Jeremy Allison <jra@samba.org>
+Reviewed-by: Ralph Boehme <slow@samba.org>
+
+Autobuild-User(master): Ralph Böhme <slow@samba.org>
+Autobuild-Date(master): Fri Oct 29 14:57:14 UTC 2021 on sn-devel-184
+
+(cherry picked from commit 0b818c6b77e972626d0b071bebcf4ce55619fb84)
+(cherry picked from commit a549dc219cba5bd61969e4919ae4142f52c133ea)
+---
+ docs-xml/smbdotconf/filename/deletevetofiles.xml | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/docs-xml/smbdotconf/filename/deletevetofiles.xml b/docs-xml/smbdotconf/filename/deletevetofiles.xml
+index 581dc05396d..570d4ac60a0 100644
+--- a/docs-xml/smbdotconf/filename/deletevetofiles.xml
++++ b/docs-xml/smbdotconf/filename/deletevetofiles.xml
+@@ -4,9 +4,12 @@
+                  xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+ <description>
+ 	<para>This option is used when Samba is attempting to 
+-	delete a directory that contains one or more vetoed directories 
+-	(see the <smbconfoption name="veto files"/>
+-	option).  If this option is set to <constant>no</constant> (the default) then if a vetoed 
++	delete a directory that contains one or more vetoed files
++	or directories or non-visible files or directories (such
++	as dangling symlinks that point nowhere).
++	(see the <smbconfoption name="veto files"/>, <smbconfoption name="hide special files"/>,
++	<smbconfoption name="hide unreadable"/>, <smbconfoption name="hide unwriteable files"/>
++	options).  If this option is set to <constant>no</constant> (the default) then if a vetoed
+ 	directory contains any non-vetoed files or directories then the 
+ 	directory delete will fail. This is usually what you want.</para>
+ 
+-- 
+2.33.1
+
diff --git a/SOURCES/samba-4.14-fix-domain-join-segfault.patch b/SOURCES/samba-4.14-fix-domain-join-segfault.patch
new file mode 100644
index 0000000..0521c27
--- /dev/null
+++ b/SOURCES/samba-4.14-fix-domain-join-segfault.patch
@@ -0,0 +1,39 @@
+From 0ef9fe22f56ef3ff202f88426c3ee48c15e4a71e Mon Sep 17 00:00:00 2001
+From: Ralph Boehme <slow@samba.org>
+Date: Fri, 26 Nov 2021 11:59:45 +0100
+Subject: [PATCH] smbd: s3-dsgetdcname: handle num_ips == 0
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=14923
+
+Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
+Signed-off-by: Ralph Boehme <slow@samba.org>
+Signed-off-by: Stefan Metzmacher <metze@samba.org>
+Reviewed-by: Guenther Deschner <gd@samba.org>
+Reviewed-by: Jeremy Allison <jra@samba.org>
+
+Autobuild-User(master): Stefan Metzmacher <metze@samba.org>
+Autobuild-Date(master): Fri Dec  3 12:54:04 UTC 2021 on sn-devel-184
+
+(cherry picked from commit 5e3df5f9ee64a80898f73585b19113354f463c44)
+---
+ source3/libsmb/dsgetdcname.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
+index f8ae96109b71..5954e48d747b 100644
+--- a/source3/libsmb/dsgetdcname.c
++++ b/source3/libsmb/dsgetdcname.c
+@@ -572,6 +572,10 @@ static NTSTATUS discover_dc_dns(TALLOC_CTX *mem_ctx,
+ 	for (i = 0; i < numdcs; i++) {
+ 		size_t j;
+ 
++		if (dcs[i].num_ips == 0) {
++			continue;
++		}
++
+ 		dclist[ret_count].hostname =
+ 			talloc_move(dclist, &dcs[i].hostname);
+ 
+-- 
+2.33.1
+
diff --git a/SOURCES/samba-4.14-fix-username-map-script.patch b/SOURCES/samba-4.14-fix-username-map-script.patch
new file mode 100644
index 0000000..8d7dcc8
--- /dev/null
+++ b/SOURCES/samba-4.14-fix-username-map-script.patch
@@ -0,0 +1,227 @@
+From 0e179b5f06988c576a1fff505c06920d51fe8ed4 Mon Sep 17 00:00:00 2001
+From: Stefan Metzmacher <metze@samba.org>
+Date: Fri, 12 Nov 2021 15:27:58 +0100
+Subject: [PATCH 1/3] CVE-2020-25727: idmap_nss: verify that the name of the
+ sid belongs to the configured domain
+
+We already check the sid belongs to the domain, but checking the name
+too feels better and make it easier to understand.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=14901
+
+Signed-off-by: Stefan Metzmacher <metze@samba.org>
+Reviewed-by: Ralph Boehme <slow@samba.org>
+(cherry picked from commit bfd093648b4af51d104096c0cb3535e8706671e5)
+---
+ source3/winbindd/idmap_nss.c | 26 +++++++++++++++++++++-----
+ 1 file changed, 21 insertions(+), 5 deletions(-)
+
+diff --git a/source3/winbindd/idmap_nss.c b/source3/winbindd/idmap_nss.c
+index da50e2b4aa7..2729a0de3f3 100644
+--- a/source3/winbindd/idmap_nss.c
++++ b/source3/winbindd/idmap_nss.c
+@@ -139,18 +139,21 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma
+ 	for (i = 0; ids[i]; i++) {
+ 		struct group *gr;
+ 		enum lsa_SidType type;
+-		const char *p = NULL;
++		const char *_domain = NULL;
++		const char *_name = NULL;
++		char *domain = NULL;
+ 		char *name = NULL;
+ 		bool ret;
+ 
+ 		/* by default calls to winbindd are disabled
+ 		   the following call will not recurse so this is safe */
+ 		(void)winbind_on();
+-		ret = winbind_lookup_sid(talloc_tos(), ids[i]->sid, NULL,
+-					 &p, &type);
++		ret = winbind_lookup_sid(talloc_tos(),
++					 ids[i]->sid,
++					 &_domain,
++					 &_name,
++					 &type);
+ 		(void)winbind_off();
+-		name = discard_const_p(char, p);
+-
+ 		if (!ret) {
+ 			/* TODO: how do we know if the name is really not mapped,
+ 			 * or something just failed ? */
+@@ -158,6 +161,18 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma
+ 			continue;
+ 		}
+ 
++		domain = discard_const_p(char, _domain);
++		name = discard_const_p(char, _name);
++
++		if (!strequal(domain, dom->name)) {
++			struct dom_sid_buf buf;
++			DBG_ERR("DOMAIN[%s] ignoring SID[%s] belongs to %s [%s\\%s]\n",
++			        dom->name, dom_sid_str_buf(ids[i]->sid, &buf),
++				sid_type_lookup(type), domain, name);
++			ids[i]->status = ID_UNMAPPED;
++			continue;
++		}
++
+ 		switch (type) {
+ 		case SID_NAME_USER: {
+ 			struct passwd *pw;
+@@ -190,6 +205,7 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma
+ 			ids[i]->status = ID_UNKNOWN;
+ 			break;
+ 		}
++		TALLOC_FREE(domain);
+ 		TALLOC_FREE(name);
+ 	}
+ 	return NT_STATUS_OK;
+-- 
+2.34.1
+
+
+From 704ae4b8308e9ae6c50e3548f98de65e97ab6aa6 Mon Sep 17 00:00:00 2001
+From: Joseph Sutton <josephsutton@catalyst.net.nz>
+Date: Fri, 12 Nov 2021 20:53:30 +1300
+Subject: [PATCH 2/3] CVE-2020-25717: nsswitch/nsstest.c: Lower 'non existent
+ uid' to make room for new accounts
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=14901
+
+Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
+Reviewed-by: Stefan Metzmacher <metze@samba.org>
+Reviewed-by: Ralph Boehme <slow@samba.org>
+(cherry picked from commit fdbee5e074ebd76d659613b8b7114d70f938c38a)
+---
+ nsswitch/nsstest.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/nsswitch/nsstest.c b/nsswitch/nsstest.c
+index e2ee9fbf3af..45270cdc459 100644
+--- a/nsswitch/nsstest.c
++++ b/nsswitch/nsstest.c
+@@ -466,7 +466,7 @@ static void nss_test_errors(void)
+ 		printf("ERROR Non existent user gave error %d\n", last_error);
+ 	}
+ 
+-	pwd = getpwuid(0xFFF0);
++	pwd = getpwuid(0xFF00);
+ 	if (pwd || last_error != NSS_STATUS_NOTFOUND) {
+ 		total_errors++;
+ 		printf("ERROR Non existent uid gave error %d\n", last_error);
+-- 
+2.34.1
+
+
+From 844723aa82cec67fd863fc327bde9fb04eab438d Mon Sep 17 00:00:00 2001
+From: Andrew Bartlett <abartlet@samba.org>
+Date: Fri, 12 Nov 2021 16:10:31 +1300
+Subject: [PATCH 3/3] CVE-2020-25717: s3:auth: Fallback to a SID/UID based
+ mapping if the named based lookup fails
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Before the CVE-2020-25717 fixes we had a fallback from
+getpwnam('DOMAIN\user') to getpwnam('user') which was very dangerous and
+unpredictable.
+
+Now we do the fallback based on sid_to_uid() followed by
+getpwuid() on the returned uid.
+
+This obsoletes 'username map [script]' based workaround adviced
+for CVE-2020-25717, when nss_winbindd is not used or
+idmap_nss is actually used.
+
+In future we may decide to prefer or only do the SID/UID based
+lookup, but for now we want to keep this unchanged as much as possible.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=14901
+
+Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
+
+Signed-off-by: Andrew Bartlett <abartlet@samba.org>
+Signed-off-by: Stefan Metzmacher <metze@samba.org>
+
+[metze@samba.org moved the new logic into the fallback codepath only
+ in order to avoid behavior changes as much as possible]
+Reviewed-by: Ralph Boehme <slow@samba.org>
+
+Autobuild-User(master): Ralph Böhme <slow@samba.org>
+Autobuild-Date(master): Mon Nov 15 19:01:56 UTC 2021 on sn-devel-184
+
+(cherry picked from commit 0a546be05295a7e4a552f9f4f0c74aeb2e9a0d6e)
+---
+ source3/auth/auth_util.c | 34 +++++++++++++++++++++++++++++++++-
+ 1 file changed, 33 insertions(+), 1 deletion(-)
+
+diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
+index 065b525500f..7a97dd45f11 100644
+--- a/source3/auth/auth_util.c
++++ b/source3/auth/auth_util.c
+@@ -1862,7 +1862,9 @@ const struct auth_session_info *get_session_info_system(void)
+ ***************************************************************************/
+ 
+ static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
+-			      const char *username, char **found_username,
++			      const char *username,
++			      const struct dom_sid *sid,
++			      char **found_username,
+ 			      struct passwd **pwd,
+ 			      bool *username_was_mapped)
+ {
+@@ -1897,6 +1899,31 @@ static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
+ 	}
+ 
+ 	passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, false);
++	if (!passwd && !*username_was_mapped) {
++		struct dom_sid_buf buf;
++		uid_t uid;
++		bool ok;
++
++		DBG_DEBUG("Failed to find authenticated user %s via "
++			  "getpwnam(), fallback to sid_to_uid(%s).\n",
++			  dom_user, dom_sid_str_buf(sid, &buf));
++
++		ok = sid_to_uid(sid, &uid);
++		if (!ok) {
++			DBG_ERR("Failed to convert SID %s to a UID (dom_user[%s])\n",
++				dom_sid_str_buf(sid, &buf), dom_user);
++			return NT_STATUS_NO_SUCH_USER;
++		}
++		passwd = getpwuid_alloc(mem_ctx, uid);
++		if (!passwd) {
++			DBG_ERR("Failed to find local account with UID %lld for SID %s (dom_user[%s])\n",
++				(long long)uid,
++				dom_sid_str_buf(sid, &buf),
++				dom_user);
++			return NT_STATUS_NO_SUCH_USER;
++		}
++		real_username = talloc_strdup(mem_ctx, passwd->pw_name);
++	}
+ 	if (!passwd) {
+ 		DEBUG(3, ("Failed to find authenticated user %s via "
+ 			  "getpwnam(), denying access.\n", dom_user));
+@@ -2042,6 +2069,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
+ 	bool username_was_mapped;
+ 	struct passwd *pwd;
+ 	struct auth_serversupplied_info *result;
++	struct dom_sid sid;
+ 	TALLOC_CTX *tmp_ctx = talloc_stackframe();
+ 
+ 	/* 
+@@ -2088,9 +2116,13 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
+ 
+ 	/* this call will try to create the user if necessary */
+ 
++	sid_copy(&sid, info3->base.domain_sid);
++	sid_append_rid(&sid, info3->base.rid);
++
+ 	nt_status = check_account(tmp_ctx,
+ 				  nt_domain,
+ 				  nt_username,
++				  &sid,
+ 				  &found_username,
+ 				  &pwd,
+ 				  &username_was_mapped);
+-- 
+2.34.1
+
diff --git a/SOURCES/samba-4.14-recursive-delete-of-veto-files.patch b/SOURCES/samba-4.14-recursive-delete-of-veto-files.patch
new file mode 100644
index 0000000..62525e7
--- /dev/null
+++ b/SOURCES/samba-4.14-recursive-delete-of-veto-files.patch
@@ -0,0 +1,295 @@
+From 505e48439364c4027aa11aeda467bbd2060b89f4 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra@samba.org>
+Date: Thu, 21 Oct 2021 15:06:20 -0700
+Subject: [PATCH] s3: smbd: Add two tests showing recursive directory delete of
+ a directory containing veto file and msdfs links over SMB2.
+
+Add knownfail.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=14878
+
+Signed-off-by: Jeremy Allison <jra@samba.org>
+Reviewed-by: Ralph Boehme <slow@samba.org>
+(cherry picked from commit ad0082d79a681b981154747dcde5713e1933b88f)
+(cherry picked from commit dab3fa1d8c27e696afa15e071331f646e06d9706)
+---
+ selftest/target/Samba3.pm               |  16 ++
+ source3/script/tests/test_veto_rmdir.sh | 217 ++++++++++++++++++++++++
+ source3/selftest/tests.py               |   3 +
+ 3 files changed, 236 insertions(+)
+ create mode 100755 source3/script/tests/test_veto_rmdir.sh
+
+diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
+index 14a1f1223b1..bbff9d74817 100755
+--- a/selftest/target/Samba3.pm
++++ b/selftest/target/Samba3.pm
+@@ -1460,6 +1460,9 @@ sub setup_fileserver
+ 	my $bad_iconv_sharedir="$share_dir/bad_iconv";
+ 	push(@dirs, $bad_iconv_sharedir);
+ 
++	my $veto_sharedir="$share_dir/veto";
++	push(@dirs,$veto_sharedir);
++
+ 	my $ip4 = Samba::get_ipv4_addr("FILESERVER");
+ 	my $fileserver_options = "
+ 	kernel change notify = yes
+@@ -1568,6 +1571,19 @@ sub setup_fileserver
+ 	comment = smb username is [%U]
+ 	vfs objects =
+ 
++[veto_files_nodelete]
++	path = $veto_sharedir
++	read only = no
++	msdfs root = yes
++	veto files = /veto_name*/
++	delete veto files = no
++
++[veto_files_delete]
++	path = $veto_sharedir
++	msdfs root = yes
++	veto files = /veto_name*/
++	delete veto files = yes
++
+ [homes]
+ 	comment = Home directories
+ 	browseable = No
+diff --git a/source3/script/tests/test_veto_rmdir.sh b/source3/script/tests/test_veto_rmdir.sh
+new file mode 100755
+index 00000000000..d3df8f1bba0
+--- /dev/null
++++ b/source3/script/tests/test_veto_rmdir.sh
+@@ -0,0 +1,217 @@
++#!/bin/sh
++#
++# Check smbclient can (or cannot) delete a directory containing veto files.
++# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14878
++#
++
++if [ $# -lt 6 ]; then
++cat <<EOF
++Usage: $0 SERVER SERVER_IP USERNAME PASSWORD SHAREPATH SMBCLIENT
++EOF
++exit 1;
++fi
++
++SERVER=${1}
++SERVER_IP=${2}
++USERNAME=${3}
++PASSWORD=${4}
++SHAREPATH=${5}
++SMBCLIENT=${6}
++shift 6
++SMBCLIENT="$VALGRIND ${SMBCLIENT}"
++ADDARGS="$@"
++
++incdir=$(dirname "$0")/../../../testprogs/blackbox
++. "$incdir"/subunit.sh
++
++failed=0
++
++rmdir_path="$SHAREPATH/dir"
++
++test_veto_nodelete_rmdir()
++{
++    local veto_path="$rmdir_path/veto_name1"
++    local msdfs_link_path="$rmdir_path/dfs_link"
++    local tmpfile=$PREFIX/smbclient.in.$$
++
++    # Create rmdir directory.
++    mkdir -p "$rmdir_path"
++    # Create veto file underneath.
++    touch "$veto_path"
++    # Create msdfs link underneath.
++    ln -s "msdfs:$SERVER_IP\\ro-tmp" "$msdfs_link_path"
++
++    cat > "$tmpfile" <<EOF
++cd dir
++ls
++quit
++EOF
++
++    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_nodelete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
++    eval echo "$cmd"
++    out=$(eval "$cmd")
++    ret=$?
++
++    # Check for smbclient error.
++    if [ $ret != 0 ] ; then
++        echo "Failed accessing share veto_files_nodelete - $ret"
++        echo "$out"
++        return 1
++    fi
++
++    # We should only see the dfs_link file.
++    echo "$out" | grep dfs_link
++    ret=$?
++    if [ $ret -ne 0 ] ; then
++       echo "Failed to see dfs_link in share veto_files_nodelete"
++       echo "$out"
++       return 1
++    fi
++
++    # Now remove the dfs_link file.
++    rm -rf "$msdfs_link_path"
++
++    # Try and remove the directory, should fail with NT_STATUS_DIRECTORY_NOT_EMPTY.
++    cat > "$tmpfile" <<EOF
++rd dir
++quit
++EOF
++
++    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_nodelete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
++    eval echo "$cmd"
++    out=$(eval "$cmd")
++    ret=$?
++
++    # Check for smbclient error.
++    if [ $ret != 0 ] ; then
++        echo "Failed accessing share veto_files_nodelete - $ret"
++        echo "$out"
++        return 1
++    fi
++
++    # We should get NT_STATUS_DIRECTORY_NOT_EMPTY.
++    echo "$out" | grep NT_STATUS_DIRECTORY_NOT_EMPTY
++    ret=$?
++    if [ $ret -ne 0 ] ; then
++       echo "Failed to get error NT_STATUS_DIRECTORY_NOT_EMPTY in share veto_files_nodelete"
++       echo "$out"
++       return 1
++    fi
++
++    # remove the veto file - directory should now be empty.
++    rm -rf "$veto_path"
++
++    # Try and remove the directory, should now succeed.
++    cat > "$tmpfile" <<EOF
++rd dir
++quit
++EOF
++
++    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_nodelete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
++    eval echo "$cmd"
++    out=$(eval "$cmd")
++    ret=$?
++
++    # Check for smbclient error.
++    if [ $ret != 0 ] ; then
++        echo "Failed accessing share veto_files_nodelete - $ret"
++        echo "$out"
++        return 1
++    fi
++
++    # We should get no NT_STATUS_ errors.
++    echo "$out" | grep NT_STATUS_
++    ret=$?
++    if [ $ret -eq 0 ] ; then
++       echo "Got error NT_STATUS_ in share veto_files_nodelete"
++       echo "$out"
++       return 1
++    fi
++
++    return 0
++}
++
++test_veto_delete_rmdir()
++{
++    local veto_path="$rmdir_path/veto_name1"
++    local msdfs_link_path="$rmdir_path/dfs_link"
++    local tmpfile=$PREFIX/smbclient.in.$$
++
++    # Create rmdir directory.
++    mkdir -p "$rmdir_path"
++    # Create veto file underneath.
++    touch "$veto_path"
++    # Create msdfs link underneath.
++    ln -s "msdfs:$SERVER_IP\\ro-tmp" "$msdfs_link_path"
++
++    cat > "$tmpfile" <<EOF
++cd dir
++ls
++quit
++EOF
++
++    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_delete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
++    eval echo "$cmd"
++    out=$(eval "$cmd")
++    ret=$?
++
++    # Check for smbclient error.
++    if [ $ret != 0 ] ; then
++        echo "Failed accessing share veto_files_delete - $ret"
++        echo "$out"
++        return 1
++    fi
++
++    # We should only see the dfs_link file.
++    echo "$out" | grep dfs_link
++    ret=$?
++    if [ $ret -ne 0 ] ; then
++       echo "Failed to see dfs_link in share veto_files_delete"
++       echo "$out"
++       return 1
++    fi
++
++    # Now remove the dfs_link file.
++    rm -rf "$msdfs_link_path"
++
++    # Try and remove the directory, should now succeed.
++    cat > "$tmpfile" <<EOF
++rd dir
++quit
++EOF
++
++    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_delete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
++    eval echo "$cmd"
++    out=$(eval "$cmd")
++    ret=$?
++
++    # Check for smbclient error.
++    if [ $ret != 0 ] ; then
++        echo "Failed accessing share veto_files_delete - $ret"
++        echo "$out"
++        return 1
++    fi
++
++    # We should get no NT_STATUS_ errors.
++    echo "$out" | grep NT_STATUS_
++    ret=$?
++    if [ $ret -eq 0 ] ; then
++       echo "Got error NT_STATUS_ in share veto_files_delete"
++       echo "$out"
++       return 1
++    fi
++
++    return 0
++}
++
++testit "rmdir cannot delete directory containing a veto file" \
++   test_veto_nodelete_rmdir || failed=$(expr "$failed" + 1)
++
++rm -rf "$rmdir_path"
++
++testit "rmdir can delete directory containing a veto file" \
++   test_veto_delete_rmdir || failed=$(expr "$failed" + 1)
++
++rm -rf "$rmdir_path"
++
++exit "$failed"
+diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
+index 651be239825..82f32ec4232 100755
+--- a/source3/selftest/tests.py
++++ b/source3/selftest/tests.py
+@@ -498,6 +498,9 @@ for env in ["fileserver"]:
+     plantestsuite("samba3.blackbox.smbclient_iconv.CORE", env + "_smb1_done",
+                   [os.path.join(samba3srcdir, "script/tests/test_smbclient_iconv.sh"),
+                    '$SERVER', '$SERVER_IP', 'bad_iconv', '$USERNAME', '$PASSWORD', smbclient3, '-mCORE'])
++    plantestsuite("samba3.blackbox.test_veto_rmdir", env,
++                  [os.path.join(samba3srcdir, "script/tests/test_veto_rmdir.sh"),
++                  '$SERVER', '$SERVER_IP', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/veto', smbclient3])
+ 
+     #
+     # tar command tests
+-- 
+2.33.1
+
diff --git a/SPECS/samba.spec b/SPECS/samba.spec
index 057aab7..8b9d20b 100644
--- a/SPECS/samba.spec
+++ b/SPECS/samba.spec
@@ -108,7 +108,7 @@
 
 %define samba_requires_eq()  %(LC_ALL="C" echo '%*' | xargs -r rpm -q --qf 'Requires: %%{name} = %%{epoch}:%%{version}\\n' | sed -e 's/ (none):/ /' -e 's/ 0:/ /' | grep -v "is not")
 
-%global baserelease 7
+%global baserelease 9
 
 %global samba_version 4.14.5
 %global talloc_version 2.3.2
@@ -184,6 +184,11 @@ Patch3:         CVE-2020-25717.patch
 Patch4:         samba-4.14-krb5pac.patch
 Patch5:         samba-4.14-fix-winbind-no-trusted-domain.patch
 Patch6:         samba-4.14-IPA-DC-add-missing-checks.patch
+Patch7:         samba-4.14-recursive-delete-of-veto-files.patch
+Patch8:         samba-4.14-del-dir-with-dangling-symlinks.patch
+Patch9:         samba-4.14-fix-username-map-script.patch
+Patch10:        samba-4.14-fix-domain-join-segfault.patch
+Patch11:        CVE-2021-44142-v4.14.patch
 
 Requires(pre): /usr/sbin/groupadd
 Requires(post): systemd
@@ -3915,6 +3920,14 @@ fi
 %endif
 
 %changelog
+* Thu Jan 27 2022 Andreas Schneider <asn@redhat.com> - 4.14.5-9
+- resolves: rhbz#2046174 - Fix username map script regression of CVE-2020-25717
+- resolves: rhbz#2046160 - Fix possible segfault while joining a domain
+- resolves: rhbz#2046152 - Fix CVE-2021-44142
+
+* Thu Dec 02 2021 Pavel Filipenský <pfilipen@redhat.com> - 4.14.5-8
+- resolves: rhbz#2026717 - Dir containing dangling symlinks cannot be deleted
+
 * Mon Nov 22 2021 Andreas Schneider <asn@redhat.com> - 4.14.5-7
 - related: rhbz#2021171 - Fix CVE-2020-25717
 - Fix running ktest (selftest)