summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2015-02-13 13:58:47 +0000
committerRobert Mustacchi <rm@joyent.com>2015-02-13 13:58:47 +0000
commit39fb3e855a4aecad22321e329e58359504b39555 (patch)
treefc78f004574ceb35febc58259402a28df6e94b82 /usr/src/uts/common/fs
parent8062190bde2b194ecd0aa6e2063cf3dddcc5d741 (diff)
parenteb20fbe2fac1596990392cf5a8ea5030948e4768 (diff)
downloadillumos-joyent-dev-overlay.tar.gz
[illumos-joyent merge]dev-overlay
commit 3b13a1ef7511135ec0c75b5f94de8075454efd79 5322 tree connect from Windows 7 fails commit 200c7a6f5f903a9dcd83c319bddeee9b627406ac OS-3820 lxbrand ptrace(2): the next generation OS-3685 lxbrand PTRACE_O_TRACEFORK race condition OS-3834 lxbrand 64-bit strace(1) reports 64-bit process as using x32 ABI OS-3794 lxbrand panic on init signal death commit f1630c2becf4af570cefc47794212e8110eb79e3 OS-3796 lxbrand remove netstat overlay script commit 653f0ca3cc17876745f96a5e25fb60faa72b33f3 OS-3798 lxbrand populate /proc/net/snmp commit d72cf7bfa828bceb8c81f81282e9b81712d032e2 OS-3797 lxbrand populate /proc/net/unix commit d0fcb88af333aa48dd2b958f3681f1b597b924cc 4545 _t_create(): Use after free in error code paths commit c62da27859e36f9fdd8cee3c6df3ad567543dcf9 4539 _t_checkfd() should not call find_tilink() if force_sync is set commit a2ca8683ba75b01f3468a17061812db2731decb6 OS-3826 lxbrand ipv4 networking broken after OS-3800 commit 6529d7987e7f46c8a923ae661b04c896f3815d91 OS-3800 lx_thunk core dumps on centos 6.6 commit f4cf1a6a363de08977c8db91c119df49e9f6c296 5186 The door_call(3c) man page contains too much commit 23c88c5ab36a96068ae184ebd20bf625426c3773 5594 nodename(4): Duplicate paragraph in the man page commit 5c644dd8f2c88f1e78ae4866f22c749a3d1b0157 5585 Typo in gethostname(3c): current processor commit 7825e891f35613dcf9e7e6d6848401511f3f96eb 4717 Missing period (.) in man pages commit 270be59d332e9c2003ef54b622a67d6f0e3ef7fc 5263 Missing space in getrbuf(9f) man page commit faf5add516ff7b15d67af766e32716c04c75716d 5528 devid_str_free() should be used for devid_get_minor_name() too commit 4812581794004eff0af2b765b832403b30bf64ab 4996 rtld _init race leads to incorrect symbol values commit 5ae8d2a82dbf2dc1b22ae6755ecefed000d7532e OS-3822 OS-3780 creates a life of fd crime in libproc commit 1f2ca518aeecee8616fccc0c46a339773faea7d5 4863 illumos-gate can't be built with fresh perl versions commit 386e9c9ebfe4116f62e7a0950acd30564fc60125 5566 elfexec is overzealous with vpages 5572 elfexec and mapelfexec can disagree on aux vectors commit 8a986bad744c8a479dfacfcdc16bcad15bbb1ec6 5101 privileges(5) manual page missing some privileges commit 9ef283481583d677cd2cf5449ef49b90eacc97d4 5261 libm should stop using synonyms.h (fix studio build) commit ed1591688000a5d179c4ba27793cae55590c55d2 5590 improper use of NULL in tools/protocmp commit ad0b1ea5d69a45fe23c434277599e315f29a5fca 5589 improper use of NULL in tools/ctf commit 8bf1e4f3b335466afe9b85d761b3822ec8c1a371 OS-3816 sync up mdb_v8 with upstream commit 97a9db610324e7db4393415018e0e737485a94cd 4393 /etc/rpc: 100133 and 100169 should be added commit dc1de1110df1be3c207fa275c52056314a438b95 OS-3806 /proc/self/fd/2 is no longer working in LX commit ebb8db03bc1050fa9dd3b184c99634f4c2eae56c OS-3810 tar doesn't properly wait for its children OS-3813 Clean up unused variables and parenthesis warnings in tar commit 4190e41f9d08bc0e41bed63c0b3641af9cfa1a1d OS-3811 LTP signal_test_05 now fails commit 86851d81a7ab61819497cbc95630c7fc812d00c9 OS-3808 lx_boot_zone_redhat relies on /tmp being cleared on reboot commit d41c05b714ac5cd589b3edd49c55f21d1d8f2589 OS-3802 LTP kill11 test case fails after vsyscall signal changes OS-3803 LTP kill12 test failing OS-3804 LTP signal03 failing OS-3805 LTP waitpid05 failing commit e3e63864a2ed092a7da41db4ea4998f461524a18 OS-3807 lx brand: asynchronous I/O operations can hang commit 91600d919baafe4e4d8bdee4168878036351c556 5578 file(1) should validate Elf_Shdr->sh_name commit 30e6ec63ea67bd88d75811ab11b9c115ff026ab3 OS-3795 lxbrand initial centos 6.6 support commit 9d47dec0481d8cd53b2c1053c96bfa3f78357d6a 5592 NULL pointer dereference in dsl_prop_notify_all_cb() commit 71ceaec61a50dff6050c6905ac8352dd58c89311 OS-3801 update boot copyright date commit 823c8a3d4ff8d31f222cb81ed5b0685e318215e1 OS-3793 lxbrand /proc/pid/maps formatted incorrectly commit da4b59e7b4853d1b5018cd3e37eb592574a673b4 OS-3768 snoop could fail more cleanly on large files commit 643588d2256f94df9beb942b812ffaa83665c09a OS-3799 lxbrand panic when accessing /proc/net/tcp from GZ commit 9a3dc1f68894cc036075fdabc3764446d5d5fa52 OS-3485 lxbrand populate /proc for netstat commit 12e2b6203a3d75549383615f039c435ab4418037 OS-3790 lxbrand vsyscall segfault when SIGSEGV handler set to SIG_DFL commit d5fef2f4802f515505a545dfee6c81b5fd377a96 OS-3792 platform uses obsolete nfs mount command commit bd181d5a0c2b96669dcb4aa44619e0b7dbbedab9 1100 cpustat usage message is incorrect commit 2515f5d4dbff605ba645d47a6851d8d0bac5b994 5527 ::spa_space fails with mdb: couldn't find member dd_phys of type struct zfs`dsl_dir' commit 6e062f4a9c9a27ea6e2e980c1b5f4c41e33aba45 5563 Some traverse() callers do strange things commit bb633f5b0e92fa59f65274f8b5637a7107ca29ec OS-3782 lx brand: vsyscall can induce fatal SIGSEGV commit 4d01dc17bafd21a83dfb4383d30137cf0ab74ed1 OS-3777 zlogin -I needs to work with docker run when in logging mode commit de267ec7980943d6c76defc73d2a3d8356d3acb2 OS-3776 project rctls should be in sync with zone rctls commit b9acd3d9851f7716ce41f37dcd04dd6067a21146 OS-3780 libproc could know about .gnu_debuglink for remote symbol tables commit 10648e3fb261910e63f8354af96444b02d016f44 OS-3773 lxbrand ltp shmctl ipcinfo can fail on a machine with >4GB of memory OS-3779 lxbrand shmctl_ipcinfo struct incorrect for 64-bit commit 181d66828bce1fbd366a3b3a9224593577390463 OS-3778 lxbrand panic when ptracing native process commit 63098359d8842cf81b6fb1b81567e12c671db06f 5511 stat.h(3head) manpage #define typo commit 7eb15eeb0b1a3f960946b7563765e128425fc13b 5568 'allthreads' needs to be global commit 32b5e9f0cda85eef94eb578dd053e155df43fed3 5554 kmdb can't trace stacks that begin within itself
Diffstat (limited to 'usr/src/uts/common/fs')
-rw-r--r--usr/src/uts/common/fs/lookup.c21
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_srv.c15
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c6
-rw-r--r--usr/src/uts/common/fs/proc/prcontrol.c4
-rw-r--r--usr/src/uts/common/fs/proc/prsubr.c3
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_common_open.c4
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_delete.c2
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_dispatch.c22
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_find.c8
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_fsops.c2
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c3
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c3
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_odir.c31
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_ofile.c108
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_opipe.c4
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_process_exit.c4
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c2
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_server.c103
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_session.c310
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_trans2_find.c6
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_tree.c157
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_tree_connect.c4
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_user.c370
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_dataset.c15
24 files changed, 651 insertions, 556 deletions
diff --git a/usr/src/uts/common/fs/lookup.c b/usr/src/uts/common/fs/lookup.c
index 6819509d00..55ffb94805 100644
--- a/usr/src/uts/common/fs/lookup.c
+++ b/usr/src/uts/common/fs/lookup.c
@@ -20,6 +20,7 @@
*/
/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -217,7 +218,6 @@ lookuppnvp(
cred_t *cr) /* user's credential */
{
vnode_t *cvp; /* current component vp */
- vnode_t *tvp; /* addressable temp ptr */
char component[MAXNAMELEN]; /* buffer for component (incl null) */
int error;
int nlink;
@@ -373,7 +373,7 @@ checkforroot:
/*
* Perform a lookup in the current directory.
*/
- error = VOP_LOOKUP(vp, component, &tvp, pnp, lookup_flags,
+ error = VOP_LOOKUP(vp, component, &cvp, pnp, lookup_flags,
rootvp, cr, NULL, NULL, pp);
/*
@@ -391,10 +391,9 @@ checkforroot:
* directory inside NFS FS.
*/
if ((error == EACCES) && retry_with_kcred)
- error = VOP_LOOKUP(vp, component, &tvp, pnp, lookup_flags,
+ error = VOP_LOOKUP(vp, component, &cvp, pnp, lookup_flags,
rootvp, zone_kcred(), NULL, NULL, pp);
- cvp = tvp;
if (error) {
cvp = NULL;
/*
@@ -440,20 +439,8 @@ checkforroot:
* be atomic!)
*/
if (vn_mountedvfs(cvp) != NULL) {
- tvp = cvp;
- if ((error = traverse(&tvp)) != 0) {
- /*
- * It is required to assign cvp here, because
- * traverse() will return a held vnode which
- * may different than the vnode that was passed
- * in (even in the error case). If traverse()
- * changes the vnode it releases the original,
- * and holds the new one.
- */
- cvp = tvp;
+ if ((error = traverse(&cvp)) != 0)
goto bad;
- }
- cvp = tvp;
}
/*
diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv.c b/usr/src/uts/common/fs/nfs/nfs4_srv.c
index 127d9e3f29..fe1a10b966 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_srv.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv.c
@@ -18,10 +18,11 @@
*
* CDDL HEADER END
*/
+
/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
- * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -869,7 +870,7 @@ static nfsstat4
do_rfs4_op_secinfo(struct compound_state *cs, char *nm, SECINFO4res *resp)
{
int error, different_export = 0;
- vnode_t *dvp, *vp, *tvp;
+ vnode_t *dvp, *vp;
struct exportinfo *exi = NULL;
fid_t fid;
uint_t count, i;
@@ -950,14 +951,12 @@ do_rfs4_op_secinfo(struct compound_state *cs, char *nm, SECINFO4res *resp)
* If it's a mountpoint, then traverse it.
*/
if (vn_ismntpt(vp)) {
- tvp = vp;
- if ((error = traverse(&tvp)) != 0) {
+ if ((error = traverse(&vp)) != 0) {
VN_RELE(vp);
return (puterrno4(error));
}
/* remember that we had to traverse mountpoint */
did_traverse = TRUE;
- vp = tvp;
different_export = 1;
} else if (vp->v_vfsp != dvp->v_vfsp) {
/*
@@ -2610,7 +2609,7 @@ do_rfs4_op_lookup(char *nm, struct svc_req *req, struct compound_state *cs)
{
int error;
int different_export = 0;
- vnode_t *vp, *tvp, *pre_tvp = NULL, *oldvp = NULL;
+ vnode_t *vp, *pre_tvp = NULL, *oldvp = NULL;
struct exportinfo *exi = NULL, *pre_exi = NULL;
nfsstat4 stat;
fid_t fid;
@@ -2708,13 +2707,11 @@ do_rfs4_op_lookup(char *nm, struct svc_req *req, struct compound_state *cs)
* need pre_tvp below if checkexport4 fails
*/
VN_HOLD(pre_tvp);
- tvp = vp;
- if ((error = traverse(&tvp)) != 0) {
+ if ((error = traverse(&vp)) != 0) {
VN_RELE(vp);
VN_RELE(pre_tvp);
return (puterrno4(error));
}
- vp = tvp;
different_export = 1;
} else if (vp->v_vfsp != cs->vp->v_vfsp) {
/*
diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c b/usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c
index 3069a98835..276d3b4f19 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c
@@ -18,6 +18,11 @@
*
* CDDL HEADER END
*/
+
+/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ */
+
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -149,6 +154,7 @@ nfs4_readdir_getvp(vnode_t *dvp, char *d_name, vnode_t **vpp,
VN_HOLD(pre_tvp);
if ((error = traverse(&vp)) != 0) {
+ VN_RELE(vp);
VN_RELE(pre_tvp);
return (error);
}
diff --git a/usr/src/uts/common/fs/proc/prcontrol.c b/usr/src/uts/common/fs/proc/prcontrol.c
index a5679a8afb..7e99d23b97 100644
--- a/usr/src/uts/common/fs/proc/prcontrol.c
+++ b/usr/src/uts/common/fs/proc/prcontrol.c
@@ -25,7 +25,7 @@
*/
/*
- * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2015, Joyent, Inc.
*/
#include <sys/types.h>
@@ -1481,7 +1481,7 @@ pr_setsig(prnode_t *pnp, siginfo_t *sip)
} else if (t->t_state == TS_STOPPED && sig == SIGKILL) {
/* If SIGKILL, set stopped lwp running */
p->p_stopsig = 0;
- t->t_schedflag |= TS_XSTART | TS_PSTART;
+ t->t_schedflag |= TS_XSTART | TS_PSTART | TS_BSTART;
t->t_dtrace_stop = 0;
setrun_locked(t);
}
diff --git a/usr/src/uts/common/fs/proc/prsubr.c b/usr/src/uts/common/fs/proc/prsubr.c
index 7801fd0ac8..284bf8cb88 100644
--- a/usr/src/uts/common/fs/proc/prsubr.c
+++ b/usr/src/uts/common/fs/proc/prsubr.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2015, Joyent, Inc.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -201,6 +201,7 @@ prchoose(proc_t *p)
case PR_SYSEXIT:
case PR_SIGNALLED:
case PR_FAULTED:
+ case PR_BRAND:
/*
* Make an lwp calling exit() be the
* last lwp seen in the process.
diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_open.c b/usr/src/uts/common/fs/smbsrv/smb_common_open.c
index 3fa43d43cb..5eaa5865c6 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_common_open.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_common_open.c
@@ -820,8 +820,8 @@ smb_open_subr(smb_request_t *sr)
status = NT_STATUS_SUCCESS;
- of = smb_ofile_open(sr->tid_tree, node, sr->smb_pid, op, SMB_FTYPE_DISK,
- uniq_fid, &err);
+ of = smb_ofile_open(sr, node, sr->smb_pid, op, SMB_FTYPE_DISK, uniq_fid,
+ &err);
if (of == NULL) {
smbsr_error(sr, err.status, err.errcls, err.errcode);
status = err.status;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_delete.c b/usr/src/uts/common/fs/smbsrv/smb_delete.c
index 4930f741ef..14eff73896 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_delete.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_delete.c
@@ -297,7 +297,7 @@ smb_delete_multiple_files(smb_request_t *sr, smb_error_t *err)
if (odid == 0)
return (-1);
- if ((od = smb_tree_lookup_odir(sr->tid_tree, odid)) == NULL)
+ if ((od = smb_tree_lookup_odir(sr, odid)) == NULL)
return (-1);
for (;;) {
diff --git a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c
index 1afcf18b28..9b1fed6f9a 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c
@@ -20,8 +20,8 @@
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -694,16 +694,13 @@ andx_more:
}
sr->user_cr = smb_user_getcred(sr->uid_user);
-
- if (!(sdd->sdt_flags & SDDF_SUPPRESS_TID) &&
- (sr->tid_tree == NULL)) {
- sr->tid_tree = smb_user_lookup_tree(
- sr->uid_user, sr->smb_tid);
- if (sr->tid_tree == NULL) {
- smbsr_error(sr, 0, ERRSRV, ERRinvnid);
- smbsr_cleanup(sr);
- goto report_error;
- }
+ }
+ if (!(sdd->sdt_flags & SDDF_SUPPRESS_TID) && (sr->tid_tree == NULL)) {
+ sr->tid_tree = smb_session_lookup_tree(session, sr->smb_tid);
+ if (sr->tid_tree == NULL) {
+ smbsr_error(sr, 0, ERRSRV, ERRinvnid);
+ smbsr_cleanup(sr);
+ goto report_error;
}
}
@@ -1116,8 +1113,7 @@ void
smbsr_lookup_file(smb_request_t *sr)
{
if (sr->fid_ofile == NULL)
- sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree,
- sr->smb_fid);
+ sr->fid_ofile = smb_ofile_lookup_by_fid(sr, sr->smb_fid);
}
static int
diff --git a/usr/src/uts/common/fs/smbsrv/smb_find.c b/usr/src/uts/common/fs/smbsrv/smb_find.c
index 1dae4e8cb5..eecbeff4df 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_find.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_find.c
@@ -306,7 +306,7 @@ smb_com_search(smb_request_t *sr)
}
}
- od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ od = smb_tree_lookup_odir(sr, odid);
if (od == NULL) {
smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
ERRDOS, ERROR_INVALID_HANDLE);
@@ -452,7 +452,7 @@ smb_com_find(smb_request_t *sr)
}
}
- od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ od = smb_tree_lookup_odir(sr, odid);
if (od == NULL) {
smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
ERRDOS, ERROR_INVALID_HANDLE);
@@ -575,7 +575,7 @@ smb_com_find_close(smb_request_t *sr)
return (SDRC_ERROR);
}
- od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ od = smb_tree_lookup_odir(sr, odid);
if (od == NULL) {
smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
ERRDOS, ERROR_INVALID_HANDLE);
@@ -649,7 +649,7 @@ smb_com_find_unique(struct smb_request *sr)
odid = smb_odir_open(sr, pn->pn_path, sattr, 0);
if (odid == 0)
return (SDRC_ERROR);
- od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ od = smb_tree_lookup_odir(sr, odid);
if (od == NULL)
return (SDRC_ERROR);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsops.c b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
index 2f4545e966..c64313fdbf 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
@@ -805,7 +805,7 @@ smb_fsop_remove_streams(smb_request_t *sr, cred_t *cr, smb_node_t *fnode)
return (-1);
}
- if ((od = smb_tree_lookup_odir(sr->tid_tree, odid)) == NULL) {
+ if ((od = smb_tree_lookup_odir(sr, odid)) == NULL) {
smbsr_errno(sr, ENOENT);
return (-1);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c b/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c
index c77c175fc1..037c1373b5 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c
@@ -264,8 +264,7 @@ smb_com_nt_create_andx(struct smb_request *sr)
if (op->rootdirfid == 0) {
op->fqi.fq_dnode = sr->tid_tree->t_snode;
} else {
- op->dir = smb_ofile_lookup_by_fid(sr->tid_tree,
- (uint16_t)op->rootdirfid);
+ op->dir = smb_ofile_lookup_by_fid(sr, (uint16_t)op->rootdirfid);
if (op->dir == NULL) {
smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
ERRDOS, ERRbadfid);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c
index fcc12f2fc8..dcfa469617 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c
@@ -173,8 +173,7 @@ smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
if (op->rootdirfid == 0) {
op->fqi.fq_dnode = sr->tid_tree->t_snode;
} else {
- op->dir = smb_ofile_lookup_by_fid(sr->tid_tree,
- (uint16_t)op->rootdirfid);
+ op->dir = smb_ofile_lookup_by_fid(sr, (uint16_t)op->rootdirfid);
if (op->dir == NULL) {
smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
ERRDOS, ERRbadfid);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_odir.c b/usr/src/uts/common/fs/smbsrv/smb_odir.c
index b8435d191a..16fffa6692 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_odir.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_odir.c
@@ -39,15 +39,15 @@
* +-------------------+ +-------------------+ +-------------------+
* | SESSION |<----->| SESSION |......| SESSION |
* +-------------------+ +-------------------+ +-------------------+
- * |
- * |
- * v
- * +-------------------+ +-------------------+ +-------------------+
- * | USER |<----->| USER |......| USER |
- * +-------------------+ +-------------------+ +-------------------+
- * |
- * |
- * v
+ * | |
+ * | |
+ * | v
+ * | +-------------------+ +-------------------+ +-------------------+
+ * | | USER |<--->| USER |...| USER |
+ * | +-------------------+ +-------------------+ +-------------------+
+ * |
+ * |
+ * v
* +-------------------+ +-------------------+ +-------------------+
* | TREE |<----->| TREE |......| TREE |
* +-------------------+ +-------------------+ +-------------------+
@@ -153,7 +153,7 @@
* and add it into the tree's list of odirs.
* Return an identifier (odid) uniquely identifying the created odir.
*
- * smb_odir_t *odir = smb_tree_lookup_odir(odid)
+ * smb_odir_t *odir = smb_tree_lookup_odir(..., odid)
* Find the odir corresponding to the specified odid in the tree's
* list of odirs. Place a hold on the odir.
*
@@ -312,9 +312,9 @@ smb_odir_open(smb_request_t *sr, char *path, uint16_t sattr, uint32_t flags)
}
if (flags & SMB_ODIR_OPENF_BACKUP_INTENT)
- cr = smb_user_getprivcred(tree->t_user);
+ cr = smb_user_getprivcred(sr->uid_user);
else
- cr = tree->t_user->u_cred;
+ cr = sr->uid_user->u_cred;
odid = smb_odir_create(sr, dnode, pattern, sattr, cr);
smb_node_release(dnode);
@@ -888,6 +888,12 @@ smb_odir_create(smb_request_t *sr, smb_node_t *dnode,
od->d_opened_by_pid = sr->smb_pid;
od->d_session = tree->t_session;
od->d_cred = cr;
+ /*
+ * grab a ref for od->d_user
+ * released in smb_odir_delete()
+ */
+ smb_user_hold_internal(sr->uid_user);
+ od->d_user = sr->uid_user;
od->d_tree = tree;
od->d_dnode = dnode;
smb_node_ref(dnode);
@@ -947,6 +953,7 @@ smb_odir_delete(void *arg)
od->d_magic = 0;
smb_node_release(od->d_dnode);
+ smb_user_release(od->d_user);
mutex_destroy(&od->d_mutex);
kmem_cache_free(od->d_tree->t_server->si_cache_odir, od);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_ofile.c b/usr/src/uts/common/fs/smbsrv/smb_ofile.c
index 8987da2950..ee45f13c8b 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_ofile.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_ofile.c
@@ -39,15 +39,15 @@
* +-------------------+ +-------------------+ +-------------------+
* | SESSION |<----->| SESSION |......| SESSION |
* +-------------------+ +-------------------+ +-------------------+
- * |
- * |
- * v
- * +-------------------+ +-------------------+ +-------------------+
- * | USER |<----->| USER |......| USER |
- * +-------------------+ +-------------------+ +-------------------+
- * |
- * |
- * v
+ * | |
+ * | |
+ * | v
+ * | +-------------------+ +-------------------+ +-------------------+
+ * | | USER |<--->| USER |...| USER |
+ * | +-------------------+ +-------------------+ +-------------------+
+ * |
+ * |
+ * v
* +-------------------+ +-------------------+ +-------------------+
* | TREE |<----->| TREE |......| TREE |
* +-------------------+ +-------------------+ +-------------------+
@@ -175,7 +175,7 @@ static void smb_ofile_netinfo_fini(smb_netfileinfo_t *);
*/
smb_ofile_t *
smb_ofile_open(
- smb_tree_t *tree,
+ smb_request_t *sr,
smb_node_t *node,
uint16_t pid,
struct open_param *op,
@@ -183,10 +183,13 @@ smb_ofile_open(
uint32_t uniqid,
smb_error_t *err)
{
+ smb_tree_t *tree = sr->tid_tree;
smb_ofile_t *of;
uint16_t fid;
smb_attr_t attr;
int rc;
+ enum errstates { EMPTY, FIDALLOC, CRHELD, MUTEXINIT };
+ enum errstates state = EMPTY;
if (smb_idpool_alloc(&tree->t_fid_pool, &fid)) {
err->status = NT_STATUS_TOO_MANY_OPENED_FILES;
@@ -194,6 +197,7 @@ smb_ofile_open(
err->errcode = ERROR_TOO_MANY_OPEN_FILES;
return (NULL);
}
+ state = FIDALLOC;
of = kmem_cache_alloc(tree->t_server->si_cache_ofile, KM_SLEEP);
bzero(of, sizeof (smb_ofile_t));
@@ -206,16 +210,23 @@ smb_ofile_open(
of->f_share_access = op->share_access;
of->f_create_options = op->create_options;
of->f_cr = (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT) ?
- smb_user_getprivcred(tree->t_user) : tree->t_user->u_cred;
+ smb_user_getprivcred(sr->uid_user) : sr->uid_user->u_cred;
crhold(of->f_cr);
+ state = CRHELD;
of->f_ftype = ftype;
of->f_server = tree->t_server;
- of->f_session = tree->t_user->u_session;
- of->f_user = tree->t_user;
+ of->f_session = tree->t_session;
+ /*
+ * grab a ref for of->f_user
+ * released in smb_ofile_delete()
+ */
+ smb_user_hold_internal(sr->uid_user);
+ of->f_user = sr->uid_user;
of->f_tree = tree;
of->f_node = node;
mutex_init(&of->f_mutex, NULL, MUTEX_DEFAULT, NULL);
+ state = MUTEXINIT;
of->f_state = SMB_OFILE_STATE_OPEN;
if (ftype == SMB_FTYPE_MESG_PIPE) {
@@ -232,15 +243,10 @@ smb_ofile_open(
attr.sa_mask = SMB_AT_UID | SMB_AT_DOSATTR;
rc = smb_node_getattr(NULL, node, of->f_cr, NULL, &attr);
if (rc != 0) {
- of->f_magic = 0;
- mutex_destroy(&of->f_mutex);
- crfree(of->f_cr);
- smb_idpool_free(&tree->t_fid_pool, of->f_fid);
- kmem_cache_free(tree->t_server->si_cache_ofile, of);
err->status = NT_STATUS_INTERNAL_ERROR;
err->errcls = ERRDOS;
err->errcode = ERROR_INTERNAL_ERROR;
- return (NULL);
+ goto errout;
}
if (crgetuid(of->f_cr) == attr.sa_vattr.va_uid) {
/*
@@ -254,16 +260,10 @@ smb_ofile_open(
of->f_mode =
smb_fsop_amask_to_omode(of->f_granted_access);
if (smb_fsop_open(node, of->f_mode, of->f_cr) != 0) {
- of->f_magic = 0;
- mutex_destroy(&of->f_mutex);
- crfree(of->f_cr);
- smb_idpool_free(&tree->t_fid_pool, of->f_fid);
- kmem_cache_free(tree->t_server->si_cache_ofile,
- of);
err->status = NT_STATUS_ACCESS_DENIED;
err->errcls = ERRDOS;
err->errcode = ERROR_ACCESS_DENIED;
- return (NULL);
+ goto errout;
}
}
@@ -290,6 +290,25 @@ smb_ofile_open(
atomic_inc_32(&tree->t_open_files);
atomic_inc_32(&of->f_session->s_file_cnt);
return (of);
+
+errout:
+ switch (state) {
+ case MUTEXINIT:
+ mutex_destroy(&of->f_mutex);
+ smb_user_release(of->f_user);
+ /*FALLTHROUGH*/
+ case CRHELD:
+ crfree(of->f_cr);
+ of->f_magic = 0;
+ kmem_cache_free(tree->t_server->si_cache_ofile, of);
+ /*FALLTHROUGH*/
+ case FIDALLOC:
+ smb_idpool_free(&tree->t_fid_pool, fid);
+ /*FALLTHROUGH*/
+ case EMPTY:
+ break;
+ }
+ return (NULL);
}
/*
@@ -601,9 +620,10 @@ smb_ofile_request_complete(smb_ofile_t *of)
*/
smb_ofile_t *
smb_ofile_lookup_by_fid(
- smb_tree_t *tree,
+ smb_request_t *sr,
uint16_t fid)
{
+ smb_tree_t *tree = sr->tid_tree;
smb_llist_t *of_list;
smb_ofile_t *of;
@@ -616,19 +636,32 @@ smb_ofile_lookup_by_fid(
while (of) {
ASSERT(of->f_magic == SMB_OFILE_MAGIC);
ASSERT(of->f_tree == tree);
- if (of->f_fid == fid) {
- mutex_enter(&of->f_mutex);
- if (of->f_state != SMB_OFILE_STATE_OPEN) {
- mutex_exit(&of->f_mutex);
- smb_llist_exit(of_list);
- return (NULL);
- }
- of->f_refcnt++;
- mutex_exit(&of->f_mutex);
+ if (of->f_fid == fid)
break;
- }
of = smb_llist_next(of_list, of);
}
+ if (of == NULL)
+ goto out;
+
+ /*
+ * Only allow use of a given FID with the same UID that
+ * was used to open it. MS-CIFS 3.3.5.14
+ */
+ if (of->f_user != sr->uid_user) {
+ of = NULL;
+ goto out;
+ }
+
+ mutex_enter(&of->f_mutex);
+ if (of->f_state != SMB_OFILE_STATE_OPEN) {
+ mutex_exit(&of->f_mutex);
+ of = NULL;
+ goto out;
+ }
+ of->f_refcnt++;
+ mutex_exit(&of->f_mutex);
+
+out:
smb_llist_exit(of_list);
return (of);
}
@@ -921,6 +954,7 @@ smb_ofile_delete(void *arg)
of->f_magic = (uint32_t)~SMB_OFILE_MAGIC;
mutex_destroy(&of->f_mutex);
crfree(of->f_cr);
+ smb_user_release(of->f_user);
kmem_cache_free(of->f_tree->t_server->si_cache_ofile, of);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_opipe.c b/usr/src/uts/common/fs/smbsrv/smb_opipe.c
index bb178f3952..90cb25aaa0 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_opipe.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_opipe.c
@@ -130,8 +130,8 @@ smb_opipe_open(smb_request_t *sr)
op->create_options = 0;
- of = smb_ofile_open(sr->tid_tree, NULL, sr->smb_pid, op,
- SMB_FTYPE_MESG_PIPE, SMB_UNIQ_FID(), &err);
+ of = smb_ofile_open(sr, NULL, sr->smb_pid, op, SMB_FTYPE_MESG_PIPE,
+ SMB_UNIQ_FID(), &err);
if (of == NULL)
return (err.status);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_process_exit.c b/usr/src/uts/common/fs/smbsrv/smb_process_exit.c
index b8c835cd57..2839ca2807 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_process_exit.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_process_exit.c
@@ -85,11 +85,11 @@ smb_com_process_exit(smb_request_t *sr)
* to be the only thing that sends this request these days and
* it doesn't provide a TID.
*/
- sr->tid_tree = smb_user_lookup_tree(sr->uid_user, sr->smb_tid);
+ sr->tid_tree = smb_session_lookup_tree(sr->session, sr->smb_tid);
if (sr->tid_tree != NULL)
smb_tree_close_pid(sr->tid_tree, sr->smb_pid);
else
- smb_user_close_pid(sr->uid_user, sr->smb_pid);
+ smb_session_close_pid(sr->session, sr->smb_pid);
rc = smbsr_encode_empty_result(sr);
return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c b/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c
index bef69e7f61..70ac2e7b24 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c
@@ -662,7 +662,7 @@ smb_encode_stream_info(smb_request_t *sr, smb_xa_t *xa, smb_queryinfo_t *qinfo)
odid = smb_odir_openat(sr, fnode);
if (odid != 0)
- od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ od = smb_tree_lookup_odir(sr, odid);
if (od != NULL)
rc = smb_odir_read_streaminfo(sr, od, sinfo, &eos);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_server.c b/usr/src/uts/common/fs/smbsrv/smb_server.c
index 3654744569..8687d42b18 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_server.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_server.c
@@ -240,7 +240,8 @@ static void smb_event_cancel(smb_server_t *, uint32_t);
static uint32_t smb_event_alloc_txid(void);
static void smb_server_disconnect_share(smb_llist_t *, const char *);
-static void smb_server_enum_private(smb_llist_t *, smb_svcenum_t *);
+static void smb_server_enum_users(smb_llist_t *, smb_svcenum_t *);
+static void smb_server_enum_trees(smb_llist_t *, smb_svcenum_t *);
static int smb_server_session_disconnect(smb_llist_t *, const char *,
const char *);
static int smb_server_fclose(smb_llist_t *, uint32_t);
@@ -833,15 +834,6 @@ smb_server_enum(smb_ioc_svcenum_t *ioc)
smb_server_t *sv;
int rc;
- switch (svcenum->se_type) {
- case SMB_SVCENUM_TYPE_USER:
- case SMB_SVCENUM_TYPE_TREE:
- case SMB_SVCENUM_TYPE_FILE:
- break;
- default:
- return (EINVAL);
- }
-
if ((rc = smb_server_lookup(&sv)) != 0)
return (rc);
@@ -849,11 +841,26 @@ smb_server_enum(smb_ioc_svcenum_t *ioc)
svcenum->se_bused = 0;
svcenum->se_nitems = 0;
- smb_server_enum_private(&sv->sv_nbt_daemon.ld_session_list, svcenum);
- smb_server_enum_private(&sv->sv_tcp_daemon.ld_session_list, svcenum);
+ switch (svcenum->se_type) {
+ case SMB_SVCENUM_TYPE_USER:
+ smb_server_enum_users(&sv->sv_nbt_daemon.ld_session_list,
+ svcenum);
+ smb_server_enum_users(&sv->sv_tcp_daemon.ld_session_list,
+ svcenum);
+ break;
+ case SMB_SVCENUM_TYPE_TREE:
+ case SMB_SVCENUM_TYPE_FILE:
+ smb_server_enum_trees(&sv->sv_nbt_daemon.ld_session_list,
+ svcenum);
+ smb_server_enum_trees(&sv->sv_tcp_daemon.ld_session_list,
+ svcenum);
+ break;
+ default:
+ rc = EINVAL;
+ }
smb_server_release(sv);
- return (0);
+ return (rc);
}
/*
@@ -1694,7 +1701,7 @@ smb_server_release(smb_server_t *sv)
* Enumerate the users associated with a session list.
*/
static void
-smb_server_enum_private(smb_llist_t *ll, smb_svcenum_t *svcenum)
+smb_server_enum_users(smb_llist_t *ll, smb_svcenum_t *svcenum)
{
smb_session_t *sn;
smb_llist_t *ulist;
@@ -1714,6 +1721,8 @@ smb_server_enum_private(smb_llist_t *ll, smb_svcenum_t *svcenum)
if (smb_user_hold(user)) {
rc = smb_user_enum(user, svcenum);
smb_user_release(user);
+ if (rc != 0)
+ break;
}
user = smb_llist_next(ulist, user);
@@ -1731,6 +1740,48 @@ smb_server_enum_private(smb_llist_t *ll, smb_svcenum_t *svcenum)
}
/*
+ * Enumerate the trees/files associated with a session list.
+ */
+static void
+smb_server_enum_trees(smb_llist_t *ll, smb_svcenum_t *svcenum)
+{
+ smb_session_t *sn;
+ smb_llist_t *tlist;
+ smb_tree_t *tree;
+ int rc = 0;
+
+ smb_llist_enter(ll, RW_READER);
+ sn = smb_llist_head(ll);
+
+ while (sn != NULL) {
+ SMB_SESSION_VALID(sn);
+ tlist = &sn->s_tree_list;
+ smb_llist_enter(tlist, RW_READER);
+ tree = smb_llist_head(tlist);
+
+ while (tree != NULL) {
+ if (smb_tree_hold(tree)) {
+ rc = smb_tree_enum(tree, svcenum);
+ smb_tree_release(tree);
+ if (rc != 0)
+ break;
+ }
+
+ tree = smb_llist_next(tlist, tree);
+ }
+
+ smb_llist_exit(tlist);
+
+ if (rc != 0)
+ break;
+
+ sn = smb_llist_next(ll, sn);
+ }
+
+ smb_llist_exit(ll);
+}
+
+/*
* Disconnect sessions associated with the specified client and username.
* Empty strings are treated as wildcards.
*/
@@ -1796,8 +1847,8 @@ static int
smb_server_fclose(smb_llist_t *ll, uint32_t uniqid)
{
smb_session_t *sn;
- smb_llist_t *ulist;
- smb_user_t *user;
+ smb_llist_t *tlist;
+ smb_tree_t *tree;
int rc = ENOENT;
smb_llist_enter(ll, RW_READER);
@@ -1805,20 +1856,20 @@ smb_server_fclose(smb_llist_t *ll, uint32_t uniqid)
while ((sn != NULL) && (rc == ENOENT)) {
SMB_SESSION_VALID(sn);
- ulist = &sn->s_user_list;
- smb_llist_enter(ulist, RW_READER);
- user = smb_llist_head(ulist);
-
- while ((user != NULL) && (rc == ENOENT)) {
- if (smb_user_hold(user)) {
- rc = smb_user_fclose(user, uniqid);
- smb_user_release(user);
+ tlist = &sn->s_tree_list;
+ smb_llist_enter(tlist, RW_READER);
+ tree = smb_llist_head(tlist);
+
+ while ((tree != NULL) && (rc == ENOENT)) {
+ if (smb_tree_hold(tree)) {
+ rc = smb_tree_fclose(tree, uniqid);
+ smb_tree_release(tree);
}
- user = smb_llist_next(ulist, user);
+ tree = smb_llist_next(tlist, tree);
}
- smb_llist_exit(ulist);
+ smb_llist_exit(tlist);
sn = smb_llist_next(ll, sn);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_session.c b/usr/src/uts/common/fs/smbsrv/smb_session.c
index 0fdac10ca6..b8284b372f 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_session.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_session.c
@@ -43,6 +43,7 @@ static int smb_session_message(smb_session_t *);
static int smb_session_xprt_puthdr(smb_session_t *, smb_xprt_t *,
uint8_t *, size_t);
static smb_user_t *smb_session_lookup_user(smb_session_t *, char *, char *);
+static smb_tree_t *smb_session_get_tree(smb_session_t *, smb_tree_t *);
static void smb_session_logoff(smb_session_t *);
static void smb_request_init_command_mbuf(smb_request_t *sr);
void dump_smb_inaddr(smb_inaddr_t *ipaddr);
@@ -624,6 +625,11 @@ smb_session_create(ksocket_t new_so, uint16_t port, smb_server_t *sv,
kmem_cache_free(sv->si_cache_session, session);
return (NULL);
}
+ if (smb_idpool_constructor(&session->s_tid_pool)) {
+ smb_idpool_destructor(&session->s_uid_pool);
+ kmem_cache_free(sv->si_cache_session, session);
+ return (NULL);
+ }
now = ddi_get_lbolt64();
@@ -642,6 +648,9 @@ smb_session_create(ksocket_t new_so, uint16_t port, smb_server_t *sv,
smb_llist_constructor(&session->s_user_list, sizeof (smb_user_t),
offsetof(smb_user_t, u_lnd));
+ smb_llist_constructor(&session->s_tree_list, sizeof (smb_tree_t),
+ offsetof(smb_tree_t, t_lnd));
+
smb_llist_constructor(&session->s_xa_list, sizeof (smb_xa_t),
offsetof(smb_xa_t, xa_lnd));
@@ -719,6 +728,7 @@ smb_session_delete(smb_session_t *session)
list_destroy(&session->s_oplock_brkreqs);
smb_slist_destructor(&session->s_req_list);
+ smb_llist_destructor(&session->s_tree_list);
smb_llist_destructor(&session->s_user_list);
smb_llist_destructor(&session->s_xa_list);
@@ -726,6 +736,7 @@ smb_session_delete(smb_session_t *session)
ASSERT(session->s_file_cnt == 0);
ASSERT(session->s_dir_cnt == 0);
+ smb_idpool_destructor(&session->s_tid_pool);
smb_idpool_destructor(&session->s_uid_pool);
if (session->sock != NULL) {
if (session->s_local_port == IPPORT_NETBIOS_SSN)
@@ -928,45 +939,306 @@ smb_session_post_user(smb_session_t *session, smb_user_t *user)
}
/*
- * Logoff all users associated with the specified session.
+ * Find a tree by tree-id.
*/
-static void
-smb_session_logoff(smb_session_t *session)
+smb_tree_t *
+smb_session_lookup_tree(
+ smb_session_t *session,
+ uint16_t tid)
+
{
- smb_user_t *user;
+ smb_tree_t *tree;
SMB_SESSION_VALID(session);
- smb_llist_enter(&session->s_user_list, RW_READER);
+ smb_llist_enter(&session->s_tree_list, RW_READER);
+ tree = smb_llist_head(&session->s_tree_list);
- user = smb_llist_head(&session->s_user_list);
- while (user) {
- SMB_USER_VALID(user);
- ASSERT(user->u_session == session);
+ while (tree) {
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ ASSERT(tree->t_session == session);
- if (smb_user_hold(user)) {
- smb_user_logoff(user);
- smb_user_release(user);
+ if (tree->t_tid == tid) {
+ if (smb_tree_hold(tree)) {
+ smb_llist_exit(&session->s_tree_list);
+ return (tree);
+ } else {
+ smb_llist_exit(&session->s_tree_list);
+ return (NULL);
+ }
}
- user = smb_llist_next(&session->s_user_list, user);
+ tree = smb_llist_next(&session->s_tree_list, tree);
}
- smb_llist_exit(&session->s_user_list);
+ smb_llist_exit(&session->s_tree_list);
+ return (NULL);
+}
+
+/*
+ * Find the first connected tree that matches the specified sharename.
+ * If the specified tree is NULL the search starts from the beginning of
+ * the user's tree list. If a tree is provided the search starts just
+ * after that tree.
+ */
+smb_tree_t *
+smb_session_lookup_share(
+ smb_session_t *session,
+ const char *sharename,
+ smb_tree_t *tree)
+{
+ SMB_SESSION_VALID(session);
+ ASSERT(sharename);
+
+ smb_llist_enter(&session->s_tree_list, RW_READER);
+
+ if (tree) {
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ ASSERT(tree->t_session == session);
+ tree = smb_llist_next(&session->s_tree_list, tree);
+ } else {
+ tree = smb_llist_head(&session->s_tree_list);
+ }
+
+ while (tree) {
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ ASSERT(tree->t_session == session);
+ if (smb_strcasecmp(tree->t_sharename, sharename, 0) == 0) {
+ if (smb_tree_hold(tree)) {
+ smb_llist_exit(&session->s_tree_list);
+ return (tree);
+ }
+ }
+ tree = smb_llist_next(&session->s_tree_list, tree);
+ }
+
+ smb_llist_exit(&session->s_tree_list);
+ return (NULL);
+}
+
+/*
+ * Find the first connected tree that matches the specified volume name.
+ * If the specified tree is NULL the search starts from the beginning of
+ * the user's tree list. If a tree is provided the search starts just
+ * after that tree.
+ */
+smb_tree_t *
+smb_session_lookup_volume(
+ smb_session_t *session,
+ const char *name,
+ smb_tree_t *tree)
+{
+ SMB_SESSION_VALID(session);
+ ASSERT(name);
+
+ smb_llist_enter(&session->s_tree_list, RW_READER);
+
+ if (tree) {
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ ASSERT(tree->t_session == session);
+ tree = smb_llist_next(&session->s_tree_list, tree);
+ } else {
+ tree = smb_llist_head(&session->s_tree_list);
+ }
+
+ while (tree) {
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ ASSERT(tree->t_session == session);
+
+ if (smb_strcasecmp(tree->t_volume, name, 0) == 0) {
+ if (smb_tree_hold(tree)) {
+ smb_llist_exit(&session->s_tree_list);
+ return (tree);
+ }
+ }
+
+ tree = smb_llist_next(&session->s_tree_list, tree);
+ }
+
+ smb_llist_exit(&session->s_tree_list);
+ return (NULL);
+}
+
+/*
+ * Disconnect all trees that match the specified client process-id.
+ */
+void
+smb_session_close_pid(
+ smb_session_t *session,
+ uint16_t pid)
+{
+ smb_tree_t *tree;
+
+ SMB_SESSION_VALID(session);
+
+ tree = smb_session_get_tree(session, NULL);
+ while (tree) {
+ smb_tree_t *next;
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ ASSERT(tree->t_session == session);
+ smb_tree_close_pid(tree, pid);
+ next = smb_session_get_tree(session, tree);
+ smb_tree_release(tree);
+ tree = next;
+ }
+}
+
+static void
+smb_session_tree_dtor(void *t)
+{
+ smb_tree_t *tree = (smb_tree_t *)t;
+
+ smb_tree_disconnect(tree, B_TRUE);
+ /* release the ref acquired during the traversal loop */
+ smb_tree_release(tree);
}
+
/*
- * Disconnect any trees associated with the specified share.
- * Iterate through the users on this session and tell each user
- * to disconnect from the share.
+ * Disconnect all trees that this user has connected.
*/
void
-smb_session_disconnect_share(smb_session_t *session, const char *sharename)
+smb_session_disconnect_owned_trees(
+ smb_session_t *session,
+ smb_user_t *owner)
+{
+ smb_tree_t *tree;
+ smb_llist_t *tree_list = &session->s_tree_list;
+
+ SMB_SESSION_VALID(session);
+ SMB_USER_VALID(owner);
+
+ smb_llist_enter(tree_list, RW_READER);
+
+ tree = smb_llist_head(tree_list);
+ while (tree) {
+ if ((tree->t_owner == owner) &&
+ smb_tree_hold(tree)) {
+ /*
+ * smb_tree_hold() succeeded, hence we are in state
+ * SMB_TREE_STATE_CONNECTED; schedule this tree
+ * for asynchronous disconnect, which will fire
+ * after we drop the llist traversal lock.
+ */
+ smb_llist_post(tree_list, tree, smb_session_tree_dtor);
+ }
+ tree = smb_llist_next(tree_list, tree);
+ }
+
+ /* drop the lock and flush the dtor queue */
+ smb_llist_exit(tree_list);
+}
+
+/*
+ * Disconnect all trees that this user has connected.
+ */
+void
+smb_session_disconnect_trees(
+ smb_session_t *session)
+{
+ smb_tree_t *tree;
+
+ SMB_SESSION_VALID(session);
+
+ tree = smb_session_get_tree(session, NULL);
+ while (tree) {
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ ASSERT(tree->t_session == session);
+ smb_tree_disconnect(tree, B_TRUE);
+ smb_tree_release(tree);
+ tree = smb_session_get_tree(session, NULL);
+ }
+}
+
+/*
+ * Disconnect all trees that match the specified share name.
+ */
+void
+smb_session_disconnect_share(
+ smb_session_t *session,
+ const char *sharename)
+{
+ smb_tree_t *tree;
+ smb_tree_t *next;
+
+ SMB_SESSION_VALID(session);
+
+ tree = smb_session_lookup_share(session, sharename, NULL);
+ while (tree) {
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ ASSERT(tree->t_session == session);
+ smb_session_cancel_requests(session, tree, NULL);
+ smb_tree_disconnect(tree, B_TRUE);
+ next = smb_session_lookup_share(session, sharename, tree);
+ smb_tree_release(tree);
+ tree = next;
+ }
+}
+
+void
+smb_session_post_tree(smb_session_t *session, smb_tree_t *tree)
+{
+ SMB_SESSION_VALID(session);
+ SMB_TREE_VALID(tree);
+ ASSERT0(tree->t_refcnt);
+ ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED);
+ ASSERT(tree->t_session == session);
+
+ smb_llist_post(&session->s_tree_list, tree, smb_tree_dealloc);
+}
+
+/*
+ * Get the next connected tree in the list. A reference is taken on
+ * the tree, which can be released later with smb_tree_release().
+ *
+ * If the specified tree is NULL the search starts from the beginning of
+ * the tree list. If a tree is provided the search starts just after
+ * that tree.
+ *
+ * Returns NULL if there are no connected trees in the list.
+ */
+static smb_tree_t *
+smb_session_get_tree(
+ smb_session_t *session,
+ smb_tree_t *tree)
+{
+ smb_llist_t *tree_list;
+
+ SMB_SESSION_VALID(session);
+ tree_list = &session->s_tree_list;
+
+ smb_llist_enter(tree_list, RW_READER);
+
+ if (tree) {
+ ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
+ tree = smb_llist_next(tree_list, tree);
+ } else {
+ tree = smb_llist_head(tree_list);
+ }
+
+ while (tree) {
+ if (smb_tree_hold(tree))
+ break;
+
+ tree = smb_llist_next(tree_list, tree);
+ }
+
+ smb_llist_exit(tree_list);
+ return (tree);
+}
+
+/*
+ * Logoff all users associated with the specified session.
+ */
+static void
+smb_session_logoff(smb_session_t *session)
{
smb_user_t *user;
SMB_SESSION_VALID(session);
+ smb_session_disconnect_trees(session);
+
smb_llist_enter(&session->s_user_list, RW_READER);
user = smb_llist_head(&session->s_user_list);
@@ -975,7 +1247,7 @@ smb_session_disconnect_share(smb_session_t *session, const char *sharename)
ASSERT(user->u_session == session);
if (smb_user_hold(user)) {
- smb_user_disconnect_share(user, sharename);
+ smb_user_logoff(user);
smb_user_release(user);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
index 037b2a3b36..d0d60cea5d 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
@@ -332,7 +332,7 @@ smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa)
return (SDRC_ERROR);
}
- od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ od = smb_tree_lookup_odir(sr, odid);
if (od == NULL)
return (SDRC_ERROR);
@@ -463,7 +463,7 @@ smb_com_trans2_find_next2(smb_request_t *sr, smb_xa_t *xa)
if (args.fa_maxdata == 0)
return (SDRC_ERROR);
- od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ od = smb_tree_lookup_odir(sr, odid);
if (od == NULL) {
smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
ERRDOS, ERROR_INVALID_HANDLE);
@@ -943,7 +943,7 @@ smb_com_find_close2(smb_request_t *sr)
if (smbsr_decode_vwv(sr, "w", &odid) != 0)
return (SDRC_ERROR);
- od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ od = smb_tree_lookup_odir(sr, odid);
if (od == NULL) {
smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
ERRDOS, ERROR_INVALID_HANDLE);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree.c b/usr/src/uts/common/fs/smbsrv/smb_tree.c
index 13adc2d803..b225c67623 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_tree.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_tree.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -40,15 +40,15 @@
* +-------------------+ +-------------------+ +-------------------+
* | SESSION |<----->| SESSION |......| SESSION |
* +-------------------+ +-------------------+ +-------------------+
- * |
- * |
- * v
- * +-------------------+ +-------------------+ +-------------------+
- * | USER |<----->| USER |......| USER |
- * +-------------------+ +-------------------+ +-------------------+
- * |
- * |
- * v
+ * | |
+ * | |
+ * | v
+ * | +-------------------+ +-------------------+ +-------------------+
+ * | | USER |<--->| USER |...| USER |
+ * | +-------------------+ +-------------------+ +-------------------+
+ * |
+ * |
+ * v
* +-------------------+ +-------------------+ +-------------------+
* | TREE |<----->| TREE |......| TREE |
* +-------------------+ +-------------------+ +-------------------+
@@ -175,7 +175,7 @@ static smb_tree_t *smb_tree_connect_core(smb_request_t *);
static smb_tree_t *smb_tree_connect_disk(smb_request_t *, const char *);
static smb_tree_t *smb_tree_connect_printq(smb_request_t *, const char *);
static smb_tree_t *smb_tree_connect_ipc(smb_request_t *, const char *);
-static smb_tree_t *smb_tree_alloc(smb_user_t *, const smb_kshare_t *,
+static smb_tree_t *smb_tree_alloc(smb_request_t *, const smb_kshare_t *,
smb_node_t *, uint32_t, uint32_t);
static boolean_t smb_tree_is_connected_locked(smb_tree_t *);
static boolean_t smb_tree_is_disconnected(smb_tree_t *);
@@ -269,6 +269,7 @@ smb_tree_connect_core(smb_request_t *sr)
}
smb_kshare_release(si);
+
return (tree);
}
@@ -361,7 +362,7 @@ smb_tree_release(
smb_llist_flush(&tree->t_odir_list);
if (smb_tree_is_disconnected(tree) && (tree->t_refcnt == 0))
- smb_user_post_tree(tree->t_user, tree);
+ smb_session_post_tree(tree->t_session, tree);
mutex_exit(&tree->t_mutex);
}
@@ -428,7 +429,7 @@ smb_tree_enum(smb_tree_t *tree, smb_svcenum_t *svcenum)
{
smb_ofile_t *of;
smb_ofile_t *next;
- int rc;
+ int rc = 0;
ASSERT(tree);
ASSERT(tree->t_magic == SMB_TREE_MAGIC);
@@ -712,8 +713,7 @@ smb_tree_connect_disk(smb_request_t *sr, const char *sharename)
if (!smb_shortnames)
sr->arg.tcon.optional_support |= SMB_UNIQUE_FILE_NAME;
- tree = smb_tree_alloc(user, si, snode, access,
- sr->sr_cfg->skc_execflags);
+ tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
smb_node_release(snode);
@@ -805,8 +805,7 @@ smb_tree_connect_printq(smb_request_t *sr, const char *sharename)
sr->sr_tcon.optional_support = SMB_SUPPORT_SEARCH_BITS;
- tree = smb_tree_alloc(user, si, snode, access,
- sr->sr_cfg->skc_execflags);
+ tree = smb_tree_alloc(sr, si, snode, access, sr->sr_cfg->skc_execflags);
smb_node_release(snode);
@@ -846,7 +845,7 @@ smb_tree_connect_ipc(smb_request_t *sr, const char *name)
sr->sr_tcon.optional_support = SMB_SUPPORT_SEARCH_BITS;
- tree = smb_tree_alloc(user, si, NULL, ACE_ALL_PERMS, 0);
+ tree = smb_tree_alloc(sr, si, NULL, ACE_ALL_PERMS, 0);
if (tree == NULL) {
smb_tree_log(sr, name, "access denied");
smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRSRV, ERRaccess);
@@ -859,41 +858,45 @@ smb_tree_connect_ipc(smb_request_t *sr, const char *name)
* Allocate a tree.
*/
static smb_tree_t *
-smb_tree_alloc(smb_user_t *user, const smb_kshare_t *si, smb_node_t *snode,
- uint32_t access, uint32_t execflags)
+smb_tree_alloc(smb_request_t *sr, const smb_kshare_t *si,
+ smb_node_t *snode, uint32_t access, uint32_t execflags)
{
+ smb_session_t *session = sr->session;
smb_tree_t *tree;
uint32_t stype = si->shr_type;
uint16_t tid;
- if (smb_idpool_alloc(&user->u_tid_pool, &tid))
+ if (smb_idpool_alloc(&session->s_tid_pool, &tid))
return (NULL);
- tree = kmem_cache_alloc(user->u_server->si_cache_tree, KM_SLEEP);
+ tree = kmem_cache_alloc(session->s_server->si_cache_tree, KM_SLEEP);
bzero(tree, sizeof (smb_tree_t));
- tree->t_user = user;
- tree->t_session = user->u_session;
- tree->t_server = user->u_server;
+ tree->t_session = session;
+ tree->t_server = session->s_server;
+
+ /* grab a ref for tree->t_owner */
+ smb_user_hold_internal(sr->uid_user);
+ tree->t_owner = sr->uid_user;
if (STYPE_ISDSK(stype) || STYPE_ISPRN(stype)) {
if (smb_tree_getattr(si, snode, tree) != 0) {
- smb_idpool_free(&user->u_tid_pool, tid);
- kmem_cache_free(user->u_server->si_cache_tree, tree);
+ smb_idpool_free(&session->s_tid_pool, tid);
+ kmem_cache_free(session->s_server->si_cache_tree, tree);
return (NULL);
}
}
if (smb_idpool_constructor(&tree->t_fid_pool)) {
- smb_idpool_free(&user->u_tid_pool, tid);
- kmem_cache_free(user->u_server->si_cache_tree, tree);
+ smb_idpool_free(&session->s_tid_pool, tid);
+ kmem_cache_free(session->s_server->si_cache_tree, tree);
return (NULL);
}
if (smb_idpool_constructor(&tree->t_odid_pool)) {
smb_idpool_destructor(&tree->t_fid_pool);
- smb_idpool_free(&user->u_tid_pool, tid);
- kmem_cache_free(user->u_server->si_cache_tree, tree);
+ smb_idpool_free(&session->s_tid_pool, tid);
+ kmem_cache_free(session->s_server->si_cache_tree, tree);
return (NULL);
}
@@ -929,11 +932,11 @@ smb_tree_alloc(smb_user_t *user, const smb_kshare_t *si, smb_node_t *snode,
tree->t_acltype = smb_fsop_acltype(snode);
}
- smb_llist_enter(&user->u_tree_list, RW_WRITER);
- smb_llist_insert_head(&user->u_tree_list, tree);
- smb_llist_exit(&user->u_tree_list);
- atomic_inc_32(&user->u_session->s_tree_cnt);
- smb_server_inc_trees(user->u_server);
+ smb_llist_enter(&session->s_tree_list, RW_WRITER);
+ smb_llist_insert_head(&session->s_tree_list, tree);
+ smb_llist_exit(&session->s_tree_list);
+ atomic_inc_32(&session->s_tree_cnt);
+ smb_server_inc_trees(session->s_server);
return (tree);
}
@@ -947,19 +950,19 @@ smb_tree_alloc(smb_user_t *user, const smb_kshare_t *si, smb_node_t *snode,
void
smb_tree_dealloc(void *arg)
{
- smb_user_t *user;
+ smb_session_t *session;
smb_tree_t *tree = (smb_tree_t *)arg;
SMB_TREE_VALID(tree);
ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED);
ASSERT(tree->t_refcnt == 0);
- user = tree->t_user;
- smb_llist_enter(&user->u_tree_list, RW_WRITER);
- smb_llist_remove(&user->u_tree_list, tree);
- smb_idpool_free(&user->u_tid_pool, tree->t_tid);
- atomic_dec_32(&tree->t_session->s_tree_cnt);
- smb_llist_exit(&user->u_tree_list);
+ session = tree->t_session;
+ smb_llist_enter(&session->s_tree_list, RW_WRITER);
+ smb_llist_remove(&session->s_tree_list, tree);
+ smb_idpool_free(&session->s_tid_pool, tree->t_tid);
+ atomic_dec_32(&session->s_tree_cnt);
+ smb_llist_exit(&session->s_tree_list);
mutex_enter(&tree->t_mutex);
mutex_exit(&tree->t_mutex);
@@ -974,6 +977,10 @@ smb_tree_dealloc(void *arg)
smb_llist_destructor(&tree->t_odir_list);
smb_idpool_destructor(&tree->t_fid_pool);
smb_idpool_destructor(&tree->t_odid_pool);
+
+ SMB_USER_VALID(tree->t_owner);
+ smb_user_release(tree->t_owner);
+
kmem_cache_free(tree->t_server->si_cache_tree, tree);
}
@@ -1234,27 +1241,38 @@ smb_tree_log(smb_request_t *sr, const char *sharename, const char *fmt, ...)
* Returns NULL if odir not found or a hold cannot be obtained.
*/
smb_odir_t *
-smb_tree_lookup_odir(smb_tree_t *tree, uint16_t odid)
+smb_tree_lookup_odir(smb_request_t *sr, uint16_t odid)
{
smb_odir_t *od;
smb_llist_t *od_list;
+ smb_tree_t *tree = sr->tid_tree;
- ASSERT(tree);
ASSERT(tree->t_magic == SMB_TREE_MAGIC);
od_list = &tree->t_odir_list;
- smb_llist_enter(od_list, RW_READER);
+ smb_llist_enter(od_list, RW_READER);
od = smb_llist_head(od_list);
while (od) {
- if (od->d_odid == odid) {
- if (!smb_odir_hold(od))
- od = NULL;
+ if (od->d_odid == odid)
break;
- }
od = smb_llist_next(od_list, od);
}
+ if (od == NULL)
+ goto out;
+
+ /*
+ * Only allow use of a given Search ID with the same UID that
+ * was used to create it. MS-CIFS 3.3.5.14
+ */
+ if (od->d_user != sr->uid_user) {
+ od = NULL;
+ goto out;
+ }
+ if (!smb_odir_hold(od))
+ od = NULL;
+out:
smb_llist_exit(od_list);
return (od);
}
@@ -1377,15 +1395,16 @@ smb_tree_close_odirs(smb_tree_t *tree, uint16_t pid)
}
static void
-smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec, int exec_type)
+smb_tree_set_execinfo(smb_tree_t *tree, smb_shr_execinfo_t *exec,
+ int exec_type)
{
exec->e_sharename = tree->t_sharename;
- exec->e_winname = tree->t_user->u_name;
- exec->e_userdom = tree->t_user->u_domain;
+ exec->e_winname = tree->t_owner->u_name;
+ exec->e_userdom = tree->t_owner->u_domain;
exec->e_srv_ipaddr = tree->t_session->local_ipaddr;
exec->e_cli_ipaddr = tree->t_session->ipaddr;
exec->e_cli_netbiosname = tree->t_session->workstation;
- exec->e_uid = crgetuid(tree->t_user->u_cred);
+ exec->e_uid = crgetuid(tree->t_owner->u_cred);
exec->e_type = exec_type;
}
@@ -1438,6 +1457,26 @@ smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen,
return (rc);
}
+static void
+smb_tree_netinfo_username(smb_tree_t *tree, char **namestr, uint32_t *namelen)
+{
+ smb_user_t *user = tree->t_owner;
+
+ /*
+ * u_domain_len and u_name_len include the '\0' in their
+ * lengths, hence the sum of the two lengths gives us room
+ * for both the '\\' and '\0' chars.
+ */
+ ASSERT(namestr);
+ ASSERT(namelen);
+ ASSERT(user->u_domain_len > 0);
+ ASSERT(user->u_name_len > 0);
+ *namelen = user->u_domain_len + user->u_name_len;
+ *namestr = kmem_alloc(*namelen, KM_SLEEP);
+ (void) snprintf(*namestr, *namelen, "%s\\%s", user->u_domain,
+ user->u_name);
+}
+
/*
* Note: ci_numusers should be the number of users connected to
* the share rather than the number of references on the tree but
@@ -1446,8 +1485,6 @@ smb_tree_netinfo_encode(smb_tree_t *tree, uint8_t *buf, size_t buflen,
static void
smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info)
{
- smb_user_t *user;
-
ASSERT(tree);
info->ci_id = tree->t_tid;
@@ -1459,13 +1496,7 @@ smb_tree_netinfo_init(smb_tree_t *tree, smb_netconnectinfo_t *info)
info->ci_sharelen = strlen(tree->t_sharename) + 1;
info->ci_share = smb_mem_strdup(tree->t_sharename);
- user = tree->t_user;
- ASSERT(user);
-
- info->ci_namelen = user->u_domain_len + user->u_name_len + 2;
- info->ci_username = kmem_alloc(info->ci_namelen, KM_SLEEP);
- (void) snprintf(info->ci_username, info->ci_namelen, "%s\\%s",
- user->u_domain, user->u_name);
+ smb_tree_netinfo_username(tree, &info->ci_username, &info->ci_namelen);
}
static void
diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c b/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c
index 1ce9720f5d..19b857e834 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
#include <smbsrv/smb_kproto.h>
@@ -362,8 +363,7 @@ smb_sdrc_t
smb_pre_tree_disconnect(smb_request_t *sr)
{
sr->uid_user = smb_session_lookup_uid(sr->session, sr->smb_uid);
- if (sr->uid_user != NULL)
- sr->tid_tree = smb_user_lookup_tree(sr->uid_user, sr->smb_tid);
+ sr->tid_tree = smb_session_lookup_tree(sr->session, sr->smb_tid);
DTRACE_SMB_1(op__TreeDisconnect__start, smb_request_t *, sr);
return (SDRC_SUCCESS);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_user.c b/usr/src/uts/common/fs/smbsrv/smb_user.c
index cc3fde7f38..09eaba699c 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_user.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_user.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -38,15 +39,15 @@
* +-------------------+ +-------------------+ +-------------------+
* | SESSION |<----->| SESSION |......| SESSION |
* +-------------------+ +-------------------+ +-------------------+
- * |
- * |
- * v
- * +-------------------+ +-------------------+ +-------------------+
- * | USER |<----->| USER |......| USER |
- * +-------------------+ +-------------------+ +-------------------+
- * |
- * |
- * v
+ * | |
+ * | |
+ * | v
+ * | +-------------------+ +-------------------+ +-------------------+
+ * | | USER |<--->| USER |...| USER |
+ * | +-------------------+ +-------------------+ +-------------------+
+ * |
+ * |
+ * v
* +-------------------+ +-------------------+ +-------------------+
* | TREE |<----->| TREE |......| TREE |
* +-------------------+ +-------------------+ +-------------------+
@@ -170,7 +171,6 @@
static boolean_t smb_user_is_logged_in(smb_user_t *);
static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *);
-static smb_tree_t *smb_user_get_tree(smb_llist_t *, smb_tree_t *);
static void smb_user_setcred(smb_user_t *, cred_t *, uint32_t);
static void smb_user_nonauth_logon(uint32_t);
static void smb_user_auth_logoff(uint32_t);
@@ -210,20 +210,15 @@ smb_user_login(
user->u_audit_sid = audit_sid;
if (!smb_idpool_alloc(&session->s_uid_pool, &user->u_uid)) {
- if (!smb_idpool_constructor(&user->u_tid_pool)) {
- smb_llist_constructor(&user->u_tree_list,
- sizeof (smb_tree_t), offsetof(smb_tree_t, t_lnd));
- mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL);
- smb_user_setcred(user, cr, privileges);
- user->u_state = SMB_USER_STATE_LOGGED_IN;
- user->u_magic = SMB_USER_MAGIC;
- smb_llist_enter(&session->s_user_list, RW_WRITER);
- smb_llist_insert_tail(&session->s_user_list, user);
- smb_llist_exit(&session->s_user_list);
- smb_server_inc_users(session->s_server);
- return (user);
- }
- smb_idpool_free(&session->s_uid_pool, user->u_uid);
+ mutex_init(&user->u_mutex, NULL, MUTEX_DEFAULT, NULL);
+ smb_user_setcred(user, cr, privileges);
+ user->u_state = SMB_USER_STATE_LOGGED_IN;
+ user->u_magic = SMB_USER_MAGIC;
+ smb_llist_enter(&session->s_user_list, RW_WRITER);
+ smb_llist_insert_tail(&session->s_user_list, user);
+ smb_llist_exit(&session->s_user_list);
+ smb_server_inc_users(session->s_server);
+ return (user);
}
smb_mem_free(user->u_name);
smb_mem_free(user->u_domain);
@@ -279,10 +274,7 @@ smb_user_logoff(
*/
user->u_state = SMB_USER_STATE_LOGGING_OFF;
mutex_exit(&user->u_mutex);
- /*
- * All the trees hanging off of this user are disconnected.
- */
- smb_user_disconnect_trees(user);
+ smb_session_disconnect_owned_trees(user->u_session, user);
smb_user_auth_logoff(user->u_audit_sid);
mutex_enter(&user->u_mutex);
user->u_state = SMB_USER_STATE_LOGGED_OFF;
@@ -301,13 +293,13 @@ smb_user_logoff(
}
/*
- * Take a reference on a user.
+ * Take a reference on a user. Do not return a reference unless the user is in
+ * the logged-in state.
*/
boolean_t
smb_user_hold(smb_user_t *user)
{
- ASSERT(user);
- ASSERT(user->u_magic == SMB_USER_MAGIC);
+ SMB_USER_VALID(user);
mutex_enter(&user->u_mutex);
@@ -322,6 +314,19 @@ smb_user_hold(smb_user_t *user)
}
/*
+ * Unconditionally take a reference on a user.
+ */
+void
+smb_user_hold_internal(smb_user_t *user)
+{
+ SMB_USER_VALID(user);
+
+ mutex_enter(&user->u_mutex);
+ user->u_refcnt++;
+ mutex_exit(&user->u_mutex);
+}
+
+/*
* Release a reference on a user. If the reference count falls to
* zero and the user has logged off, post the object for deletion.
* Object deletion is deferred to avoid modifying a list while an
@@ -337,9 +342,6 @@ smb_user_release(
ASSERT(user->u_refcnt);
user->u_refcnt--;
- /* flush the tree list's delete queue */
- smb_llist_flush(&user->u_tree_list);
-
switch (user->u_state) {
case SMB_USER_STATE_LOGGED_OFF:
if (user->u_refcnt == 0)
@@ -357,248 +359,6 @@ smb_user_release(
mutex_exit(&user->u_mutex);
}
-void
-smb_user_post_tree(smb_user_t *user, smb_tree_t *tree)
-{
- SMB_USER_VALID(user);
- SMB_TREE_VALID(tree);
- ASSERT(tree->t_refcnt == 0);
- ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED);
- ASSERT(tree->t_user == user);
-
- smb_llist_post(&user->u_tree_list, tree, smb_tree_dealloc);
-}
-
-
-/*
- * Find a tree by tree-id.
- */
-smb_tree_t *
-smb_user_lookup_tree(
- smb_user_t *user,
- uint16_t tid)
-
-{
- smb_tree_t *tree;
-
- ASSERT(user);
- ASSERT(user->u_magic == SMB_USER_MAGIC);
-
- smb_llist_enter(&user->u_tree_list, RW_READER);
- tree = smb_llist_head(&user->u_tree_list);
-
- while (tree) {
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
- ASSERT(tree->t_user == user);
-
- if (tree->t_tid == tid) {
- if (smb_tree_hold(tree)) {
- smb_llist_exit(&user->u_tree_list);
- return (tree);
- } else {
- smb_llist_exit(&user->u_tree_list);
- return (NULL);
- }
- }
-
- tree = smb_llist_next(&user->u_tree_list, tree);
- }
-
- smb_llist_exit(&user->u_tree_list);
- return (NULL);
-}
-
-/*
- * Find the first connected tree that matches the specified sharename.
- * If the specified tree is NULL the search starts from the beginning of
- * the user's tree list. If a tree is provided the search starts just
- * after that tree.
- */
-smb_tree_t *
-smb_user_lookup_share(
- smb_user_t *user,
- const char *sharename,
- smb_tree_t *tree)
-{
- ASSERT(user);
- ASSERT(user->u_magic == SMB_USER_MAGIC);
- ASSERT(sharename);
-
- smb_llist_enter(&user->u_tree_list, RW_READER);
-
- if (tree) {
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
- ASSERT(tree->t_user == user);
- tree = smb_llist_next(&user->u_tree_list, tree);
- } else {
- tree = smb_llist_head(&user->u_tree_list);
- }
-
- while (tree) {
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
- ASSERT(tree->t_user == user);
- if (smb_strcasecmp(tree->t_sharename, sharename, 0) == 0) {
- if (smb_tree_hold(tree)) {
- smb_llist_exit(&user->u_tree_list);
- return (tree);
- }
- }
- tree = smb_llist_next(&user->u_tree_list, tree);
- }
-
- smb_llist_exit(&user->u_tree_list);
- return (NULL);
-}
-
-/*
- * Find the first connected tree that matches the specified volume name.
- * If the specified tree is NULL the search starts from the beginning of
- * the user's tree list. If a tree is provided the search starts just
- * after that tree.
- */
-smb_tree_t *
-smb_user_lookup_volume(
- smb_user_t *user,
- const char *name,
- smb_tree_t *tree)
-{
- ASSERT(user);
- ASSERT(user->u_magic == SMB_USER_MAGIC);
- ASSERT(name);
-
- smb_llist_enter(&user->u_tree_list, RW_READER);
-
- if (tree) {
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
- ASSERT(tree->t_user == user);
- tree = smb_llist_next(&user->u_tree_list, tree);
- } else {
- tree = smb_llist_head(&user->u_tree_list);
- }
-
- while (tree) {
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
- ASSERT(tree->t_user == user);
-
- if (smb_strcasecmp(tree->t_volume, name, 0) == 0) {
- if (smb_tree_hold(tree)) {
- smb_llist_exit(&user->u_tree_list);
- return (tree);
- }
- }
-
- tree = smb_llist_next(&user->u_tree_list, tree);
- }
-
- smb_llist_exit(&user->u_tree_list);
- return (NULL);
-}
-
-/*
- * Disconnect all trees that match the specified client process-id.
- */
-void
-smb_user_close_pid(
- smb_user_t *user,
- uint16_t pid)
-{
- smb_tree_t *tree;
-
- ASSERT(user);
- ASSERT(user->u_magic == SMB_USER_MAGIC);
-
- tree = smb_user_get_tree(&user->u_tree_list, NULL);
- while (tree) {
- smb_tree_t *next;
- ASSERT(tree->t_user == user);
- smb_tree_close_pid(tree, pid);
- next = smb_user_get_tree(&user->u_tree_list, tree);
- smb_tree_release(tree);
- tree = next;
- }
-}
-
-/*
- * Disconnect all trees that this user has connected.
- */
-void
-smb_user_disconnect_trees(
- smb_user_t *user)
-{
- smb_tree_t *tree;
-
- ASSERT(user);
- ASSERT(user->u_magic == SMB_USER_MAGIC);
-
- tree = smb_user_get_tree(&user->u_tree_list, NULL);
- while (tree) {
- ASSERT(tree->t_user == user);
- smb_tree_disconnect(tree, B_TRUE);
- smb_tree_release(tree);
- tree = smb_user_get_tree(&user->u_tree_list, NULL);
- }
-}
-
-/*
- * Disconnect all trees that match the specified share name.
- */
-void
-smb_user_disconnect_share(
- smb_user_t *user,
- const char *sharename)
-{
- smb_tree_t *tree;
- smb_tree_t *next;
-
- ASSERT(user);
- ASSERT(user->u_magic == SMB_USER_MAGIC);
- ASSERT(user->u_refcnt);
-
- tree = smb_user_lookup_share(user, sharename, NULL);
- while (tree) {
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
- smb_session_cancel_requests(user->u_session, tree, NULL);
- smb_tree_disconnect(tree, B_TRUE);
- next = smb_user_lookup_share(user, sharename, tree);
- smb_tree_release(tree);
- tree = next;
- }
-}
-
-/*
- * Close a file by its unique id.
- */
-int
-smb_user_fclose(smb_user_t *user, uint32_t uniqid)
-{
- smb_llist_t *tree_list;
- smb_tree_t *tree;
- int rc = ENOENT;
-
- ASSERT(user);
- ASSERT(user->u_magic == SMB_USER_MAGIC);
-
- tree_list = &user->u_tree_list;
- ASSERT(tree_list);
-
- smb_llist_enter(tree_list, RW_READER);
- tree = smb_llist_head(tree_list);
-
- while ((tree != NULL) && (rc == ENOENT)) {
- ASSERT(tree->t_user == user);
-
- if (smb_tree_hold(tree)) {
- rc = smb_tree_fclose(tree, uniqid);
- smb_tree_release(tree);
- }
-
- tree = smb_llist_next(tree_list, tree);
- }
-
- smb_llist_exit(tree_list);
- return (rc);
-}
-
/*
* Determine whether or not the user is an administrator.
* Members of the administrators group have administrative rights.
@@ -688,9 +448,7 @@ smb_user_namecmp(smb_user_t *user, const char *name)
int
smb_user_enum(smb_user_t *user, smb_svcenum_t *svcenum)
{
- smb_tree_t *tree;
- smb_tree_t *next;
- int rc;
+ int rc = 0;
ASSERT(user);
ASSERT(user->u_magic == SMB_USER_MAGIC);
@@ -698,21 +456,6 @@ smb_user_enum(smb_user_t *user, smb_svcenum_t *svcenum)
if (svcenum->se_type == SMB_SVCENUM_TYPE_USER)
return (smb_user_enum_private(user, svcenum));
- tree = smb_user_get_tree(&user->u_tree_list, NULL);
- while (tree) {
- ASSERT(tree->t_user == user);
-
- rc = smb_tree_enum(tree, svcenum);
- if (rc != 0) {
- smb_tree_release(tree);
- break;
- }
-
- next = smb_user_get_tree(&user->u_tree_list, tree);
- smb_tree_release(tree);
- tree = next;
- }
-
return (rc);
}
@@ -769,8 +512,6 @@ smb_user_delete(void *arg)
user->u_magic = (uint32_t)~SMB_USER_MAGIC;
mutex_destroy(&user->u_mutex);
- smb_llist_destructor(&user->u_tree_list);
- smb_idpool_destructor(&user->u_tid_pool);
if (user->u_cred)
crfree(user->u_cred);
if (user->u_privcred)
@@ -780,43 +521,6 @@ smb_user_delete(void *arg)
kmem_cache_free(user->u_server->si_cache_user, user);
}
-/*
- * Get the next connected tree in the list. A reference is taken on
- * the tree, which can be released later with smb_tree_release().
- *
- * If the specified tree is NULL the search starts from the beginning of
- * the tree list. If a tree is provided the search starts just after
- * that tree.
- *
- * Returns NULL if there are no connected trees in the list.
- */
-static smb_tree_t *
-smb_user_get_tree(
- smb_llist_t *tree_list,
- smb_tree_t *tree)
-{
- ASSERT(tree_list);
-
- smb_llist_enter(tree_list, RW_READER);
-
- if (tree) {
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
- tree = smb_llist_next(tree_list, tree);
- } else {
- tree = smb_llist_head(tree_list);
- }
-
- while (tree) {
- if (smb_tree_hold(tree))
- break;
-
- tree = smb_llist_next(tree_list, tree);
- }
-
- smb_llist_exit(tree_list);
- return (tree);
-}
-
cred_t *
smb_user_getcred(smb_user_t *user)
{
diff --git a/usr/src/uts/common/fs/zfs/dsl_dataset.c b/usr/src/uts/common/fs/zfs/dsl_dataset.c
index ba9c766c65..b4ab4ec3fd 100644
--- a/usr/src/uts/common/fs/zfs/dsl_dataset.c
+++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c
@@ -363,8 +363,19 @@ dsl_dataset_snap_remove(dsl_dataset_t *ds, const char *name, dmu_tx_t *tx,
boolean_t
dsl_dataset_try_add_ref(dsl_pool_t *dp, dsl_dataset_t *ds, void *tag)
{
- return (dmu_buf_try_add_ref(ds->ds_dbuf, dp->dp_meta_objset,
- ds->ds_object, DMU_BONUS_BLKID, tag));
+ dmu_buf_t *dbuf = ds->ds_dbuf;
+ boolean_t result = B_FALSE;
+
+ if (dbuf != NULL && dmu_buf_try_add_ref(dbuf, dp->dp_meta_objset,
+ ds->ds_object, DMU_BONUS_BLKID, tag)) {
+
+ if (ds == dmu_buf_get_user(dbuf))
+ result = B_TRUE;
+ else
+ dmu_buf_rele(dbuf, tag);
+ }
+
+ return (result);
}
int