From: Volker Lendecke Date: Tue, 14 Jun 2022 14:33:57 +0000 (+0200) Subject: VFS: NULL dirfsp for openat on stream opens X-Git-Tag: tevent-0.13.0~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c267c9839eb75ee458e28d545e8941aec35b8062;p=thirdparty%2Fsamba.git VFS: NULL dirfsp for openat on stream opens The main optimization is to avoid non_widelink_open() for streams opens based on the fact that all streams opens are relative to fsp->base_fsp, which is a pathref fsp already. Neither streams_xattr nor streams_depot referenced dirfsp for the streams case. Make this more obvious in the callers by passing NULL and asserting this: non-streams opens and streams opens are just different things, streams-opens can and do reference a base fsp and don't need the non_widelink_open logic. Signed-off-by: Volker Lendecke Reviewed-by: Ralph Boehme --- diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index 05ab8fcea69..685c15bcaa7 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -2666,7 +2666,7 @@ static ssize_t fruit_pwrite_meta_stream(vfs_handle_struct *handle, } fd = SMB_VFS_NEXT_OPENAT(handle, - fsp->conn->cwd_fsp, + NULL, /* opening a stream */ fsp->fsp_name, fsp, fio->flags, diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c index 107543f6bbc..6722d712bff 100644 --- a/source3/modules/vfs_streams_depot.c +++ b/source3/modules/vfs_streams_depot.c @@ -684,6 +684,7 @@ static int streams_depot_openat(struct vfs_handle_struct *handle, } SMB_ASSERT(fsp_is_alternate_stream(fsp)); + SMB_ASSERT(dirfsp == NULL); SMB_ASSERT(VALID_STAT(fsp->base_fsp->fsp_name->st)); create_it = (mode & O_CREAT); diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c index 3e39770bb37..dd689261449 100644 --- a/source3/modules/vfs_streams_xattr.c +++ b/source3/modules/vfs_streams_xattr.c @@ -344,6 +344,7 @@ static int streams_xattr_openat(struct vfs_handle_struct *handle, } SMB_ASSERT(fsp_is_alternate_stream(fsp)); + SMB_ASSERT(dirfsp == NULL); status = streams_xattr_get_name(handle, talloc_tos(), smb_fname->stream_name, &xattr_name); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index c9660555569..d6ce87cc5fb 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -667,7 +667,7 @@ NTSTATUS open_stream_pathref_fsp( fd = SMB_VFS_OPENAT( conn, - dirfsp, + NULL, /* stream open is relative to fsp->base_fsp */ smb_fname, fsp, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 8cb349d78b0..ce9b43fa072 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -937,6 +937,35 @@ NTSTATUS fd_openat(const struct files_struct *dirfsp, flags |= O_NOFOLLOW; } + if (fsp_is_alternate_stream(fsp)) { + int fd; + + SMB_ASSERT(is_named_stream(smb_fname)); + + fd = SMB_VFS_OPENAT( + conn, + NULL, /* stream open is relative to fsp->base_fsp */ + smb_fname, + fsp, + flags, + mode); + if (fd == -1) { + status = map_nt_error_from_unix(errno); + } + fsp_set_fd(fsp, fd); + + if (fd != -1) { + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("vfs_stat_fsp failed: %s\n", + nt_errstr(status)); + fd_close(fsp); + } + } + + return status; + } + /* * Only follow symlinks within a share * definition. diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c index b27eca87ab4..dab458de69e 100644 --- a/source3/torture/cmd_vfs.c +++ b/source3/torture/cmd_vfs.c @@ -418,6 +418,8 @@ static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c goto fail; } + TALLOC_FREE(fspcwd); + fsp->base_fsp = base_name->fsp; }