summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnoop C S <anoopcs@samba.org>2022-08-19 12:07:08 +0530
committerJule Anger <janger@samba.org>2022-08-30 09:48:11 +0000
commite0375100d798459d87d51c300f87049baf1027c2 (patch)
tree7e60e386f5e9cc78af138527f1d73bd78a1917f0
parenta8eab509154fcd0b93b193ead231a7b62f28d38d (diff)
downloadsamba-e0375100d798459d87d51c300f87049baf1027c2.tar.gz
vfs_glusterfs: Use glfs_openat() for SMB_VFS_OPENAT
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15157 Signed-off-by: Anoop C S <anoopcs@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org> (cherry picked from commit 184a9913241acd4f69128ced3370d3bf49b95f3b)
-rw-r--r--source3/modules/vfs_glusterfs.c105
1 files changed, 76 insertions, 29 deletions
diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
index 92fc0a80e9f..3503dfc251f 100644
--- a/source3/modules/vfs_glusterfs.c
+++ b/source3/modules/vfs_glusterfs.c
@@ -765,9 +765,12 @@ static int vfs_gluster_openat(struct vfs_handle_struct *handle,
files_struct *fsp,
const struct vfs_open_how *how)
{
- struct smb_filename *name = NULL;
+ int flags = how->flags;
+ struct smb_filename *full_fname = NULL;
+ bool have_opath = false;
bool became_root = false;
glfs_fd_t *glfd;
+ glfs_fd_t *pglfd = NULL;
glfs_fd_t **p_tmp;
START_PROFILE(syscall_openat);
@@ -778,58 +781,103 @@ static int vfs_gluster_openat(struct vfs_handle_struct *handle,
return -1;
}
- /*
- * Looks like glfs API doesn't have openat().
- */
- if (fsp_get_pathref_fd(dirfsp) != AT_FDCWD) {
- name = full_path_from_dirfsp_atname(talloc_tos(),
- dirfsp,
- smb_fname);
- if (name == NULL) {
- END_PROFILE(syscall_openat);
- return -1;
- }
- smb_fname = name;
- }
-
p_tmp = VFS_ADD_FSP_EXTENSION(handle, fsp, glfs_fd_t *, NULL);
if (p_tmp == NULL) {
- TALLOC_FREE(name);
END_PROFILE(syscall_openat);
errno = ENOMEM;
return -1;
}
+#ifdef O_PATH
+ have_opath = true;
if (fsp->fsp_flags.is_pathref) {
- /*
- * ceph doesn't support O_PATH so we have to fallback to
- * become_root().
- */
+ flags |= O_PATH;
+ }
+#endif
+
+ full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+ dirfsp,
+ smb_fname);
+ if (full_fname == NULL) {
+ END_PROFILE(syscall_openat);
+ return -1;
+ }
+
+ if (fsp->fsp_flags.is_pathref && !have_opath) {
become_root();
became_root = true;
}
- if (how->flags & O_DIRECTORY) {
- glfd = glfs_opendir(handle->data, smb_fname->base_name);
- } else if (how->flags & O_CREAT) {
+ /*
+ * O_CREAT flag in open is handled differently in a way which is *NOT*
+ * safe against symlink race situations. We use glfs_creat() instead
+ * for correctness as glfs_openat() is broken with O_CREAT present
+ * in open flags.
+ */
+ if (flags & O_CREAT) {
+ if (fsp_get_pathref_fd(dirfsp) != AT_FDCWD) {
+ /*
+ * Replace smb_fname with full_path constructed above.
+ */
+ smb_fname = full_fname;
+ }
+
+ /*
+ * smb_fname can either be a full_path or the same one
+ * as received from the caller. In the latter case we
+ * are operating at current working directory.
+ */
glfd = glfs_creat(handle->data,
smb_fname->base_name,
- how->flags,
+ flags,
how->mode);
} else {
- glfd = glfs_open(handle->data,
- smb_fname->base_name,
- how->flags);
+ if (fsp_get_pathref_fd(dirfsp) != AT_FDCWD) {
+#ifdef HAVE_GFAPI_VER_7_11
+ /*
+ * Fetch Gluster fd for parent directory using dirfsp
+ * before calling glfs_openat();
+ */
+ pglfd = vfs_gluster_fetch_glfd(handle, dirfsp);
+ if (pglfd == NULL) {
+ END_PROFILE(syscall_openat);
+ DBG_ERR("Failed to fetch gluster fd\n");
+ return -1;
+ }
+
+ glfd = glfs_openat(pglfd,
+ smb_fname->base_name,
+ flags,
+ how->mode);
+#else
+ /*
+ * Replace smb_fname with full_path constructed above.
+ */
+ smb_fname = full_fname;
+#endif
+ }
+
+ if (pglfd == NULL) {
+ /*
+ * smb_fname can either be a full_path or the same one
+ * as received from the caller. In the latter case we
+ * are operating at current working directory.
+ */
+ glfd = glfs_open(handle->data,
+ smb_fname->base_name,
+ flags);
+ }
}
if (became_root) {
unbecome_root();
}
+ TALLOC_FREE(full_fname);
+
fsp->fsp_flags.have_proc_fds = false;
if (glfd == NULL) {
- TALLOC_FREE(name);
END_PROFILE(syscall_openat);
/* no extension destroy_fn, so no need to save errno */
VFS_REMOVE_FSP_EXTENSION(handle, fsp);
@@ -838,7 +886,6 @@ static int vfs_gluster_openat(struct vfs_handle_struct *handle,
*p_tmp = glfd;
- TALLOC_FREE(name);
END_PROFILE(syscall_openat);
/* An arbitrary value for error reporting, so you know its us. */
return 13371337;