diff options
author | davide <davide@FreeBSD.org> | 2012-10-31 03:34:07 +0000 |
---|---|---|
committer | davide <davide@FreeBSD.org> | 2012-10-31 03:34:07 +0000 |
commit | 793cdde76e978e65ad5e743e35dbe3a92b381e90 (patch) | |
tree | 0c92e4f2f9c4d973dcd0bbeb244ef685f1342ee1 /sys/fs/smbfs/smbfs_vfsops.c | |
parent | a7cdc19e4b4ea767e597c3017133326b0697bd0d (diff) | |
download | FreeBSD-src-793cdde76e978e65ad5e743e35dbe3a92b381e90.zip FreeBSD-src-793cdde76e978e65ad5e743e35dbe3a92b381e90.tar.gz |
Fix panic due to page faults while in kernel mode, under conditions of
VM pressure. The reason is that in some codepaths pointers to stack
variables were passed from one thread to another.
In collaboration with: pho
Reported by: pho's stress2 suite
Sponsored by: iXsystems inc.
Diffstat (limited to 'sys/fs/smbfs/smbfs_vfsops.c')
-rw-r--r-- | sys/fs/smbfs/smbfs_vfsops.c | 53 |
1 files changed, 34 insertions, 19 deletions
diff --git a/sys/fs/smbfs/smbfs_vfsops.c b/sys/fs/smbfs/smbfs_vfsops.c index 2443001..c3d5a88 100644 --- a/sys/fs/smbfs/smbfs_vfsops.c +++ b/sys/fs/smbfs/smbfs_vfsops.c @@ -137,7 +137,7 @@ smbfs_mount(struct mount *mp) struct smb_share *ssp = NULL; struct vnode *vp; struct thread *td; - struct smb_cred scred; + struct smb_cred *scred; int error, v; char *pc, *pe; @@ -150,15 +150,18 @@ smbfs_mount(struct mount *mp) return (EINVAL); } - smb_makescred(&scred, td, td->td_ucred); + scred = smbfs_malloc_scred(); + smb_makescred(scred, td, td->td_ucred); if (1 != vfs_scanopt(mp->mnt_optnew, "dev", "%d", &v)) { vfs_mount_error(mp, "No dev option"); + smbfs_free_scred(scred); return (EINVAL); } - error = smb_dev2share(v, SMBM_EXEC, &scred, &ssp); + error = smb_dev2share(v, SMBM_EXEC, scred, &ssp); if (error) { printf("invalid device handle %d (%d)\n", v, error); vfs_mount_error(mp, "invalid device handle %d (%d)\n", v, error); + smbfs_free_scred(scred); return error; } vcp = SSTOVC(ssp); @@ -237,6 +240,7 @@ smbfs_mount(struct mount *mp) #ifdef DIAGNOSTIC SMBERROR("mp=%p\n", mp); #endif + smbfs_free_scred(scred); return error; bad: if (smp) { @@ -246,7 +250,8 @@ bad: free(smp, M_SMBFSDATA); } if (ssp) - smb_share_put(ssp, &scred); + smb_share_put(ssp, scred); + smbfs_free_scred(scred); return error; } @@ -256,7 +261,7 @@ smbfs_unmount(struct mount *mp, int mntflags) { struct thread *td; struct smbmount *smp = VFSTOSMBFS(mp); - struct smb_cred scred; + struct smb_cred *scred; int error, flags; SMBVDEBUG("smbfs_unmount: flags=%04x\n", mntflags); @@ -279,11 +284,12 @@ smbfs_unmount(struct mount *mp, int mntflags) } while (error == EBUSY && smp->sm_didrele != 0); if (error) return error; - smb_makescred(&scred, td, td->td_ucred); + scred = smbfs_malloc_scred(); + smb_makescred(scred, td, td->td_ucred); error = smb_share_lock(smp->sm_share, LK_EXCLUSIVE); if (error) - return error; - smb_share_put(smp->sm_share, &scred); + goto out; + smb_share_put(smp->sm_share, scred); mp->mnt_data = NULL; if (smp->sm_hash) @@ -293,6 +299,8 @@ smbfs_unmount(struct mount *mp, int mntflags) MNT_ILOCK(mp); mp->mnt_flag &= ~MNT_LOCAL; MNT_IUNLOCK(mp); +out: + smbfs_free_scred(scred); return error; } @@ -308,7 +316,7 @@ smbfs_root(struct mount *mp, int flags, struct vnode **vpp) struct smbfattr fattr; struct thread *td; struct ucred *cred; - struct smb_cred scred; + struct smb_cred *scred; int error; td = curthread; @@ -323,19 +331,22 @@ smbfs_root(struct mount *mp, int flags, struct vnode **vpp) *vpp = SMBTOV(smp->sm_root); return vget(*vpp, LK_EXCLUSIVE | LK_RETRY, td); } - smb_makescred(&scred, td, cred); - error = smbfs_smb_lookup(NULL, NULL, 0, &fattr, &scred); + scred = smbfs_malloc_scred(); + smb_makescred(scred, td, cred); + error = smbfs_smb_lookup(NULL, NULL, 0, &fattr, scred); if (error) - return error; + goto out; error = smbfs_nget(mp, NULL, "TheRooT", 7, &fattr, &vp); if (error) - return error; + goto out; ASSERT_VOP_LOCKED(vp, "smbfs_root"); vp->v_vflag |= VV_ROOT; np = VTOSMB(vp); smp->sm_root = np; *vpp = vp; - return 0; +out: + smbfs_free_scred(scred); + return error; } /* @@ -381,7 +392,7 @@ smbfs_statfs(struct mount *mp, struct statfs *sbp) struct smbmount *smp = VFSTOSMBFS(mp); struct smbnode *np = smp->sm_root; struct smb_share *ssp = smp->sm_share; - struct smb_cred scred; + struct smb_cred *scred; int error = 0; if (np == NULL) { @@ -390,14 +401,18 @@ smbfs_statfs(struct mount *mp, struct statfs *sbp) } sbp->f_iosize = SSTOVC(ssp)->vc_txmax; /* optimal transfer block size */ - smb_makescred(&scred, td, td->td_ucred); + scred = smbfs_malloc_scred(); + smb_makescred(scred, td, td->td_ucred); if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0) - error = smbfs_smb_statfs2(ssp, sbp, &scred); + error = smbfs_smb_statfs2(ssp, sbp, scred); else - error = smbfs_smb_statfs(ssp, sbp, &scred); - if (error) + error = smbfs_smb_statfs(ssp, sbp, scred); + if (error) { + smbfs_free_scred(scred); return error; + } sbp->f_flags = 0; /* copy of mount exported flags */ + smbfs_free_scred(scred); return 0; } |