The branch, master has been updated
via c7839facdbc smbd: Remove non_widelink_open()
via 31eac22e080 smbd: simplify openat_pathref_fullname()
via 9a80e4e27a6 smbd: simplify open_stream_pathref_fsp()
via 0bb35e24614 pysmbd: Python code calls smbd code with "." and ".."
via 800363a2cd8 smbd: Simplify filename_convert_dirfsp_nosymlink()
via 5052be51629 net: filename_convert_dirfsp() needs mangling
initialized
via 56e3a8e3f80 smbd: Add open_rootdir_pathref_fsp()
via 0fc8d8bfc56 smbd: Factor out filename_convert_dirfsp_rel()
via 99fa20b418f smbd: Fix following symlinks if basedir != cwd_fsp
via 82fd2230a89 smbd: Slightly simplify
filename_convert_dirfsp_nosymlink()
via 88abb775dca smbd: Use OpenDir_from_pathref() in rmdir_internals()
via 10512eebec6 smbd: Use OpenDir_from_pathref() in
can_delete_directory_fsp()
via c0bbeded932 smbd: Simplify OpenDir_from_pathref()
via 9550f4370e4 smbd: Enable fd_openat(cwd_fsp, "/absolute/share/path")
via e571da800f8 smbd: Tighten non_wide_link_open() for absolute root
share open
via 88f582d3ca4 smbd: Ignore twrp in chdir_below_conn()
via bd30c9c128c smbd: Simplify filename_convert_dirfsp()
via 3ab6a9a9bf2 smbd: Inline dup_file_fsp() into fcb_or_dos_open()
from 6e9c6dd6d6d vfs: Don't ever call openat(-1, ...) for relative paths
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit c7839facdbcf551d50179340ead4418f4d7384d3
Author: Volker Lendecke <[email protected]>
Date: Mon Oct 21 09:41:06 2024 +0200
smbd: Remove non_widelink_open()
Better look at the final code, not at the patch. The idea is to call
filename_convert_dirfsp() from fd_openat() and just have one place to
follow symlinks.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
Autobuild-User(master): Ralph Böhme <[email protected]>
Autobuild-Date(master): Tue Nov 12 19:21:11 UTC 2024 on atb-devel-224
commit 31eac22e08029a5bb41432a946017b3eb5f71d78
Author: Volker Lendecke <[email protected]>
Date: Tue Oct 8 17:42:11 2024 +0200
smbd: simplify openat_pathref_fullname()
We don't have to deal with stream opens anymore.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 9a80e4e27a6ee5f1020b80373f1ce12d70130963
Author: Volker Lendecke <[email protected]>
Date: Tue Oct 8 17:40:41 2024 +0200
smbd: simplify open_stream_pathref_fsp()
Looks more complex, but we don't have to go through all of
fd_openat()/non_widelink_open() for opening streams. SMB_VFS_OPENAT
knows how to deal with this.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 0bb35e246141f6cbea4831d30d3375f3e7bce72d
Author: Volker Lendecke <[email protected]>
Date: Mon Oct 21 15:45:47 2024 +0200
pysmbd: Python code calls smbd code with "." and ".."
Soon we will call filename_convert_dirfsp() on these, which can't deal
with paths that are invalid by containing . and .. as path components.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 800363a2cd8c54cf03f5de1062923b0647aa3cd6
Author: Volker Lendecke <[email protected]>
Date: Fri Oct 11 12:46:53 2024 +0200
smbd: Simplify filename_convert_dirfsp_nosymlink()
Looks more complex, but this avoids calling openat_pathref_fsp, which
eventually calls into non_widelink_open(). We need to open the pretty
paranoid
SMB_ASSERT in openat_pathref_fsp_lcomp() a little bit.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 5052be51629b8bea3888350d952543e9e07d6540
Author: Volker Lendecke <[email protected]>
Date: Wed Oct 23 17:09:04 2024 +0200
net: filename_convert_dirfsp() needs mangling initialized
We'll call filename_convert_dirfsp() from a lot more places soon.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 56e3a8e3f80533a972913ed4a0efe7c98185e57e
Author: Volker Lendecke <[email protected]>
Date: Fri Oct 11 14:56:21 2024 +0200
smbd: Add open_rootdir_pathref_fsp()
Get a pathref handle on the file system root. This will serve as
"basedir" for filename_convert_dirfsp_rel() to turn an absolute path
into one relative to the handle created here.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 0fc8d8bfc563b7568a4cd75355785c5783344c5b
Author: Volker Lendecke <[email protected]>
Date: Fri Oct 11 11:58:51 2024 +0200
smbd: Factor out filename_convert_dirfsp_rel()
Soon we'll have a caller that needs the last component as a relative
file name. Make sure it does not have to call get_lcomp or so.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 99fa20b418fac0f1fa1571a4bd1ad50757e822a1
Author: Volker Lendecke <[email protected]>
Date: Wed Oct 23 14:14:39 2024 +0200
smbd: Fix following symlinks if basedir != cwd_fsp
Unused so far, but soon we'll call this routine with a basedir that's
somewhere below the share root.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 82fd2230a8967a29288259d82acca7b6831e717d
Author: Volker Lendecke <[email protected]>
Date: Thu Oct 10 10:16:14 2024 +0200
smbd: Slightly simplify filename_convert_dirfsp_nosymlink()
Reference conn->cwd_fsp just once, shrinks next patches
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 88abb775dca6d9afe248b266b0868151e0ffbe31
Author: Volker Lendecke <[email protected]>
Date: Wed Oct 9 15:49:10 2024 +0200
smbd: Use OpenDir_from_pathref() in rmdir_internals()
Make strace look nicer
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 10512eebec60346c302b86eb77231372b8ad617a
Author: Volker Lendecke <[email protected]>
Date: Wed Oct 9 13:36:00 2024 +0200
smbd: Use OpenDir_from_pathref() in can_delete_directory_fsp()
This avoids a full path traversal if /proc/self/fd is available.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit c0bbeded932f00b0cdc3954d549d6566c85fdc0b
Author: Volker Lendecke <[email protected]>
Date: Thu Oct 10 17:16:02 2024 +0200
smbd: Simplify OpenDir_from_pathref()
Use the /proc/self/fd trick to make get_real_filename_fullscan_at look
a bit nicer and faster in strace. Direct SMB_VFS_OPENAT also is
cheaper in user space, we don't need the full fd_openat and
non_widelink_open magic here.
Also avoid opening ".", which can fail where a full path open would
succeed: If the directory in question does not give "x" perms to the
user, we get a handle on the dir as such but can't cd into it.
I haven't seen real-world cases of this, but one of our tests creates
such a scenario. I have further refactoring in my local tree that make
this patch necessary.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 9550f4370e47d765b8a23a8be91fe54d097b67aa
Author: Volker Lendecke <[email protected]>
Date: Sat Oct 19 17:30:09 2024 +0200
smbd: Enable fd_openat(cwd_fsp, "/absolute/share/path")
So far fd_openat needed to be called with cwd_fsp and "." if you
wanted to open the share root, this enables using the absolute share
path. The next patch will remove sending the "." with cwd_fsp as a
simplification. Enable that with this little change.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit e571da800f8d371a70e89ce89d8b35ae712bb6e8
Author: Volker Lendecke <[email protected]>
Date: Sat Oct 19 17:29:01 2024 +0200
smbd: Tighten non_wide_link_open() for absolute root share open
Make it clear that non_widelink_open being called for absolute paths
is not done during regular operations, i.e. when we have passed our
pathnames through filename_convert_dirfsp and we work on a real
dirfsp.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 88f582d3ca4b735583ee3e3faa9546756e426ba0
Author: Volker Lendecke <[email protected]>
Date: Sun Oct 20 14:41:55 2024 +0200
smbd: Ignore twrp in chdir_below_conn()
We can't deal with snapdir paths in non_widelink_open fully with
snapdirseverywhere active: There is no way for
shadow_copy2_parent_pathname() to work when a snapshot directory is
below the directory that we want to calculate the parent for. What is
the parent directory supposed to point at? I don't know.
For me the only way out is to accept that we should ignore what
happens behind shadow_copy2's path manipulation in core
smbd. This *might* open symlink races, but the whole point of
snapshots is that they are r/o copies of the real active file system
and as such they should be immune to those races.
Found while trying to refactor code around fd_openat()
P.S: This code will go away pretty soon
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit bd30c9c128c203c3ed4b123b651862a9953f6cf2
Author: Volker Lendecke <[email protected]>
Date: Tue Oct 8 15:51:06 2024 +0200
smbd: Simplify filename_convert_dirfsp()
If we do the S_ISLNK check in the lower level, the if-condition is
simpler and we get the close_file_free() call for free.
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
commit 3ab6a9a9bf2cadee2930a3a4bf0685c901a7ee5d
Author: Volker Lendecke <[email protected]>
Date: Thu Oct 10 16:34:50 2024 +0200
smbd: Inline dup_file_fsp() into fcb_or_dos_open()
Only used once, an not really complex
Signed-off-by: Volker Lendecke <[email protected]>
Reviewed-by: Ralph Boehme <[email protected]>
-----------------------------------------------------------------------
Summary of changes:
source3/include/proto.h | 9 +
source3/smbd/close.c | 7 +-
source3/smbd/dir.c | 49 ++++-
source3/smbd/filename.c | 92 ++++++---
source3/smbd/files.c | 219 ++++++++++----------
source3/smbd/open.c | 501 ++++++++++------------------------------------
source3/smbd/proto.h | 10 +-
source3/smbd/pysmbd.c | 49 +++--
source3/smbd/smb1_utils.c | 30 ++-
source3/utils/net_vfs.c | 1 +
10 files changed, 392 insertions(+), 575 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source3/include/proto.h b/source3/include/proto.h
index f398106e5a2..ee28afa6a56 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -713,6 +713,15 @@ NTSTATUS safe_symlink_target_path(TALLOC_CTX *mem_ctx,
const char *target,
size_t unparsed,
char **_relative);
+NTSTATUS filename_convert_dirfsp_rel(TALLOC_CTX *mem_ctx,
+ connection_struct *conn,
+ struct files_struct *basedir,
+ const char *name_in,
+ uint32_t ucf_flags,
+ NTTIME twrp,
+ struct files_struct **_dirfsp,
+ struct smb_filename **_smb_fname,
+ struct smb_filename **_smb_fname_rel);
NTSTATUS filename_convert_dirfsp(
TALLOC_CTX *ctx,
connection_struct *conn,
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index 603a4c01e7e..53e2aae1bf3 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -1183,12 +1183,7 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct
files_struct *fsp)
* files non-visible to the client. If not, fail the delete.
*/
- status = OpenDir(talloc_tos(),
- conn,
- smb_dname,
- NULL,
- 0,
- &dir_hnd);
+ status = OpenDir_from_pathref(talloc_tos(), fsp, NULL, 0, &dir_hnd);
if (!NT_STATUS_IS_OK(status)) {
/*
* Note, we deliberately squash the error here
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index 3aaf070d5ad..451e21b62af 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -1066,19 +1066,55 @@ NTSTATUS OpenDir_from_pathref(TALLOC_CTX *mem_ctx,
uint32_t attr,
struct smb_Dir **_dir_hnd)
{
- struct files_struct *fsp = NULL;
+ struct connection_struct *conn = dirfsp->conn;
+ struct files_struct *new_fsp = NULL;
struct smb_Dir *dir_hnd = NULL;
+ const struct vfs_open_how how = {.flags = O_RDONLY | O_DIRECTORY};
+ int old_fd;
NTSTATUS status;
- status = openat_internal_dir_from_pathref(dirfsp, O_RDONLY, &fsp);
+ status = create_internal_dirfsp(conn, dirfsp->fsp_name, &new_fsp);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- status = OpenDir_fsp(mem_ctx, fsp->conn, fsp, mask, attr, &dir_hnd);
+ if (dirfsp->fsp_flags.have_proc_fds &&
+ ((old_fd = fsp_get_pathref_fd(dirfsp)) != -1))
+ {
+ struct sys_proc_fd_path_buf buf;
+ struct smb_filename proc_fname = {
+ .base_name = sys_proc_fd_path(old_fd, &buf),
+ };
+ int new_fd;
+
+ new_fd = SMB_VFS_OPENAT(
+ conn, conn->cwd_fsp, &proc_fname, new_fsp, &how);
+ if (new_fd == -1) {
+ status = map_nt_error_from_unix(errno);
+ DBG_DEBUG("SMB_VFS_OPENAT(%s) returned %s\n",
+ proc_fname.base_name, strerror(errno));
+ file_free(NULL, new_fsp);
+ return status;
+ }
+ fsp_set_fd(new_fsp, new_fd);
+ } else {
+ status = fd_openat(conn->cwd_fsp,
+ dirfsp->fsp_name,
+ new_fsp,
+ &how);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("fd_openat(%s) returned %s\n",
+ dirfsp->fsp_name->base_name,
+ nt_errstr(status));
+ file_free(NULL, new_fsp);
+ return status;
+ }
+ }
+
+ status = OpenDir_fsp(mem_ctx, conn, new_fsp, mask, attr, &dir_hnd);
if (!NT_STATUS_IS_OK(status)) {
- fd_close(fsp);
- file_free(NULL, fsp);
+ fd_close(new_fsp);
+ file_free(NULL, new_fsp);
return status;
}
@@ -1514,8 +1550,7 @@ NTSTATUS can_delete_directory_fsp(files_struct *fsp)
struct connection_struct *conn = fsp->conn;
struct smb_Dir *dir_hnd = NULL;
- status = OpenDir(
- talloc_tos(), conn, fsp->fsp_name, NULL, 0, &dir_hnd);
+ status = OpenDir_from_pathref(talloc_tos(), fsp, NULL, 0, &dir_hnd);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index e6bc60ae217..89a5fe4f338 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -667,11 +667,13 @@ fail:
static NTSTATUS filename_convert_dirfsp_nosymlink(
TALLOC_CTX *mem_ctx,
connection_struct *conn,
+ struct files_struct *basedir,
const char *name_in,
uint32_t ucf_flags,
NTTIME twrp,
struct files_struct **_dirfsp,
struct smb_filename **_smb_fname,
+ struct smb_filename **_smb_fname_rel,
struct reparse_data_buffer **_symlink_err)
{
struct smb_filename *smb_dirname = NULL;
@@ -704,7 +706,7 @@ static NTSTATUS filename_convert_dirfsp_nosymlink(
.st_ex_ctime = omit,
};
- *_dirfsp = conn->cwd_fsp;
+ *_dirfsp = basedir;
*_smb_fname = smb_fname;
return NT_STATUS_OK;
}
@@ -750,15 +752,19 @@ static NTSTATUS filename_convert_dirfsp_nosymlink(
}
if (dirname[0] == '\0') {
- status = synthetic_pathref(
+ smb_dirname = synthetic_smb_fname(
mem_ctx,
- conn->cwd_fsp,
".",
NULL,
NULL,
0,
- posix ? SMB_FILENAME_POSIX_PATH : 0,
- &smb_dirname);
+ posix ? SMB_FILENAME_POSIX_PATH : 0);
+ if (smb_dirname == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ status = openat_pathref_fsp_lcomp(basedir,
+ smb_dirname,
+ UCF_POSIX_PATHNAMES);
} else {
status = normalize_filename_case(conn, dirname, ucf_flags);
if (!NT_STATUS_IS_OK(status)) {
@@ -770,7 +776,7 @@ static NTSTATUS filename_convert_dirfsp_nosymlink(
status = openat_pathref_fsp_nosymlink(mem_ctx,
conn,
- conn->cwd_fsp,
+ basedir,
dirname,
twrp,
posix,
@@ -1033,12 +1039,19 @@ static NTSTATUS filename_convert_dirfsp_nosymlink(
}
done:
+ if (S_ISLNK(smb_fname->st.st_ex_mode) &&
+ !(ucf_flags & UCF_LCOMP_LNK_OK)) {
+ status = NT_STATUS_STOPPED_ON_SYMLINK;
+ *_symlink_err = symlink_err;
+ goto fail;
+ }
+
*_dirfsp = smb_dirname->fsp;
*_smb_fname = smb_fname;
*_symlink_err = symlink_err;
smb_fname_fsp_unlink(smb_fname_rel);
- TALLOC_FREE(smb_fname_rel);
+ *_smb_fname_rel = smb_fname_rel;
return NT_STATUS_OK;
fail:
@@ -1059,19 +1072,21 @@ fail:
return status;
}
-NTSTATUS filename_convert_dirfsp(
- TALLOC_CTX *mem_ctx,
- connection_struct *conn,
- const char *name_in,
- uint32_t ucf_flags,
- NTTIME twrp,
- struct files_struct **_dirfsp,
- struct smb_filename **_smb_fname)
+NTSTATUS filename_convert_dirfsp_rel(TALLOC_CTX *mem_ctx,
+ connection_struct *conn,
+ struct files_struct *basedir,
+ const char *name_in,
+ uint32_t ucf_flags,
+ NTTIME twrp,
+ struct files_struct **_dirfsp,
+ struct smb_filename **_smb_fname,
+ struct smb_filename **_smb_fname_rel)
{
struct reparse_data_buffer *symlink_err = NULL;
struct symlink_reparse_struct *lnk = NULL;
NTSTATUS status;
char *target = NULL;
+ char *base_name = NULL;
char *safe_target = NULL;
size_t symlink_redirects = 0;
int ret;
@@ -1083,28 +1098,20 @@ next:
status = filename_convert_dirfsp_nosymlink(mem_ctx,
conn,
+ basedir,
name_in,
ucf_flags,
twrp,
_dirfsp,
_smb_fname,
+ _smb_fname_rel,
&symlink_err);
- if (NT_STATUS_IS_OK(status) && S_ISLNK((*_smb_fname)->st.st_ex_mode)) {
- /*
- * lcomp is a symlink
- */
- if (ucf_flags & UCF_LCOMP_LNK_OK) {
- TALLOC_FREE(symlink_err);
- return NT_STATUS_OK;
- }
- close_file_free(NULL, _dirfsp, ERROR_CLOSE);
- status = NT_STATUS_STOPPED_ON_SYMLINK;
- }
-
if (!NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
return status;
}
+ TALLOC_FREE(*_smb_fname_rel);
+
lnk = &symlink_err->parsed.lnk;
/*
@@ -1150,9 +1157,13 @@ next:
return map_nt_error_from_unix(ret);
}
+ if (basedir != conn->cwd_fsp) {
+ base_name = basedir->fsp_name->base_name;
+ }
+
status = safe_symlink_target_path(mem_ctx,
conn->connectpath,
- NULL,
+ base_name,
target,
lnk->unparsed_path_length,
&safe_target);
@@ -1161,12 +1172,37 @@ next:
return status;
}
name_in = safe_target;
+ basedir = conn->cwd_fsp;
symlink_redirects += 1;
goto next;
}
+NTSTATUS filename_convert_dirfsp(TALLOC_CTX *ctx,
+ connection_struct *conn,
+ const char *name_in,
+ uint32_t ucf_flags,
+ NTTIME twrp,
+ struct files_struct **_dirfsp,
+ struct smb_filename **_smb_name)
+{
+ struct smb_filename *smb_fname_rel = NULL;
+ NTSTATUS status;
+
+ status = filename_convert_dirfsp_rel(ctx,
+ conn,
+ conn->cwd_fsp,
+ name_in,
+ ucf_flags,
+ twrp,
+ _dirfsp,
+ _smb_name,
+ &smb_fname_rel);
+ TALLOC_FREE(smb_fname_rel);
+ return status;
+}
+
char *full_path_from_dirfsp_at_basename(TALLOC_CTX *mem_ctx,
const struct files_struct *dirfsp,
const char *at_base_name)
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index c75d9168fbc..28a0e0c0187 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -286,52 +286,6 @@ NTSTATUS open_internal_dirfsp(connection_struct *conn,
return NT_STATUS_OK;
}
-/*
- * Convert a pathref dirfsp into a real fsp. No need to do any cwd
- * tricks, we just open ".".
- */
-NTSTATUS openat_internal_dir_from_pathref(
- struct files_struct *dirfsp,
- int _open_flags,
- struct files_struct **_fsp)
-{
- struct connection_struct *conn = dirfsp->conn;
- struct smb_filename *smb_dname = dirfsp->fsp_name;
- struct files_struct *fsp = NULL;
- char dot[] = ".";
- struct smb_filename smb_dot = {
- .base_name = dot,
- .flags = smb_dname->flags,
- .twrp = smb_dname->twrp,
- };
- struct vfs_open_how how = { .flags = _open_flags, };
- NTSTATUS status;
-
- status = create_internal_dirfsp(conn, smb_dname, &fsp);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- /*
- * Pointless for opening ".", but you never know...
- */
- how.flags |= O_NOFOLLOW;
-
- status = fd_openat(dirfsp, &smb_dot, fsp, &how);
- if (!NT_STATUS_IS_OK(status)) {
- DBG_INFO("fd_openat(\"%s\", \".\") failed: %s\n",
- fsp_str_dbg(dirfsp),
- nt_errstr(status));
- file_free(NULL, fsp);
- return status;
- }
-
- fsp->fsp_name->st = smb_dname->st;
- fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
- *_fsp = fsp;
- return NT_STATUS_OK;
-}
-
/*
* The "link" in the name doesn't imply link in the filesystem
* sense. It's a object that "links" together an fsp and an smb_fname
@@ -450,20 +404,16 @@ static int smb_fname_fsp_destructor(struct smb_filename
*smb_fname)
static NTSTATUS openat_pathref_fullname(
struct connection_struct *conn,
const struct files_struct *dirfsp,
- struct files_struct *basefsp,
struct smb_filename **full_fname,
struct smb_filename *smb_fname,
const struct vfs_open_how *how)
{
struct files_struct *fsp = NULL;
- bool have_dirfsp = (dirfsp != NULL);
- bool have_basefsp = (basefsp != NULL);
NTSTATUS status;
DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(smb_fname));
SMB_ASSERT(smb_fname->fsp == NULL);
- SMB_ASSERT(have_dirfsp != have_basefsp);
status = fsp_new(conn, conn, &fsp);
if (!NT_STATUS_IS_OK(status)) {
@@ -480,7 +430,6 @@ static NTSTATUS openat_pathref_fullname(
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
- fsp_set_base_fsp(fsp, basefsp);
status = fd_openat(dirfsp, smb_fname, fsp, how);
if (!NT_STATUS_IS_OK(status)) {
@@ -539,7 +488,6 @@ fail:
smb_fname_str_dbg(smb_fname),
nt_errstr(status));
- fsp_set_base_fsp(fsp, NULL);
fd_close(fsp);
file_free(NULL, fsp);
return status;
@@ -592,7 +540,7 @@ NTSTATUS openat_pathref_fsp(const struct files_struct
*dirfsp,
goto fail;
}
status = openat_pathref_fullname(
- conn, dirfsp, NULL, &full_fname, smb_fname, &how);
+ conn, dirfsp, &full_fname, smb_fname, &how);
TALLOC_FREE(full_fname);
return status;
}
@@ -615,7 +563,7 @@ NTSTATUS openat_pathref_fsp(const struct files_struct
*dirfsp,
}
status = openat_pathref_fullname(
- conn, dirfsp, NULL, &full_fname, base_fname, &how);
+ conn, dirfsp, &full_fname, base_fname, &how);
TALLOC_FREE(full_fname);
if (!NT_STATUS_IS_OK(status)) {
DBG_DEBUG("openat_pathref_fullname() failed: %s\n",
@@ -636,6 +584,62 @@ fail:
return status;
}
+NTSTATUS open_rootdir_pathref_fsp(connection_struct *conn,
+ struct files_struct **_fsp)
+{
+ struct smb_filename slash = { .base_name = discard_const_p(char, "/") };
+ struct vfs_open_how how = { .flags = O_RDONLY|O_DIRECTORY, };
+ struct files_struct *fsp = NULL;
+ NTSTATUS status;
+ int fd;
+
+ status = fsp_new(conn, conn, &fsp);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+ GetTimeOfDay(&fsp->open_time);
+ fsp_set_gen_id(fsp);
+ ZERO_STRUCT(conn->sconn->fsp_fi_cache);
+ fsp->fsp_flags.is_pathref = true;
+
+ status = fsp_set_smb_fname(fsp, &slash);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto fail;
+ }
+
+ fd = SMB_VFS_OPENAT(conn,
+ conn->cwd_fsp,
+ fsp->fsp_name,
+ fsp,
+ &how);
+ if (fd == -1) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
+ }
+ fsp_set_fd(fsp, fd);
+
+ status = vfs_stat_fsp(fsp);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("vfs_stat_fsp(\"/\") failed: %s\n",
nt_errstr(status));
+ goto close_fail;
+ }
+ fsp->fsp_flags.is_directory = S_ISDIR(fsp->fsp_name->st.st_ex_mode);
+ if (!fsp->fsp_flags.is_directory) {
+ DBG_DEBUG("\"/\" not a directory\n");
+ status = NT_STATUS_UNEXPECTED_IO_ERROR;
+ goto close_fail;
+ }
+ fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
+ *_fsp = fsp;
+ return NT_STATUS_OK;
+
+close_fail:
+ fd_close(fsp);
+fail:
+ file_free(NULL, fsp);
+ return status;
+}
+
/*
* Open a stream given an already opened base_fsp. Avoid
* non_widelink_open: This is only valid for the case where we have a
@@ -646,11 +650,13 @@ NTSTATUS open_stream_pathref_fsp(
struct smb_filename *smb_fname)
{
struct files_struct *base_fsp = *_base_fsp;
+ struct files_struct *fsp = NULL;
connection_struct *conn = base_fsp->conn;
struct smb_filename *base_fname = base_fsp->fsp_name;
struct smb_filename *full_fname = NULL;
struct vfs_open_how how = { .flags = O_RDONLY|O_NONBLOCK, };
NTSTATUS status;
+ int fd;
SMB_ASSERT(smb_fname->fsp == NULL);
SMB_ASSERT(is_named_stream(smb_fname));
@@ -666,9 +672,61 @@ NTSTATUS open_stream_pathref_fsp(
--
Samba Shared Repository