changeset 13930:f2303e5259ca

604 CIFS server should traverse child mount points Reviewed by: Gordon Ross <gwr@nexenta.com> Reviewed by: Eric Schrock <eric.schrock@delphix.com> Approved by: Garrett D'Amore <garrett@damore.org>
author Aram Hăvărneanu <aram@nexenta.com>
date Tue, 15 Feb 2011 21:27:02 -0500
parents cb100869484a
children 3f18ae9d8c98
files usr/src/cmd/smbsrv/smbd/server.xml usr/src/lib/libshare/smb/libshare_smb.c usr/src/lib/smbsrv/libsmb/common/libsmb.h usr/src/lib/smbsrv/libsmb/common/smb_cfg.c usr/src/lib/smbsrv/libsmb/common/smb_info.c usr/src/lib/smbsrv/libsmb/common/smb_kmod.c usr/src/man/man4/smb.4 usr/src/uts/common/fs/smbsrv/smb_pathname.c usr/src/uts/common/fs/smbsrv/smb_server.c usr/src/uts/common/fs/smbsrv/smb_tree.c usr/src/uts/common/smbsrv/smb_ioctl.h usr/src/uts/common/smbsrv/smb_ktypes.h usr/src/uts/common/smbsrv/smbinfo.h
diffstat 13 files changed, 65 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/smbsrv/smbd/server.xml	Sun Jan 27 03:02:37 2013 +0000
+++ b/usr/src/cmd/smbsrv/smbd/server.xml	Tue Feb 15 21:27:02 2011 -0500
@@ -21,8 +21,8 @@
 
 CDDL HEADER END
 
+Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
 Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
-Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
 
 NOTE:  This service manifest is not editable; its contents will
 be overwritten by package or patch operations, including
@@ -217,6 +217,8 @@
 			value='5.0' override='true'/>
 		<propval name='dfs_stdroot_num' type='integer'
 			value='0' override='true'/>
+		<propval name='traverse_mounts' type='boolean'
+			value='true' override='true'/>
 	</property_group>
 
 	<!-- SMB service-specific shares exec configuration defaults -->
--- a/usr/src/lib/libshare/smb/libshare_smb.c	Sun Jan 27 03:02:37 2013 +0000
+++ b/usr/src/lib/libshare/smb/libshare_smb.c	Tue Feb 15 21:27:02 2011 -0500
@@ -916,6 +916,8 @@
 	    SMB_REFRESH_REFRESH },
 	{ SMB_CI_PRINT_ENABLE, 0, 0, print_enable_validator,
 	    SMB_REFRESH_REFRESH },
+	{ SMB_CI_TRAVERSE_MOUNTS, 0, 0, true_false_validator,
+	    SMB_REFRESH_REFRESH },
 	{ SMB_CI_MAP, 0, MAX_VALUE_BUFLEN, cmd_validator, SMB_REFRESH_REFRESH },
 	{ SMB_CI_UNMAP, 0, MAX_VALUE_BUFLEN, cmd_validator,
 	    SMB_REFRESH_REFRESH },
--- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h	Sun Jan 27 03:02:37 2013 +0000
+++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h	Tue Feb 15 21:27:02 2011 -0500
@@ -150,6 +150,7 @@
 	SMB_CI_UNMAP,
 	SMB_CI_DISPOSITION,
 	SMB_CI_DFS_STDROOT_NUM,
+	SMB_CI_TRAVERSE_MOUNTS,
 	SMB_CI_MAX
 } smb_cfg_id_t;
 
--- a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c	Sun Jan 27 03:02:37 2013 +0000
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c	Tue Feb 15 21:27:02 2011 -0500
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -132,9 +133,8 @@
 	{SMB_CI_MAP, "map", SCF_TYPE_ASTRING, SMB_CF_EXEC},
 	{SMB_CI_UNMAP, "unmap", SCF_TYPE_ASTRING, SMB_CF_EXEC},
 	{SMB_CI_DISPOSITION, "disposition", SCF_TYPE_ASTRING, SMB_CF_EXEC},
-
-	{SMB_CI_DFS_STDROOT_NUM, "dfs_stdroot_num", SCF_TYPE_INTEGER, 0}
-
+	{SMB_CI_DFS_STDROOT_NUM, "dfs_stdroot_num", SCF_TYPE_INTEGER, 0},
+	{SMB_CI_TRAVERSE_MOUNTS, "traverse_mounts", SCF_TYPE_BOOLEAN, 0}
 	/* SMB_CI_MAX */
 };
 
--- a/usr/src/lib/smbsrv/libsmb/common/smb_info.c	Sun Jan 27 03:02:37 2013 +0000
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_info.c	Tue Feb 15 21:27:02 2011 -0500
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #include <assert.h>
@@ -92,6 +93,7 @@
 	kcfg->skc_print_enable = smb_config_getbool(SMB_CI_PRINT_ENABLE);
 	kcfg->skc_oplock_enable = smb_config_getbool(SMB_CI_OPLOCK_ENABLE);
 	kcfg->skc_sync_enable = smb_config_getbool(SMB_CI_SYNC_ENABLE);
+	kcfg->skc_traverse_mounts = smb_config_getbool(SMB_CI_TRAVERSE_MOUNTS);
 	kcfg->skc_secmode = smb_config_get_secmode();
 	(void) smb_getdomainname(kcfg->skc_nbdomain,
 	    sizeof (kcfg->skc_nbdomain));
--- a/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c	Sun Jan 27 03:02:37 2013 +0000
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c	Tue Feb 15 21:27:02 2011 -0500
@@ -86,6 +86,7 @@
 	ioc.secmode = cfg->skc_secmode;
 	ioc.ipv6_enable = cfg->skc_ipv6_enable;
 	ioc.print_enable = cfg->skc_print_enable;
+	ioc.traverse_mounts = cfg->skc_traverse_mounts;
 	ioc.exec_flags = cfg->skc_execflags;
 	ioc.version = cfg->skc_version;
 
--- a/usr/src/man/man4/smb.4	Sun Jan 27 03:02:37 2013 +0000
+++ b/usr/src/man/man4/smb.4	Tue Feb 15 21:27:02 2011 -0500
@@ -1,5 +1,6 @@
 '\" te
 .\" Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved.
+.\" Copyright 2011, Nexenta Systems, Inc. All Rights Reserved.
 .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.
 .\"  See the License for the specific language governing permissions and limitations under the License. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the
 .\" fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
@@ -401,6 +402,20 @@
 .sp
 .ne 2
 .na
+\fB\fBtraverse_mounts\fR\fR
+.ad
+.sp .6
+.RS 4n
+The \fBtraverse_mounts\fR setting determines how the SMB server
+presents sub-mounts underneath an SMB share.  When \fBtraverse_mounts\fR
+is \fBtrue\fR (the default), sub-mounts are presented to SMB clients
+like any other subdirectory.   When \fBtraverse_mounts\fR is \fBfalse\fR,
+sub-mounts are not shown to SMB clients.
+.RE
+
+.sp
+.ne 2
+.na
 \fB\fBunmap\fR\fR
 .ad
 .sp .6
--- a/usr/src/uts/common/fs/smbsrv/smb_pathname.c	Sun Jan 27 03:02:37 2013 +0000
+++ b/usr/src/uts/common/fs/smbsrv/smb_pathname.c	Tue Feb 15 21:27:02 2011 -0500
@@ -129,9 +129,9 @@
  * smb_fsop_lookup(), smb_vop_lookup() and other smb_vop_*() routines in the
  * following areas:
  *
- *	- non-traversal of child mounts		(handled by smb_pathname_reduce)
- *	- unmangling 				(handled in smb_pathname)
- *	- "chroot" behavior of share root 	(handled by lookuppnvp)
+ *	- traversal of child mounts (handled by smb_pathname_reduce)
+ *	- unmangling                (handled in smb_pathname)
+ *	- "chroot" behavior of share root (handled by lookuppnvp)
  *
  * In addition, it needs to replace backslashes with forward slashes.  It also
  * ensures that link processing is done correctly, and that directory
@@ -271,18 +271,26 @@
 	kmem_free(usepath, MAXPATHLEN);
 
 	/*
-	 * Prevent access to anything outside of the share root, except
-	 * when mapping a share because that may require traversal from
-	 * / to a mounted file system.  share_root_node is NULL when
-	 * mapping a share.
+	 * Prevent traversal to another file system if mount point
+	 * traversal is disabled.
 	 *
 	 * Note that we disregard whether the traversal of the path went
 	 * outside of the file system and then came back (say via a link).
+	 * This means that only symlinks that are expressed relatively to
+	 * the share root work.
+	 *
+	 * share_root_node is NULL when mapping a share, so we disregard
+	 * that case.
 	 */
 
 	if ((err == 0) && share_root_node) {
-		if (share_root_node->vp->v_vfsp != (*dir_node)->vp->v_vfsp)
+		if (share_root_node->vp->v_vfsp != (*dir_node)->vp->v_vfsp) {
 			err = EACCES;
+			if ((sr) && (sr)->tid_tree &&
+			    smb_tree_has_feature((sr)->tid_tree,
+			    SMB_TREE_TRAVERSE_MOUNTS))
+				err = 0;
+		}
 	}
 
 	if (err) {
--- a/usr/src/uts/common/fs/smbsrv/smb_server.c	Sun Jan 27 03:02:37 2013 +0000
+++ b/usr/src/uts/common/fs/smbsrv/smb_server.c	Tue Feb 15 21:27:02 2011 -0500
@@ -1844,6 +1844,7 @@
 	sv->sv_cfg.skc_secmode = ioc->secmode;
 	sv->sv_cfg.skc_ipv6_enable = ioc->ipv6_enable;
 	sv->sv_cfg.skc_print_enable = ioc->print_enable;
+	sv->sv_cfg.skc_traverse_mounts = ioc->traverse_mounts;
 	sv->sv_cfg.skc_execflags = ioc->exec_flags;
 	sv->sv_cfg.skc_version = ioc->version;
 	(void) strlcpy(sv->sv_cfg.skc_nbdomain, ioc->nbdomain,
--- a/usr/src/uts/common/fs/smbsrv/smb_tree.c	Sun Jan 27 03:02:37 2013 +0000
+++ b/usr/src/uts/common/fs/smbsrv/smb_tree.c	Tue Feb 15 21:27:02 2011 -0500
@@ -20,8 +20,8 @@
  */
 
 /*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -1107,6 +1107,8 @@
 static void
 smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree)
 {
+	smb_session_t *ssn = tree->t_session;
+
 	typedef struct smb_mtype {
 		char		*mt_name;
 		size_t		mt_namelen;
@@ -1134,11 +1136,15 @@
 	if (si->shr_flags & SMB_SHRF_ABE)
 		flags |= SMB_TREE_ABE;
 
-	if (smb_session_oplocks_enable(tree->t_session)) {
+	if (ssn->s_cfg.skc_oplock_enable) {
 		/* if 'smb' zfs property: oplocks=enabled */
 		flags |= SMB_TREE_OPLOCKS;
 	}
 
+	/* Global config option for now.  Later make per-share. */
+	if (ssn->s_cfg.skc_traverse_mounts)
+		flags |= SMB_TREE_TRAVERSE_MOUNTS;
+
 	/* if 'smb' zfs property: shortnames=enabled */
 	if (smb_shortnames)
 		flags |= SMB_TREE_SHORTNAMES;
--- a/usr/src/uts/common/smbsrv/smb_ioctl.h	Sun Jan 27 03:02:37 2013 +0000
+++ b/usr/src/uts/common/smbsrv/smb_ioctl.h	Tue Feb 15 21:27:02 2011 -0500
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef _SMB_IOCTL_H_
@@ -158,6 +159,7 @@
 	int32_t		secmode;
 	int32_t		ipv6_enable;
 	int32_t		print_enable;
+	int32_t		traverse_mounts;
 	uint32_t	exec_flags;
 	smb_version_t	version;
 	char		nbdomain[NETBIOS_NAME_SZ];
--- a/usr/src/uts/common/smbsrv/smb_ktypes.h	Sun Jan 27 03:02:37 2013 +0000
+++ b/usr/src/uts/common/smbsrv/smb_ktypes.h	Tue Feb 15 21:27:02 2011 -0500
@@ -1029,6 +1029,7 @@
 #define	SMB_TREE_QUOTA			0x00010000
 #define	SMB_TREE_DFSROOT		0x00020000
 #define	SMB_TREE_SPARSE			0x00040000
+#define	SMB_TREE_TRAVERSE_MOUNTS	0x00080000
 
 typedef enum {
 	SMB_TREE_STATE_CONNECTED = 0,
@@ -1103,12 +1104,16 @@
 	smb_tree_has_feature((sr)->tid_tree, SMB_TREE_SHORTNAMES) : 0)
 
 /*
- * SMB_TREE_CONTAINS_NODE is used to check that a node is in the same
- * file system as the tree.
+ * SMB_TREE_CONTAINS_NODE is used to check if a node is on the same
+ * file system as the tree's root filesystem, or if mount point traversal
+ * should be allowed.  Note that this is also called in some cases with
+ * sr=NULL, where it is expected to evaluate to TRUE.
  */
+
 #define	SMB_TREE_CONTAINS_NODE(sr, node)                                \
-	(((sr) && (sr)->tid_tree) ?                                     \
-	(SMB_TREE_VFS((sr)->tid_tree) == SMB_NODE_VFS(node)) : 1)
+	((sr) == NULL || (sr)->tid_tree == NULL ||                      \
+	SMB_TREE_VFS((sr)->tid_tree) == SMB_NODE_VFS(node) ||           \
+	smb_tree_has_feature((sr)->tid_tree, SMB_TREE_TRAVERSE_MOUNTS))
 
 /*
  * SMB_OFILE_IS_READONLY reflects whether an ofile is readonly or not.
--- a/usr/src/uts/common/smbsrv/smbinfo.h	Sun Jan 27 03:02:37 2013 +0000
+++ b/usr/src/uts/common/smbsrv/smbinfo.h	Tue Feb 15 21:27:02 2011 -0500
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #ifndef	_SMBSRV_SMBINFO_H
@@ -126,6 +127,7 @@
 	int32_t skc_secmode;
 	int32_t skc_ipv6_enable;
 	int32_t skc_print_enable;
+	int32_t skc_traverse_mounts;
 	uint32_t skc_execflags;
 	smb_version_t skc_version;
 	char skc_nbdomain[NETBIOS_NAME_SZ];