From: Volker Lendecke Date: Sun, 13 Mar 2022 09:48:12 +0000 (+0100) Subject: smbd: Add openat_internal_dir_from_pathref() X-Git-Tag: talloc-2.3.4~331 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=df29512b72f652728afd6ce161e4eec50c2400a8;p=thirdparty%2Fsamba.git smbd: Add openat_internal_dir_from_pathref() If we have a directory pathref fsp, do an openat(dirfd, ".", O_RDONLY) to cheaply get a real directory handle. Signed-off-by: Volker Lendecke Reviewed-by: Ralph Boehme --- diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 542f1fe4181..caee85a674e 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -282,6 +282,56 @@ 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, + }; + NTSTATUS status; + + SMB_ASSERT(dirfsp != conn->cwd_fsp); + SMB_ASSERT(VALID_STAT(smb_dname->st)); + SMB_ASSERT(S_ISDIR(smb_dname->st.st_ex_mode)); + SMB_ASSERT(fsp_get_pathref_fd(dirfsp) != -1); + + status = create_internal_dirfsp(conn, smb_dname, &fsp); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* + * Pointless for opening ".", but you never know... + */ + open_flags |= O_NOFOLLOW; + + status = fd_openat(dirfsp, &smb_dot, fsp, open_flags, 0); + 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 diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index b78111c25c2..b6449b105f3 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -439,6 +439,10 @@ NTSTATUS open_internal_dirfsp(connection_struct *conn, const struct smb_filename *smb_dname, int open_flags, struct files_struct **_fsp); +NTSTATUS openat_internal_dir_from_pathref( + struct files_struct *dirfsp, + int open_flags, + struct files_struct **_fsp); NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp, struct smb_filename *smb_fname);