diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/fs.d/mount.c | 27 | ||||
-rw-r--r-- | usr/src/cmd/fs.d/smbclnt/mount/Makefile | 6 | ||||
-rw-r--r-- | usr/src/cmd/fs.d/smbclnt/mount/mount.c | 25 | ||||
-rw-r--r-- | usr/src/cmd/fs.d/smbclnt/umount/Makefile | 9 | ||||
-rw-r--r-- | usr/src/cmd/fs.d/smbclnt/umount/umount.c | 27 | ||||
-rw-r--r-- | usr/src/cmd/fs.d/umount.c | 28 | ||||
-rw-r--r-- | usr/src/lib/libsecdb/exec_attr.txt | 2 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/ctx.c | 10 | ||||
-rw-r--r-- | usr/src/lib/libsmbfs/smb/nb.c | 18 | ||||
-rw-r--r-- | usr/src/pkg/manifests/system-file-system-smb.mf | 4 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbclnt/smbfs/smbfs.h | 3 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbclnt/smbfs/smbfs_client.c | 6 | ||||
-rw-r--r-- | usr/src/uts/common/fs/smbclnt/smbfs/smbfs_vnops.c | 129 |
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); } |