summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/fs.d/mount.c27
-rw-r--r--usr/src/cmd/fs.d/smbclnt/mount/Makefile6
-rw-r--r--usr/src/cmd/fs.d/smbclnt/mount/mount.c25
-rw-r--r--usr/src/cmd/fs.d/smbclnt/umount/Makefile9
-rw-r--r--usr/src/cmd/fs.d/smbclnt/umount/umount.c27
-rw-r--r--usr/src/cmd/fs.d/umount.c28
-rw-r--r--usr/src/lib/libsecdb/exec_attr.txt2
-rw-r--r--usr/src/lib/libsmbfs/smb/ctx.c10
-rw-r--r--usr/src/lib/libsmbfs/smb/nb.c18
-rw-r--r--usr/src/pkg/manifests/system-file-system-smb.mf4
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs.h3
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_client.c6
-rw-r--r--usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c129
13 files changed, 168 insertions, 126 deletions
diff --git a/usr/src/cmd/fs.d/mount.c b/usr/src/cmd/fs.d/mount.c
index e3ab3f3f3a..23c070f880 100644
--- a/usr/src/cmd/fs.d/mount.c
+++ b/usr/src/cmd/fs.d/mount.c
@@ -23,7 +23,7 @@
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -810,13 +810,6 @@ doexec(char *fstype, char *newargv[])
char *vfs_path = VFS_PATH;
char *alt_path = ALT_PATH;
int i;
- int smbfs;
-
- /*
- * Special case smbfs file system.
- * Execute command in profile if possible.
- */
- smbfs = strcmp(fstype, "smbfs") == 0;
/* build the full pathname of the fstype dependent command. */
sprintf(full_path, "%s/%s/%s", vfs_path, fstype, myname);
@@ -839,18 +832,6 @@ doexec(char *fstype, char *newargv[])
* '..mount: not found' message when '/usr' is mounted
*/
if (access(full_path, 0) == 0) {
- if (smbfs) {
- /*
- * Run mount_smbfs(1m) with pfexec so that we can
- * add sys_mount privilege, (via exec_attr, etc.)
- * allowing normal users to mount on any directory
- * they own.
- */
- newargv[0] = "pfexec";
- newargv[1] = full_path;
- execv("/usr/bin/pfexec", &newargv[0]);
- newargv[1] = myname;
- }
execv(full_path, &newargv[1]);
if (errno == EACCES) {
fprintf(stderr,
@@ -863,12 +844,6 @@ doexec(char *fstype, char *newargv[])
execv("/sbin/sh", &newargv[0]);
}
}
- if (smbfs) {
- newargv[0] = "pfexec";
- newargv[1] = alter_path;
- execv("/usr/bin/pfexec", &newargv[0]);
- newargv[1] = myname;
- }
execv(alter_path, &newargv[1]);
if (errno == EACCES) {
fprintf(stderr, gettext(
diff --git a/usr/src/cmd/fs.d/smbclnt/mount/Makefile b/usr/src/cmd/fs.d/smbclnt/mount/Makefile
index 5d5da5ec5c..a21e37dd93 100644
--- a/usr/src/cmd/fs.d/smbclnt/mount/Makefile
+++ b/usr/src/cmd/fs.d/smbclnt/mount/Makefile
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -34,10 +34,12 @@ ROOTFS_PROG= $(LIBPROG)
include ../../Makefile.fstype
OBJS= $(LIBPROG).o
-SRCS= $(LIBPROG).c $(FSLIBSRC)
+SRCS= $(LIBPROG).c
POFILE= $(LIBPROG).po
CLOBBERFILES += $(LIBPROG)
+$(ROOTLIBFSTYPE)/mount := FILEMODE= 04555
+
CFLAGS += $(CCVERBOSE)
C99MODE= $(C99_ENABLE)
diff --git a/usr/src/cmd/fs.d/smbclnt/mount/mount.c b/usr/src/cmd/fs.d/smbclnt/mount/mount.c
index 03ade9f329..1e2422d4e4 100644
--- a/usr/src/cmd/fs.d/smbclnt/mount/mount.c
+++ b/usr/src/cmd/fs.d/smbclnt/mount/mount.c
@@ -50,6 +50,7 @@
#include <libintl.h>
#include <locale.h>
#include <libscf.h>
+#include <priv_utils.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -175,6 +176,21 @@ main(int argc, char *argv[])
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
+
+ /*
+ * Normal users are allowed to run "mount -F smbfs ..."
+ * to mount on a directory they own. To allow that, this
+ * program is installed setuid root, and it adds SYS_MOUNT
+ * privilege here (if needed), and then restores the user's
+ * normal privileges. When root runs this, it's a no-op.
+ */
+ if (__init_suid_priv(0, PRIV_SYS_MOUNT, (char *)NULL) < 0) {
+ (void) fprintf(stderr,
+ gettext("Insufficient privileges, "
+ "%s must be set-uid root\n"), argv[0]);
+ exit(RET_ERR);
+ }
+
if (argc == 2) {
if (strcmp(argv[1], "-h") == 0) {
usage();
@@ -363,9 +379,14 @@ again:
*/
mdata.devfd = ctx->ct_dev_fd;
- if (mount(mnt.mnt_special, mnt.mnt_mountp,
+ /* Need sys_mount privilege for the mount call. */
+ (void) __priv_bracket(PRIV_ON);
+ err2 = mount(mnt.mnt_special, mnt.mnt_mountp,
mntflags, fstype, &mdata, sizeof (mdata),
- mnt.mnt_mntopts, MAX_MNTOPT_STR) < 0) {
+ mnt.mnt_mntopts, MAX_MNTOPT_STR);
+ (void) __priv_bracket(PRIV_OFF);
+
+ if (err2 < 0) {
if (errno != ENOENT) {
err(EX_MNT, gettext("mount_smbfs: %s"),
mnt.mnt_mountp);
diff --git a/usr/src/cmd/fs.d/smbclnt/umount/Makefile b/usr/src/cmd/fs.d/smbclnt/umount/Makefile
index 2cae8a40eb..d85891b6db 100644
--- a/usr/src/cmd/fs.d/smbclnt/umount/Makefile
+++ b/usr/src/cmd/fs.d/smbclnt/umount/Makefile
@@ -19,10 +19,10 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
+
#
# cmd/fs.d/smbclnt/umount/Makefile
#
@@ -37,12 +37,13 @@ COMMON= $(FSLIB)
OBJS= $(LIBPROG).o $(COMMON)
SRCS= $(LIBPROG).c $(FSLIBSRC)
POFILE= $(LIBPROG).po
+CLOBBERFILES += $(LIBPROG)
+
+$(ROOTLIBFSTYPE)/umount := FILEMODE= 04555
CPPFLAGS += -I../.. -I../lib
CFLAGS += $(CCVERBOSE)
-CLOBBERFILES += $(LIBPROG)
-
.KEEP_STATE:
all: $(ROOTFS_PROG)
diff --git a/usr/src/cmd/fs.d/smbclnt/umount/umount.c b/usr/src/cmd/fs.d/smbclnt/umount/umount.c
index 3540392bac..5bf6984e78 100644
--- a/usr/src/cmd/fs.d/smbclnt/umount/umount.c
+++ b/usr/src/cmd/fs.d/smbclnt/umount/umount.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* smbfs umount
*/
@@ -43,7 +41,7 @@
#include <errno.h>
#include <locale.h>
#include <fslib.h>
-#include <priv.h>
+#include <priv_utils.h>
#define RET_OK 0
#define RET_ERR 32
@@ -70,6 +68,19 @@ main(int argc, char *argv[])
#endif
(void) textdomain(TEXT_DOMAIN);
+ /*
+ * Normal users are allowed to umount smbfs mounts they own.
+ * To allow that, this program is installed setuid root, and
+ * it adds SYS_MOUNT privilege here (if needed), and then
+ * restores the user's normal privileges.
+ */
+ if (__init_suid_priv(0, PRIV_SYS_MOUNT, (char *)NULL) < 0) {
+ (void) fprintf(stderr,
+ gettext("Insufficient privileges, "
+ "%s must be set-uid root\n"), argv[0]);
+ exit(RET_ERR);
+ }
+
myname = strrchr(argv[0], '/');
myname = myname ? myname+1 : argv[0];
(void) sprintf(typename, "smbfs %s", myname);
@@ -120,13 +131,19 @@ static int
smbfs_unmount(char *pathname, int umnt_flag)
{
struct extmnttab *mntp;
+ int rc;
mntp = mnttab_find(pathname);
if (mntp) {
pathname = mntp->mnt_mountp;
}
- if (umount2(pathname, umnt_flag) < 0) {
+ /* Need sys_mount privilege for the umount call. */
+ (void) __priv_bracket(PRIV_ON);
+ rc = umount2(pathname, umnt_flag);
+ (void) __priv_bracket(PRIV_OFF);
+
+ if (rc < 0) {
pr_err(gettext("%s: %s\n"), pathname, strerror(errno));
return (RET_ERR);
}
diff --git a/usr/src/cmd/fs.d/umount.c b/usr/src/cmd/fs.d/umount.c
index 44db8e3a79..da08a82432 100644
--- a/usr/src/cmd/fs.d/umount.c
+++ b/usr/src/cmd/fs.d/umount.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -27,8 +27,6 @@
/* All Rights Reserved */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdio.h>
#include <stdio_ext.h>
#include <limits.h>
@@ -355,7 +353,6 @@ doexec(struct mnttab *ment)
char alter_path[FULLPATH_MAX];
char *newargv[ARGV_MAX];
int ii;
- int smbfs;
if (strlen(ment->mnt_fstype) > (size_t)FSTYPE_MAX) {
fprintf(stderr, gettext(
@@ -364,12 +361,6 @@ doexec(struct mnttab *ment)
exit(1);
}
- /*
- * Special case smbfs file system.
- * Execute command in profile if possible.
- */
- smbfs = strcmp(ment->mnt_fstype, "smbfs") == 0;
-
/* build the full pathname of the fstype dependent command. */
sprintf(full_path, "%s/%s/%s", fs_path, ment->mnt_fstype,
myname);
@@ -408,29 +399,12 @@ doexec(struct mnttab *ment)
}
/* Try to exec the fstype dependent umount. */
- if (smbfs) {
- /*
- * Run umount_smbfs(1m) with pfexec so that we can
- * add sys_mount privilege, (via exec_attr, etc.)
- * allowing normal users to unmount any directory
- * they own.
- */
- newargv[0] = "pfexec";
- newargv[1] = full_path;
- execv("/usr/bin/pfexec", &newargv[0]);
- newargv[1] = myname;
- }
execv(full_path, &newargv[1]);
if (errno == ENOEXEC) {
newargv[0] = "sh";
newargv[1] = full_path;
execv("/sbin/sh", &newargv[0]);
}
- if (smbfs) {
- newargv[0] = "pfexec";
- newargv[1] = alter_path;
- execv("/usr/bin/pfexec", &newargv[0]);
- }
newargv[1] = myname;
execv(alter_path, &newargv[1]);
if (errno == ENOEXEC) {
diff --git a/usr/src/lib/libsecdb/exec_attr.txt b/usr/src/lib/libsecdb/exec_attr.txt
index b7cfde648e..c469518383 100644
--- a/usr/src/lib/libsecdb/exec_attr.txt
+++ b/usr/src/lib/libsecdb/exec_attr.txt
@@ -36,8 +36,6 @@ Audit Control:suser:cmd:::/usr/sbin/auditd:uid=0
Audit Review:suser:cmd:::/usr/sbin/auditreduce:euid=0
Audit Review:suser:cmd:::/usr/sbin/auditstat:euid=0
Audit Review:suser:cmd:::/usr/sbin/praudit:euid=0
-Basic Solaris User:solaris:cmd:::/usr/lib/fs/smbfs/mount:privs=sys_mount
-Basic Solaris User:solaris:cmd:::/usr/lib/fs/smbfs/umount:privs=sys_mount
Contract Observer:solaris:cmd:::/usr/bin/ctwatch:\
privs=contract_event,contract_observer
Cron Management:suser:cmd:::/usr/bin/crontab:euid=0
diff --git a/usr/src/lib/libsmbfs/smb/ctx.c b/usr/src/lib/libsmbfs/smb/ctx.c
index 40a62a3853..d29ec7bf0b 100644
--- a/usr/src/lib/libsmbfs/smb/ctx.c
+++ b/usr/src/lib/libsmbfs/smb/ctx.c
@@ -33,7 +33,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1253,6 +1253,14 @@ smb_ctx_get_tree(struct smb_ctx *ctx)
strlcpy(tcon->tc_sh.sh_name, ctx->ct_origshare,
sizeof (tcon->tc_sh.sh_name));
+ /*
+ * Share password (unused - no share-level security)
+ * MS-SMB 2.2.6 says this should be null terminated,
+ * and the length includes the null. Did bzero above,
+ * so just set length for the null.
+ */
+ tcon->tc_sh.sh_pwlen = 1;
+
/* The share "use" type. */
stype = smb_use_type_str(ctx->ct_shtype_req);
strlcpy(tcon->tc_sh.sh_type_req, stype,
diff --git a/usr/src/lib/libsmbfs/smb/nb.c b/usr/src/lib/libsmbfs/smb/nb.c
index 4957b88d2c..6a8eb8c2e4 100644
--- a/usr/src/lib/libsmbfs/smb/nb.c
+++ b/usr/src/lib/libsmbfs/smb/nb.c
@@ -33,7 +33,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -114,7 +114,6 @@ nb_ctx_create(struct nb_ctx **ctxpp)
if (ctx == NULL)
return (ENOMEM);
bzero(ctx, sizeof (struct nb_ctx));
- ctx->nb_flags = NBCF_NS_ENABLE | NBCF_BC_ENABLE;
*ctxpp = ctx;
return (0);
}
@@ -135,9 +134,9 @@ nb_ctx_setnbflags(struct nb_ctx *nb, int ns_ena, int bc_ena)
{
nb->nb_flags &= ~(NBCF_NS_ENABLE | NBCF_BC_ENABLE);
if (ns_ena) {
- nb->nb_flags = NBCF_NS_ENABLE;
+ nb->nb_flags |= NBCF_NS_ENABLE;
if (bc_ena)
- nb->nb_flags = NBCF_BC_ENABLE;
+ nb->nb_flags |= NBCF_BC_ENABLE;
}
}
@@ -284,16 +283,11 @@ nb_ctx_readrcsection(struct rcfile *rcfile, struct nb_ctx *ctx,
* have to get both boolean values first,
* either from settings or defaults.
*/
- nbns_enable = nbns_broadcast = -1; /* not set */
+ nbns_enable = nbns_broadcast = 1; /* defaults */
rc_getbool(rcfile, sname, "nbns_enable", &nbns_enable);
rc_getbool(rcfile, sname, "nbns_broadcast", &nbns_broadcast);
- if (nbns_enable >= 0 || nbns_broadcast >= 0) {
- if (nbns_enable < 0)
- nbns_enable = 1; /* default */
- if (nbns_broadcast < 0)
- nbns_broadcast = 1; /* default */
- nb_ctx_setnbflags(ctx, nbns_enable, nbns_broadcast);
- }
+ nb_ctx_setnbflags(ctx, nbns_enable, nbns_broadcast);
+
return (0);
}
diff --git a/usr/src/pkg/manifests/system-file-system-smb.mf b/usr/src/pkg/manifests/system-file-system-smb.mf
index cc6be650f8..852d5f7223 100644
--- a/usr/src/pkg/manifests/system-file-system-smb.mf
+++ b/usr/src/pkg/manifests/system-file-system-smb.mf
@@ -72,8 +72,8 @@ $(i386_ONLY)file path=usr/kernel/kmdb/smbfs group=sys mode=0555
file path=usr/lib/$(ARCH64)/libsmbfs.so.1
file path=usr/lib/fs/smbfs/$(ARCH64)/libshare_smbfs.so.1
file path=usr/lib/fs/smbfs/libshare_smbfs.so.1
-file path=usr/lib/fs/smbfs/mount mode=0555
-file path=usr/lib/fs/smbfs/umount mode=0555
+file path=usr/lib/fs/smbfs/mount mode=4555
+file path=usr/lib/fs/smbfs/umount mode=4555
file path=usr/lib/libsmbfs.so.1
file path=usr/lib/mdb/kvm/$(ARCH64)/nsmb.so mode=0555
file path=usr/lib/mdb/kvm/$(ARCH64)/smbfs.so mode=0555
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs.h b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs.h
index 68c626094a..6565be5ef3 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs.h
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs.h
@@ -33,7 +33,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -54,6 +54,7 @@
#include <sys/list.h>
#include <sys/t_lock.h>
#include <sys/vfs.h>
+#include <sys/vfs_opreg.h>
#include <sys/fs/smbfs_mount.h>
/*
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_client.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_client.c
index 3cda4b6ec1..8d4c617b52 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_client.c
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_client.c
@@ -222,14 +222,14 @@ smbfs_attrcache_fa(vnode_t *vp, struct smbfattr *fap)
/*
* We allow v_type to change, so set that here
- * (and the mode, which is derived from it).
+ * (and the mode, which depends on the type).
*/
if (fap->fa_attr & SMB_FA_DIR) {
vtype = VDIR;
- mode = S_IFDIR | smi->smi_dmode;
+ mode = smi->smi_dmode;
} else {
vtype = VREG;
- mode = S_IFREG | smi->smi_fmode;
+ mode = smi->smi_fmode;
}
mutex_enter(&np->r_statelock);
diff --git a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c
index 64946a3326..30926e61b0 100644
--- a/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c
+++ b/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c
@@ -114,6 +114,8 @@ static int smbfssetattr(vnode_t *, struct vattr *, int, cred_t *);
static int smbfs_accessx(void *, int, cred_t *);
static int smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
caller_context_t *);
+static void smbfs_rele_fid(smbnode_t *, struct smb_cred *);
+
/*
* These are the vnode ops routines which implement the vnode interface to
* the networked file system. These routines just take their parameters,
@@ -418,14 +420,10 @@ smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
{
smbnode_t *np;
smbmntinfo_t *smi;
- smb_share_t *ssp;
- cred_t *oldcr;
- int error = 0;
struct smb_cred scred;
np = VTOSMB(vp);
smi = VTOSMI(vp);
- ssp = smi->smi_share;
/*
* Don't "bail out" for VFS_UNMOUNTED here,
@@ -437,7 +435,7 @@ smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
* open; if we happen to get here from the wrong zone we can't do
* anything over the wire.
*/
- if (VTOSMI(vp)->smi_zone != curproc->p_zone) {
+ if (smi->smi_zone != curproc->p_zone) {
/*
* We could attempt to clean up locks, except we're sure
* that the current process didn't acquire any locks on
@@ -465,7 +463,7 @@ smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
* process on this file are released no matter what the
* incoming reference count is.
*/
- if (VTOSMI(vp)->smi_flags & SMI_LLOCK) {
+ if (smi->smi_flags & SMI_LLOCK) {
pid_t pid = ddi_get_pid();
cleanlocks(vp, pid, 0);
cleanshares(vp, pid);
@@ -480,19 +478,44 @@ smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
return (0);
/*
- * Do the CIFS close.
- * Darwin code
- */
-
- /*
+ * Decrement the reference count for the FID
+ * and possibly do the OtW close.
+ *
* Exclusive lock for modifying n_fid stuff.
* Don't want this one ever interruptible.
*/
(void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
smb_credinit(&scred, cr);
+ smbfs_rele_fid(np, &scred);
+
+ smb_credrele(&scred);
+ smbfs_rw_exit(&np->r_lkserlock);
+
+ return (0);
+}
+
+/*
+ * Helper for smbfs_close. Decrement the reference count
+ * for an SMB-level file or directory ID, and when the last
+ * reference for the fid goes away, do the OtW close.
+ * Also called in smbfs_inactive (defensive cleanup).
+ */
+static void
+smbfs_rele_fid(smbnode_t *np, struct smb_cred *scred)
+{
+ smb_share_t *ssp;
+ cred_t *oldcr;
+ struct smbfs_fctx *fctx;
+ int error;
+ uint16_t ofid;
+
+ ssp = np->n_mount->smi_share;
error = 0;
+ /* Make sure we serialize for n_dirseq use. */
+ ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_WRITER));
+
/*
* Note that vp->v_type may change if a remote node
* is deleted and recreated as a different type, and
@@ -500,29 +523,35 @@ smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
* Now use n_ovtype to keep track of the v_type
* we had during open (see comments above).
*/
- if (np->n_ovtype == VDIR) {
- struct smbfs_fctx *fctx;
+ switch (np->n_ovtype) {
+ case VDIR:
ASSERT(np->n_dirrefs > 0);
if (--np->n_dirrefs)
- goto out;
+ return;
if ((fctx = np->n_dirseq) != NULL) {
np->n_dirseq = NULL;
np->n_dirofs = 0;
- error = smbfs_smb_findclose(fctx, &scred);
+ error = smbfs_smb_findclose(fctx, scred);
}
- } else {
- uint16_t ofid;
+ break;
+
+ case VREG:
ASSERT(np->n_fidrefs > 0);
if (--np->n_fidrefs)
- goto out;
+ return;
if ((ofid = np->n_fid) != SMB_FID_UNUSED) {
np->n_fid = SMB_FID_UNUSED;
/* After reconnect, n_fid is invalid */
if (np->n_vcgenid == ssp->ss_vcgenid) {
error = smbfs_smb_close(
- ssp, ofid, NULL, &scred);
+ ssp, ofid, NULL, scred);
}
}
+ break;
+
+ default:
+ SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype);
+ break;
}
if (error) {
SMBVDEBUG("error %d closing %s\n",
@@ -543,13 +572,6 @@ smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
mutex_exit(&np->r_statelock);
if (oldcr != NULL)
crfree(oldcr);
-
-out:
- smb_credrele(&scred);
- smbfs_rw_exit(&np->r_lkserlock);
-
- /* don't return any errors */
- return (0);
}
/* ARGSUSED */
@@ -1294,6 +1316,7 @@ static void
smbfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
{
smbnode_t *np;
+ struct smb_cred scred;
/*
* Don't "bail out" for VFS_UNMOUNTED here,
@@ -1312,23 +1335,51 @@ smbfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
*/
/*
- * Some paranoia from the Darwin code:
- * Make sure the FID was closed.
- * If we see this, it's a bug!
+ * Defend against the possibility that higher-level callers
+ * might not correctly balance open and close calls. If we
+ * get here with open references remaining, it means there
+ * was a missing VOP_CLOSE somewhere. If that happens, do
+ * the close here so we don't "leak" FIDs on the server.
*
- * No rw_enter here, as this should be the
- * last ref, and we're just looking...
+ * Exclusive lock for modifying n_fid stuff.
+ * Don't want this one ever interruptible.
*/
- if (np->n_fidrefs > 0) {
- SMBVDEBUG("opencount %d fid %d file %s\n",
+ (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0);
+ smb_credinit(&scred, cr);
+
+ switch (np->n_ovtype) {
+ case VNON:
+ /* not open (OK) */
+ break;
+
+ case VDIR:
+ if (np->n_dirrefs == 0)
+ break;
+ SMBVDEBUG("open dir: refs %d path %s\n",
+ np->n_dirrefs, np->n_rpath);
+ /* Force last close. */
+ np->n_dirrefs = 1;
+ smbfs_rele_fid(np, &scred);
+ break;
+
+ case VREG:
+ if (np->n_fidrefs == 0)
+ break;
+ SMBVDEBUG("open file: refs %d id 0x%x path %s\n",
np->n_fidrefs, np->n_fid, np->n_rpath);
+ /* Force last close. */
+ np->n_fidrefs = 1;
+ smbfs_rele_fid(np, &scred);
+ break;
+
+ default:
+ SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype);
+ np->n_ovtype = VNON;
+ break;
}
- if (np->n_dirrefs > 0) {
- uint_t fid = (np->n_dirseq) ?
- np->n_dirseq->f_Sid : 0;
- SMBVDEBUG("opencount %d fid %d dir %s\n",
- np->n_dirrefs, fid, np->n_rpath);
- }
+
+ smb_credrele(&scred);
+ smbfs_rw_exit(&np->r_lkserlock);
smbfs_addfree(np);
}