s3: VFS: Don't allow symlink, link or rename on already converted paths.
authorJeremy Allison <jra@samba.org>
Fri, 27 Jan 2017 01:19:24 +0000 (17:19 -0800)
committerJeremy Allison <jra@samba.org>
Mon, 30 Jan 2017 21:26:29 +0000 (22:26 +0100)
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

source3/modules/vfs_shadow_copy2.c

index f2a80f4b456746525dc3e74b32e272c880f38f4d..402eb70936b3c54a95f86023085bcb46c33e02a1 100644 (file)
@@ -1109,15 +1109,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,
-                                        &timestamp_src, NULL)) {
+                                        &timestamp_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,
-                                        &timestamp_dst, NULL)) {
+                                        &timestamp_dst, NULL, &snappath_dst)) {
                return -1;
        }
        if (timestamp_src != 0) {
@@ -1128,6 +1130,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);
 }
 
@@ -1136,19 +1149,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,
-                                        &timestamp_old, NULL)) {
+       if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, oldname,
+                                        &timestamp_old, NULL, &snappath_old)) {
                return -1;
        }
-       if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, newname,
-                                        &timestamp_new, NULL)) {
+       if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, newname,
+                                        &timestamp_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);
 }
 
@@ -1157,19 +1179,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,
-                                        &timestamp_old, NULL)) {
+       if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, oldname,
+                                        &timestamp_old, NULL, &snappath_old)) {
                return -1;
        }
-       if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, newname,
-                                        &timestamp_new, NULL)) {
+       if (!shadow_copy2_strip_snapshot_internal(talloc_tos(), handle, newname,
+                                        &timestamp_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);
 }