From c29438f8238c3cf436e126c99f6f9f6bcca4efaf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 30 Jun 2017 11:32:59 -0700 Subject: [PATCH] s3: VFS: Change SMB_VFS_REALPATH to take and return struct smb_filename * instead of char *. We need to migrate all pathname based VFS calls to use a struct to finish modernising the VFS with extra timestamp and flags parameters. Signed-off-by: Jeremy Allison Reviewed-by: Richard Sharpe --- examples/VFS/skel_opaque.c | 4 +- examples/VFS/skel_transparent.c | 6 ++- source3/include/vfs.h | 10 ++++- source3/include/vfs_macros.h | 8 ++-- source3/modules/vfs_cap.c | 30 +++++++++++++-- source3/modules/vfs_catia.c | 28 ++++++++++---- source3/modules/vfs_ceph.c | 14 ++++++- source3/modules/vfs_default.c | 13 +++++-- source3/modules/vfs_fake_dfq.c | 57 +++++++++++++++++----------- source3/modules/vfs_full_audit.c | 14 ++++--- source3/modules/vfs_glusterfs.c | 17 ++++++--- source3/modules/vfs_media_harmony.c | 34 +++++++---------- source3/modules/vfs_shadow_copy2.c | 60 +++++++++++++++-------------- source3/modules/vfs_snapper.c | 42 ++++++++++++--------- source3/modules/vfs_time_audit.c | 14 ++++--- source3/modules/vfs_unityed_media.c | 23 ++++++------ source3/smbd/open.c | 26 ++++++++----- source3/smbd/service.c | 10 +++-- source3/smbd/vfs.c | 75 +++++++++++++++++++++---------------- source3/torture/cmd_vfs.c | 10 ++++- 20 files changed, 308 insertions(+), 187 deletions(-) diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c index 8bfc520c8eb..f8f98575f62 100644 --- a/examples/VFS/skel_opaque.c +++ b/examples/VFS/skel_opaque.c @@ -512,7 +512,9 @@ static int skel_mknod(vfs_handle_struct *handle, return -1; } -static char *skel_realpath(vfs_handle_struct *handle, const char *path) +static struct smb_filename *skel_realpath(vfs_handle_struct *handle, + TALLOC_CTX *ctx, + const struct smb_filename *smb_fname) { errno = ENOSYS; return NULL; diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c index a5ba6a9c4d8..29a97852974 100644 --- a/examples/VFS/skel_transparent.c +++ b/examples/VFS/skel_transparent.c @@ -602,9 +602,11 @@ static int skel_mknod(vfs_handle_struct *handle, return SMB_VFS_NEXT_MKNOD(handle, smb_fname, mode, dev); } -static char *skel_realpath(vfs_handle_struct *handle, const char *path) +static struct smb_filename *skel_realpath(vfs_handle_struct *handle, + TALLOC_CTX *ctx, + const struct smb_filename *smb_fname) { - return SMB_VFS_NEXT_REALPATH(handle, path); + return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname); } static int skel_chflags(vfs_handle_struct *handle, diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 716e194a4ee..1aa44ee14e1 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -234,6 +234,8 @@ to const struct smb_filename * */ /* Version 37 - Change conn->cwd from char * to struct smb_filename * */ +/* Version 37 - Change realpath from char * + to struct smb_filename * */ #define SMB_VFS_INTERFACE_VERSION 37 @@ -769,7 +771,9 @@ struct vfs_fn_pointers { const struct smb_filename *smb_fname, mode_t mode, SMB_DEV_T dev); - char *(*realpath_fn)(struct vfs_handle_struct *handle, const char *path); + struct smb_filename *(*realpath_fn)(struct vfs_handle_struct *handle, + TALLOC_CTX *ctx, + const struct smb_filename *smb_fname); int (*chflags_fn)(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname, unsigned int flags); @@ -1279,7 +1283,9 @@ int smb_vfs_call_mknod(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname, mode_t mode, SMB_DEV_T dev); -char *smb_vfs_call_realpath(struct vfs_handle_struct *handle, const char *path); +struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle, + TALLOC_CTX *ctx, + const struct smb_filename *smb_fname); int smb_vfs_call_chflags(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname, unsigned int flags); diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index 29f03389cce..0e8245e752d 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -331,10 +331,10 @@ #define SMB_VFS_NEXT_MKNOD(handle, smb_fname, mode, dev) \ smb_vfs_call_mknod((handle)->next, (smb_fname), (mode), (dev)) -#define SMB_VFS_REALPATH(conn, path) \ - smb_vfs_call_realpath((conn)->vfs_handles, (path)) -#define SMB_VFS_NEXT_REALPATH(handle, path) \ - smb_vfs_call_realpath((handle)->next, (path)) +#define SMB_VFS_REALPATH(conn, ctx, smb_fname) \ + smb_vfs_call_realpath((conn)->vfs_handles, (ctx), (smb_fname)) +#define SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname) \ + smb_vfs_call_realpath((handle)->next, (ctx), (smb_fname)) #define SMB_VFS_CHFLAGS(conn, smb_fname, flags) \ smb_vfs_call_chflags((conn)->vfs_handles, (smb_fname), (flags)) diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c index 44a81bbcefb..e4d30cb4e5a 100644 --- a/source3/modules/vfs_cap.c +++ b/source3/modules/vfs_cap.c @@ -667,16 +667,40 @@ static int cap_mknod(vfs_handle_struct *handle, return ret; } -static char *cap_realpath(vfs_handle_struct *handle, const char *path) +static struct smb_filename *cap_realpath(vfs_handle_struct *handle, + TALLOC_CTX *ctx, + const struct smb_filename *smb_fname) { /* monyo need capencode'ed and capdecode'ed? */ - char *cappath = capencode(talloc_tos(), path); + struct smb_filename *cap_smb_fname = NULL; + struct smb_filename *return_fname = NULL; + char *cappath = capencode(talloc_tos(), smb_fname->base_name); + int saved_errno = 0; if (!cappath) { errno = ENOMEM; return NULL; } - return SMB_VFS_NEXT_REALPATH(handle, cappath); + cap_smb_fname = synthetic_smb_fname(ctx, + cappath, + NULL, + NULL, + smb_fname->flags); + if (cap_smb_fname == NULL) { + TALLOC_FREE(cappath); + errno = ENOMEM; + return NULL; + } + return_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, cap_smb_fname); + if (return_fname == NULL) { + saved_errno = errno; + } + TALLOC_FREE(cappath); + TALLOC_FREE(cap_smb_fname); + if (saved_errno != 0) { + errno = saved_errno; + } + return return_fname; } static int cap_chmod_acl(vfs_handle_struct *handle, diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c index 7db50a26206..6adf4414af6 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/modules/vfs_catia.c @@ -1055,24 +1055,38 @@ static int catia_ntimes(vfs_handle_struct *handle, return ret; } -static char * -catia_realpath(vfs_handle_struct *handle, const char *path) +static struct smb_filename * +catia_realpath(vfs_handle_struct *handle, + TALLOC_CTX *ctx, + const struct smb_filename *smb_fname) { char *mapped_name = NULL; + struct smb_filename *catia_smb_fname = NULL; + struct smb_filename *return_fname = NULL; NTSTATUS status; - char *ret = NULL; - status = catia_string_replace_allocate(handle->conn, path, + status = catia_string_replace_allocate(handle->conn, + smb_fname->base_name, &mapped_name, vfs_translate_to_unix); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); return NULL; } - ret = SMB_VFS_NEXT_REALPATH(handle, mapped_name); + catia_smb_fname = synthetic_smb_fname(talloc_tos(), + mapped_name, + NULL, + NULL, + smb_fname->flags); + if (catia_smb_fname == NULL) { + TALLOC_FREE(mapped_name); + errno = ENOMEM; + return NULL; + } + return_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, catia_smb_fname); TALLOC_FREE(mapped_name); - - return ret; + TALLOC_FREE(catia_smb_fname); + return return_fname; } static int catia_chflags(struct vfs_handle_struct *handle, diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c index 7d3f4a7bbaa..488ebc7795d 100644 --- a/source3/modules/vfs_ceph.c +++ b/source3/modules/vfs_ceph.c @@ -1191,10 +1191,14 @@ static int cephwrap_mknod(struct vfs_handle_struct *handle, * This is a simple version of real-path ... a better version is needed to * ask libceph about symbolic links. */ -static char *cephwrap_realpath(struct vfs_handle_struct *handle, const char *path) +static struct smb_filename *cephwrap_realpath(struct vfs_handle_struct *handle, + TALLOC_CTX *ctx, + const struct smb_filename *smb_fname) { char *result; + const char *path = smb_fname->base_name; size_t len = strlen(path); + struct smb_filename *result_fname = NULL; result = SMB_MALLOC_ARRAY(char, PATH_MAX+1); if (len && (path[0] == '/')) { @@ -1216,7 +1220,13 @@ static char *cephwrap_realpath(struct vfs_handle_struct *handle, const char *pa if (r < 0) return NULL; } DBG_DEBUG("[CEPH] realpath(%p, %s) = %s\n", handle, path, result); - return result; + result_fname = synthetic_smb_fname(ctx, + result, + NULL, + NULL, + 0); + SAFE_FREE(result); + return result_fname; } static int cephwrap_chflags(struct vfs_handle_struct *handle, diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index b01a0078180..3336232e3d6 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -2487,14 +2487,21 @@ static int vfswrap_mknod(vfs_handle_struct *handle, return result; } -static char *vfswrap_realpath(vfs_handle_struct *handle, const char *path) +static struct smb_filename *vfswrap_realpath(vfs_handle_struct *handle, + TALLOC_CTX *ctx, + const struct smb_filename *smb_fname) { char *result; + struct smb_filename *result_fname = NULL; START_PROFILE(syscall_realpath); - result = sys_realpath(path); + result = sys_realpath(smb_fname->base_name); END_PROFILE(syscall_realpath); - return result; + if (result) { + result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0); + SAFE_FREE(result); + } + return result_fname; } static int vfswrap_chflags(vfs_handle_struct *handle, diff --git a/source3/modules/vfs_fake_dfq.c b/source3/modules/vfs_fake_dfq.c index 971db68bc55..019b2e8891d 100644 --- a/source3/modules/vfs_fake_dfq.c +++ b/source3/modules/vfs_fake_dfq.c @@ -61,24 +61,27 @@ static uint64_t dfq_disk_free(vfs_handle_struct *handle, uint64_t free_1k; int snum = SNUM(handle->conn); uint64_t dfq_bsize = 0; - char *rpath = NULL; + struct smb_filename *rpath_fname = NULL; /* look up the params based on real path to be resilient * to refactoring of path<->realpath */ - rpath = SMB_VFS_NEXT_REALPATH(handle, smb_fname->base_name); - if (rpath != NULL) { - dfq_bsize = dfq_load_param(snum, rpath, "df", "block size", 0); + rpath_fname = SMB_VFS_NEXT_REALPATH(handle, talloc_tos(), smb_fname); + if (rpath_fname != NULL) { + dfq_bsize = dfq_load_param(snum, rpath_fname->base_name, + "df", "block size", 0); } if (dfq_bsize == 0) { - SAFE_FREE(rpath); + TALLOC_FREE(rpath_fname); return SMB_VFS_NEXT_DISK_FREE(handle, smb_fname, bsize, dfree, dsize); } *bsize = dfq_bsize; - *dfree = dfq_load_param(snum, rpath, "df", "disk free", 0); - *dsize = dfq_load_param(snum, rpath, "df", "disk size", 0); + *dfree = dfq_load_param(snum, rpath_fname->base_name, + "df", "disk free", 0); + *dsize = dfq_load_param(snum, rpath_fname->base_name, + "df", "disk size", 0); if ((*bsize) < 1024) { free_1k = (*dfree) / (1024 / (*bsize)); @@ -86,7 +89,7 @@ static uint64_t dfq_disk_free(vfs_handle_struct *handle, free_1k = ((*bsize) / 1024) * (*dfree); } - SAFE_FREE(rpath); + TALLOC_FREE(rpath_fname); return free_1k; } @@ -101,10 +104,10 @@ static int dfq_get_quota(struct vfs_handle_struct *handle, char *section = NULL; int snum = SNUM(handle->conn); uint64_t bsize = 0; - char *rpath = NULL; + struct smb_filename *rpath_fname = NULL; - rpath = SMB_VFS_NEXT_REALPATH(handle, smb_fname->base_name); - if (rpath == NULL) { + rpath_fname = SMB_VFS_NEXT_REALPATH(handle, talloc_tos(), smb_fname); + if (rpath_fname == NULL) { goto dflt; } @@ -131,18 +134,21 @@ static int dfq_get_quota(struct vfs_handle_struct *handle, goto dflt; } - bsize = dfq_load_param(snum, rpath, section, "block size", 4096); + bsize = dfq_load_param(snum, rpath_fname->base_name, + section, "block size", 4096); if (bsize == 0) { goto dflt; } - if (dfq_load_param(snum, rpath, section, "err", 0) != 0) { + if (dfq_load_param(snum, rpath_fname->base_name, + section, "err", 0) != 0) { errno = ENOTSUP; rc = -1; goto out; } - if (dfq_load_param(snum, rpath, section, "nosys", 0) != 0) { + if (dfq_load_param(snum, rpath_fname->base_name, + section, "nosys", 0) != 0) { errno = ENOSYS; rc = -1; goto out; @@ -151,15 +157,22 @@ static int dfq_get_quota(struct vfs_handle_struct *handle, ZERO_STRUCTP(qt); qt->bsize = bsize; - qt->hardlimit = dfq_load_param(snum, rpath, section, "hard limit", 0); - qt->softlimit = dfq_load_param(snum, rpath, section, "soft limit", 0); - qt->curblocks = dfq_load_param(snum, rpath, section, "cur blocks", 0); + qt->hardlimit = dfq_load_param(snum, rpath_fname->base_name, + section, "hard limit", 0); + qt->softlimit = dfq_load_param(snum, rpath_fname->base_name, + section, "soft limit", 0); + qt->curblocks = dfq_load_param(snum, rpath_fname->base_name, + section, "cur blocks", 0); qt->ihardlimit = - dfq_load_param(snum, rpath, section, "inode hard limit", 0); + dfq_load_param(snum, rpath_fname->base_name, + section, "inode hard limit", 0); qt->isoftlimit = - dfq_load_param(snum, rpath, section, "inode soft limit", 0); - qt->curinodes = dfq_load_param(snum, rpath, section, "cur inodes", 0); - qt->qflags = dfq_load_param(snum, rpath, section, "qflags", QUOTAS_DENY_DISK); + dfq_load_param(snum, rpath_fname->base_name, + section, "inode soft limit", 0); + qt->curinodes = dfq_load_param(snum, rpath_fname->base_name, + section, "cur inodes", 0); + qt->qflags = dfq_load_param(snum, rpath_fname->base_name, + section, "qflags", QUOTAS_DENY_DISK); goto out; @@ -169,7 +182,7 @@ dflt: out: save_errno = errno; TALLOC_FREE(section); - SAFE_FREE(rpath); + TALLOC_FREE(rpath_fname); errno = save_errno; return rc; } diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index 51783245566..e66ad9ebe43 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -1685,16 +1685,18 @@ static int smb_full_audit_mknod(vfs_handle_struct *handle, return result; } -static char *smb_full_audit_realpath(vfs_handle_struct *handle, - const char *path) +static struct smb_filename *smb_full_audit_realpath(vfs_handle_struct *handle, + TALLOC_CTX *ctx, + const struct smb_filename *smb_fname) { - char *result; + struct smb_filename *result_fname = NULL; - result = SMB_VFS_NEXT_REALPATH(handle, path); + result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname); - do_log(SMB_VFS_OP_REALPATH, (result != NULL), handle, "%s", path); + do_log(SMB_VFS_OP_REALPATH, (result_fname != NULL), handle, "%s", + smb_fname->base_name); - return result; + return result_fname; } static int smb_full_audit_chflags(vfs_handle_struct *handle, diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c index 52539b36fd9..188463f6d51 100644 --- a/source3/modules/vfs_glusterfs.c +++ b/source3/modules/vfs_glusterfs.c @@ -1149,10 +1149,12 @@ static int vfs_gluster_fallocate(struct vfs_handle_struct *handle, return -1; } -static char *vfs_gluster_realpath(struct vfs_handle_struct *handle, - const char *path) +static struct smb_filename *vfs_gluster_realpath(struct vfs_handle_struct *handle, + TALLOC_CTX *ctx, + const struct smb_filename *smb_fname) { char *result = NULL; + struct smb_filename *result_fname = NULL; char *resolved_path = SMB_MALLOC_ARRAY(char, PATH_MAX+1); if (resolved_path == NULL) { @@ -1160,12 +1162,15 @@ static char *vfs_gluster_realpath(struct vfs_handle_struct *handle, return NULL; } - result = glfs_realpath(handle->data, path, resolved_path); - if (result == NULL) { - SAFE_FREE(resolved_path); + result = glfs_realpath(handle->data, + smb_fname->base_name, + resolved_path); + if (result != NULL) { + result_fname = synthetic_smb_fname(ctx, result, NULL, NULL, 0); } - return result; + SAFE_FREE(resolved_path); + return result_fname; } static bool vfs_gluster_lock(struct vfs_handle_struct *handle, diff --git a/source3/modules/vfs_media_harmony.c b/source3/modules/vfs_media_harmony.c index bd774b83909..e39a4447bc9 100644 --- a/source3/modules/vfs_media_harmony.c +++ b/source3/modules/vfs_media_harmony.c @@ -1863,36 +1863,28 @@ out: * Success: return path pointer * Failure: set errno, return NULL pointer */ -static char *mh_realpath(vfs_handle_struct *handle, - const char *path) +static struct smb_filename *mh_realpath(vfs_handle_struct *handle, + TALLOC_CTX *ctx, + const struct smb_filename *smb_fname) { - char *buf; - char *clientPath; - TALLOC_CTX *ctx; + struct smb_filename *result_fname = NULL; + struct smb_filename *clientFname = NULL; DEBUG(MH_INFO_DEBUG, ("Entering mh_realpath\n")); - if (!is_in_media_files(path)) - { - buf = SMB_VFS_NEXT_REALPATH(handle, path); - goto out; + if (!is_in_media_files(smb_fname->base_name)) { + return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname); } - clientPath = NULL; - ctx = talloc_tos(); - - if (alloc_get_client_path(handle, ctx, - path, - &clientPath)) - { - buf = NULL; + if (alloc_get_client_smb_fname(handle, ctx, + smb_fname, + &clientFname) != 0) { goto err; } - buf = SMB_VFS_NEXT_REALPATH(handle, clientPath); + result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, clientFname); err: - TALLOC_FREE(clientPath); -out: - return buf; + TALLOC_FREE(clientFname); + return result_fname; } /* diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index b20213a698c..2977d7bdc3f 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -78,8 +78,8 @@ struct shadow_copy2_private { char *shadow_cwd; /* Absolute $cwd path. */ /* Absolute connectpath - can vary depending on $cwd. */ char *shadow_connectpath; - /* malloc'ed realpath return. */ - char *shadow_realpath; + /* talloc'ed realpath return. */ + struct smb_filename *shadow_realpath; }; static int shadow_copy2_get_shadow_copy_data( @@ -1742,40 +1742,47 @@ static int shadow_copy2_mknod(vfs_handle_struct *handle, return ret; } -static char *shadow_copy2_realpath(vfs_handle_struct *handle, - const char *fname) +static struct smb_filename *shadow_copy2_realpath(vfs_handle_struct *handle, + TALLOC_CTX *ctx, + const struct smb_filename *smb_fname) { time_t timestamp = 0; char *stripped = NULL; - char *tmp = NULL; - char *result = NULL; + struct smb_filename *result_fname = NULL; + struct smb_filename *conv_fname = NULL; int saved_errno = 0; - if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, - ×tamp, &stripped)) { + if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, + smb_fname->base_name, + ×tamp, &stripped)) { goto done; } if (timestamp == 0) { - return SMB_VFS_NEXT_REALPATH(handle, fname); + return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname); } - tmp = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); - if (tmp == NULL) { + conv_fname = cp_smb_filename(talloc_tos(), smb_fname); + if (conv_fname == NULL) { + goto done; + } + conv_fname->base_name = shadow_copy2_convert( + conv_fname, handle, stripped, timestamp); + if (conv_fname->base_name == NULL) { goto done; } - result = SMB_VFS_NEXT_REALPATH(handle, tmp); + result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, conv_fname); done: - if (result == NULL) { + if (result_fname == NULL) { saved_errno = errno; } - TALLOC_FREE(tmp); + TALLOC_FREE(conv_fname); TALLOC_FREE(stripped); if (saved_errno != 0) { errno = saved_errno; } - return result; + return result_fname; } /** @@ -2698,6 +2705,8 @@ static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle, time_t timestamp = 0; char *stripped = NULL; char *tmp = NULL; + struct smb_filename smb_fname = {0}; + struct smb_filename *result_fname = NULL; char *result = NULL; char *parent_dir = NULL; int saved_errno = 0; @@ -2760,17 +2769,20 @@ static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle, (int)rootpath_len, tmp); tmp[rootpath_len] = '\0'; - result = SMB_VFS_NEXT_REALPATH(handle, tmp); - if (result == NULL) { + smb_fname = (struct smb_filename) { .base_name = tmp }; + + result_fname = SMB_VFS_NEXT_REALPATH(handle, priv, &smb_fname); + if (result_fname == NULL) { goto done; } /* - * SMB_VFS_NEXT_REALPATH returns a malloc'ed string. + * SMB_VFS_NEXT_REALPATH returns a talloc'ed string. * Don't leak memory. */ - SAFE_FREE(priv->shadow_realpath); - priv->shadow_realpath = result; + TALLOC_FREE(priv->shadow_realpath); + priv->shadow_realpath = result_fname; + result = priv->shadow_realpath->base_name; DBG_DEBUG("connect path is [%s]\n", result); @@ -2890,12 +2902,6 @@ static int shadow_copy2_get_quota(vfs_handle_struct *handle, return ret; } -static int shadow_copy2_private_destructor(struct shadow_copy2_private *priv) -{ - SAFE_FREE(priv->shadow_realpath); - return 0; -} - static int shadow_copy2_connect(struct vfs_handle_struct *handle, const char *service, const char *user) { @@ -2927,8 +2933,6 @@ static int shadow_copy2_connect(struct vfs_handle_struct *handle, return -1; } - talloc_set_destructor(priv, shadow_copy2_private_destructor); - priv->snaps = talloc_zero(priv, struct shadow_copy2_snaplist_info); if (priv->snaps == NULL) { DBG_ERR("talloc_zero() failed\n"); diff --git a/source3/modules/vfs_snapper.c b/source3/modules/vfs_snapper.c index 05d57671db7..9dbb74f8fe9 100644 --- a/source3/modules/vfs_snapper.c +++ b/source3/modules/vfs_snapper.c @@ -2507,39 +2507,47 @@ static int snapper_gmt_mknod(vfs_handle_struct *handle, return ret; } -static char *snapper_gmt_realpath(vfs_handle_struct *handle, - const char *fname) +static struct smb_filename *snapper_gmt_realpath(vfs_handle_struct *handle, + TALLOC_CTX *ctx, + const struct smb_filename *smb_fname) { - time_t timestamp; + time_t timestamp = 0; char *stripped = NULL; - char *tmp = NULL; - char *result = NULL; - int saved_errno; + struct smb_filename *result_fname = NULL; + struct smb_filename *conv_smb_fname = NULL; + int saved_errno = 0; - if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, fname, + if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, + smb_fname->base_name, ×tamp, &stripped)) { goto done; } if (timestamp == 0) { - return SMB_VFS_NEXT_REALPATH(handle, fname); + return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname); } - tmp = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp); - if (tmp == NULL) { + conv_smb_fname = cp_smb_filename(talloc_tos(), smb_fname); + if (conv_smb_fname == NULL) { goto done; } - - result = SMB_VFS_NEXT_REALPATH(handle, tmp); - if (result == NULL) { + conv_smb_fname->base_name = snapper_gmt_convert(conv_smb_fname, handle, + stripped, timestamp); + if (conv_smb_fname->base_name == NULL) { goto done; } + result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, conv_smb_fname); + done: - saved_errno = errno; - TALLOC_FREE(tmp); + if (result_fname == NULL) { + saved_errno = errno; + } + TALLOC_FREE(conv_smb_fname); TALLOC_FREE(stripped); - errno = saved_errno; - return result; + if (saved_errno != 0) { + errno = saved_errno; + } + return result_fname; } static NTSTATUS snapper_gmt_fget_nt_acl(vfs_handle_struct *handle, diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c index 22075e7ac16..905ad22fa6c 100644 --- a/source3/modules/vfs_time_audit.c +++ b/source3/modules/vfs_time_audit.c @@ -1513,23 +1513,25 @@ static int smb_time_audit_mknod(vfs_handle_struct *handle, return result; } -static char *smb_time_audit_realpath(vfs_handle_struct *handle, - const char *path) +static struct smb_filename *smb_time_audit_realpath(vfs_handle_struct *handle, + TALLOC_CTX *ctx, + const struct smb_filename *smb_fname) { - char *result; + struct smb_filename *result_fname; struct timespec ts1,ts2; double timediff; clock_gettime_mono(&ts1); - result = SMB_VFS_NEXT_REALPATH(handle, path); + result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname); clock_gettime_mono(&ts2); timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9; if (timediff > audit_timeout) { - smb_time_audit_log_fname("realpath", timediff, path); + smb_time_audit_log_fname("realpath", timediff, + smb_fname->base_name); } - return result; + return result_fname; } static int smb_time_audit_chflags(vfs_handle_struct *handle, diff --git a/source3/modules/vfs_unityed_media.c b/source3/modules/vfs_unityed_media.c index 435deeb0579..34881bc50b7 100644 --- a/source3/modules/vfs_unityed_media.c +++ b/source3/modules/vfs_unityed_media.c @@ -1444,30 +1444,31 @@ err: return status; } -static char *um_realpath(vfs_handle_struct *handle, - const char *path) +static struct smb_filename *um_realpath(vfs_handle_struct *handle, + TALLOC_CTX *ctx, + const struct smb_filename *smb_fname) { - char *buf = NULL; - char *client_path = NULL; + struct smb_filename *client_fname = NULL; + struct smb_filename *result_fname = NULL; int status; DEBUG(10, ("Entering um_realpath\n")); - if (!is_in_media_files(path)) { - return SMB_VFS_NEXT_REALPATH(handle, path); + if (!is_in_media_files(smb_fname->base_name)) { + return SMB_VFS_NEXT_REALPATH(handle, ctx, smb_fname); } - status = alloc_get_client_path(handle, talloc_tos(), - path, &client_path); + status = alloc_get_client_smb_fname(handle, talloc_tos(), + smb_fname, &client_fname); if (status != 0) { goto err; } - buf = SMB_VFS_NEXT_REALPATH(handle, client_path); + result_fname = SMB_VFS_NEXT_REALPATH(handle, ctx, client_fname); err: - TALLOC_FREE(client_path); - return buf; + TALLOC_FREE(client_fname); + return result_fname; } static int um_chflags(vfs_handle_struct *handle, diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ac637ba7834..d7f471ed671 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -410,9 +410,11 @@ static int process_symlink_open(struct connection_struct *conn, { int fd = -1; char *link_target = NULL; + struct smb_filename target_fname = {0}; int link_len = -1; struct smb_filename *oldwd_fname = NULL; size_t rootdir_len = 0; + struct smb_filename *resolved_fname = NULL; char *resolved_name = NULL; bool matched = false; int saved_errno = 0; @@ -444,12 +446,14 @@ static int process_symlink_open(struct connection_struct *conn, /* Ensure it's at least null terminated. */ link_target[link_len] = '\0'; + target_fname = (struct smb_filename){ .base_name = link_target }; /* Convert to an absolute path. */ - resolved_name = SMB_VFS_REALPATH(conn, link_target); - if (resolved_name == NULL) { + resolved_fname = SMB_VFS_REALPATH(conn, talloc_tos(), &target_fname); + if (resolved_fname == NULL) { goto out; } + resolved_name = resolved_fname->base_name; /* * We know conn_rootdir starts with '/' and @@ -471,18 +475,22 @@ static int process_symlink_open(struct connection_struct *conn, */ if (resolved_name[rootdir_len] == '\0') { /* Link to the root of the share. */ - smb_fname->base_name = talloc_strdup(talloc_tos(), "."); - if (smb_fname->base_name == NULL) { - errno = ENOMEM; - goto out; - } + TALLOC_FREE(smb_fname->base_name); + smb_fname->base_name = talloc_strdup(smb_fname, "."); } else if (resolved_name[rootdir_len] == '/') { - smb_fname->base_name = &resolved_name[rootdir_len+1]; + TALLOC_FREE(smb_fname->base_name); + smb_fname->base_name = talloc_strdup(smb_fname, + &resolved_name[rootdir_len+1]); } else { errno = EACCES; goto out; } + if (smb_fname->base_name == NULL) { + errno = ENOMEM; + goto out; + } + oldwd_fname = vfs_GetWd(talloc_tos(), conn); if (oldwd_fname == NULL) { goto out; @@ -507,7 +515,7 @@ static int process_symlink_open(struct connection_struct *conn, out: - SAFE_FREE(resolved_name); + TALLOC_FREE(resolved_fname); TALLOC_FREE(link_target); if (oldwd_fname != NULL) { int ret = vfs_ChDir(conn, oldwd_fname); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index ed739c9baf1..75a47dee0ca 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -36,12 +36,14 @@ static bool canonicalize_connect_path(connection_struct *conn) { bool ret; - char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath); - if (!resolved_name) { + struct smb_filename con_fname = { .base_name = conn->connectpath }; + struct smb_filename *resolved_fname = SMB_VFS_REALPATH(conn, talloc_tos(), + &con_fname); + if (resolved_fname == NULL) { return false; } - ret = set_conn_connectpath(conn,resolved_name); - SAFE_FREE(resolved_name); + ret = set_conn_connectpath(conn,resolved_fname->base_name); + TALLOC_FREE(resolved_fname); return ret; } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 5c4e9c37b30..7607bcb0537 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -1024,8 +1024,9 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn, const char *conn_rootdir; size_t rootdir_len; char *dir_name = NULL; - const char *last_component = NULL; char *resolved_name = NULL; + const char *last_component = NULL; + struct smb_filename *resolved_fname = NULL; struct smb_filename *saved_dir_fname = NULL; struct smb_filename *smb_fname_cwd = NULL; struct privilege_paths *priv_paths = NULL; @@ -1072,12 +1073,19 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn, goto err; } + smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0); + if (smb_fname_cwd == NULL) { + status = NT_STATUS_NO_MEMORY; + goto err; + } + /* Get the absolute path of the parent directory. */ - resolved_name = SMB_VFS_REALPATH(conn,"."); - if (!resolved_name) { + resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname_cwd); + if (resolved_fname == NULL) { status = map_nt_error_from_unix(errno); goto err; } + resolved_name = resolved_fname->base_name; if (*resolved_name != '/') { DEBUG(0,("check_reduced_name_with_privilege: realpath " @@ -1091,12 +1099,6 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn, resolved_name)); /* Now check the stat value is the same. */ - smb_fname_cwd = synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, 0); - if (smb_fname_cwd == NULL) { - status = NT_STATUS_NO_MEMORY; - goto err; - } - if (SMB_VFS_LSTAT(conn, smb_fname_cwd) != 0) { status = map_nt_error_from_unix(errno); goto err; @@ -1186,7 +1188,7 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn, vfs_ChDir(conn, saved_dir_fname); TALLOC_FREE(saved_dir_fname); } - SAFE_FREE(resolved_name); + TALLOC_FREE(resolved_fname); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(priv_paths); } @@ -1209,6 +1211,9 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *cwd_name, const char *fname) { + TALLOC_CTX *ctx = talloc_tos(); + struct smb_filename smb_fname = { .base_name = discard_const(fname) }; + struct smb_filename *resolved_fname; char *resolved_name = NULL; char *new_fname = NULL; bool allow_symlinks = true; @@ -1216,9 +1221,9 @@ NTSTATUS check_reduced_name(connection_struct *conn, DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath); - resolved_name = SMB_VFS_REALPATH(conn,fname); + resolved_fname = SMB_VFS_REALPATH(conn, ctx, &smb_fname); - if (!resolved_name) { + if (resolved_fname == NULL) { switch (errno) { case ENOTDIR: DEBUG(3,("check_reduced_name: Component not a " @@ -1227,11 +1232,9 @@ NTSTATUS check_reduced_name(connection_struct *conn, return NT_STATUS_OBJECT_PATH_NOT_FOUND; case ENOENT: { - TALLOC_CTX *ctx = talloc_tos(); char *dir_name = NULL; + struct smb_filename dir_fname = {0}; const char *last_component = NULL; - char *new_name = NULL; - int ret; /* Last component didn't exist. Remove it and try and canonicalise @@ -1242,8 +1245,12 @@ NTSTATUS check_reduced_name(connection_struct *conn, return NT_STATUS_NO_MEMORY; } - resolved_name = SMB_VFS_REALPATH(conn,dir_name); - if (!resolved_name) { + dir_fname = (struct smb_filename) + { .base_name = dir_name }; + resolved_fname = SMB_VFS_REALPATH(conn, + ctx, + &dir_fname); + if (resolved_fname == NULL) { NTSTATUS status = map_nt_error_from_unix(errno); if (errno == ENOENT || errno == ENOTDIR) { @@ -1257,13 +1264,13 @@ NTSTATUS check_reduced_name(connection_struct *conn, nt_errstr(status))); return status; } - ret = asprintf(&new_name, "%s/%s", - resolved_name, last_component); - SAFE_FREE(resolved_name); - if (ret == -1) { + resolved_name = talloc_asprintf(ctx, + "%s/%s", + resolved_fname->base_name, + last_component); + if (resolved_name == NULL) { return NT_STATUS_NO_MEMORY; } - resolved_name = new_name; break; } default: @@ -1271,6 +1278,8 @@ NTSTATUS check_reduced_name(connection_struct *conn, "realpath for %s\n", fname)); return map_nt_error_from_unix(errno); } + } else { + resolved_name = resolved_fname->base_name; } DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname, @@ -1279,7 +1288,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, if (*resolved_name != '/') { DEBUG(0,("check_reduced_name: realpath doesn't return " "absolute paths !\n")); - SAFE_FREE(resolved_name); + TALLOC_FREE(resolved_fname); return NT_STATUS_OBJECT_NAME_INVALID; } @@ -1295,7 +1304,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, if (conn_rootdir == NULL) { DEBUG(2, ("check_reduced_name: Could not get " "conn_rootdir\n")); - SAFE_FREE(resolved_name); + TALLOC_FREE(resolved_fname); return NT_STATUS_ACCESS_DENIED; } @@ -1324,7 +1333,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, conn_rootdir)); DEBUGADD(2, ("resolved_name=%s\n", resolved_name)); - SAFE_FREE(resolved_name); + TALLOC_FREE(resolved_fname); return NT_STATUS_ACCESS_DENIED; } } @@ -1347,7 +1356,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, "in resolved_name: %s\n", *p, fname)); - SAFE_FREE(resolved_name); + TALLOC_FREE(resolved_fname); return NT_STATUS_ACCESS_DENIED; } @@ -1361,12 +1370,12 @@ NTSTATUS check_reduced_name(connection_struct *conn, * sent (cwd_name+fname). */ if (cwd_name != NULL && !ISDOT(cwd_name)) { - new_fname = talloc_asprintf(talloc_tos(), + new_fname = talloc_asprintf(ctx, "%s/%s", cwd_name, fname); if (new_fname == NULL) { - SAFE_FREE(resolved_name); + TALLOC_FREE(resolved_fname); return NT_STATUS_NO_MEMORY; } fname = new_fname; @@ -1376,7 +1385,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, DEBUG(2, ("check_reduced_name: Bad access " "attempt: %s is a symlink to %s\n", fname, p)); - SAFE_FREE(resolved_name); + TALLOC_FREE(resolved_fname); TALLOC_FREE(new_fname); return NT_STATUS_ACCESS_DENIED; } @@ -1386,7 +1395,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, out: DBG_INFO("%s reduced to %s\n", fname, resolved_name); - SAFE_FREE(resolved_name); + TALLOC_FREE(resolved_fname); TALLOC_FREE(new_fname); return NT_STATUS_OK; } @@ -2212,10 +2221,12 @@ int smb_vfs_call_mknod(struct vfs_handle_struct *handle, return handle->fns->mknod_fn(handle, smb_fname, mode, dev); } -char *smb_vfs_call_realpath(struct vfs_handle_struct *handle, const char *path) +struct smb_filename *smb_vfs_call_realpath(struct vfs_handle_struct *handle, + TALLOC_CTX *ctx, + const struct smb_filename *smb_fname) { VFS_FIND(realpath); - return handle->fns->realpath_fn(handle, path); + return handle->fns->realpath_fn(handle, ctx, smb_fname); } int smb_vfs_call_chflags(struct vfs_handle_struct *handle, diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c index fd09df9bcd6..034136f3d23 100644 --- a/source3/torture/cmd_vfs.c +++ b/source3/torture/cmd_vfs.c @@ -1340,12 +1340,20 @@ static NTSTATUS cmd_mknod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, static NTSTATUS cmd_realpath(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { + struct smb_filename *smb_fname = NULL; + if (argc != 2) { printf("Usage: realpath \n"); return NT_STATUS_OK; } - if (SMB_VFS_REALPATH(vfs->conn, argv[1]) == NULL) { + smb_fname = synthetic_smb_fname_split(mem_ctx, + argv[1], + lp_posix_pathnames()); + if (smb_fname == NULL) { + return NT_STATUS_NO_MEMORY; + } + if (SMB_VFS_REALPATH(vfs->conn, mem_ctx, smb_fname) == NULL) { printf("realpath: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } -- 2.11.4.GIT