From a8f9b969ce76037582dd70d078578b6d5d5d109f Mon Sep 17 00:00:00 2001 From: Daniel Kobras Date: Fri, 23 Jun 2017 15:39:21 +0200 Subject: [PATCH] s3: smbd: fix regression with non-wide symlinks to directories The errno set 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. BUG: https://bugzilla.samba.org/show_bug.cgi?id=12860 Signed-off-by: Daniel Kobras --- source3/smbd/open.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e68e2ac..89c0a74 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -581,7 +581,15 @@ 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. + */ + 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 +610,15 @@ static int non_widelink_open(struct connection_struct *conn, mode, link_depth); if (fd == -1) { + /* + * O_DIRECTORY on neither a directory, nor a + * symlink. Just return errno from initial + * open() + */ + if (saved_errno == ENOTDIR && + errno == EINVAL) { + goto out; + } saved_errno = link_errno_convert(errno); } -- 2.9.0