diff options
author | Ralph Boehme <slow@samba.org> | 2017-07-07 12:57:57 +0200 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2017-07-24 04:25:45 +0200 |
commit | 9ff57c8760b04f6c913778d94de5cc84b7767aac (patch) | |
tree | dd4efe89eb2d01647d4399f9487d043c1b063468 | |
parent | 9fb0aa56baf317c5bf18417c5516f951207af82d (diff) | |
download | samba-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.c | 30 |
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); |