--- samba-4.18.2-old/source3/smbd/open.c 2023-04-19 12:18:56.254875400 +0200 +++ samba-4.18.2/source3/smbd/open.c 2023-05-31 00:04:28.140440000 +0200 @@ -1204,9 +1204,6 @@ int new_fd; NTSTATUS status; - if (!fsp->fsp_flags.have_proc_fds) { - return NT_STATUS_MORE_PROCESSING_REQUIRED; - } old_fd = fsp_get_pathref_fd(fsp); if (old_fd == -1) { @@ -1222,6 +1219,14 @@ return NT_STATUS_INVALID_HANDLE; } +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + new_fd = openat(old_fd, "", O_EMPTY_PATH|flags); + if (new_fd < 0) { +#endif + if (!fsp->fsp_flags.have_proc_fds) { + return NT_STATUS_MORE_PROCESSING_REQUIRED; + } + p = sys_proc_fd_path(old_fd, buf, sizeof(buf)); if (p == NULL) { return NT_STATUS_NO_MEMORY; @@ -1231,13 +1238,14 @@ .base_name = discard_const_p(char, p), }; - fsp->fsp_flags.is_pathref = false; - new_fd = SMB_VFS_OPENAT(fsp->conn, fsp->conn->cwd_fsp, &proc_fname, fsp, &how); +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + } +#endif if (new_fd == -1) { status = map_nt_error_from_unix(errno); fd_close(fsp); @@ -1250,6 +1258,8 @@ } fsp_set_fd(fsp, new_fd); + fsp->fsp_flags.is_pathref = false; + return NT_STATUS_OK; } --- samba-4.18.2-old/source3/modules/vfs_default.c 2023-01-18 16:32:24.198553300 +0100 +++ samba-4.18.2/source3/modules/vfs_default.c 2023-05-30 23:28:52.593571000 +0200 @@ -2721,7 +2721,10 @@ static int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode) { - int result; + int result, fd; +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + int real_fd; +#endif START_PROFILE(syscall_fchmod); @@ -2731,8 +2734,22 @@ return result; } + fd = fsp_get_pathref_fd(fsp); + +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + real_fd = openat(fd, "", O_EMPTY_PATH); + if (real_fd >= 0) { + int saved_errno; + + result = fchmod(real_fd, mode); + saved_errno = errno; + close(real_fd); + errno = saved_errno; + END_PROFILE(syscall_fchmod); + return result; + } +#endif if (fsp->fsp_flags.have_proc_fds) { - int fd = fsp_get_pathref_fd(fsp); const char *p = NULL; char buf[PATH_MAX]; @@ -2758,7 +2775,10 @@ static int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid) { #ifdef HAVE_FCHOWN - int result; + int result, fd; +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + int real_fd; +#endif START_PROFILE(syscall_fchown); if (!fsp->fsp_flags.is_pathref) { @@ -2767,8 +2787,22 @@ return result; } + fd = fsp_get_pathref_fd(fsp); + +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + real_fd = openat(fd, "", O_EMPTY_PATH); + if (real_fd >= 0) { + int saved_errno; + + result = fchown(real_fd, uid, gid); + saved_errno = errno; + close(real_fd); + errno = saved_errno; + END_PROFILE(syscall_fchown); + return result; + } +#endif if (fsp->fsp_flags.have_proc_fds) { - int fd = fsp_get_pathref_fd(fsp); const char *p = NULL; char buf[PATH_MAX]; @@ -2855,9 +2889,12 @@ files_struct *fsp, struct smb_file_time *ft) { - int result = -1; + int result = -1, fd; struct timespec ts[2]; struct timespec *times = NULL; +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + int real_fd; +#endif START_PROFILE(syscall_fntimes); @@ -2900,8 +2937,22 @@ goto out; } + fd = fsp_get_pathref_fd(fsp); + +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + real_fd = openat(fd, "", O_EMPTY_PATH); + if (real_fd >= 0) { + int saved_errno; + + result = futimens(real_fd, times); + saved_errno = errno; + close(real_fd); + errno = saved_errno; + goto out; + } +#endif + if (fsp->fsp_flags.have_proc_fds) { - int fd = fsp_get_pathref_fd(fsp); const char *p = NULL; char buf[PATH_MAX]; @@ -3322,6 +3373,9 @@ { #ifdef HAVE_FCHFLAGS int fd = fsp_get_pathref_fd(fsp); +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + int real_fd; +#endif SMB_ASSERT(!fsp_is_alternate_stream(fsp)); @@ -3329,6 +3383,18 @@ return fchflags(fd, flags); } +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + real_fd = openat(fd, "", O_EMPTY_PATH); + if (real_fd >= 0) { + int saved_errno, result; + + result = fchflags(real_fd, flags); + saved_errno = errno; + close(real_fd); + errno = saved_errno; + return result; + } +#endif if (fsp->fsp_flags.have_proc_fds) { const char *p = NULL; char buf[PATH_MAX]; @@ -3569,6 +3635,9 @@ size_t size) { int fd = fsp_get_pathref_fd(fsp); +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + int real_fd; +#endif SMB_ASSERT(!fsp_is_alternate_stream(fsp)); @@ -3576,6 +3645,18 @@ return fgetxattr(fd, name, value, size); } +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + real_fd = openat(fd, "", O_EMPTY_PATH); + if (real_fd >= 0) { + int saved_errno, result; + + result = fgetxattr(real_fd, name, value, size); + saved_errno = errno; + close(real_fd); + errno = saved_errno; + return result; + } +#endif if (fsp->fsp_flags.have_proc_fds) { const char *p = NULL; char buf[PATH_MAX]; @@ -3895,6 +3976,9 @@ static ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, char *list, size_t size) { int fd = fsp_get_pathref_fd(fsp); +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + int real_fd; +#endif SMB_ASSERT(!fsp_is_alternate_stream(fsp)); @@ -3902,6 +3986,18 @@ return flistxattr(fd, list, size); } +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + real_fd = openat(fd, "", O_EMPTY_PATH); + if (real_fd >= 0) { + int saved_errno, result; + + result = flistxattr(real_fd, list, size); + saved_errno = errno; + close(real_fd); + errno = saved_errno; + return result; + } +#endif if (fsp->fsp_flags.have_proc_fds) { const char *p = NULL; char buf[PATH_MAX]; @@ -3923,6 +4019,9 @@ static int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name) { int fd = fsp_get_pathref_fd(fsp); +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + int real_fd; +#endif SMB_ASSERT(!fsp_is_alternate_stream(fsp)); @@ -3930,6 +4029,18 @@ return fremovexattr(fd, name); } +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + real_fd = openat(fd, "", O_EMPTY_PATH); + if (real_fd >= 0) { + int saved_errno, result; + + result = fremovexattr(real_fd, name); + saved_errno = errno; + close(real_fd); + errno = saved_errno; + return result; + } +#endif if (fsp->fsp_flags.have_proc_fds) { const char *p = NULL; char buf[PATH_MAX]; @@ -3951,6 +4062,9 @@ static int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, const void *value, size_t size, int flags) { int fd = fsp_get_pathref_fd(fsp); +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + int real_fd; +#endif SMB_ASSERT(!fsp_is_alternate_stream(fsp)); @@ -3958,6 +4072,18 @@ return fsetxattr(fd, name, value, size, flags); } +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + real_fd = openat(fd, "", O_EMPTY_PATH); + if (real_fd >= 0) { + int saved_errno, result; + + result = fsetxattr(real_fd, name, value, size, flags); + saved_errno = errno; + close(real_fd); + errno = saved_errno; + return result; + } +#endif if (fsp->fsp_flags.have_proc_fds) { const char *p = NULL; char buf[PATH_MAX]; --- samba-4.18.2-old/source3/modules/vfs_zfsacl.c 2023-01-18 16:32:24.210553400 +0100 +++ samba-4.18.2/source3/modules/vfs_zfsacl.c 2023-05-30 23:09:26.917913000 +0200 @@ -234,6 +234,7 @@ SMB_ASSERT(i == naces); +#if 0 /* Original */ /* store acl */ fd = fsp_get_pathref_fd(fsp); if (fd == -1) { @@ -241,6 +242,36 @@ return false; } rv = facl(fd, ACE_SETACL, naces, acebuf); +#else + if (!fsp->fsp_flags.is_pathref) { + rv = facl(fsp_get_io_fd(fsp), ACE_SETACL, naces, acebuf); + } else { +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + fd = fsp_get_pathref_fd(fsp); + + /* First try this for versions of FreeBSD that allows facl() on O_PATH fd's */ + rv = facl(fd, ACE_SETACL, naces, acebuf); + if (rv < 0 && errno == EBADF) { + /* Fall back to getting a real fd via openat() */ + int saved_errno, real_fd; + + real_fd = openat(fd, "", O_EMPTY_PATH); + if (real_fd < 0) { + errno = EBADF; + return false; + } + + rv = facl(real_fd, ACE_SETACL, naces, acebuf); + saved_errno = errno; + close(real_fd); + errno = saved_errno; + } +#else + /* Last ditch fallback */ + rv = acl(fsp->fsp_name->base_name, ACE_SETACL, naces, acebuf); +#endif + } +#endif if (rv != 0) { if(errno == ENOSYS) { DEBUG(9, ("acl(ACE_SETACL, %s): Operation is not " @@ -286,12 +317,40 @@ ace_t *acebuf = NULL; int fd; +#if 0 /* Original */ fd = fsp_get_pathref_fd(fsp); if (fd == -1) { errno = EBADF; return -1; } naces = facl(fd, ACE_GETACLCNT, 0, NULL); +#else + if (!fsp->fsp_flags.is_pathref) { + naces = facl(fsp_get_io_fd(fsp), ACE_GETACLCNT, 0, NULL); + } else { +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + fd = fsp_get_pathref_fd(fsp); + + /* First try this for versions of FreeBSD that allows facl() on O_PATH fd's */ + naces = facl(fd, ACE_GETACLCNT, 0, NULL); + if (naces < 0 && errno == EBADF) { + int saved_errno, real_fd; + + real_fd = openat(fd, "", O_EMPTY_PATH); + if (real_fd < 0) { + errno = EBADF; + return false; + } + rv = facl(real_fd, ACE_GETACLCNT, 0, NULL); + saved_errno = errno; + close(real_fd); + errno = saved_errno; + } +#else + naces = acl(fsp->fsp_name->base_name, ACE_GETACLCNT, 0, NULL); +#endif + } +#endif if (naces == -1) { int dbg_level = 10; @@ -309,7 +368,35 @@ return -1; } +#if 0 /* Original */ rv = facl(fd, ACE_GETACL, naces, acebuf); +#else + if (!fsp->fsp_flags.is_pathref) { + rv = facl(fsp_get_io_fd(fsp), ACE_GETACL, naces, acebuf); + } else { +#if defined(HAVE_OPENAT) && defined(O_EMPTY_PATH) + fd = fsp_get_pathref_fd(fsp); + + /* First try this for versions of FreeBSD that allows facl() on O_PATH fd's */ + rv = facl(fd, ACE_GETACL, naces, acebuf); + if (rv < 0 && errno == EBADF) { + int saved_errno, real_fd; + + real_fd = openat(fd, "", O_EMPTY_PATH); + if (real_fd < 0) { + errno = EBADF; + return false; + } + rv = facl(real_fd, ACE_GETACL, naces, acebuf); + saved_errno = errno; + close(real_fd); + errno = saved_errno; + } +#else + rv = acl(fsp->fsp_name->base_name, ACE_GETACL, naces, acebuf); +#endif + } +#endif if (rv == -1) { DBG_DEBUG("acl(ACE_GETACL, %s): %s ", fsp_str_dbg(fsp), strerror(errno));