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

Reply via email to