summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorGordon Ross <Gordon.Ross@Sun.COM>2010-03-26 20:19:35 -0400
committerGordon Ross <Gordon.Ross@Sun.COM>2010-03-26 20:19:35 -0400
commit42d159821800ff240cc201c8fe07f575b9e8a62b (patch)
treea4e901af0d3640fb37060cb6a0a085bcb2fd18c5 /usr/src
parent1e81ac6e0a5d3782b6bdbcc7e2cbda4fda909ab9 (diff)
downloadillumos-joyent-42d159821800ff240cc201c8fe07f575b9e8a62b.tar.gz
6905120 mount -F smbfs as the Primary Administrator renders the mount point owned by root.
6912466 mount of share from Quantel server fails 6927024 Should defend against opens without closes 6935160 smbfs does not compile with gcc
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);
}