summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2017-07-07 12:57:57 +0200
committerKarolin Seeger <kseeger@samba.org>2017-07-24 04:25:45 +0200
commit9ff57c8760b04f6c913778d94de5cc84b7767aac (patch)
treedd4efe89eb2d01647d4399f9487d043c1b063468
parent9fb0aa56baf317c5bf18417c5516f951207af82d (diff)
downloadsamba-9ff57c8760b04f6c913778d94de5cc84b7767aac.tar.gz
s3/smbd: let non_widelink_open() chdir() to directories directly
If the caller passes O_DIRECTORY we just try to chdir() to smb_fname directly, not to the parent directory. The security check in check_reduced_name() will continue to work, but this fixes the case of an open() for a previous version of a subdirectory that contains snapshopt. Eg: [share] path = /shares/test vfs objects = shadow_copy2 shadow:snapdir = .snapshots shadow:snapdirseverywhere = yes Directory tree with fake snapshots: $ tree -a /shares/test/ /shares/test/ ├── dir │   ├── file │   └── .snapshots │   └── @GMT-2017.07.04-04.30.12 │   └── file ├── dir2 │   └── file ├── file ├── .snapshots │   └── @GMT-2001.01.01-00.00.00 │   ├── dir2 │   │   └── file │   └── file └── testfsctl.dat ./bin/smbclient -U slow%x //localhost/share -c 'ls @GMT-2017.07.04-04.30.12/dir/*' NT_STATUS_OBJECT_NAME_NOT_FOUND listing \@GMT-2017.07.04-04.30.12\dir\* Bug: https://bugzilla.samba.org/show_bug.cgi?id=12885 Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org> (cherry picked from commit b886a9443d49f6e27fa3863d87c9e24d12e62874) Autobuild-User(v4-4-test): Karolin Seeger <kseeger@samba.org> Autobuild-Date(v4-4-test): Mon Jul 24 04:25:45 CEST 2017 on sn-devel-144
-rw-r--r--source3/smbd/open.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index f19af87103b..5efb6f56eb1 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -527,12 +527,32 @@ static int non_widelink_open(struct connection_struct *conn,
char *oldwd = NULL;
char *parent_dir = NULL;
const char *final_component = NULL;
+ bool is_directory = false;
+ bool ok;
- if (!parent_dirname(talloc_tos(),
- smb_fname->base_name,
- &parent_dir,
- &final_component)) {
- goto out;
+#ifdef O_DIRECTORY
+ if (flags & O_DIRECTORY) {
+ is_directory = true;
+ }
+#endif
+
+ if (is_directory) {
+ parent_dir = talloc_strdup(talloc_tos(), smb_fname->base_name);
+ if (parent_dir == NULL) {
+ saved_errno = errno;
+ goto out;
+ }
+
+ final_component = ".";
+ } else {
+ ok = parent_dirname(talloc_tos(),
+ smb_fname->base_name,
+ &parent_dir,
+ &final_component);
+ if (!ok) {
+ saved_errno = errno;
+ goto out;
+ }
}
oldwd = vfs_GetWd(talloc_tos(), conn);