summaryrefslogtreecommitdiffstats
path: root/sys/fs/smbfs/smbfs_vfsops.c
diff options
context:
space:
mode:
authordavide <davide@FreeBSD.org>2012-10-31 03:34:07 +0000
committerdavide <davide@FreeBSD.org>2012-10-31 03:34:07 +0000
commit793cdde76e978e65ad5e743e35dbe3a92b381e90 (patch)
tree0c92e4f2f9c4d973dcd0bbeb244ef685f1342ee1 /sys/fs/smbfs/smbfs_vfsops.c
parenta7cdc19e4b4ea767e597c3017133326b0697bd0d (diff)
downloadFreeBSD-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.c53
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;
}
OpenPOWER on IntegriCloud