[SCM] Samba Shared Repository - branch master updated
Volker Lendecke
vlendec at samba.org
Mon Aug 15 16:01:01 UTC 2022
The branch, master has been updated
via 076c22fbd7e selftest/Samba3: let nt4_dc* use vfs_default:VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS=no
via 4708ba2f013 vfs_default: Use openat2(RESOLVE_NO_SYMLINKS) if available
via 8544f4490a0 vfs_default: prepare O_PATH usage with openat2()
via d6653067b20 s3:smbd: let openat_pathref_dirfsp_nosymlink() try VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS first
via 35b99c87ef9 s3:smbd: let openat_pathref_dirfsp_nosymlink() handle ELOOP similar to ENOTDIR
via 17484d069b9 s3:smbd: let openat_pathref_dirfsp_nosymlink() do a verification loop against . and .. first
via f7dc2755832 vfs: define VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS
via ae1a84f7313 lib/replace: let DISABLE_OPATH also undef __NR_openat2
via f7618dd31a9 lib/replace: add fallback defines for __NR_openat2
via b89001e9226 lib/replace: use syscall(__NR_openat2) if available
via 37ba6df174d lib/replace: always include <sys/syscall.h> in replace.c if available
via ce804b78164 lib/replace: add a replacement for openat2() that returns ENOSYS
via 2369d083336 vfs_btrfs: fix include order, includes.h or replace.h should be first
via cea9451f780 vfs_io_uring: hide a possible definition of struct open_how in liburing/compat.h
via 2b51bad7475 wafsamba: allow cflags for CHECK_TYPE[_IN]()
via 085f1485753 s3:tests: add a lot more tests to test_symlink_traversal_smb2.sh
from a38fad29803 s3:utils: Fix NULL check
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 076c22fbd7ecbf22dbfeb1711609f07fd42f88b0
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 12 10:55:42 2022 +0200
selftest/Samba3: let nt4_dc* use vfs_default:VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS=no
We should always test the code path without openat2 being available,
even if the kernel supports it.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Autobuild-User(master): Volker Lendecke <vl at samba.org>
Autobuild-Date(master): Mon Aug 15 16:00:26 UTC 2022 on sn-devel-184
commit 4708ba2f013c5f5ea5aa5dcf4873c2b4a86fb8ff
Author: Volker Lendecke <vl at samba.org>
Date: Fri Jun 17 17:41:52 2022 +0200
vfs_default: Use openat2(RESOLVE_NO_SYMLINKS) if available
This improves the following test:
time smbtorture //127.0.0.1/m -Uroot%test \
smb2.create.bench-path-contention-shared \
--option='torture:bench_path=Apps\1\2\3\4\5\6\7\8\9\10' \
--option="torture:timelimit=600" \
--option="torture:nprocs=1"
From:
open[num/s=14186,avslat=0.000044,minlat=0.000042,maxlat=0.000079]
close[num/s=14185,avslat=0.000027,minlat=0.000025,maxlat=0.000057]
to:
open[num/s=16917,avslat=0.000038,minlat=0.000035,maxlat=0.000340]
close[num/s=16916,avslat=0.000020,minlat=0.000019,maxlat=0.000104]
Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
Signed-off-by: Volker Lendecke <vl at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
commit 8544f4490a0b5e54b807daedddb96778744b62ee
Author: Stefan Metzmacher <metze at samba.org>
Date: Wed Jul 27 18:43:14 2022 +0000
vfs_default: prepare O_PATH usage with openat2()
When O_PATH is specified in flags, flag bits other than O_CLOEXEC,
O_DIRECTORY, and O_NOFOLLOW are ignored.
In preparation to use openat2(), which gives an error instead of
ignoring flags, we better remove unexpected flags, callers typically
pass O_RDONLY and O_NONBLOCK.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
commit d6653067b20e61af1f05423764c8486a1a5445c8
Author: Volker Lendecke <vl at samba.org>
Date: Thu Jul 14 19:44:04 2022 +0200
s3:smbd: let openat_pathref_dirfsp_nosymlink() try VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS first
This will reduce the amount of syscalls and the related cost drastically
for long path names.
Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
Signed-off-by: Volker Lendecke <vl at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
commit 35b99c87ef92df006f8b0a41bbea051f0faeadb9
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 12 19:12:44 2022 +0200
s3:smbd: let openat_pathref_dirfsp_nosymlink() handle ELOOP similar to ENOTDIR
This is no likely to happen as we use O_NOFOLLOW with O_DIRECTORY,
but it's better to be prepared...
This will be more important in the upcoming openat2(RESOLVE_NO_SYMLINK)
case, but we should be consitent...
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
commit 17484d069b92d08b0228fb509ea42ab4c3f496a8
Author: Stefan Metzmacher <metze at samba.org>
Date: Wed Aug 10 22:01:10 2022 +0200
s3:smbd: let openat_pathref_dirfsp_nosymlink() do a verification loop against . and .. first
I guess we should catch NT_STATUS_OBJECT_NAME_INVALID first,
currently the check is already done in check_path_syntax*,
but we may remove it in future.
But the most important reason for this is the
openat2(RESOLVE_NO_SYMLINK) optimization, which will
be introduced in the following commits.
Review with: git show -w
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
commit f7dc27558329eea7d2c4d75ee101c7f9d3a7afe3
Author: Volker Lendecke <vl at samba.org>
Date: Fri Jun 3 16:45:41 2022 +0200
vfs: define VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS
This will allow us to make use of openat2(RESOLVE_NO_SYMLINKS) soon.
The caller should check if connection_struct.open_how_resolve contains
VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS before using it, this avoids waisting
cpu time. But even then the caller must be prepared to handle -1/ENOSYS.
Pair-Programmed-With: Stefan Metzmacher <metze at samba.org>
Signed-off-by: Volker Lendecke <vl at samba.org>
Signed-off-by: Stefan Metzmacher <metze at samba.org>
commit ae1a84f7313bdf4702492451714eacc78ee7745f
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 12 10:53:06 2022 +0200
lib/replace: let DISABLE_OPATH also undef __NR_openat2
The reason for DISABLE_OPATH is to simulate a non-linux
system, so we should not use openat2() either.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
commit f7618dd31a9f8f6c0dbfdedd1a664eed25e2e449
Author: Stefan Metzmacher <metze at samba.org>
Date: Mon Aug 8 15:33:24 2022 +0200
lib/replace: add fallback defines for __NR_openat2
sys/syscall.h might be older than the runtime kernel.
If the kernel has support for openat2() we should
try to use if anyway.
The callers have to deal with ENOSYS anyway,
so there's no difference if we get that from syscall(__NR_openat2)
or directly from rep_openat2().
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
commit b89001e9226ecb0f4e5c906f7195f0e53cd7d608
Author: Stefan Metzmacher <metze at samba.org>
Date: Mon Aug 8 15:25:39 2022 +0200
lib/replace: use syscall(__NR_openat2) if available
There's no glibc wrapper for openat2() yet, so we need
to use syscall(__NR_openat2) ourself.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
commit 37ba6df174d73b82e951de401cba7f839ad61ab5
Author: Stefan Metzmacher <metze at samba.org>
Date: Mon Aug 8 15:24:28 2022 +0200
lib/replace: always include <sys/syscall.h> in replace.c if available
It will be used for openat2() soon.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
commit ce804b78164a3166a16ca3071028536761fd18d7
Author: Stefan Metzmacher <metze at samba.org>
Date: Mon Aug 8 15:23:29 2022 +0200
lib/replace: add a replacement for openat2() that returns ENOSYS
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
commit 2369d0833361faf4a125431e735fce7efb6024d6
Author: Stefan Metzmacher <metze at samba.org>
Date: Mon Aug 8 15:29:28 2022 +0200
vfs_btrfs: fix include order, includes.h or replace.h should be first
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
commit cea9451f780d13e528f1722a67eccbbc78b2daf9
Author: Stefan Metzmacher <metze at samba.org>
Date: Tue Aug 9 10:29:24 2022 +0000
vfs_io_uring: hide a possible definition of struct open_how in liburing/compat.h
liburing.h will include liburing/compat.h, which either includes
linux/openat2.h or defines struct open_how itself.
This will help with the following changes, which will provide
openat2() via libreplace's system/filesys.h, either including
linux/openat2.h or defining open_how ourself.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
commit 2b51bad747551605ba3b70ac3b692107a0cd7aad
Author: Stefan Metzmacher <metze at samba.org>
Date: Thu Aug 11 00:41:28 2022 +0200
wafsamba: allow cflags for CHECK_TYPE[_IN]()
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
commit 085f14857531dab179af66a69962486c7dd2592c
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Aug 12 19:07:39 2022 +0200
s3:tests: add a lot more tests to test_symlink_traversal_smb2.sh
We now also test more path components checking the difference between
OBJECT_NAME_NOT_FOUND and OBJECT_PATH_NOT_FOUND.
We also test with symlinks within the path instead of only checking
symlinks as final path components (at least for the dirfsp part).
This ensures the following commits won't introduce regressions
when adding the openat2(RESOLVE_NO_SYMLINK) optimization.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
-----------------------------------------------------------------------
Summary of changes:
buildtools/wafsamba/samba_autoconf.py | 7 +-
lib/replace/replace.c | 52 ++++++++-
lib/replace/system/filesys.h | 35 +++++++
lib/replace/wscript | 1 +
selftest/target/Samba3.pm | 2 +
source3/include/vfs.h | 3 +
source3/modules/vfs_btrfs.c | 4 +-
source3/modules/vfs_default.c | 71 ++++++++++++-
source3/modules/vfs_io_uring.c | 18 ++++
.../script/tests/test_symlink_traversal_smb2.sh | 116 +++++++++++++++++++++
source3/smbd/files.c | 111 ++++++++++++++++++--
source3/wscript | 13 +++
12 files changed, 416 insertions(+), 17 deletions(-)
Changeset truncated at 500 lines:
diff --git a/buildtools/wafsamba/samba_autoconf.py b/buildtools/wafsamba/samba_autoconf.py
index 9db53e40724..3ca2f334190 100644
--- a/buildtools/wafsamba/samba_autoconf.py
+++ b/buildtools/wafsamba/samba_autoconf.py
@@ -146,7 +146,7 @@ def header_list(conf, headers=None, lib=None):
@conf
-def CHECK_TYPE(conf, t, alternate=None, headers=None, define=None, lib=None, msg=None):
+def CHECK_TYPE(conf, t, alternate=None, headers=None, define=None, lib=None, msg=None, cflags=''):
'''check for a single type'''
if define is None:
define = 'HAVE_' + t.upper().replace(' ', '_')
@@ -158,6 +158,7 @@ def CHECK_TYPE(conf, t, alternate=None, headers=None, define=None, lib=None, msg
headers=headers,
local_include=False,
msg=msg,
+ cflags=cflags,
lib=lib,
link=False)
if not ret and alternate:
@@ -177,9 +178,9 @@ def CHECK_TYPES(conf, list, headers=None, define=None, alternate=None, lib=None)
@conf
-def CHECK_TYPE_IN(conf, t, headers=None, alternate=None, define=None):
+def CHECK_TYPE_IN(conf, t, headers=None, alternate=None, define=None, cflags=''):
'''check for a single type with a header'''
- return CHECK_TYPE(conf, t, headers=headers, alternate=alternate, define=define)
+ return CHECK_TYPE(conf, t, headers=headers, alternate=alternate, define=define, cflags=cflags)
@conf
diff --git a/lib/replace/replace.c b/lib/replace/replace.c
index 0652cb4e6d6..cbf372e494f 100644
--- a/lib/replace/replace.c
+++ b/lib/replace/replace.c
@@ -33,6 +33,10 @@
#include "system/locale.h"
#include "system/wait.h"
+#ifdef HAVE_SYS_SYSCALL_H
+#include <sys/syscall.h>
+#endif
+
#ifdef _WIN32
#define mkdir(d,m) _mkdir(d)
#endif
@@ -1058,9 +1062,6 @@ const char *rep_getprogname(void)
#endif /* HAVE_GETPROGNAME */
#ifndef HAVE_COPY_FILE_RANGE
-# ifdef HAVE_SYSCALL_COPY_FILE_RANGE
-# include <sys/syscall.h>
-# endif
ssize_t rep_copy_file_range(int fd_in,
loff_t *off_in,
int fd_out,
@@ -1081,3 +1082,48 @@ ssize_t rep_copy_file_range(int fd_in,
return -1;
}
#endif /* HAVE_COPY_FILE_RANGE */
+
+#ifndef HAVE_OPENAT2
+
+/* fallback known wellknown __NR_openat2 values */
+#ifndef __NR_openat2
+# if defined(LINUX) && defined(HAVE_SYS_SYSCALL_H)
+# if defined(__i386__)
+# define __NR_openat2 437
+# elif defined(__x86_64__) && defined(__LP64__)
+# define __NR_openat2 437 /* 437 0x1B5 */
+# elif defined(__x86_64__) && defined(__ILP32__)
+# define __NR_openat2 1073742261 /* 1073742261 0x400001B5 */
+# elif defined(__aarch64__)
+# define __NR_openat2 437
+# elif defined(__arm__)
+# define __NR_openat2 437
+# elif defined(__sparc__)
+# define __NR_openat2 437
+# endif
+# endif /* defined(LINUX) && defined(HAVE_SYS_SYSCALL_H) */
+#endif /* !__NR_openat2 */
+
+#ifdef DISABLE_OPATH
+/*
+ * systems without O_PATH also don't have openat2,
+ * so make sure we at a realistic combination.
+ */
+#undef __NR_openat2
+#endif /* DISABLE_OPATH */
+
+long rep_openat2(int dirfd, const char *pathname,
+ struct open_how *how, size_t size)
+{
+#ifdef __NR_openat2
+ return syscall(__NR_openat2,
+ dirfd,
+ pathname,
+ how,
+ size);
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+#endif /* !HAVE_OPENAT2 */
diff --git a/lib/replace/system/filesys.h b/lib/replace/system/filesys.h
index bb9482c69af..8005b18780f 100644
--- a/lib/replace/system/filesys.h
+++ b/lib/replace/system/filesys.h
@@ -243,4 +243,39 @@ int rep_fsetxattr (int filedes, const char *name, const void *value, size_t size
#endif /* !defined(HAVE_XATTR_XATTR) || defined(XATTR_ADDITIONAL_OPTIONS) */
+#ifdef HAVE_LINUX_OPENAT2_H
+#include <linux/openat2.h>
+#else /* ! HAVE_LINUX_OPENAT2_H */
+/* how->resolve flags for openat2(2). */
+#define RESOLVE_NO_XDEV 0x01 /* Block mount-point crossings
+ (includes bind-mounts). */
+#define RESOLVE_NO_MAGICLINKS 0x02 /* Block traversal through procfs-style
+ "magic-links". */
+#define RESOLVE_NO_SYMLINKS 0x04 /* Block traversal through all symlinks
+ (implies OEXT_NO_MAGICLINKS) */
+#define RESOLVE_BENEATH 0x08 /* Block "lexical" trickery like
+ "..", symlinks, and absolute
+ paths which escape the dirfd. */
+#define RESOLVE_IN_ROOT 0x10 /* Make all jumps to "/" and ".."
+ be scoped inside the dirfd
+ (similar to chroot(2)). */
+#define RESOLVE_CACHED 0x20 /* Only complete if resolution can be
+ completed through cached lookup. May
+ return -EAGAIN if that's not
+ possible. */
+struct __rep_open_how {
+ uint64_t flags;
+ uint64_t mode;
+ uint64_t resolve;
+};
+#define open_how __rep_open_how
+#endif /* ! HAVE_LINUX_OPENAT2_H */
+
+#ifndef HAVE_OPENAT2
+long rep_openat2(int dirfd, const char *pathname,
+ struct open_how *how, size_t size);
+#define openat2(dirfd, pathname, how, size) \
+ rep_openat2(dirfd, pathname, how, size)
+#endif /* !HAVE_OPENAT2 */
+
#endif
diff --git a/lib/replace/wscript b/lib/replace/wscript
index dd9b19219a1..2f179992c82 100644
--- a/lib/replace/wscript
+++ b/lib/replace/wscript
@@ -66,6 +66,7 @@ def configure(conf):
conf.CHECK_HEADERS('errno.h')
conf.CHECK_HEADERS('getopt.h iconv.h')
conf.CHECK_HEADERS('memory.h nss.h sasl/sasl.h')
+ conf.CHECK_HEADERS('linux/openat2.h')
conf.CHECK_FUNCS_IN('inotify_init', 'inotify', checklibc=True,
headers='sys/inotify.h')
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 2313f6fce36..387856e07a0 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -275,6 +275,8 @@ sub setup_nt4_dc
server schannel = auto
rpc start on demand helpers = false
+ vfs_default:VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS = no
+
fss: sequence timeout = 1
check parent directory delete on close = yes
";
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 866d2a5f4a8..2fd8d1cdd06 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -716,6 +716,7 @@ typedef struct connection_struct {
bool ipc;
bool read_only; /* Attributes for the current user of the share. */
bool have_proc_fds;
+ uint64_t open_how_resolve; /* supported vfs_open_how.resolve features */
uint32_t share_access;
/* Does this filesystem honor
sub second timestamps on files
@@ -905,6 +906,8 @@ struct vfs_aio_state {
uint64_t duration;
};
+#define VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS 1
+
struct vfs_open_how {
int flags;
mode_t mode;
diff --git a/source3/modules/vfs_btrfs.c b/source3/modules/vfs_btrfs.c
index 1ee3f1831c6..a7ba0ece206 100644
--- a/source3/modules/vfs_btrfs.c
+++ b/source3/modules/vfs_btrfs.c
@@ -17,6 +17,8 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "includes.h"
+#include "system/filesys.h"
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <sys/ioctl.h>
@@ -24,8 +26,6 @@
#include <fcntl.h>
#include <dirent.h>
#include <libgen.h>
-#include "system/filesys.h"
-#include "includes.h"
#include "smbd/smbd.h"
#include "smbd/globals.h"
#include "librpc/gen_ndr/smbXsrv.h"
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index dee8ff50df4..48ff174ebbe 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -49,7 +49,28 @@
static int vfswrap_connect(vfs_handle_struct *handle, const char *service, const char *user)
{
+ bool bval;
+
handle->conn->have_proc_fds = sys_have_proc_fds();
+
+ /*
+ * assume the kernel will support openat2(),
+ * it will be reset on the first ENOSYS.
+ *
+ * Note that libreplace will always provide openat2(),
+ * but return -1/errno = ENOSYS...
+ *
+ * The option is only there to test the fallback code.
+ */
+ bval = lp_parm_bool(SNUM(handle->conn),
+ "vfs_default",
+ "VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS",
+ true);
+ if (bval) {
+ handle->conn->open_how_resolve |=
+ VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS;
+ }
+
return 0; /* Return >= 0 for success */
}
@@ -701,7 +722,7 @@ static int vfswrap_openat(vfs_handle_struct *handle,
START_PROFILE(syscall_openat);
- if (how->resolve != 0) {
+ if (how->resolve & ~VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS) {
errno = ENOSYS;
result = -1;
goto out;
@@ -714,8 +735,55 @@ static int vfswrap_openat(vfs_handle_struct *handle,
if (fsp->fsp_flags.is_pathref) {
flags |= O_PATH;
}
+ if (flags & O_PATH) {
+ /*
+ * From "man 2 openat":
+ *
+ * When O_PATH is specified in flags, flag bits other than
+ * O_CLOEXEC, O_DIRECTORY, and O_NOFOLLOW are ignored.
+ *
+ * From "man 2 openat2":
+ *
+ * Whereas openat(2) ignores unknown bits in its flags
+ * argument, openat2() returns an error if unknown or
+ * conflicting flags are specified in how.flags.
+ *
+ * So we better clear ignored/invalid flags
+ * and only keep the exptected once.
+ */
+ flags &= (O_PATH|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW);
+ }
#endif
+ if (how->resolve & VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS) {
+ struct open_how linux_how = {
+ .flags = flags,
+ .mode = mode,
+ .resolve = RESOLVE_NO_SYMLINKS,
+ };
+
+ result = openat2(fsp_get_pathref_fd(dirfsp),
+ smb_fname->base_name,
+ &linux_how,
+ sizeof(linux_how));
+ if (result == -1) {
+ if (errno == ENOSYS) {
+ /*
+ * The kernel doesn't support
+ * openat2(), so indicate to
+ * the callers that
+ * VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS
+ * would just be a waste of time.
+ */
+ fsp->conn->open_how_resolve &=
+ ~VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS;
+ }
+ goto out;
+ }
+
+ goto done;
+ }
+
if (fsp->fsp_flags.is_pathref && !have_opath) {
become_root();
became_root = true;
@@ -730,6 +798,7 @@ static int vfswrap_openat(vfs_handle_struct *handle,
unbecome_root();
}
+done:
fsp->fsp_flags.have_proc_fds = fsp->conn->have_proc_fds;
out:
diff --git a/source3/modules/vfs_io_uring.c b/source3/modules/vfs_io_uring.c
index 5168df7a97b..65dd151bb02 100644
--- a/source3/modules/vfs_io_uring.c
+++ b/source3/modules/vfs_io_uring.c
@@ -20,6 +20,24 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "replace.h"
+
+/*
+ * liburing.h only needs a forward declaration
+ * of struct open_how.
+ *
+ * If struct open_how is defined in liburing/compat.h
+ * itself, hide it away in order to avoid conflicts
+ * with including linux/openat2.h or defining 'struct open_how'
+ * in libreplace.
+ */
+struct open_how;
+#ifdef HAVE_STRUCT_OPEN_HOW_LIBURING_COMPAT_H
+#define open_how __ignore_liburing_compat_h_open_how
+#include <liburing/compat.h>
+#undef open_how
+#endif /* HAVE_STRUCT_OPEN_HOW_LIBURING_COMPAT_H */
+
#include "includes.h"
#include "system/filesys.h"
#include "smbd/smbd.h"
diff --git a/source3/script/tests/test_symlink_traversal_smb2.sh b/source3/script/tests/test_symlink_traversal_smb2.sh
index eadd7592de5..971d5344216 100755
--- a/source3/script/tests/test_symlink_traversal_smb2.sh
+++ b/source3/script/tests/test_symlink_traversal_smb2.sh
@@ -50,7 +50,11 @@ do_cleanup()
(
#subshell.
cd "$share_test_dir" || return
+ rm -f "symlink_to_dot"
rm -f "file_exists"
+ rm -f "symlink_to_file_exists"
+ rm -rf "dir_exists"
+ rm -f "symlink_to_dir_exists"
rm -f "symlink_noexist"
rm -f "symlink_file_outside_share"
rm -f "symlink_file_outside_share_noexist"
@@ -93,7 +97,13 @@ chmod 0 "$dir_outside_share_noperms"
(
#subshell.
cd "$share_test_dir" || return
+ ln -s "." "symlink_to_dot"
touch "file_exists"
+ ln -s "file_exists" "symlink_to_file_exists"
+ mkdir "dir_exists"
+ ln -s "dir_exists" "symlink_to_dir_exists"
+ touch "dir_exists/subfile_exists"
+ mkdir "dir_exists/subdir_exists"
ln -s "noexist" "symlink_noexist"
ln -s "$file_outside_share" "symlink_file_outside_share"
ln -s "$file_outside_share_noexist" "symlink_file_outside_share_noexist"
@@ -107,7 +117,13 @@ chmod 0 "$dir_outside_share_noperms"
(
#subshell
cd "emptydir" || return
+ ln -s "." "symlink_to_dot"
touch "file_exists"
+ ln -s "file_exists" "symlink_to_file_exists"
+ mkdir "dir_exists"
+ ln -s "dir_exists" "symlink_to_dir_exists"
+ touch "dir_exists/subfile_exists"
+ mkdir "dir_exists/subdir_exists"
ln -s "noexist" "symlink_noexist"
ln -s "$file_outside_share" "symlink_file_outside_share"
ln -s "$file_outside_share_noexist" "symlink_file_outside_share_noexist"
@@ -126,6 +142,8 @@ chmod 0 "$dir_outside_share_noperms"
touch "dir_inside_share_noperms/noperm_file_exists"
chmod 0 "dir_inside_share_noperms"
ln -s "dir_inside_share_noperms" "symlink_dir_inside_share_noperms"
+ mkdir "dir_inside_share_noperms/noperm_subdir_exists"
+ touch "dir_inside_share_noperms/noperm_subdir_exists/noperm_subdir_file_exists"
)
#
@@ -179,25 +197,33 @@ test_symlink_traversal_SMB2_onename()
#
smbclient_expect_error "get" "$name" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
smbclient_expect_error "get" "$name/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "get" "$name/noexistsdir/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
smbclient_expect_error "get" "$name/*" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1
smbclient_expect_error "get" "$name/*/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1
+ smbclient_expect_error "get" "$name/*/noexistsdir/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1
# Now in subdirectory emptydir
smbclient_expect_error "get" "emptydir/$name" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
smbclient_expect_error "get" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "get" "emptydir/$name/noexistsdir/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
smbclient_expect_error "get" "emptydir/$name/*" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1
smbclient_expect_error "get" "emptydir/$name/*/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1
+ smbclient_expect_error "get" "emptydir/$name/*/noexistsdir/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1
#
# ls commands.
#
smbclient_expect_error "ls" "$name" "" "NT_STATUS_NO_SUCH_FILE" || return 1
smbclient_expect_error "ls" "$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "$name/noexistsdir/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
smbclient_expect_error "ls" "$name/*" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
smbclient_expect_error "ls" "$name/*/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1
+ smbclient_expect_error "ls" "$name/*/noexistsdir/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1
# Now in subdirectory emptydir
smbclient_expect_error "ls" "emptydir/$name" "" "NT_STATUS_NO_SUCH_FILE" || return 1
smbclient_expect_error "ls" "emptydir/$name/noexist" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "emptydir/$name/noexistsdir/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
smbclient_expect_error "ls" "emptydir/$name/*" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
smbclient_expect_error "ls" "emptydir/$name/*/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1
+ smbclient_expect_error "ls" "emptydir/$name/*/noexistsdir/noexist" "" "NT_STATUS_OBJECT_NAME_INVALID" || return 1
#
# del commands.
@@ -215,9 +241,21 @@ test_symlink_traversal_SMB2_onename()
#
smbclient_expect_error "rename" "file_exists" "$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
smbclient_expect_error "rename" "file_exists" "$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "rename" "symlink_to_file_exists" "$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+ smbclient_expect_error "rename" "symlink_to_file_exists" "$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "rename" "dir_exists" "$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+ smbclient_expect_error "rename" "dir_exists" "$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "rename" "symlink_to_dir_exists" "$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+ smbclient_expect_error "rename" "symlink_to_dir_exists" "$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
# Now in subdirectory emptydir
smbclient_expect_error "rename" "file_exists" "emptydir/$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
smbclient_expect_error "rename" "file_exists" "emptydir/$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "rename" "symlink_to_file_exists" "emptydir/$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+ smbclient_expect_error "rename" "symlink_to_file_exists" "emptydir/$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "rename" "dir_exists" "emptydir/$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+ smbclient_expect_error "rename" "dir_exists" "emptydir/$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "rename" "symlink_to_dir_exists" "emptydir/$name" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+ smbclient_expect_error "rename" "symlink_to_dir_exists" "emptydir/$name/noexist" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
fi
return 0
}
@@ -234,6 +272,80 @@ test_symlink_traversal_SMB2()
test_symlink_traversal_SMB2_onename "symlink_dir_outside_share_noexist" "no rename" || return 1
test_symlink_traversal_SMB2_onename "symlink_file_outside_share_noperms" "do rename" || return 1
test_symlink_traversal_SMB2_onename "symlink_dir_outside_share_noperms" "do rename" || return 1
+
+ # Note the share has 'follow symlinks = yes'
+ smbclient_expect_error "ls" "." "" "NT_STATUS_NO_SUCH_FILE" || return 1
+ smbclient_expect_error "ls" "noexist1" "" "NT_STATUS_NO_SUCH_FILE" || return 1
+ smbclient_expect_error "ls" "noexist1/noexist2" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "noexist1/noexist2/noexist3" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "symlink_to_dot" "" "NT_STATUS_OK" || return 1
+ smbclient_expect_error "ls" "symlink_to_dot/noexist1" "" "NT_STATUS_NO_SUCH_FILE" || return 1
+ smbclient_expect_error "ls" "symlink_to_dot/noexist1/noexist2" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "symlink_to_dot/noexist1/noexist2/noexist3" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "file_exists" "" "NT_STATUS_OK" || return 1
+ smbclient_expect_error "ls" "file_exists/noexist1" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1
+ smbclient_expect_error "ls" "file_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "file_exists/noexist1/noexist2/noexist3" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "symlink_to_file_exists" "" "NT_STATUS_OK" || return 1
+ smbclient_expect_error "ls" "symlink_to_file_exists/noexist1" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1
+ smbclient_expect_error "ls" "symlink_to_file_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "symlink_to_file_exists/noexist1/noexist2/noexist" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "dir_exists" "" "NT_STATUS_OK" || return 1
+ smbclient_expect_error "ls" "dir_exists/noexist1" "" "NT_STATUS_NO_SUCH_FILE" || return 1
+ smbclient_expect_error "ls" "dir_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "dir_exists/noexist1/noexist2/noexist3" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "dir_exists/subfile_exists" "" "NT_STATUS_OK" || return 1
+ smbclient_expect_error "ls" "dir_exists/subfile_exists/noexist1" "" "NT_STATUS_NOT_A_DIRECTORY" || return 1
+ smbclient_expect_error "ls" "dir_exists/subfile_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "dir_exists/subfile_exists/noexist1/noexist2/noexist3" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "dir_exists/subdir_exists" "" "NT_STATUS_OK" || return 1
+ smbclient_expect_error "ls" "dir_exists/subdir_exists/noexist1" "" "NT_STATUS_NO_SUCH_FILE" || return 1
+ smbclient_expect_error "ls" "dir_exists/subdir_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "dir_exists/subdir_exists/noexist1/noexist2/noexist3" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+ smbclient_expect_error "ls" "symlink_to_dir_exists" "" "NT_STATUS_OK" || return 1
+ smbclient_expect_error "ls" "symlink_to_dir_exists/noexist1" "" "NT_STATUS_NO_SUCH_FILE" || return 1
+ smbclient_expect_error "ls" "symlink_to_dir_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
--
Samba Shared Repository
More information about the samba-cvs
mailing list