From 374225938840092afba19939ad64eec0f21e0d25 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 23 Jun 2017 11:12:22 -0700 Subject: [PATCH 1/2] s3: smbd: Add regression test for non-wide symlinks to directories fail over SMB2. Mark as knownfail. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12860 Signed-off-by: Jeremy Allison --- selftest/knownfail | 1 + selftest/target/Samba3.pm | 8 +++++ source3/script/tests/test_smbclient_s3.sh | 55 +++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/selftest/knownfail b/selftest/knownfail index c6047c85445..9f9e9761465 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -335,3 +335,4 @@ # We currently don't send referrals for LDAP modify of non-replicated attrs ^samba4.ldap.rodc.python\(rodc\).__main__.RodcTests.test_modify_nonreplicated.* ^samba4.ldap.rodc_rwdc.python.*.__main__.RodcRwdcTests.test_change_password_reveal_on_demand_kerberos +^samba3.blackbox.smbclient_s3.*follow local symlinks.* diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index d93d98e3af3..6854d7c0ecd 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -1355,6 +1355,9 @@ sub provision($$$$$$$$$) my $nosymlinks_shrdir="$shrdir/nosymlinks"; push(@dirs,$nosymlinks_shrdir); + my $local_symlinks_shrdir="$shrdir/local_symlinks"; + push(@dirs,$local_symlinks_shrdir); + # this gets autocreated by winbindd my $wbsockdir="$prefix_abs/winbindd"; @@ -1976,6 +1979,11 @@ sub provision($$$$$$$$$) path = $nosymlinks_shrdir follow symlinks = no +[local_symlinks] + copy = tmp + path = $local_symlinks_shrdir + follow symlinks = yes + [kernel_oplocks] copy = tmp kernel oplocks = yes diff --git a/source3/script/tests/test_smbclient_s3.sh b/source3/script/tests/test_smbclient_s3.sh index 050dd81623e..1c5a13d110f 100755 --- a/source3/script/tests/test_smbclient_s3.sh +++ b/source3/script/tests/test_smbclient_s3.sh @@ -1215,6 +1215,57 @@ EOF fi } +# Test we can follow normal symlinks. +# Bug: https://bugzilla.samba.org/show_bug.cgi?id=12860 +# Note - this needs to be tested over SMB3, not SMB1. + +test_local_symlinks() +{ +# Setup test dirs. + LOCAL_RAWARGS="${CONFIGURATION} -mSMB3" + LOCAL_ADDARGS="${LOCAL_RAWARGS} $*" + + test_dir="$LOCAL_PATH/local_symlinks/test" + + slink_name="$test_dir/sym_name" + slink_target_dir="$test_dir/dir1" + + rm -rf $test_dir + + mkdir -p $test_dir + mkdir $slink_target_dir + ln -s $slink_target_dir $slink_name + +# Can we cd into the symlink name and ls ? + tmpfile=$PREFIX/smbclient_interactive_prompt_commands + cat > $tmpfile < Date: Fri, 23 Jun 2017 15:39:21 +0200 Subject: [PATCH 2/2] s3: smbd: fix regression with non-wide symlinks to directories over SMB2+ The errno returned by open() is ambiguous when called with flags O_NOFOLLOW and O_DIRECTORY on a symlink. With ELOOP, we know for certain that we've tried to open a symlink. With ENOTDIR, we might have hit a symlink, and need to perform further checks to be sure. Adjust non_widelink_open() accordingly. This fixes a regression where symlinks to directories within the same share were no longer followed for some call paths on systems returning ENOTDIR in the above case. Also remove the knownfail added in previous commit. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12860 Signed-off-by: Daniel Kobras Reviewed-by: Jeremy Allison --- selftest/knownfail | 1 - source3/smbd/open.c | 22 +++++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/selftest/knownfail b/selftest/knownfail index 9f9e9761465..c6047c85445 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -335,4 +335,3 @@ # We currently don't send referrals for LDAP modify of non-replicated attrs ^samba4.ldap.rodc.python\(rodc\).__main__.RodcTests.test_modify_nonreplicated.* ^samba4.ldap.rodc_rwdc.python.*.__main__.RodcRwdcTests.test_change_password_reveal_on_demand_kerberos -^samba3.blackbox.smbclient_s3.*follow local symlinks.* diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e68e2ace850..382b16a97c5 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -581,7 +581,18 @@ static int non_widelink_open(struct connection_struct *conn, if (fd == -1) { saved_errno = link_errno_convert(errno); - if (saved_errno == ELOOP) { + /* + * Trying to open a symlink to a directory with O_NOFOLLOW and + * O_DIRECTORY can return either of ELOOP and ENOTDIR. So + * ENOTDIR really means: might be a symlink, but we're not sure. + * In this case, we just assume there's a symlink. If we were + * wrong, process_symlink_open() will return EINVAL. We check + * this below, and fall back to returning the initial + * saved_errno. + * + * BUG: https://bugzilla.samba.org/show_bug.cgi?id=12860 + */ + if (saved_errno == ELOOP || saved_errno == ENOTDIR) { if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) { /* Never follow symlinks on posix open. */ goto out; @@ -602,6 +613,15 @@ static int non_widelink_open(struct connection_struct *conn, mode, link_depth); if (fd == -1) { + if (saved_errno == ENOTDIR && + errno == EINVAL) { + /* + * O_DIRECTORY on neither a directory, + * nor a symlink. Just return + * saved_errno from initial open() + */ + goto out; + } saved_errno = link_errno_convert(errno); } -- 2.11.0