The Samba-Bugzilla – Attachment 12891 Details for
Bug 12531
vfs_shadow_copy2 doesn't cope with server changing directories.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
git-am fix for 4.4.next
bug-12531-4.4 (text/plain), 77.28 KB, created by
Jeremy Allison
on 2017-01-31 18:29:15 UTC
(
hide
)
Description:
git-am fix for 4.4.next
Filename:
MIME Type:
Creator:
Jeremy Allison
Created:
2017-01-31 18:29:15 UTC
Size:
77.28 KB
patch
obsolete
>From e3f5becc2cae4b12667ea2b6701dff9b011aa308 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Wed, 11 Jan 2017 16:30:38 -0800 >Subject: [PATCH 01/20] s3: smbd: Correctly canonicalize any incoming shadow > copy path. > >Converts to: > >@GMT-token/path/last_component > >from all incoming path types. Allows shadow_copy modules >to work when current directory is changed after removing >last component. > >Ultimately when the VFS ABI is changed to add a timestamp >to struct smb_filename, this is where the parsing will be >done. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit 39678ed6af708fb6f2760bfb51051add11e3c498) >--- > source3/smbd/filename.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 150 insertions(+) > >diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c >index ce40c0a502f..046ce9c8391 100644 >--- a/source3/smbd/filename.c >+++ b/source3/smbd/filename.c >@@ -220,6 +220,148 @@ static NTSTATUS check_parent_exists(TALLOC_CTX *ctx, > return NT_STATUS_OK; > } > >+/* >+ * Re-order a known good @GMT-token path. >+ */ >+ >+static NTSTATUS rearrange_snapshot_path(struct smb_filename *smb_fname, >+ char *startp, >+ char *endp) >+{ >+ size_t endlen = 0; >+ size_t gmt_len = endp - startp; >+ char gmt_store[gmt_len + 1]; >+ char *parent = NULL; >+ const char *last_component = NULL; >+ char *newstr; >+ bool ret; >+ >+ DBG_DEBUG("|%s| -> ", smb_fname->base_name); >+ >+ /* Save off the @GMT-token. */ >+ memcpy(gmt_store, startp, gmt_len); >+ gmt_store[gmt_len] = '\0'; >+ >+ if (*endp == '/') { >+ /* Remove any trailing '/' */ >+ endp++; >+ } >+ >+ if (*endp == '\0') { >+ /* >+ * @GMT-token was at end of path. >+ * Remove any preceeding '/' >+ */ >+ if (startp > smb_fname->base_name && startp[-1] == '/') { >+ startp--; >+ } >+ } >+ >+ /* Remove @GMT-token from the path. */ >+ endlen = strlen(endp); >+ memmove(startp, endp, endlen + 1); >+ >+ /* Split the remaining path into components. */ >+ ret = parent_dirname(smb_fname, >+ smb_fname->base_name, >+ &parent, >+ &last_component); >+ if (ret == false) { >+ /* Must terminate debug with \n */ >+ DBG_DEBUG("NT_STATUS_NO_MEMORY\n"); >+ return NT_STATUS_NO_MEMORY; >+ } >+ >+ if (ISDOT(parent)) { >+ if (last_component[0] == '\0') { >+ newstr = talloc_strdup(smb_fname, >+ gmt_store); >+ } else { >+ newstr = talloc_asprintf(smb_fname, >+ "%s/%s", >+ gmt_store, >+ last_component); >+ } >+ } else { >+ newstr = talloc_asprintf(smb_fname, >+ "%s/%s/%s", >+ gmt_store, >+ parent, >+ last_component); >+ } >+ >+ TALLOC_FREE(parent); >+ TALLOC_FREE(smb_fname->base_name); >+ smb_fname->base_name = newstr; >+ >+ DBG_DEBUG("|%s|\n", newstr); >+ >+ return NT_STATUS_OK; >+} >+ >+/* >+ * Canonicalize any incoming pathname potentially containining >+ * a @GMT-token into a path that looks like: >+ * >+ * @GMT-YYYY-MM-DD-HH-MM-SS/path/name/components/last_component >+ * >+ * Leaves single path @GMT-token -component alone: >+ * >+ * @GMT-YYYY-MM-DD-HH-MM-SS -> @GMT-YYYY-MM-DD-HH-MM-SS >+ * >+ * Eventually when struct smb_filename is updated and the VFS >+ * ABI is changed this will remove the @GMT-YYYY-MM-DD-HH-MM-SS >+ * and store in the struct smb_filename as a struct timeval field >+ * instead. >+ */ >+ >+static NTSTATUS canonicalize_snapshot_path(struct smb_filename *smb_fname) >+{ >+ char *startp = strchr_m(smb_fname->base_name, '@'); >+ char *endp = NULL; >+ struct tm tm; >+ >+ if (startp == NULL) { >+ /* No @ */ >+ return NT_STATUS_OK; >+ } >+ >+ startp = strstr_m(startp, "@GMT-"); >+ if (startp == NULL) { >+ /* No @ */ >+ return NT_STATUS_OK; >+ } >+ >+ if ((startp > smb_fname->base_name) && (startp[-1] != '/')) { >+ /* the GMT-token does not start a path-component */ >+ return NT_STATUS_OK; >+ } >+ >+ endp = strptime(startp, GMT_FORMAT, &tm); >+ if (endp == NULL) { >+ /* Not a valid timestring. */ >+ return NT_STATUS_OK; >+ } >+ >+ if ( endp[0] == '\0') { >+ return rearrange_snapshot_path(smb_fname, >+ startp, >+ endp); >+ } >+ >+ if (endp[0] != '/') { >+ /* >+ * It is not a complete path component, i.e. the path >+ * component continues after the gmt-token. >+ */ >+ return NT_STATUS_OK; >+ } >+ >+ return rearrange_snapshot_path(smb_fname, >+ startp, >+ endp); >+} >+ > /**************************************************************************** > This routine is called to convert names from the dos namespace to unix > namespace. It needs to handle any case conversions, mangling, format changes, >@@ -354,6 +496,14 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, > goto err; > } > >+ /* Canonicalize any @GMT- paths. */ >+ if (posix_pathnames == false) { >+ status = canonicalize_snapshot_path(smb_fname); >+ if (!NT_STATUS_IS_OK(status)) { >+ goto err; >+ } >+ } >+ > /* > * Large directory fix normalization. If we're case sensitive, and > * the case preserving parameters are set to "no", normalize the case of >-- >2.11.0.483.g087da7b7c-goog > > >From 6704a8fcfb35c9f7c0910cce08f478168a6b8d9b Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Tue, 17 Jan 2017 11:33:18 -0800 >Subject: [PATCH 02/20] s3: lib: Add canonicalize_absolute_path(). > >Resolves any invalid path components (.) (..) >in an absolute POSIX path. > >We will be re-using this in several places. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit 02599c39337c3049762a6b0bd6290577817ee5a5) >--- > source3/lib/util_path.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++ > source3/lib/util_path.h | 1 + > 2 files changed, 134 insertions(+) > >diff --git a/source3/lib/util_path.c b/source3/lib/util_path.c >index 509ba5ff727..cbad2e15d48 100644 >--- a/source3/lib/util_path.c >+++ b/source3/lib/util_path.c >@@ -93,3 +93,136 @@ char *cache_path(const char *name) > { > return xx_path(name, lp_cache_directory()); > } >+ >+/** >+ * @brief Removes any invalid path components in an absolute POSIX path. >+ * >+ * @param ctx Talloc context to return string. >+ * >+ * @param abs_path Absolute path string to process. >+ * >+ * @retval Pointer to a talloc'ed string containing the absolute full path. >+ **/ >+ >+char *canonicalize_absolute_path(TALLOC_CTX *ctx, const char *abs_path) >+{ >+ char *destname; >+ char *d; >+ const char *s = abs_path; >+ bool start_of_name_component = true; >+ >+ /* Allocate for strlen + '\0' + possible leading '/' */ >+ destname = (char *)talloc_size(ctx, strlen(abs_path) + 2); >+ if (destname == NULL) { >+ return NULL; >+ } >+ d = destname; >+ >+ *d++ = '/'; /* Always start with root. */ >+ >+ while (*s) { >+ if (*s == '/') { >+ /* Eat multiple '/' */ >+ while (*s == '/') { >+ s++; >+ } >+ if ((d > destname + 1) && (*s != '\0')) { >+ *d++ = '/'; >+ } >+ start_of_name_component = true; >+ continue; >+ } >+ >+ if (start_of_name_component) { >+ if ((s[0] == '.') && (s[1] == '.') && >+ (s[2] == '/' || s[2] == '\0')) { >+ /* Uh oh - "/../" or "/..\0" ! */ >+ >+ /* Go past the ../ or .. */ >+ if (s[2] == '/') { >+ s += 3; >+ } else { >+ s += 2; /* Go past the .. */ >+ } >+ >+ /* If we just added a '/' - delete it */ >+ if ((d > destname) && (*(d-1) == '/')) { >+ *(d-1) = '\0'; >+ d--; >+ } >+ >+ /* >+ * Are we at the start ? >+ * Can't go back further if so. >+ */ >+ if (d <= destname) { >+ *d++ = '/'; /* Can't delete root */ >+ continue; >+ } >+ /* Go back one level... */ >+ /* >+ * Decrement d first as d points to >+ * the *next* char to write into. >+ */ >+ for (d--; d > destname; d--) { >+ if (*d == '/') { >+ break; >+ } >+ } >+ /* >+ * We're still at the start of a name >+ * component, just the previous one. >+ */ >+ continue; >+ } else if ((s[0] == '.') && >+ ((s[1] == '\0') || s[1] == '/')) { >+ /* >+ * Component of pathname can't be "." only. >+ * Skip the '.' . >+ */ >+ if (s[1] == '/') { >+ s += 2; >+ } else { >+ s++; >+ } >+ continue; >+ } >+ } >+ >+ if (!(*s & 0x80)) { >+ *d++ = *s++; >+ } else { >+ size_t siz; >+ /* Get the size of the next MB character. */ >+ next_codepoint(s,&siz); >+ switch(siz) { >+ case 5: >+ *d++ = *s++; >+ /*fall through*/ >+ case 4: >+ *d++ = *s++; >+ /*fall through*/ >+ case 3: >+ *d++ = *s++; >+ /*fall through*/ >+ case 2: >+ *d++ = *s++; >+ /*fall through*/ >+ case 1: >+ *d++ = *s++; >+ break; >+ default: >+ break; >+ } >+ } >+ start_of_name_component = false; >+ } >+ *d = '\0'; >+ >+ /* And must not end in '/' */ >+ if (d > destname + 1 && (*(d-1) == '/')) { >+ *(d-1) = '\0'; >+ } >+ >+ return destname; >+} >diff --git a/source3/lib/util_path.h b/source3/lib/util_path.h >index 118a4bed524..16e27926084 100644 >--- a/source3/lib/util_path.h >+++ b/source3/lib/util_path.h >@@ -27,5 +27,6 @@ > char *lock_path(const char *name); > char *state_path(const char *name); > char *cache_path(const char *name); >+char *canonicalize_absolute_path(TALLOC_CTX *ctx, const char *abs_path); > > #endif >-- >2.11.0.483.g087da7b7c-goog > > >From ea19e0b889f506f5d9b42c5d3c28f7e88a4284a3 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 19 Jan 2017 15:18:41 -0800 >Subject: [PATCH 03/20] s3: lib: Fix two old, old bugs in > set_conn_connectpath(), now in canonicalize_absolute_path(). > >Canonicalizing a path of /foo/bar/../baz would return /foo/barbaz >as moving forward 3 characters would delete the / character. > >Canonicalizing /foo/.. would end up as '\0'. > >Test to follow. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit 82979afc46cc5e466bdd999a94080e7a5df95518) >--- > source3/lib/util_path.c | 18 ++++++++++++------ > 1 file changed, 12 insertions(+), 6 deletions(-) > >diff --git a/source3/lib/util_path.c b/source3/lib/util_path.c >index cbad2e15d48..6f58a03ae58 100644 >--- a/source3/lib/util_path.c >+++ b/source3/lib/util_path.c >@@ -138,12 +138,8 @@ char *canonicalize_absolute_path(TALLOC_CTX *ctx, const char *abs_path) > (s[2] == '/' || s[2] == '\0')) { > /* Uh oh - "/../" or "/..\0" ! */ > >- /* Go past the ../ or .. */ >- if (s[2] == '/') { >- s += 3; >- } else { >- s += 2; /* Go past the .. */ >- } >+ /* Go past the .. leaving us on the / or '\0' */ >+ s += 2; > > /* If we just added a '/' - delete it */ > if ((d > destname) && (*(d-1) == '/')) { >@@ -169,6 +165,16 @@ char *canonicalize_absolute_path(TALLOC_CTX *ctx, const char *abs_path) > break; > } > } >+ >+ /* >+ * Are we at the start ? >+ * Can't go back further if so. >+ */ >+ if (d <= destname) { >+ *d++ = '/'; /* Can't delete root */ >+ continue; >+ } >+ > /* > * We're still at the start of a name > * component, just the previous one. >-- >2.11.0.483.g087da7b7c-goog > > >From b1a120ce1569c4fbff7f6f9f524f700af63e0360 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 26 Jan 2017 16:08:42 -0800 >Subject: [PATCH 04/20] s3: smbtorture: Add new local test > LOCAL-CANONICALIZE-PATH > >Tests new canonicalize_absolute_path() function. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit a51363309a4330b65e34ae941ec99d180bdbab56) >--- > source3/selftest/tests.py | 1 + > source3/torture/torture.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 45 insertions(+) > >diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py >index e389fae9ae4..b3df98c86d6 100755 >--- a/source3/selftest/tests.py >+++ b/source3/selftest/tests.py >@@ -113,6 +113,7 @@ local_tests = [ > "LOCAL-MESSAGING-FDPASS2", > "LOCAL-MESSAGING-FDPASS2a", > "LOCAL-MESSAGING-FDPASS2b", >+ "LOCAL-CANONICALIZE-PATH", > "LOCAL-hex_encode_buf", > "LOCAL-sprintf_append", > "LOCAL-remove_duplicate_addrs2"] >diff --git a/source3/torture/torture.c b/source3/torture/torture.c >index cfe33a81b61..0341c85547b 100644 >--- a/source3/torture/torture.c >+++ b/source3/torture/torture.c >@@ -9878,6 +9878,49 @@ static bool run_local_tdb_writer(int dummy) > return true; > } > >+static bool run_local_canonicalize_path(int dummy) >+{ >+ const char *src[] = { >+ "/foo/..", >+ "/..", >+ "/foo/bar/../baz", >+ "/foo/././", >+ "/../foo", >+ ".././././", >+ ".././././../../../boo", >+ "./..", >+ NULL >+ }; >+ const char *dst[] = { >+ "/", >+ "/", >+ "/foo/baz", >+ "/foo", >+ "/foo", >+ "/", >+ "/boo", >+ "/", >+ NULL >+ }; >+ unsigned int i; >+ >+ for (i = 0; src[i] != NULL; i++) { >+ char *d = canonicalize_absolute_path(talloc_tos(), src[i]); >+ if (d == NULL) { >+ perror("talloc fail\n"); >+ return false; >+ } >+ if (strcmp(d, dst[i]) != 0) { >+ d_fprintf(stderr, >+ "canonicalize missmatch %s -> %s != %s", >+ src[i], d, dst[i]); >+ return false; >+ } >+ talloc_free(d); >+ } >+ return true; >+} >+ > static double create_procs(bool (*fn)(int), bool *result) > { > int i, status; >@@ -10108,6 +10151,7 @@ static struct { > { "local-tdb-writer", run_local_tdb_writer, 0 }, > { "LOCAL-DBWRAP-CTDB", run_local_dbwrap_ctdb, 0 }, > { "LOCAL-BENCH-PTHREADPOOL", run_bench_pthreadpool, 0 }, >+ { "LOCAL-CANONICALIZE-PATH", run_local_canonicalize_path, 0 }, > { "qpathinfo-bufsize", run_qpathinfo_bufsize, 0 }, > {NULL, NULL, 0}}; > >-- >2.11.0.483.g087da7b7c-goog > > >From c581e75c692d4c8093a9e9480993de4194688f78 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Tue, 17 Jan 2017 11:35:52 -0800 >Subject: [PATCH 05/20] s3: smbd: Make set_conn_connectpath() call > canonicalize_absolute_path(). > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit d650d65488761b30fa34d42cb1ab400618a78c33) >--- > source3/smbd/service.c | 103 ++----------------------------------------------- > 1 file changed, 3 insertions(+), 100 deletions(-) > >diff --git a/source3/smbd/service.c b/source3/smbd/service.c >index 0c70250e309..ebcdda5ec12 100644 >--- a/source3/smbd/service.c >+++ b/source3/smbd/service.c >@@ -31,6 +31,7 @@ > #include "lib/param/loadparm.h" > #include "messages.h" > #include "lib/afs/afs_funcs.h" >+#include "lib/util_path.h" > > static bool canonicalize_connect_path(connection_struct *conn) > { >@@ -47,118 +48,20 @@ static bool canonicalize_connect_path(connection_struct *conn) > /**************************************************************************** > Ensure when setting connectpath it is a canonicalized (no ./ // or ../) > absolute path stating in / and not ending in /. >- Observent people will notice a similarity between this and check_path_syntax :-). > ****************************************************************************/ > > bool set_conn_connectpath(connection_struct *conn, const char *connectpath) > { > char *destname; >- char *d; >- const char *s = connectpath; >- bool start_of_name_component = true; > > if (connectpath == NULL || connectpath[0] == '\0') { > return false; > } > >- /* Allocate for strlen + '\0' + possible leading '/' */ >- destname = (char *)talloc_size(conn, strlen(connectpath) + 2); >- if (!destname) { >+ destname = canonicalize_absolute_path(conn, connectpath); >+ if (destname == NULL) { > return false; > } >- d = destname; >- >- *d++ = '/'; /* Always start with root. */ >- >- while (*s) { >- if (*s == '/') { >- /* Eat multiple '/' */ >- while (*s == '/') { >- s++; >- } >- if ((d > destname + 1) && (*s != '\0')) { >- *d++ = '/'; >- } >- start_of_name_component = True; >- continue; >- } >- >- if (start_of_name_component) { >- if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) { >- /* Uh oh - "/../" or "/..\0" ! */ >- >- /* Go past the ../ or .. */ >- if (s[2] == '/') { >- s += 3; >- } else { >- s += 2; /* Go past the .. */ >- } >- >- /* If we just added a '/' - delete it */ >- if ((d > destname) && (*(d-1) == '/')) { >- *(d-1) = '\0'; >- d--; >- } >- >- /* Are we at the start ? Can't go back further if so. */ >- if (d <= destname) { >- *d++ = '/'; /* Can't delete root */ >- continue; >- } >- /* Go back one level... */ >- /* Decrement d first as d points to the *next* char to write into. */ >- for (d--; d > destname; d--) { >- if (*d == '/') { >- break; >- } >- } >- /* We're still at the start of a name component, just the previous one. */ >- continue; >- } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) { >- /* Component of pathname can't be "." only - skip the '.' . */ >- if (s[1] == '/') { >- s += 2; >- } else { >- s++; >- } >- continue; >- } >- } >- >- if (!(*s & 0x80)) { >- *d++ = *s++; >- } else { >- size_t siz; >- /* Get the size of the next MB character. */ >- next_codepoint(s,&siz); >- switch(siz) { >- case 5: >- *d++ = *s++; >- /*fall through*/ >- case 4: >- *d++ = *s++; >- /*fall through*/ >- case 3: >- *d++ = *s++; >- /*fall through*/ >- case 2: >- *d++ = *s++; >- /*fall through*/ >- case 1: >- *d++ = *s++; >- break; >- default: >- break; >- } >- } >- start_of_name_component = false; >- } >- *d = '\0'; >- >- /* And must not end in '/' */ >- if (d > destname + 1 && (*(d-1) == '/')) { >- *(d-1) = '\0'; >- } > > DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n", > lp_servicename(talloc_tos(), SNUM(conn)), destname )); >-- >2.11.0.483.g087da7b7c-goog > > >From a4388dc88591f256a2000a06802618a8f7c3ee74 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 20 Jan 2017 11:42:39 -0800 >Subject: [PATCH 06/20] s3: VFS: shadow_copy2: Correctly initialize timestamp > and stripped variables. > >Allow the called functions to be fixed to not touch them on error. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit 0a190f4dd950c947d47c42163d11ea4bd6e6e508) >--- > source3/modules/vfs_shadow_copy2.c | 116 +++++++++++++++++++------------------ > 1 file changed, 61 insertions(+), 55 deletions(-) > >diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c >index 5750b65ccae..80f544d90b7 100644 >--- a/source3/modules/vfs_shadow_copy2.c >+++ b/source3/modules/vfs_shadow_copy2.c >@@ -228,10 +228,10 @@ static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx, > char **pstripped) > { > struct tm tm; >- time_t timestamp; >+ time_t timestamp = 0; > const char *p; > char *q; >- char *stripped; >+ char *stripped = NULL; > size_t rest_len, dst_len; > struct shadow_copy2_config *config; > const char *snapdir; >@@ -694,8 +694,8 @@ static DIR *shadow_copy2_opendir(vfs_handle_struct *handle, > const char *mask, > uint32_t attr) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > DIR *ret; > int saved_errno; > char *conv; >@@ -723,7 +723,8 @@ static int shadow_copy2_rename(vfs_handle_struct *handle, > const struct smb_filename *smb_fname_src, > const struct smb_filename *smb_fname_dst) > { >- time_t timestamp_src, timestamp_dst; >+ time_t timestamp_src = 0; >+ time_t timestamp_dst = 0; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, > smb_fname_src->base_name, >@@ -749,7 +750,8 @@ static int shadow_copy2_rename(vfs_handle_struct *handle, > static int shadow_copy2_symlink(vfs_handle_struct *handle, > const char *oldname, const char *newname) > { >- time_t timestamp_old, timestamp_new; >+ time_t timestamp_old = 0; >+ time_t timestamp_new = 0; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, oldname, > ×tamp_old, NULL)) { >@@ -769,7 +771,8 @@ static int shadow_copy2_symlink(vfs_handle_struct *handle, > static int shadow_copy2_link(vfs_handle_struct *handle, > const char *oldname, const char *newname) > { >- time_t timestamp_old, timestamp_new; >+ time_t timestamp_old = 0; >+ time_t timestamp_new = 0; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, oldname, > ×tamp_old, NULL)) { >@@ -789,8 +792,9 @@ static int shadow_copy2_link(vfs_handle_struct *handle, > static int shadow_copy2_stat(vfs_handle_struct *handle, > struct smb_filename *smb_fname) > { >- time_t timestamp; >- char *stripped, *tmp; >+ time_t timestamp = 0; >+ char *stripped = NULL; >+ char *tmp; > int ret, saved_errno; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, >@@ -828,8 +832,9 @@ static int shadow_copy2_stat(vfs_handle_struct *handle, > static int shadow_copy2_lstat(vfs_handle_struct *handle, > struct smb_filename *smb_fname) > { >- time_t timestamp; >- char *stripped, *tmp; >+ time_t timestamp = 0; >+ char *stripped = NULL; >+ char *tmp; > int ret, saved_errno; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, >@@ -867,7 +872,7 @@ static int shadow_copy2_lstat(vfs_handle_struct *handle, > static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp, > SMB_STRUCT_STAT *sbuf) > { >- time_t timestamp; >+ time_t timestamp = 0; > int ret; > > ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf); >@@ -889,8 +894,9 @@ static int shadow_copy2_open(vfs_handle_struct *handle, > struct smb_filename *smb_fname, files_struct *fsp, > int flags, mode_t mode) > { >- time_t timestamp; >- char *stripped, *tmp; >+ time_t timestamp = 0; >+ char *stripped = NULL; >+ char *tmp; > int ret, saved_errno; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, >@@ -925,8 +931,8 @@ static int shadow_copy2_open(vfs_handle_struct *handle, > static int shadow_copy2_unlink(vfs_handle_struct *handle, > const struct smb_filename *smb_fname) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > int ret, saved_errno; > struct smb_filename *conv; > >@@ -959,8 +965,8 @@ static int shadow_copy2_unlink(vfs_handle_struct *handle, > static int shadow_copy2_chmod(vfs_handle_struct *handle, const char *fname, > mode_t mode) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > int ret, saved_errno; > char *conv; > >@@ -986,8 +992,8 @@ static int shadow_copy2_chmod(vfs_handle_struct *handle, const char *fname, > static int shadow_copy2_chown(vfs_handle_struct *handle, const char *fname, > uid_t uid, gid_t gid) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > int ret, saved_errno; > char *conv; > >@@ -1013,8 +1019,8 @@ static int shadow_copy2_chown(vfs_handle_struct *handle, const char *fname, > static int shadow_copy2_chdir(vfs_handle_struct *handle, > const char *fname) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > int ret, saved_errno; > char *conv; > >@@ -1041,8 +1047,8 @@ static int shadow_copy2_ntimes(vfs_handle_struct *handle, > const struct smb_filename *smb_fname, > struct smb_file_time *ft) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > int ret, saved_errno; > struct smb_filename *conv; > >@@ -1075,7 +1081,7 @@ static int shadow_copy2_ntimes(vfs_handle_struct *handle, > static int shadow_copy2_readlink(vfs_handle_struct *handle, > const char *fname, char *buf, size_t bufsiz) > { >- time_t timestamp; >+ time_t timestamp = 0; > char *stripped; > int ret, saved_errno; > char *conv; >@@ -1102,8 +1108,8 @@ static int shadow_copy2_readlink(vfs_handle_struct *handle, > static int shadow_copy2_mknod(vfs_handle_struct *handle, > const char *fname, mode_t mode, SMB_DEV_T dev) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > int ret, saved_errno; > char *conv; > >@@ -1129,7 +1135,7 @@ static int shadow_copy2_mknod(vfs_handle_struct *handle, > static char *shadow_copy2_realpath(vfs_handle_struct *handle, > const char *fname) > { >- time_t timestamp; >+ time_t timestamp = 0; > char *stripped = NULL; > char *tmp = NULL; > char *result = NULL; >@@ -1462,8 +1468,8 @@ static NTSTATUS shadow_copy2_fget_nt_acl(vfs_handle_struct *handle, > TALLOC_CTX *mem_ctx, > struct security_descriptor **ppdesc) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > NTSTATUS status; > char *conv; > >@@ -1494,8 +1500,8 @@ static NTSTATUS shadow_copy2_get_nt_acl(vfs_handle_struct *handle, > TALLOC_CTX *mem_ctx, > struct security_descriptor **ppdesc) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > NTSTATUS status; > char *conv; > >@@ -1521,8 +1527,8 @@ static NTSTATUS shadow_copy2_get_nt_acl(vfs_handle_struct *handle, > static int shadow_copy2_mkdir(vfs_handle_struct *handle, > const char *fname, mode_t mode) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > int ret, saved_errno; > char *conv; > >@@ -1547,8 +1553,8 @@ static int shadow_copy2_mkdir(vfs_handle_struct *handle, > > static int shadow_copy2_rmdir(vfs_handle_struct *handle, const char *fname) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > int ret, saved_errno; > char *conv; > >@@ -1574,8 +1580,8 @@ static int shadow_copy2_rmdir(vfs_handle_struct *handle, const char *fname) > static int shadow_copy2_chflags(vfs_handle_struct *handle, const char *fname, > unsigned int flags) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > int ret, saved_errno; > char *conv; > >@@ -1602,8 +1608,8 @@ static ssize_t shadow_copy2_getxattr(vfs_handle_struct *handle, > const char *fname, const char *aname, > void *value, size_t size) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > ssize_t ret; > int saved_errno; > char *conv; >@@ -1632,8 +1638,8 @@ static ssize_t shadow_copy2_listxattr(struct vfs_handle_struct *handle, > const char *fname, > char *list, size_t size) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > ssize_t ret; > int saved_errno; > char *conv; >@@ -1660,8 +1666,8 @@ static ssize_t shadow_copy2_listxattr(struct vfs_handle_struct *handle, > static int shadow_copy2_removexattr(vfs_handle_struct *handle, > const char *fname, const char *aname) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > int ret, saved_errno; > char *conv; > >@@ -1689,8 +1695,8 @@ static int shadow_copy2_setxattr(struct vfs_handle_struct *handle, > const char *aname, const void *value, > size_t size, int flags) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > ssize_t ret; > int saved_errno; > char *conv; >@@ -1718,8 +1724,8 @@ static int shadow_copy2_setxattr(struct vfs_handle_struct *handle, > static int shadow_copy2_chmod_acl(vfs_handle_struct *handle, > const char *fname, mode_t mode) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > ssize_t ret; > int saved_errno; > char *conv; >@@ -1749,8 +1755,8 @@ static int shadow_copy2_get_real_filename(struct vfs_handle_struct *handle, > TALLOC_CTX *mem_ctx, > char **found_name) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > ssize_t ret; > int saved_errno; > char *conv; >@@ -1788,7 +1794,7 @@ static int shadow_copy2_get_real_filename(struct vfs_handle_struct *handle, > static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle, > const char *fname) > { >- time_t timestamp; >+ time_t timestamp = 0; > char *stripped = NULL; > char *tmp = NULL; > char *result = NULL; >@@ -1863,8 +1869,8 @@ static uint64_t shadow_copy2_disk_free(vfs_handle_struct *handle, > const char *path, uint64_t *bsize, > uint64_t *dfree, uint64_t *dsize) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > ssize_t ret; > int saved_errno; > char *conv; >@@ -1897,8 +1903,8 @@ static int shadow_copy2_get_quota(vfs_handle_struct *handle, const char *path, > enum SMB_QUOTA_TYPE qtype, unid_t id, > SMB_DISK_QUOTA *dq) > { >- time_t timestamp; >- char *stripped; >+ time_t timestamp = 0; >+ char *stripped = NULL; > int ret; > int saved_errno; > char *conv; >-- >2.11.0.483.g087da7b7c-goog > > >From 964e382c90baba6bc4328aa2d7c3541f47f59a2d Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 20 Jan 2017 11:45:54 -0800 >Subject: [PATCH 07/20] s3: VFS: shadow_copy2: Ensure pathnames for parameters > are correctly relative and terminated. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit 979e39252bcc88e8aacb543b8bf322dd6f17fe7f) >--- > source3/modules/vfs_shadow_copy2.c | 5 +++++ > 1 file changed, 5 insertions(+) > >diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c >index 80f544d90b7..562b4c400c0 100644 >--- a/source3/modules/vfs_shadow_copy2.c >+++ b/source3/modules/vfs_shadow_copy2.c >@@ -2161,6 +2161,11 @@ static int shadow_copy2_connect(struct vfs_handle_struct *handle, > } > } > >+ trim_string(config->mount_point, NULL, "/"); >+ trim_string(config->rel_connectpath, "/", "/"); >+ trim_string(config->snapdir, NULL, "/"); >+ trim_string(config->snapshot_basepath, NULL, "/"); >+ > DEBUG(10, ("shadow_copy2_connect: configuration:\n" > " share root: '%s'\n" > " mountpoint: '%s'\n" >-- >2.11.0.483.g087da7b7c-goog > > >From 015db3c97b368bba51c2cbc4d0db1c66686456e5 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 20 Jan 2017 11:48:40 -0800 >Subject: [PATCH 08/20] s3: VFS: shadow_copy2: Fix length comparison to ensure > we don't overstep a length. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit 37ef8d3f65bd1215717eb51b2e1cdb84a7bed348) >--- > source3/modules/vfs_shadow_copy2.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c >index 562b4c400c0..711d8ac1ac0 100644 >--- a/source3/modules/vfs_shadow_copy2.c >+++ b/source3/modules/vfs_shadow_copy2.c >@@ -2123,7 +2123,7 @@ static int shadow_copy2_connect(struct vfs_handle_struct *handle, > } > > if (config->rel_connectpath == NULL && >- strlen(basedir) != strlen(handle->conn->connectpath)) { >+ strlen(basedir) < strlen(handle->conn->connectpath)) { > config->rel_connectpath = talloc_strdup(config, > handle->conn->connectpath + strlen(basedir)); > if (config->rel_connectpath == NULL) { >-- >2.11.0.483.g087da7b7c-goog > > >From 47d1697932f3c310936e5c95d10900a4536ff21a Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 20 Jan 2017 11:50:49 -0800 >Subject: [PATCH 09/20] s3: VFS: shadow_copy2: Add two new variables to the > config data. Not yet used. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit 72fe2b62e3ee7462e5be855b01943f28b26c36c1) >--- > source3/modules/vfs_shadow_copy2.c | 3 +++ > 1 file changed, 3 insertions(+) > >diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c >index 711d8ac1ac0..7355b629e18 100644 >--- a/source3/modules/vfs_shadow_copy2.c >+++ b/source3/modules/vfs_shadow_copy2.c >@@ -48,6 +48,9 @@ struct shadow_copy2_config { > char *mount_point; > char *rel_connectpath; /* share root, relative to a snapshot root */ > char *snapshot_basepath; /* the absolute version of snapdir */ >+ char *shadow_cwd; /* Absolute $cwd path. */ >+ /* Absolute connectpath - can vary depending on $cwd. */ >+ char *shadow_connectpath; > }; > > static bool shadow_copy2_find_slashes(TALLOC_CTX *mem_ctx, const char *str, >-- >2.11.0.483.g087da7b7c-goog > > >From 95fdc3a2e3f8f3e6bd65540cdb0e657385940bd7 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 20 Jan 2017 11:54:56 -0800 >Subject: [PATCH 10/20] s3: VFS: shadow_copy2: Add a wrapper function to call > the original shadow_copy2_strip_snapshot(). > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Allows an extra (currently unused) parameter to be added. > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit 5aa1ea95157475dfd2d056f0158b14b2b90895a9) >--- > source3/modules/vfs_shadow_copy2.c | 19 +++++++++++++++++-- > 1 file changed, 17 insertions(+), 2 deletions(-) > >diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c >index 7355b629e18..a0ada76b597 100644 >--- a/source3/modules/vfs_shadow_copy2.c >+++ b/source3/modules/vfs_shadow_copy2.c >@@ -224,11 +224,12 @@ static char *shadow_copy2_snapshot_path(TALLOC_CTX *mem_ctx, > * handed in via the smb layer. > * Returns the parsed timestamp and the stripped filename. > */ >-static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx, >+static bool shadow_copy2_strip_snapshot_internal(TALLOC_CTX *mem_ctx, > struct vfs_handle_struct *handle, > const char *name, > time_t *ptimestamp, >- char **pstripped) >+ char **pstripped, >+ char **psnappath) > { > struct tm tm; > time_t timestamp = 0; >@@ -402,6 +403,20 @@ no_snapshot: > return true; > } > >+static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx, >+ struct vfs_handle_struct *handle, >+ const char *orig_name, >+ time_t *ptimestamp, >+ char **pstripped) >+{ >+ return shadow_copy2_strip_snapshot_internal(mem_ctx, >+ handle, >+ orig_name, >+ ptimestamp, >+ pstripped, >+ NULL); >+} >+ > static char *shadow_copy2_find_mount_point(TALLOC_CTX *mem_ctx, > vfs_handle_struct *handle) > { >-- >2.11.0.483.g087da7b7c-goog > > >From c0363a1a1647cec779cb1fdc3ef4dad58cce8b0f Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 20 Jan 2017 11:56:21 -0800 >Subject: [PATCH 11/20] s3: VFS: shadow_copy2: Change a parameter name. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Allows easy substitution later. > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit 2887465108aef5e2e7c64417437ecb86c7460e16) >--- > source3/modules/vfs_shadow_copy2.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > >diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c >index a0ada76b597..0a6b10d22d6 100644 >--- a/source3/modules/vfs_shadow_copy2.c >+++ b/source3/modules/vfs_shadow_copy2.c >@@ -226,7 +226,7 @@ static char *shadow_copy2_snapshot_path(TALLOC_CTX *mem_ctx, > */ > static bool shadow_copy2_strip_snapshot_internal(TALLOC_CTX *mem_ctx, > struct vfs_handle_struct *handle, >- const char *name, >+ const char *orig_name, > time_t *ptimestamp, > char **pstripped, > char **psnappath) >@@ -241,6 +241,7 @@ static bool shadow_copy2_strip_snapshot_internal(TALLOC_CTX *mem_ctx, > const char *snapdir; > ssize_t snapdirlen; > ptrdiff_t len_before_gmt; >+ const char *name = orig_name; > > SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config, > return false); >-- >2.11.0.483.g087da7b7c-goog > > >From e4d2225099f82629697df224668a8152c2017b38 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 20 Jan 2017 12:00:08 -0800 >Subject: [PATCH 12/20] s3: VFS: shadow_copy2: Add two currently unused > functions to make pathnames absolute or relative to $cwd. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit 9d65107b8f2864dba8d41b3316c483b3f36d0697) >--- > source3/modules/vfs_shadow_copy2.c | 45 ++++++++++++++++++++++++++++++++++++++ > 1 file changed, 45 insertions(+) > >diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c >index 0a6b10d22d6..7b4502a9eb6 100644 >--- a/source3/modules/vfs_shadow_copy2.c >+++ b/source3/modules/vfs_shadow_copy2.c >@@ -34,6 +34,7 @@ > #include "system/filesys.h" > #include "include/ntioctl.h" > #include "util_tdb.h" >+#include "lib/util_path.h" > > struct shadow_copy2_config { > char *gmt_format; >@@ -219,6 +220,50 @@ static char *shadow_copy2_snapshot_path(TALLOC_CTX *mem_ctx, > return result; > } > >+static char *make_path_absolute(TALLOC_CTX *mem_ctx, >+ struct shadow_copy2_config *config, >+ const char *name) >+{ >+ char *newpath = NULL; >+ char *abs_path = NULL; >+ >+ if (name[0] != '/') { >+ newpath = talloc_asprintf(mem_ctx, >+ "%s/%s", >+ config->shadow_cwd, >+ name); >+ if (newpath == NULL) { >+ return NULL; >+ } >+ name = newpath; >+ } >+ abs_path = canonicalize_absolute_path(mem_ctx, name); >+ TALLOC_FREE(newpath); >+ return abs_path; >+} >+ >+/* Return a $cwd-relative path. */ >+static bool make_relative_path(const char *cwd, char *abs_path) >+{ >+ size_t cwd_len = strlen(cwd); >+ size_t abs_len = strlen(abs_path); >+ >+ if (abs_len < cwd_len) { >+ return false; >+ } >+ if (memcmp(abs_path, cwd, cwd_len) != 0) { >+ return false; >+ } >+ if (abs_path[cwd_len] != '/' && abs_path[cwd_len] != '\0') { >+ return false; >+ } >+ if (abs_path[cwd_len] == '/') { >+ cwd_len++; >+ } >+ memmove(abs_path, &abs_path[cwd_len], abs_len + 1 - cwd_len); >+ return true; >+} >+ > /** > * Strip a snapshot component from a filename as > * handed in via the smb layer. >-- >2.11.0.483.g087da7b7c-goog > > >From 1ef467d2dd2358252381279d186a55e417ef3e7d Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 20 Jan 2017 12:06:55 -0800 >Subject: [PATCH 13/20] s3: VFS: shadow_copy2: Fix chdir to store off the > needed private variables. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >This is not yet used, the users of this will be added later. > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit 27340df4b52e4341f134667c59d71656a7a1fdae) >--- > source3/modules/vfs_shadow_copy2.c | 81 ++++++++++++++++++++++++++++++++------ > 1 file changed, 68 insertions(+), 13 deletions(-) > >diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c >index 7b4502a9eb6..81cd9f45987 100644 >--- a/source3/modules/vfs_shadow_copy2.c >+++ b/source3/modules/vfs_shadow_copy2.c >@@ -1080,30 +1080,85 @@ static int shadow_copy2_chown(vfs_handle_struct *handle, const char *fname, > return ret; > } > >+static void store_cwd_data(vfs_handle_struct *handle, >+ const char *connectpath) >+{ >+ struct shadow_copy2_config *config = NULL; >+ char *cwd = NULL; >+ >+ SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config, >+ return); >+ >+ TALLOC_FREE(config->shadow_cwd); >+ cwd = SMB_VFS_NEXT_GETWD(handle); >+ if (cwd == NULL) { >+ smb_panic("getwd failed\n"); >+ } >+ DBG_DEBUG("shadow cwd = %s\n", cwd); >+ config->shadow_cwd = talloc_strdup(config, cwd); >+ SAFE_FREE(cwd); >+ if (config->shadow_cwd == NULL) { >+ smb_panic("talloc failed\n"); >+ } >+ TALLOC_FREE(config->shadow_connectpath); >+ if (connectpath) { >+ DBG_DEBUG("shadow conectpath = %s\n", connectpath); >+ config->shadow_connectpath = talloc_strdup(config, connectpath); >+ if (config->shadow_connectpath == NULL) { >+ smb_panic("talloc failed\n"); >+ } >+ } >+} >+ > static int shadow_copy2_chdir(vfs_handle_struct *handle, > const char *fname) > { > time_t timestamp = 0; > char *stripped = NULL; >- int ret, saved_errno; >- char *conv; >+ char *snappath = NULL; >+ int ret = -1; >+ int saved_errno = 0; >+ char *conv = NULL; >+ size_t rootpath_len = 0; > >- if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, >- ×tamp, &stripped)) { >+ if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, fname, >+ ×tamp, &stripped, &snappath)) { > return -1; > } >- if (timestamp == 0) { >- return SMB_VFS_NEXT_CHDIR(handle, fname); >+ if (stripped != NULL) { >+ conv = shadow_copy2_do_convert(talloc_tos(), >+ handle, >+ stripped, >+ timestamp, >+ &rootpath_len); >+ TALLOC_FREE(stripped); >+ if (conv == NULL) { >+ return -1; >+ } >+ fname = conv; > } >- conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp); >- TALLOC_FREE(stripped); >- if (conv == NULL) { >- return -1; >+ >+ ret = SMB_VFS_NEXT_CHDIR(handle, fname); >+ if (ret == -1) { >+ saved_errno = errno; > } >- ret = SMB_VFS_NEXT_CHDIR(handle, conv); >- saved_errno = errno; >+ >+ if (ret == 0) { >+ if (conv != NULL && rootpath_len != 0) { >+ conv[rootpath_len] = '\0'; >+ } else if (snappath != 0) { >+ TALLOC_FREE(conv); >+ conv = snappath; >+ } >+ store_cwd_data(handle, conv); >+ } >+ >+ TALLOC_FREE(stripped); > TALLOC_FREE(conv); >- errno = saved_errno; >+ >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >-- >2.11.0.483.g087da7b7c-goog > > >From 4e4ac5f5e4602e1f7590b3e704d109ab6aef0f06 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Fri, 20 Jan 2017 12:09:08 -0800 >Subject: [PATCH 14/20] s3: VFS: Allow shadow_copy2_connectpath() to return the > cached path derived from $cwd. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit 42bd1acad75a6b5ea81fe4b30c067dd82623c042) >--- > source3/modules/vfs_shadow_copy2.c | 10 ++++++++++ > 1 file changed, 10 insertions(+) > >diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c >index 81cd9f45987..59cc65644af 100644 >--- a/source3/modules/vfs_shadow_copy2.c >+++ b/source3/modules/vfs_shadow_copy2.c >@@ -1920,9 +1920,19 @@ static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle, > char *parent_dir = NULL; > int saved_errno; > size_t rootpath_len = 0; >+ struct shadow_copy2_config *config = NULL; >+ >+ SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config, >+ return NULL); > > DBG_DEBUG("Calc connect path for [%s]\n", fname); > >+ if (config->shadow_connectpath != NULL) { >+ DBG_DEBUG("cached connect path is [%s]\n", >+ config->shadow_connectpath); >+ return config->shadow_connectpath; >+ } >+ > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, > ×tamp, &stripped)) { > goto done; >-- >2.11.0.483.g087da7b7c-goog > > >From 3ff4c9003cc09327c6731aa5268699204db6584e Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 26 Jan 2017 10:24:52 -0800 >Subject: [PATCH 15/20] s3: VFS: Ensure shadow:format cannot contain a / path > separator. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit cd4f940162b17e4f7345d392326a31ae478230fa) >--- > source3/modules/vfs_shadow_copy2.c | 9 +++++++++ > 1 file changed, 9 insertions(+) > >diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c >index 59cc65644af..2ef7662ab8d 100644 >--- a/source3/modules/vfs_shadow_copy2.c >+++ b/source3/modules/vfs_shadow_copy2.c >@@ -2099,6 +2099,15 @@ static int shadow_copy2_connect(struct vfs_handle_struct *handle, > return -1; > } > >+ /* config->gmt_format must not contain a path separator. */ >+ if (strchr(config->gmt_format, '/') != NULL) { >+ DEBUG(0, ("shadow:format %s must not contain a /" >+ "character. Unable to initialize module.\n", >+ config->gmt_format)); >+ errno = EINVAL; >+ return -1; >+ } >+ > config->use_sscanf = lp_parm_bool(SNUM(handle->conn), > "shadow", "sscanf", false); > >-- >2.11.0.483.g087da7b7c-goog > > >From c8d58c9fe58a482417c6698e2b81cc794bfb9650 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 26 Jan 2017 10:35:50 -0800 >Subject: [PATCH 16/20] s3: VFS: Add utility function > check_for_converted_path(). > >Detects an already converted path. Not yet used. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit b94dc85d339c9a10496edd07b85bdd7808d2e332) >--- > source3/modules/vfs_shadow_copy2.c | 108 +++++++++++++++++++++++++++++++++++++ > 1 file changed, 108 insertions(+) > >diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c >index 2ef7662ab8d..3e3aef4deaf 100644 >--- a/source3/modules/vfs_shadow_copy2.c >+++ b/source3/modules/vfs_shadow_copy2.c >@@ -264,6 +264,114 @@ static bool make_relative_path(const char *cwd, char *abs_path) > return true; > } > >+static bool shadow_copy2_snapshot_to_gmt(vfs_handle_struct *handle, >+ const char *name, >+ char *gmt, size_t gmt_len); >+ >+/* >+ * Check if an incoming filename is already a snapshot converted pathname. >+ * >+ * If so, it returns the pathname truncated at the snapshot point which >+ * will be used as the connectpath. >+ */ >+ >+static int check_for_converted_path(TALLOC_CTX *mem_ctx, >+ struct vfs_handle_struct *handle, >+ struct shadow_copy2_config *config, >+ char *abs_path, >+ bool *ppath_already_converted, >+ char **pconnectpath) >+{ >+ size_t snapdirlen = 0; >+ char *p = strstr_m(abs_path, config->snapdir); >+ char *q = NULL; >+ char *connect_path = NULL; >+ char snapshot[GMT_NAME_LEN+1]; >+ >+ *ppath_already_converted = false; >+ >+ if (p == NULL) { >+ /* Must at least contain shadow:snapdir. */ >+ return 0; >+ } >+ >+ if (config->snapdir[0] == '/' && >+ p != abs_path) { >+ /* Absolute shadow:snapdir must be at the start. */ >+ return 0; >+ } >+ >+ snapdirlen = strlen(config->snapdir); >+ if (p[snapdirlen] != '/') { >+ /* shadow:snapdir must end as a separate component. */ >+ return 0; >+ } >+ >+ if (p > abs_path && p[-1] != '/') { >+ /* shadow:snapdir must start as a separate component. */ >+ return 0; >+ } >+ >+ p += snapdirlen; >+ p++; /* Move past the / */ >+ >+ /* >+ * Need to return up to the next path >+ * component after the time. >+ * This will be used as the connectpath. >+ */ >+ q = strchr(p, '/'); >+ if (q == NULL) { >+ /* >+ * No next path component. >+ * Use entire string. >+ */ >+ connect_path = talloc_strdup(mem_ctx, >+ abs_path); >+ } else { >+ connect_path = talloc_strndup(mem_ctx, >+ abs_path, >+ q - abs_path); >+ } >+ if (connect_path == NULL) { >+ return ENOMEM; >+ } >+ >+ /* >+ * Point p at the same offset in connect_path as >+ * it is in abs_path. >+ */ >+ >+ p = &connect_path[p - abs_path]; >+ >+ /* >+ * Now ensure there is a time string at p. >+ * The SMB-format @GMT-token string is returned >+ * in snapshot. >+ */ >+ >+ if (!shadow_copy2_snapshot_to_gmt(handle, >+ p, >+ snapshot, >+ sizeof(snapshot))) { >+ TALLOC_FREE(connect_path); >+ return 0; >+ } >+ >+ if (pconnectpath != NULL) { >+ *pconnectpath = connect_path; >+ } >+ >+ *ppath_already_converted = true; >+ >+ DBG_DEBUG("path |%s| is already converted. " >+ "connect path = |%s|\n", >+ abs_path, >+ connect_path); >+ >+ return 0; >+} >+ > /** > * Strip a snapshot component from a filename as > * handed in via the smb layer. >-- >2.11.0.483.g087da7b7c-goog > > >From f79a82f1dd568c2e5c3c849722d55dff07fb41ee Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 26 Jan 2017 10:49:51 -0800 >Subject: [PATCH 17/20] s3: VFS: shadow_copy2: Fix module to work with variable > current working directory. > >Completely cleans up the horrible shadow_copy2_strip_snapshot() >and adds an explaination of what it's actually trying to do. > >* This function does two things. >* >* 1). Checks if an incoming filename is already a >* snapshot converted pathname. >* If so, it returns the pathname truncated >* at the snapshot point which will be used >* as the connectpath, and then does an early return. >* >* 2). Checks if an incoming filename contains an >* SMB-layer @GMT- style timestamp. >* If so, it strips the timestamp, and returns >* both the timestamp and the stripped path >* (making it cwd-relative). > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit 128d5f27cd42b0c7efcbe3d28fe3eee881e0734b) >--- > source3/modules/vfs_shadow_copy2.c | 189 ++++++++++++++++++------------------- > 1 file changed, 92 insertions(+), 97 deletions(-) > >diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c >index 3e3aef4deaf..d213866a425 100644 >--- a/source3/modules/vfs_shadow_copy2.c >+++ b/source3/modules/vfs_shadow_copy2.c >@@ -373,10 +373,21 @@ static int check_for_converted_path(TALLOC_CTX *mem_ctx, > } > > /** >- * Strip a snapshot component from a filename as >- * handed in via the smb layer. >- * Returns the parsed timestamp and the stripped filename. >+ * This function does two things. >+ * >+ * 1). Checks if an incoming filename is already a >+ * snapshot converted pathname. >+ * If so, it returns the pathname truncated >+ * at the snapshot point which will be used >+ * as the connectpath, and then does an early return. >+ * >+ * 2). Checks if an incoming filename contains an >+ * SMB-layer @GMT- style timestamp. >+ * If so, it strips the timestamp, and returns >+ * both the timestamp and the stripped path >+ * (making it cwd-relative). > */ >+ > static bool shadow_copy2_strip_snapshot_internal(TALLOC_CTX *mem_ctx, > struct vfs_handle_struct *handle, > const char *orig_name, >@@ -391,62 +402,72 @@ static bool shadow_copy2_strip_snapshot_internal(TALLOC_CTX *mem_ctx, > char *stripped = NULL; > size_t rest_len, dst_len; > struct shadow_copy2_config *config; >- const char *snapdir; >- ssize_t snapdirlen; > ptrdiff_t len_before_gmt; > const char *name = orig_name; >+ char *abs_path = NULL; >+ bool ret = true; >+ bool already_converted = false; >+ int err = 0; > > SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config, > return false); > > DEBUG(10, (__location__ ": enter path '%s'\n", name)); > >+ abs_path = make_path_absolute(mem_ctx, config, name); >+ if (abs_path == NULL) { >+ ret = false; >+ goto out; >+ } >+ name = abs_path; >+ >+ DEBUG(10, (__location__ ": abs path '%s'\n", name)); >+ >+ err = check_for_converted_path(mem_ctx, >+ handle, >+ config, >+ abs_path, >+ &already_converted, >+ psnappath); >+ if (err != 0) { >+ /* error in conversion. */ >+ ret = false; >+ goto out; >+ } >+ >+ if (already_converted) { >+ goto out; >+ } >+ >+ /* >+ * From here we're only looking to strip an >+ * SMB-layer @GMT- token. >+ */ >+ > p = strstr_m(name, "@GMT-"); > if (p == NULL) { > DEBUG(11, ("@GMT not found\n")); >- goto no_snapshot; >+ goto out; > } > if ((p > name) && (p[-1] != '/')) { > /* the GMT-token does not start a path-component */ > DEBUG(10, ("not at start, p=%p, name=%p, p[-1]=%d\n", > p, name, (int)p[-1])); >- goto no_snapshot; >+ goto out; > } > >- /* >- * Figure out whether we got an already converted string. One >- * case where this happens is in a smb2 create call with the >- * mxac create blob set. We do the get_acl call on >- * fsp->fsp_name, which is already converted. We are converted >- * if we got a file name of the form ".snapshots/@GMT-", >- * i.e. ".snapshots/" precedes "p". >- */ >- >- snapdir = lp_parm_const_string(SNUM(handle->conn), "shadow", "snapdir", >- ".snapshots"); >- snapdirlen = strlen(snapdir); > len_before_gmt = p - name; > >- if ((len_before_gmt >= (snapdirlen + 1)) && (p[-1] == '/')) { >- const char *parent_snapdir = p - (snapdirlen+1); >- >- DEBUG(10, ("parent_snapdir = %s\n", parent_snapdir)); >- >- if (strncmp(parent_snapdir, snapdir, snapdirlen) == 0) { >- DEBUG(10, ("name=%s is already converted\n", name)); >- goto no_snapshot; >- } >- } > q = strptime(p, GMT_FORMAT, &tm); > if (q == NULL) { > DEBUG(10, ("strptime failed\n")); >- goto no_snapshot; >+ goto out; > } > tm.tm_isdst = -1; > timestamp = timegm(&tm); > if (timestamp == (time_t)-1) { > DEBUG(10, ("timestamp==-1\n")); >- goto no_snapshot; >+ goto out; > } > if (q[0] == '\0') { > /* >@@ -456,14 +477,33 @@ static bool shadow_copy2_strip_snapshot_internal(TALLOC_CTX *mem_ctx, > * with a path prefix. > */ > if (pstripped != NULL) { >+ if (len_before_gmt > 0) { >+ /* >+ * There is a slash before >+ * the @GMT-. Remove it. >+ */ >+ len_before_gmt -= 1; >+ } > stripped = talloc_strndup(mem_ctx, name, p - name); > if (stripped == NULL) { >- return false; >+ ret = false; >+ goto out; >+ } >+ if (orig_name[0] != '/') { >+ if (make_relative_path(config->shadow_cwd, >+ stripped) == false) { >+ DEBUG(10, (__location__ ": path '%s' " >+ "doesn't start with cwd '%s\n", >+ stripped, config->shadow_cwd)); >+ ret = false; >+ errno = ENOENT; >+ goto out; >+ } > } > *pstripped = stripped; > } > *ptimestamp = timestamp; >- return true; >+ goto out; > } > if (q[0] != '/') { > /* >@@ -471,75 +511,18 @@ static bool shadow_copy2_strip_snapshot_internal(TALLOC_CTX *mem_ctx, > * component continues after the gmt-token. > */ > DEBUG(10, ("q[0] = %d\n", (int)q[0])); >- goto no_snapshot; >+ goto out; > } > q += 1; > > rest_len = strlen(q); > dst_len = (p-name) + rest_len; > >- if (config->snapdirseverywhere) { >- char *insert; >- bool have_insert; >- insert = shadow_copy2_insert_string(talloc_tos(), handle, >- timestamp); >- if (insert == NULL) { >- errno = ENOMEM; >- return false; >- } >- >- DEBUG(10, (__location__ ": snapdirseverywhere mode.\n" >- "path '%s'.\n" >- "insert string '%s'\n", name, insert)); >- >- have_insert = (strstr(name, insert+1) != NULL); >- DEBUG(10, ("have_insert=%d, name=%s, insert+1=%s\n", >- (int)have_insert, name, insert+1)); >- if (have_insert) { >- DEBUG(10, (__location__ ": insert string '%s' found in " >- "path '%s' found in snapdirseverywhere mode " >- "==> already converted\n", insert, name)); >- TALLOC_FREE(insert); >- goto no_snapshot; >- } >- TALLOC_FREE(insert); >- } else { >- char *snapshot_path; >- char *s; >- >- snapshot_path = shadow_copy2_snapshot_path(talloc_tos(), >- handle, >- timestamp); >- if (snapshot_path == NULL) { >- errno = ENOMEM; >- return false; >- } >- >- DEBUG(10, (__location__ " path: '%s'.\n" >- "snapshot path: '%s'\n", name, snapshot_path)); >- >- s = strstr(name, snapshot_path); >- if (s == name) { >- /* >- * this starts with "snapshot_basepath/GMT-Token" >- * so it is already a converted absolute >- * path. Don't process further. >- */ >- DEBUG(10, (__location__ ": path '%s' starts with " >- "snapshot path '%s' (not in " >- "snapdirseverywhere mode) ==> " >- "already converted\n", name, snapshot_path)); >- talloc_free(snapshot_path); >- goto no_snapshot; >- } >- talloc_free(snapshot_path); >- } >- > if (pstripped != NULL) { > stripped = talloc_array(mem_ctx, char, dst_len+1); > if (stripped == NULL) { >- errno = ENOMEM; >- return false; >+ ret = false; >+ goto out; > } > if (p > name) { > memcpy(stripped, name, p-name); >@@ -548,13 +531,25 @@ static bool shadow_copy2_strip_snapshot_internal(TALLOC_CTX *mem_ctx, > memcpy(stripped + (p-name), q, rest_len); > } > stripped[dst_len] = '\0'; >+ if (orig_name[0] != '/') { >+ if (make_relative_path(config->shadow_cwd, >+ stripped) == false) { >+ DEBUG(10, (__location__ ": path '%s' " >+ "doesn't start with cwd '%s\n", >+ stripped, config->shadow_cwd)); >+ ret = false; >+ errno = ENOENT; >+ goto out; >+ } >+ } > *pstripped = stripped; > } > *ptimestamp = timestamp; >- return true; >-no_snapshot: >- *ptimestamp = 0; >- return true; >+ ret = true; >+ >+ out: >+ TALLOC_FREE(abs_path); >+ return ret; > } > > static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx, >-- >2.11.0.483.g087da7b7c-goog > > >From 7bdedb8aa9fe0c48ba1dc6e4a85dab285dad1fe7 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Mon, 23 Jan 2017 10:06:44 -0800 >Subject: [PATCH 18/20] s3: VFS: shadow_copy2: Fix a memory leak in the > connectpath function. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit 4d339a88851f601fae195ac8ff0691cbd3504f41) >--- > source3/modules/vfs_shadow_copy2.c | 17 +++++++++++++++++ > 1 file changed, 17 insertions(+) > >diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c >index d213866a425..df4cebe2858 100644 >--- a/source3/modules/vfs_shadow_copy2.c >+++ b/source3/modules/vfs_shadow_copy2.c >@@ -52,6 +52,8 @@ struct shadow_copy2_config { > char *shadow_cwd; /* Absolute $cwd path. */ > /* Absolute connectpath - can vary depending on $cwd. */ > char *shadow_connectpath; >+ /* malloc'ed realpath return. */ >+ char *shadow_realpath; > }; > > static bool shadow_copy2_find_slashes(TALLOC_CTX *mem_ctx, const char *str, >@@ -2086,6 +2088,13 @@ static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle, > goto done; > } > >+ /* >+ * SMB_VFS_NEXT_REALPATH returns a malloc'ed string. >+ * Don't leak memory. >+ */ >+ SAFE_FREE(config->shadow_realpath); >+ config->shadow_realpath = result; >+ > DBG_DEBUG("connect path is [%s]\n", result); > > done: >@@ -2164,6 +2173,12 @@ static int shadow_copy2_get_quota(vfs_handle_struct *handle, const char *path, > return ret; > } > >+static int shadow_copy2_config_destructor(struct shadow_copy2_config *config) >+{ >+ SAFE_FREE(config->shadow_realpath); >+ return 0; >+} >+ > static int shadow_copy2_connect(struct vfs_handle_struct *handle, > const char *service, const char *user) > { >@@ -2192,6 +2207,8 @@ static int shadow_copy2_connect(struct vfs_handle_struct *handle, > return -1; > } > >+ talloc_set_destructor(config, shadow_copy2_config_destructor); >+ > gmt_format = lp_parm_const_string(SNUM(handle->conn), > "shadow", "format", > GMT_FORMAT); >-- >2.11.0.483.g087da7b7c-goog > > >From 0a310cf2ce84ca028969bae7ae9c15e63d01db90 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Mon, 23 Jan 2017 10:20:13 -0800 >Subject: [PATCH 19/20] s3: VFS: shadow_copy2: Fix usage of saved_errno to only > set errno on error. > >Rationale: > >VFS calls must act like their POSIX equivalents, and the POSIX versions >*only* set errno on a failure. There is actually code in the upper smbd >layers that depends on errno being correct on a fail return from a VFS call. > >For a compound VFS module like this, a common pattern is : > >SMB_VFS_CALL_X() >{ > int ret; > > syscall1(); > ret = syscall2(); > syscall3(); > > return ret; >} > >Where if *any* of the contained syscallX()'s fail, they'll set errno. >However, the actual errno we should return is *only* the one returned >if syscall2() fails (the others are lstat's checking for existence etc.). > >So what we should do to correctly return only the errno from syscall2() is: > >SMB_VFS_CALL_X() >{ > int ret; > int saved_errno = 0; > > syscall1() > > ret = syscall2(); > if (ret == -1) { > saved_errno = errno; > } > syscall3() > > if (saved_errno != 0) { > errno = saved_errno; > } > return ret; >} > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> >(backported from commit cda6764f1a8db96182bfd1855440bc6a1ba1abee) >--- > source3/modules/vfs_shadow_copy2.c | 254 ++++++++++++++++++++++++++----------- > 1 file changed, 182 insertions(+), 72 deletions(-) > >diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c >index df4cebe2858..8c07fa7fde3 100644 >--- a/source3/modules/vfs_shadow_copy2.c >+++ b/source3/modules/vfs_shadow_copy2.c >@@ -619,7 +619,8 @@ static char *shadow_copy2_do_convert(TALLOC_CTX *mem_ctx, > char *insert = NULL; > char *converted = NULL; > size_t insertlen, connectlen = 0; >- int i, saved_errno; >+ int saved_errno = 0; >+ int i; > size_t min_offset; > struct shadow_copy2_config *config; > size_t in_share_offset = 0; >@@ -802,12 +803,16 @@ static char *shadow_copy2_do_convert(TALLOC_CTX *mem_ctx, > errno = ENOENT; > } > fail: >- saved_errno = errno; >+ if (result == NULL) { >+ saved_errno = errno; >+ } > TALLOC_FREE(converted); > TALLOC_FREE(insert); > TALLOC_FREE(slashes); > TALLOC_FREE(path); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return result; > } > >@@ -866,7 +871,7 @@ static DIR *shadow_copy2_opendir(vfs_handle_struct *handle, > time_t timestamp = 0; > char *stripped = NULL; > DIR *ret; >- int saved_errno; >+ int saved_errno = 0; > char *conv; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, >@@ -882,9 +887,13 @@ static DIR *shadow_copy2_opendir(vfs_handle_struct *handle, > return NULL; > } > ret = SMB_VFS_NEXT_OPENDIR(handle, conv, mask, attr); >- saved_errno = errno; >+ if (ret == NULL) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -964,7 +973,8 @@ static int shadow_copy2_stat(vfs_handle_struct *handle, > time_t timestamp = 0; > char *stripped = NULL; > char *tmp; >- int ret, saved_errno; >+ int saved_errno = 0; >+ int ret; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, > smb_fname->base_name, >@@ -986,7 +996,9 @@ static int shadow_copy2_stat(vfs_handle_struct *handle, > } > > ret = SMB_VFS_NEXT_STAT(handle, smb_fname); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > > TALLOC_FREE(smb_fname->base_name); > smb_fname->base_name = tmp; >@@ -994,7 +1006,9 @@ static int shadow_copy2_stat(vfs_handle_struct *handle, > if (ret == 0) { > convert_sbuf(handle, smb_fname->base_name, &smb_fname->st); > } >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -1004,7 +1018,8 @@ static int shadow_copy2_lstat(vfs_handle_struct *handle, > time_t timestamp = 0; > char *stripped = NULL; > char *tmp; >- int ret, saved_errno; >+ int saved_errno = 0; >+ int ret; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, > smb_fname->base_name, >@@ -1026,7 +1041,9 @@ static int shadow_copy2_lstat(vfs_handle_struct *handle, > } > > ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > > TALLOC_FREE(smb_fname->base_name); > smb_fname->base_name = tmp; >@@ -1034,7 +1051,9 @@ static int shadow_copy2_lstat(vfs_handle_struct *handle, > if (ret == 0) { > convert_sbuf(handle, smb_fname->base_name, &smb_fname->st); > } >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -1066,7 +1085,8 @@ static int shadow_copy2_open(vfs_handle_struct *handle, > time_t timestamp = 0; > char *stripped = NULL; > char *tmp; >- int ret, saved_errno; >+ int saved_errno = 0; >+ int ret; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, > smb_fname->base_name, >@@ -1088,12 +1108,16 @@ static int shadow_copy2_open(vfs_handle_struct *handle, > } > > ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > > TALLOC_FREE(smb_fname->base_name); > smb_fname->base_name = tmp; > >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -1102,7 +1126,8 @@ static int shadow_copy2_unlink(vfs_handle_struct *handle, > { > time_t timestamp = 0; > char *stripped = NULL; >- int ret, saved_errno; >+ int saved_errno = 0; >+ int ret; > struct smb_filename *conv; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, >@@ -1125,9 +1150,13 @@ static int shadow_copy2_unlink(vfs_handle_struct *handle, > return -1; > } > ret = SMB_VFS_NEXT_UNLINK(handle, conv); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -1136,7 +1165,8 @@ static int shadow_copy2_chmod(vfs_handle_struct *handle, const char *fname, > { > time_t timestamp = 0; > char *stripped = NULL; >- int ret, saved_errno; >+ int saved_errno = 0; >+ int ret; > char *conv; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, >@@ -1152,9 +1182,13 @@ static int shadow_copy2_chmod(vfs_handle_struct *handle, const char *fname, > return -1; > } > ret = SMB_VFS_NEXT_CHMOD(handle, conv, mode); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -1163,7 +1197,8 @@ static int shadow_copy2_chown(vfs_handle_struct *handle, const char *fname, > { > time_t timestamp = 0; > char *stripped = NULL; >- int ret, saved_errno; >+ int saved_errno = 0; >+ int ret; > char *conv; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, >@@ -1179,9 +1214,13 @@ static int shadow_copy2_chown(vfs_handle_struct *handle, const char *fname, > return -1; > } > ret = SMB_VFS_NEXT_CHOWN(handle, conv, uid, gid); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -1273,7 +1312,8 @@ static int shadow_copy2_ntimes(vfs_handle_struct *handle, > { > time_t timestamp = 0; > char *stripped = NULL; >- int ret, saved_errno; >+ int saved_errno = 0; >+ int ret; > struct smb_filename *conv; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, >@@ -1296,9 +1336,13 @@ static int shadow_copy2_ntimes(vfs_handle_struct *handle, > return -1; > } > ret = SMB_VFS_NEXT_NTIMES(handle, conv, ft); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -1307,7 +1351,8 @@ static int shadow_copy2_readlink(vfs_handle_struct *handle, > { > time_t timestamp = 0; > char *stripped; >- int ret, saved_errno; >+ int saved_errno = 0; >+ int ret; > char *conv; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, >@@ -1323,9 +1368,13 @@ static int shadow_copy2_readlink(vfs_handle_struct *handle, > return -1; > } > ret = SMB_VFS_NEXT_READLINK(handle, conv, buf, bufsiz); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -1334,7 +1383,8 @@ static int shadow_copy2_mknod(vfs_handle_struct *handle, > { > time_t timestamp = 0; > char *stripped = NULL; >- int ret, saved_errno; >+ int saved_errno = 0; >+ int ret; > char *conv; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, >@@ -1350,9 +1400,13 @@ static int shadow_copy2_mknod(vfs_handle_struct *handle, > return -1; > } > ret = SMB_VFS_NEXT_MKNOD(handle, conv, mode, dev); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -1363,7 +1417,7 @@ static char *shadow_copy2_realpath(vfs_handle_struct *handle, > char *stripped = NULL; > char *tmp = NULL; > char *result = NULL; >- int saved_errno; >+ int saved_errno = 0; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, > ×tamp, &stripped)) { >@@ -1381,10 +1435,14 @@ static char *shadow_copy2_realpath(vfs_handle_struct *handle, > result = SMB_VFS_NEXT_REALPATH(handle, tmp); > > done: >- saved_errno = errno; >+ if (result == NULL) { >+ saved_errno = errno; >+ } > TALLOC_FREE(tmp); > TALLOC_FREE(stripped); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return result; > } > >@@ -1753,7 +1811,8 @@ static int shadow_copy2_mkdir(vfs_handle_struct *handle, > { > time_t timestamp = 0; > char *stripped = NULL; >- int ret, saved_errno; >+ int saved_errno = 0; >+ int ret; > char *conv; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, >@@ -1769,9 +1828,13 @@ static int shadow_copy2_mkdir(vfs_handle_struct *handle, > return -1; > } > ret = SMB_VFS_NEXT_MKDIR(handle, conv, mode); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -1779,7 +1842,8 @@ static int shadow_copy2_rmdir(vfs_handle_struct *handle, const char *fname) > { > time_t timestamp = 0; > char *stripped = NULL; >- int ret, saved_errno; >+ int saved_errno = 0; >+ int ret; > char *conv; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, >@@ -1795,9 +1859,13 @@ static int shadow_copy2_rmdir(vfs_handle_struct *handle, const char *fname) > return -1; > } > ret = SMB_VFS_NEXT_RMDIR(handle, conv); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -1806,7 +1874,8 @@ static int shadow_copy2_chflags(vfs_handle_struct *handle, const char *fname, > { > time_t timestamp = 0; > char *stripped = NULL; >- int ret, saved_errno; >+ int saved_errno = 0; >+ int ret; > char *conv; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, >@@ -1822,9 +1891,13 @@ static int shadow_copy2_chflags(vfs_handle_struct *handle, const char *fname, > return -1; > } > ret = SMB_VFS_NEXT_CHFLAGS(handle, conv, flags); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -1835,7 +1908,7 @@ static ssize_t shadow_copy2_getxattr(vfs_handle_struct *handle, > time_t timestamp = 0; > char *stripped = NULL; > ssize_t ret; >- int saved_errno; >+ int saved_errno = 0; > char *conv; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, >@@ -1852,9 +1925,13 @@ static ssize_t shadow_copy2_getxattr(vfs_handle_struct *handle, > return -1; > } > ret = SMB_VFS_NEXT_GETXATTR(handle, conv, aname, value, size); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -1865,7 +1942,7 @@ static ssize_t shadow_copy2_listxattr(struct vfs_handle_struct *handle, > time_t timestamp = 0; > char *stripped = NULL; > ssize_t ret; >- int saved_errno; >+ int saved_errno = 0; > char *conv; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, >@@ -1881,9 +1958,13 @@ static ssize_t shadow_copy2_listxattr(struct vfs_handle_struct *handle, > return -1; > } > ret = SMB_VFS_NEXT_LISTXATTR(handle, conv, list, size); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -1892,7 +1973,8 @@ static int shadow_copy2_removexattr(vfs_handle_struct *handle, > { > time_t timestamp = 0; > char *stripped = NULL; >- int ret, saved_errno; >+ int saved_errno = 0; >+ int ret; > char *conv; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, >@@ -1908,9 +1990,13 @@ static int shadow_copy2_removexattr(vfs_handle_struct *handle, > return -1; > } > ret = SMB_VFS_NEXT_REMOVEXATTR(handle, conv, aname); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -1922,7 +2008,7 @@ static int shadow_copy2_setxattr(struct vfs_handle_struct *handle, > time_t timestamp = 0; > char *stripped = NULL; > ssize_t ret; >- int saved_errno; >+ int saved_errno = 0; > char *conv; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, >@@ -1939,9 +2025,13 @@ static int shadow_copy2_setxattr(struct vfs_handle_struct *handle, > return -1; > } > ret = SMB_VFS_NEXT_SETXATTR(handle, conv, aname, value, size, flags); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -1951,7 +2041,7 @@ static int shadow_copy2_chmod_acl(vfs_handle_struct *handle, > time_t timestamp = 0; > char *stripped = NULL; > ssize_t ret; >- int saved_errno; >+ int saved_errno = 0; > char *conv; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname, >@@ -1967,9 +2057,13 @@ static int shadow_copy2_chmod_acl(vfs_handle_struct *handle, > return -1; > } > ret = SMB_VFS_NEXT_CHMOD_ACL(handle, conv, mode); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -1982,7 +2076,7 @@ static int shadow_copy2_get_real_filename(struct vfs_handle_struct *handle, > time_t timestamp = 0; > char *stripped = NULL; > ssize_t ret; >- int saved_errno; >+ int saved_errno = 0; > char *conv; > > DEBUG(10, ("shadow_copy2_get_real_filename called for path=[%s], " >@@ -2009,9 +2103,13 @@ static int shadow_copy2_get_real_filename(struct vfs_handle_struct *handle, > ret = SMB_VFS_NEXT_GET_REAL_FILENAME(handle, conv, name, > mem_ctx, found_name); > DEBUG(10, ("NEXT_REAL_FILE_NAME returned %d\n", (int)ret)); >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return ret; > } > >@@ -2023,7 +2121,7 @@ static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle, > char *tmp = NULL; > char *result = NULL; > char *parent_dir = NULL; >- int saved_errno; >+ int saved_errno = 0; > size_t rootpath_len = 0; > struct shadow_copy2_config *config = NULL; > >@@ -2098,11 +2196,15 @@ static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle, > DBG_DEBUG("connect path is [%s]\n", result); > > done: >- saved_errno = errno; >+ if (result == NULL) { >+ saved_errno = errno; >+ } > TALLOC_FREE(tmp); > TALLOC_FREE(stripped); > TALLOC_FREE(parent_dir); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > return result; > } > >@@ -2113,7 +2215,7 @@ static uint64_t shadow_copy2_disk_free(vfs_handle_struct *handle, > time_t timestamp = 0; > char *stripped = NULL; > ssize_t ret; >- int saved_errno; >+ int saved_errno = 0; > char *conv; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, path, >@@ -2133,9 +2235,13 @@ static uint64_t shadow_copy2_disk_free(vfs_handle_struct *handle, > > ret = SMB_VFS_NEXT_DISK_FREE(handle, conv, bsize, dfree, dsize); > >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > > return ret; > } >@@ -2147,7 +2253,7 @@ static int shadow_copy2_get_quota(vfs_handle_struct *handle, const char *path, > time_t timestamp = 0; > char *stripped = NULL; > int ret; >- int saved_errno; >+ int saved_errno = 0; > char *conv; > > if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, path, ×tamp, >@@ -2166,9 +2272,13 @@ static int shadow_copy2_get_quota(vfs_handle_struct *handle, const char *path, > > ret = SMB_VFS_NEXT_GET_QUOTA(handle, conv, qtype, id, dq); > >- saved_errno = errno; >+ if (ret == -1) { >+ saved_errno = errno; >+ } > TALLOC_FREE(conv); >- errno = saved_errno; >+ if (saved_errno != 0) { >+ errno = saved_errno; >+ } > > return ret; > } >-- >2.11.0.483.g087da7b7c-goog > > >From 2e6b0608db5a392a632a0f7b4b861a6dab914c19 Mon Sep 17 00:00:00 2001 >From: Jeremy Allison <jra@samba.org> >Date: Thu, 26 Jan 2017 17:19:24 -0800 >Subject: [PATCH 20/20] s3: VFS: Don't allow symlink, link or rename on already > converted paths. > >Snapshot paths are a read-only filesystem. > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=12531 > >Signed-off-by: Jeremy Allison <jra@samba.org> >Reviewed-by: Uri Simchoni <uri@samba.org> > >Autobuild-User(master): Jeremy Allison <jra@samba.org> >Autobuild-Date(master): Mon Jan 30 22:26:29 CET 2017 on sn-devel-144 > >(backported from commit 0e1deb77f2b310ad7e5dd784174207adacf1c981) >--- > source3/modules/vfs_shadow_copy2.c | 55 +++++++++++++++++++++++++++++--------- > 1 file changed, 43 insertions(+), 12 deletions(-) > >diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c >index 8c07fa7fde3..b7b2935962f 100644 >--- a/source3/modules/vfs_shadow_copy2.c >+++ b/source3/modules/vfs_shadow_copy2.c >@@ -903,15 +903,17 @@ static int shadow_copy2_rename(vfs_handle_struct *handle, > { > time_t timestamp_src = 0; > time_t timestamp_dst = 0; >+ char *snappath_src = NULL; >+ char *snappath_dst = NULL; > >- if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, >+ if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, > smb_fname_src->base_name, >- ×tamp_src, NULL)) { >+ ×tamp_src, NULL, &snappath_src)) { > return -1; > } >- if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, >+ if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, > smb_fname_dst->base_name, >- ×tamp_dst, NULL)) { >+ ×tamp_dst, NULL, &snappath_dst)) { > return -1; > } > if (timestamp_src != 0) { >@@ -922,6 +924,17 @@ static int shadow_copy2_rename(vfs_handle_struct *handle, > errno = EROFS; > return -1; > } >+ /* >+ * Don't allow rename on already converted paths. >+ */ >+ if (snappath_src != NULL) { >+ errno = EXDEV; >+ return -1; >+ } >+ if (snappath_dst != NULL) { >+ errno = EROFS; >+ return -1; >+ } > return SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst); > } > >@@ -930,19 +943,28 @@ static int shadow_copy2_symlink(vfs_handle_struct *handle, > { > time_t timestamp_old = 0; > time_t timestamp_new = 0; >+ char *snappath_old = NULL; >+ char *snappath_new = NULL; > >- if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, oldname, >- ×tamp_old, NULL)) { >+ if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, oldname, >+ ×tamp_old, NULL, &snappath_old)) { > return -1; > } >- if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, newname, >- ×tamp_new, NULL)) { >+ if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, newname, >+ ×tamp_new, NULL, &snappath_new)) { > return -1; > } > if ((timestamp_old != 0) || (timestamp_new != 0)) { > errno = EROFS; > return -1; > } >+ /* >+ * Don't allow symlinks on already converted paths. >+ */ >+ if ((snappath_old != NULL) || (snappath_new != NULL)) { >+ errno = EROFS; >+ return -1; >+ } > return SMB_VFS_NEXT_SYMLINK(handle, oldname, newname); > } > >@@ -951,19 +973,28 @@ static int shadow_copy2_link(vfs_handle_struct *handle, > { > time_t timestamp_old = 0; > time_t timestamp_new = 0; >+ char *snappath_old = NULL; >+ char *snappath_new = NULL; > >- if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, oldname, >- ×tamp_old, NULL)) { >+ if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, oldname, >+ ×tamp_old, NULL, &snappath_old)) { > return -1; > } >- if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, newname, >- ×tamp_new, NULL)) { >+ if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, newname, >+ ×tamp_new, NULL, &snappath_new)) { > return -1; > } > if ((timestamp_old != 0) || (timestamp_new != 0)) { > errno = EROFS; > return -1; > } >+ /* >+ * Don't allow links on already converted paths. >+ */ >+ if ((snappath_old != NULL) || (snappath_new != NULL)) { >+ errno = EROFS; >+ return -1; >+ } > return SMB_VFS_NEXT_LINK(handle, oldname, newname); > } > >-- >2.11.0.483.g087da7b7c-goog >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 12531
:
12844
|
12846
|
12849
|
12850
|
12851
|
12852
|
12860
|
12889
|
12890
|
12891
|
12904