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.
This commit is contained in:
Davide Italiano 2012-10-31 03:34:07 +00:00
parent 994f027fbc
commit afe097512c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=242386
11 changed files with 419 additions and 220 deletions

View file

@ -75,7 +75,7 @@ smbfs_readvdir(struct vnode *vp, struct uio *uio, struct ucred *cred)
{
struct dirent de;
struct componentname cn;
struct smb_cred scred;
struct smb_cred *scred;
struct smbfs_fctx *ctx;
struct vnode *newvp;
struct smbnode *np = VTOSMB(vp);
@ -84,11 +84,14 @@ smbfs_readvdir(struct vnode *vp, struct uio *uio, struct ucred *cred)
np = VTOSMB(vp);
SMBVDEBUG("dirname='%s'\n", np->n_name);
smb_makescred(&scred, uio->uio_td, cred);
scred = smbfs_malloc_scred();
smb_makescred(scred, uio->uio_td, cred);
offset = uio->uio_offset / DE_SIZE; /* offset in the directory */
limit = uio->uio_resid / DE_SIZE;
if (uio->uio_resid < DE_SIZE || uio->uio_offset < 0)
return EINVAL;
if (uio->uio_resid < DE_SIZE || uio->uio_offset < 0) {
error = EINVAL;
goto out;
}
while (limit && offset < 2) {
limit--;
bzero((caddr_t)&de, DE_SIZE);
@ -104,40 +107,43 @@ smbfs_readvdir(struct vnode *vp, struct uio *uio, struct ucred *cred)
de.d_type = DT_DIR;
error = uiomove(&de, DE_SIZE, uio);
if (error)
return error;
goto out;
offset++;
uio->uio_offset += DE_SIZE;
}
if (limit == 0)
return 0;
if (limit == 0) {
error = 0;
goto out;
}
if (offset != np->n_dirofs || np->n_dirseq == NULL) {
SMBVDEBUG("Reopening search %ld:%ld\n", offset, np->n_dirofs);
if (np->n_dirseq) {
smbfs_findclose(np->n_dirseq, &scred);
smbfs_findclose(np->n_dirseq, scred);
np->n_dirseq = NULL;
}
np->n_dirofs = 2;
error = smbfs_findopen(np, "*", 1,
SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR,
&scred, &ctx);
scred, &ctx);
if (error) {
SMBVDEBUG("can not open search, error = %d", error);
return error;
goto out;
}
np->n_dirseq = ctx;
} else
ctx = np->n_dirseq;
while (np->n_dirofs < offset) {
error = smbfs_findnext(ctx, offset - np->n_dirofs++, &scred);
error = smbfs_findnext(ctx, offset - np->n_dirofs++, scred);
if (error) {
smbfs_findclose(np->n_dirseq, &scred);
smbfs_findclose(np->n_dirseq, scred);
np->n_dirseq = NULL;
return error == ENOENT ? 0 : error;
error = ENOENT ? 0 : error;
goto out;
}
}
error = 0;
for (; limit; limit--, offset++) {
error = smbfs_findnext(ctx, limit, &scred);
error = smbfs_findnext(ctx, limit, scred);
if (error)
break;
np->n_dirofs++;
@ -165,6 +171,8 @@ smbfs_readvdir(struct vnode *vp, struct uio *uio, struct ucred *cred)
if (error == ENOENT)
error = 0;
uio->uio_offset = offset * DE_SIZE;
out:
smbfs_free_scred(scred);
return error;
}
@ -175,7 +183,7 @@ smbfs_readvnode(struct vnode *vp, struct uio *uiop, struct ucred *cred)
struct smbnode *np = VTOSMB(vp);
struct thread *td;
struct vattr vattr;
struct smb_cred scred;
struct smb_cred *scred;
int error, lks;
/*
@ -223,8 +231,11 @@ smbfs_readvnode(struct vnode *vp, struct uio *uiop, struct ucred *cred)
np->n_mtime.tv_sec = vattr.va_mtime.tv_sec;
}
}
smb_makescred(&scred, td, cred);
return smb_read(smp->sm_share, np->n_fid, uiop, &scred);
scred = smbfs_malloc_scred();
smb_makescred(scred, td, cred);
error = smb_read(smp->sm_share, np->n_fid, uiop, scred);
smbfs_free_scred(scred);
return (error);
}
int
@ -233,7 +244,7 @@ smbfs_writevnode(struct vnode *vp, struct uio *uiop,
{
struct smbmount *smp = VTOSMBFS(vp);
struct smbnode *np = VTOSMB(vp);
struct smb_cred scred;
struct smb_cred *scred;
struct thread *td;
int error = 0;
@ -272,9 +283,11 @@ smbfs_writevnode(struct vnode *vp, struct uio *uiop,
if (vn_rlimit_fsize(vp, uiop, td))
return (EFBIG);
smb_makescred(&scred, td, cred);
error = smb_write(smp->sm_share, np->n_fid, uiop, &scred);
scred = smbfs_malloc_scred();
smb_makescred(scred, td, cred);
error = smb_write(smp->sm_share, np->n_fid, uiop, scred);
smbfs_free_scred(scred);
SMBVDEBUG("after: ofs=%jd,resid=%zd\n", (intmax_t)uiop->uio_offset,
uiop->uio_resid);
if (!error) {
@ -294,17 +307,19 @@ smbfs_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td
{
struct smbmount *smp = VFSTOSMBFS(vp->v_mount);
struct smbnode *np = VTOSMB(vp);
struct uio uio, *uiop = &uio;
struct uio *uiop;
struct iovec io;
struct smb_cred scred;
struct smb_cred *scred;
int error = 0;
uiop = malloc(sizeof(struct uio), M_SMBFSDATA, M_WAITOK);
uiop->uio_iov = &io;
uiop->uio_iovcnt = 1;
uiop->uio_segflg = UIO_SYSSPACE;
uiop->uio_td = td;
smb_makescred(&scred, td, cr);
scred = smbfs_malloc_scred();
smb_makescred(scred, td, cr);
if (bp->b_iocmd == BIO_READ) {
io.iov_len = uiop->uio_resid = bp->b_bcount;
@ -313,7 +328,7 @@ smbfs_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td
switch (vp->v_type) {
case VREG:
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
error = smb_read(smp->sm_share, np->n_fid, uiop, &scred);
error = smb_read(smp->sm_share, np->n_fid, uiop, scred);
if (error)
break;
if (uiop->uio_resid) {
@ -340,7 +355,7 @@ smbfs_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff;
io.iov_base = (char *)bp->b_data + bp->b_dirtyoff;
uiop->uio_rw = UIO_WRITE;
error = smb_write(smp->sm_share, np->n_fid, uiop, &scred);
error = smb_write(smp->sm_share, np->n_fid, uiop, scred);
/*
* For an interrupted write, the buffer is still valid
@ -380,11 +395,15 @@ smbfs_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td
} else {
bp->b_resid = 0;
bufdone(bp);
free(uiop, M_SMBFSDATA);
smbfs_free_scred(scred);
return 0;
}
}
bp->b_resid = uiop->uio_resid;
bufdone(bp);
free(uiop, M_SMBFSDATA);
smbfs_free_scred(scred);
return error;
}
@ -415,7 +434,7 @@ smbfs_getpages(ap)
struct ucred *cred;
struct smbmount *smp;
struct smbnode *np;
struct smb_cred scred;
struct smb_cred *scred;
vm_object_t object;
vm_page_t *pages, m;
@ -455,7 +474,8 @@ smbfs_getpages(ap)
}
VM_OBJECT_UNLOCK(object);
smb_makescred(&scred, td, cred);
scred = smbfs_malloc_scred();
smb_makescred(scred, td, cred);
bp = getpbuf(&smbfs_pbuf_freecnt);
@ -474,7 +494,8 @@ smbfs_getpages(ap)
uio.uio_rw = UIO_READ;
uio.uio_td = td;
error = smb_read(smp->sm_share, np->n_fid, &uio, &scred);
error = smb_read(smp->sm_share, np->n_fid, &uio, scred);
smbfs_free_scred(scred);
pmap_qremove(kva, npages);
relpbuf(bp, &smbfs_pbuf_freecnt);
@ -570,7 +591,7 @@ smbfs_putpages(ap)
int *rtvals;
struct smbmount *smp;
struct smbnode *np;
struct smb_cred scred;
struct smb_cred *scred;
vm_page_t *pages;
td = curthread; /* XXX */
@ -606,8 +627,10 @@ smbfs_putpages(ap)
SMBVDEBUG("ofs=%jd,resid=%zd\n", (intmax_t)uio.uio_offset,
uio.uio_resid);
smb_makescred(&scred, td, cred);
error = smb_write(smp->sm_share, np->n_fid, &uio, &scred);
scred = smbfs_malloc_scred();
smb_makescred(scred, td, cred);
error = smb_write(smp->sm_share, np->n_fid, &uio, scred);
smbfs_free_scred(scred);
/* VOP_CLOSE(vp, FWRITE, cred, td);*/
SMBVDEBUG("paged write done: %d\n", error);

View file

@ -349,25 +349,27 @@ smbfs_inactive(ap)
struct ucred *cred = td->td_ucred;
struct vnode *vp = ap->a_vp;
struct smbnode *np = VTOSMB(vp);
struct smb_cred scred;
struct smb_cred *scred;
struct vattr va;
SMBVDEBUG("%s: %d\n", VTOSMB(vp)->n_name, vrefcnt(vp));
if ((np->n_flag & NOPEN) != 0) {
smb_makescred(&scred, td, cred);
scred = smbfs_malloc_scred();
smb_makescred(scred, td, cred);
smbfs_vinvalbuf(vp, td);
if (vp->v_type == VREG) {
VOP_GETATTR(vp, &va, cred);
smbfs_smb_close(np->n_mount->sm_share, np->n_fid,
&np->n_mtime, &scred);
&np->n_mtime, scred);
} else if (vp->v_type == VDIR) {
if (np->n_dirseq != NULL) {
smbfs_findclose(np->n_dirseq, &scred);
smbfs_findclose(np->n_dirseq, scred);
np->n_dirseq = NULL;
}
}
np->n_flag &= ~NOPEN;
smbfs_attr_cacheremove(vp);
smbfs_free_scred(scred);
}
if (np->n_flag & NGONE)
vrecycle(vp);

View file

@ -87,16 +87,19 @@ smbfs_smb_lockandx(struct smbnode *np, int op, u_int32_t pid, off_t start, off_t
struct smb_cred *scred)
{
struct smb_share *ssp = np->n_mount->sm_share;
struct smb_rq rq, *rqp = &rq;
struct smb_rq *rqp;
struct mbchain *mbp;
u_char ltype = 0;
int error;
if (op == SMB_LOCK_SHARED)
ltype |= SMB_LOCKING_ANDX_SHARED_LOCK;
rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK);
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_LOCKING_ANDX, scred);
if (error)
if (error) {
free(rqp, M_SMBFSDATA);
return error;
}
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_uint8(mbp, 0xff); /* secondary command */
@ -116,6 +119,7 @@ smbfs_smb_lockandx(struct smbnode *np, int op, u_int32_t pid, off_t start, off_t
smb_rq_bend(rqp);
error = smb_rq_simple(rqp);
smb_rq_done(rqp);
free(rqp, M_SMBFSDATA);
return error;
}
@ -179,20 +183,24 @@ int
smbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp,
struct smb_cred *scred)
{
struct smb_rq rq, *rqp = &rq;
struct smb_rq *rqp;
struct mdchain *mdp;
u_int16_t units, bpu, bsize, funits;
int error;
rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK);
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION_DISK, scred);
if (error)
if (error) {
free(rqp, M_SMBFSDATA);
return error;
}
smb_rq_wstart(rqp);
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
smb_rq_bend(rqp);
error = smb_rq_simple(rqp);
if (error) {
free(rqp, M_SMBFSDATA);
smb_rq_done(rqp);
return error;
}
@ -208,6 +216,7 @@ smbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp,
sbp->f_files = 0xffff; /* total file nodes in filesystem */
sbp->f_ffree = 0xffff; /* free file nodes in fs */
smb_rq_done(rqp);
free(rqp, M_SMBFSDATA);
return 0;
}
@ -244,16 +253,19 @@ static int
smb_smb_flush(struct smbnode *np, struct smb_cred *scred)
{
struct smb_share *ssp = np->n_mount->sm_share;
struct smb_rq rq, *rqp = &rq;
struct smb_rq *rqp;
struct mbchain *mbp;
int error;
if ((np->n_flag & NOPEN) == 0 || !SMBTOV(np) ||
SMBTOV(np)->v_type != VREG)
return 0; /* not a regular open file */
rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK);
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_FLUSH, scred);
if (error)
if (error) {
free(rqp, M_SMBFSDATA);
return (error);
}
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM);
@ -262,6 +274,7 @@ smb_smb_flush(struct smbnode *np, struct smb_cred *scred)
smb_rq_bend(rqp);
error = smb_rq_simple(rqp);
smb_rq_done(rqp);
free(rqp, M_SMBFSDATA);
if (!error)
np->n_flag &= ~NFLUSHWIRE;
return (error);
@ -279,7 +292,7 @@ int
smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred)
{
struct smb_share *ssp = np->n_mount->sm_share;
struct smb_rq rq, *rqp = &rq;
struct smb_rq *rqp;
struct mbchain *mbp;
int error;
@ -288,9 +301,12 @@ smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred)
return (0);
}
rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK);
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_WRITE, scred);
if (error)
if (error) {
free(rqp, M_SMBFSDATA);
return error;
}
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM);
@ -304,6 +320,7 @@ smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred)
smb_rq_bend(rqp);
error = smb_rq_simple(rqp);
smb_rq_done(rqp);
free(rqp, M_SMBFSDATA);
return error;
}
@ -311,7 +328,7 @@ int
smbfs_smb_query_info(struct smbnode *np, const char *name, int len,
struct smbfattr *fap, struct smb_cred *scred)
{
struct smb_rq rq, *rqp = &rq;
struct smb_rq *rqp;
struct smb_share *ssp = np->n_mount->sm_share;
struct mbchain *mbp;
struct mdchain *mdp;
@ -320,9 +337,12 @@ smbfs_smb_query_info(struct smbnode *np, const char *name, int len,
u_int16_t wattr;
u_int32_t lint;
rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK);
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION, scred);
if (error)
if (error) {
free(rqp, M_SMBFSDATA);
return error;
}
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
smb_rq_wend(rqp);
@ -357,6 +377,7 @@ smbfs_smb_query_info(struct smbnode *np, const char *name, int len,
fap->fa_size = lint;
} while(0);
smb_rq_done(rqp);
free(rqp, M_SMBFSDATA);
return error;
}
@ -367,15 +388,18 @@ int
smbfs_smb_setpattr(struct smbnode *np, u_int16_t attr, struct timespec *mtime,
struct smb_cred *scred)
{
struct smb_rq rq, *rqp = &rq;
struct smb_rq *rqp;
struct smb_share *ssp = np->n_mount->sm_share;
struct mbchain *mbp;
u_long time;
int error, svtz;
rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK);
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION, scred);
if (error)
if (error) {
free(rqp, M_SMBFSDATA);
return error;
}
svtz = SSTOVC(ssp)->vc_sopt.sv_tz;
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
@ -407,6 +431,7 @@ smbfs_smb_setpattr(struct smbnode *np, u_int16_t attr, struct timespec *mtime,
}
} while(0);
smb_rq_done(rqp);
free(rqp, M_SMBFSDATA);
return error;
}
@ -523,15 +548,18 @@ int
smbfs_smb_setftime(struct smbnode *np, struct timespec *mtime,
struct timespec *atime, struct smb_cred *scred)
{
struct smb_rq rq, *rqp = &rq;
struct smb_rq *rqp;
struct smb_share *ssp = np->n_mount->sm_share;
struct mbchain *mbp;
u_int16_t date, time;
int error, tzoff;
rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK);
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION2, scred);
if (error)
if (error) {
free(rqp, M_SMBFSDATA);
return error;
}
tzoff = SSTOVC(ssp)->vc_sopt.sv_tz;
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
@ -556,6 +584,7 @@ smbfs_smb_setftime(struct smbnode *np, struct timespec *mtime,
error = smb_rq_simple(rqp);
SMBSDEBUG("%d\n", error);
smb_rq_done(rqp);
free(rqp, M_SMBFSDATA);
return error;
}
@ -611,7 +640,7 @@ smbfs_smb_setfattrNT(struct smbnode *np, u_int16_t attr, struct timespec *mtime,
int
smbfs_smb_open(struct smbnode *np, int accmode, struct smb_cred *scred)
{
struct smb_rq rq, *rqp = &rq;
struct smb_rq *rqp;
struct smb_share *ssp = np->n_mount->sm_share;
struct mbchain *mbp;
struct mdchain *mdp;
@ -619,9 +648,12 @@ smbfs_smb_open(struct smbnode *np, int accmode, struct smb_cred *scred)
u_int16_t fid, wattr, grantedmode;
int error;
rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK);
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN, scred);
if (error)
if (error) {
free(rqp, M_SMBFSDATA);
return error;
}
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_uint16le(mbp, accmode);
@ -652,6 +684,7 @@ smbfs_smb_open(struct smbnode *np, int accmode, struct smb_cred *scred)
*/
} while(0);
smb_rq_done(rqp);
free(rqp, M_SMBFSDATA);
if (error)
return error;
np->n_fid = fid;
@ -664,14 +697,17 @@ int
smbfs_smb_close(struct smb_share *ssp, u_int16_t fid, struct timespec *mtime,
struct smb_cred *scred)
{
struct smb_rq rq, *rqp = &rq;
struct smb_rq *rqp;
struct mbchain *mbp;
u_long time;
int error;
rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK);
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scred);
if (error)
if (error) {
free(rqp, M_SMBFSDATA);
return error;
}
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_mem(mbp, (caddr_t)&fid, sizeof(fid), MB_MSYSTEM);
@ -685,6 +721,7 @@ smbfs_smb_close(struct smb_share *ssp, u_int16_t fid, struct timespec *mtime,
smb_rq_bend(rqp);
error = smb_rq_simple(rqp);
smb_rq_done(rqp);
free(rqp, M_SMBFSDATA);
return error;
}
@ -692,7 +729,7 @@ int
smbfs_smb_create(struct smbnode *dnp, const char *name, int nmlen,
struct smb_cred *scred)
{
struct smb_rq rq, *rqp = &rq;
struct smb_rq *rqp;
struct smb_share *ssp = dnp->n_mount->sm_share;
struct mbchain *mbp;
struct mdchain *mdp;
@ -702,9 +739,12 @@ smbfs_smb_create(struct smbnode *dnp, const char *name, int nmlen,
u_long tm;
int error;
rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK);
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE, scred);
if (error)
if (error) {
free(rqp, M_SMBFSDATA);
return error;
}
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_uint16le(mbp, SMB_FA_ARCHIVE); /* attributes */
@ -731,20 +771,24 @@ smbfs_smb_create(struct smbnode *dnp, const char *name, int nmlen,
if (error)
return error;
smbfs_smb_close(ssp, fid, &ctime, scred);
free(rqp, M_SMBFSDATA);
return error;
}
int
smbfs_smb_delete(struct smbnode *np, struct smb_cred *scred)
{
struct smb_rq rq, *rqp = &rq;
struct smb_rq *rqp;
struct smb_share *ssp = np->n_mount->sm_share;
struct mbchain *mbp;
int error;
rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK);
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE, scred);
if (error)
if (error) {
free(rqp, M_SMBFSDATA);
return error;
}
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN);
@ -757,6 +801,7 @@ smbfs_smb_delete(struct smbnode *np, struct smb_cred *scred)
error = smb_rq_simple(rqp);
}
smb_rq_done(rqp);
free(rqp, M_SMBFSDATA);
return error;
}
@ -764,14 +809,17 @@ int
smbfs_smb_rename(struct smbnode *src, struct smbnode *tdnp,
const char *tname, int tnmlen, struct smb_cred *scred)
{
struct smb_rq rq, *rqp = &rq;
struct smb_rq *rqp;
struct smb_share *ssp = src->n_mount->sm_share;
struct mbchain *mbp;
int error;
rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK);
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_RENAME, scred);
if (error)
if (error) {
free(rqp, M_SMBFSDATA);
return error;
}
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN);
@ -790,6 +838,7 @@ smbfs_smb_rename(struct smbnode *src, struct smbnode *tdnp,
error = smb_rq_simple(rqp);
} while(0);
smb_rq_done(rqp);
free(rqp, M_SMBFSDATA);
return error;
}
@ -797,14 +846,17 @@ int
smbfs_smb_move(struct smbnode *src, struct smbnode *tdnp,
const char *tname, int tnmlen, u_int16_t flags, struct smb_cred *scred)
{
struct smb_rq rq, *rqp = &rq;
struct smb_rq *rqp;
struct smb_share *ssp = src->n_mount->sm_share;
struct mbchain *mbp;
int error;
rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK);
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_MOVE, scred);
if (error)
if (error) {
free(rqp, M_SMBFSDATA);
return error;
}
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_uint16le(mbp, SMB_TID_UNKNOWN);
@ -825,6 +877,7 @@ smbfs_smb_move(struct smbnode *src, struct smbnode *tdnp,
error = smb_rq_simple(rqp);
} while(0);
smb_rq_done(rqp);
free(rqp, M_SMBFSDATA);
return error;
}
@ -832,14 +885,17 @@ int
smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int len,
struct smb_cred *scred)
{
struct smb_rq rq, *rqp = &rq;
struct smb_rq *rqp;
struct smb_share *ssp = dnp->n_mount->sm_share;
struct mbchain *mbp;
int error;
rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK);
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE_DIRECTORY, scred);
if (error)
if (error) {
free(rqp, M_SMBFSDATA);
return error;
}
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
smb_rq_wend(rqp);
@ -851,20 +907,24 @@ smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int len,
error = smb_rq_simple(rqp);
}
smb_rq_done(rqp);
free(rqp, M_SMBFSDATA);
return error;
}
int
smbfs_smb_rmdir(struct smbnode *np, struct smb_cred *scred)
{
struct smb_rq rq, *rqp = &rq;
struct smb_rq *rqp;
struct smb_share *ssp = np->n_mount->sm_share;
struct mbchain *mbp;
int error;
rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK);
error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE_DIRECTORY, scred);
if (error)
if (error) {
free(rqp, M_SMBFSDATA);
return error;
}
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
smb_rq_wend(rqp);
@ -876,6 +936,7 @@ smbfs_smb_rmdir(struct smbnode *np, struct smb_cred *scred)
error = smb_rq_simple(rqp);
}
smb_rq_done(rqp);
free(rqp, M_SMBFSDATA);
return error;
}
@ -1139,13 +1200,16 @@ smbfs_smb_trans2find2(struct smbfs_fctx *ctx)
static int
smbfs_smb_findclose2(struct smbfs_fctx *ctx)
{
struct smb_rq rq, *rqp = &rq;
struct smb_rq *rqp;
struct mbchain *mbp;
int error;
rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK);
error = smb_rq_init(rqp, SSTOCP(ctx->f_ssp), SMB_COM_FIND_CLOSE2, ctx->f_scred);
if (error)
if (error) {
free(rqp, M_SMBFSDATA);
return error;
}
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_mem(mbp, (caddr_t)&ctx->f_Sid, 2, MB_MSYSTEM);
@ -1154,6 +1218,7 @@ smbfs_smb_findclose2(struct smbfs_fctx *ctx)
smb_rq_bend(rqp);
error = smb_rq_simple(rqp);
smb_rq_done(rqp);
free(rqp, M_SMBFSDATA);
return error;
}

View file

@ -46,6 +46,7 @@
#include <fs/smbfs/smbfs_subr.h>
MALLOC_DEFINE(M_SMBFSDATA, "smbfs_data", "SMBFS private data");
MALLOC_DEFINE(M_SMBFSCRED, "smbfs_cred", "SMBFS cred data");
void
smb_time_local2server(struct timespec *tsp, int tzoff, u_long *seconds)
@ -222,3 +223,15 @@ smbfs_fname_tolocal(struct smb_vc *vcp, char *name, int *nmlen, int caseopt)
}
return error;
}
void *
smbfs_malloc_scred(void)
{
return (malloc(sizeof(struct smb_cred), M_SMBFSCRED, M_WAITOK));
}
void
smbfs_free_scred(void *scred)
{
free(scred, M_SMBFSCRED);
}

View file

@ -30,6 +30,7 @@
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_SMBFSDATA);
MALLOC_DECLARE(M_SMBFSCRED);
#endif
#define SMBFSERR(format, args...) printf("%s: "format, __func__ ,## args)
@ -178,4 +179,6 @@ void smb_time_unix2dos(struct timespec *tsp, int tzoff, u_int16_t *ddp,
u_int16_t *dtp, u_int8_t *dhp);
void smb_dos2unixtime (u_int dd, u_int dt, u_int dh, int tzoff, struct timespec *tsp);
void *smbfs_malloc_scred(void);
void smbfs_free_scred(void *);
#endif /* !_FS_SMBFS_SMBFS_SUBR_H_ */

View file

@ -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 @@ smbfs_mount(struct mount *mp)
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;
}

View file

@ -153,7 +153,7 @@ smbfs_open(ap)
{
struct vnode *vp = ap->a_vp;
struct smbnode *np = VTOSMB(vp);
struct smb_cred scred;
struct smb_cred *scred;
struct vattr vattr;
int mode = ap->a_mode;
int error, accmode;
@ -197,14 +197,15 @@ smbfs_open(ap)
accmode = SMB_SM_DENYNONE|SMB_AM_OPENREAD;
if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
accmode = SMB_SM_DENYNONE|SMB_AM_OPENRW;
smb_makescred(&scred, ap->a_td, ap->a_cred);
error = smbfs_smb_open(np, accmode, &scred);
scred = smbfs_malloc_scred();
smb_makescred(scred, ap->a_td, ap->a_cred);
error = smbfs_smb_open(np, accmode, scred);
if (error) {
if (mode & FWRITE)
return EACCES;
else if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
accmode = SMB_SM_DENYNONE|SMB_AM_OPENREAD;
error = smbfs_smb_open(np, accmode, &scred);
error = smbfs_smb_open(np, accmode, scred);
}
}
if (error == 0) {
@ -212,6 +213,7 @@ smbfs_open(ap)
vnode_create_vobject(ap->a_vp, vattr.va_size, ap->a_td);
}
smbfs_attr_cacheremove(vp);
smbfs_free_scred(scred);
return error;
}
@ -228,12 +230,14 @@ smbfs_close(ap)
struct vnode *vp = ap->a_vp;
struct thread *td = ap->a_td;
struct smbnode *np = VTOSMB(vp);
struct smb_cred scred;
struct smb_cred *scred;
if (vp->v_type == VDIR && (np->n_flag & NOPEN) != 0 &&
np->n_dirseq != NULL) {
smb_makescred(&scred, td, ap->a_cred);
smbfs_findclose(np->n_dirseq, &scred);
scred = smbfs_malloc_scred();
smb_makescred(scred, td, ap->a_cred);
smbfs_findclose(np->n_dirseq, scred);
smbfs_free_scred(scred);
np->n_dirseq = NULL;
}
return 0;
@ -254,7 +258,7 @@ smbfs_getattr(ap)
struct smbnode *np = VTOSMB(vp);
struct vattr *va=ap->a_vap;
struct smbfattr fattr;
struct smb_cred scred;
struct smb_cred *scred;
u_quad_t oldsize;
int error;
@ -263,17 +267,20 @@ smbfs_getattr(ap)
if (!error)
return 0;
SMBVDEBUG("not in the cache\n");
smb_makescred(&scred, curthread, ap->a_cred);
scred = smbfs_malloc_scred();
smb_makescred(scred, curthread, ap->a_cred);
oldsize = np->n_size;
error = smbfs_smb_lookup(np, NULL, 0, &fattr, &scred);
error = smbfs_smb_lookup(np, NULL, 0, &fattr, scred);
if (error) {
SMBVDEBUG("error %d\n", error);
smbfs_free_scred(scred);
return error;
}
smbfs_attr_cacheenter(vp, &fattr);
smbfs_attr_cachelookup(vp, va);
if (np->n_flag & NOPEN)
np->n_size = oldsize;
smbfs_free_scred(scred);
return 0;
}
@ -289,7 +296,7 @@ smbfs_setattr(ap)
struct smbnode *np = VTOSMB(vp);
struct vattr *vap = ap->a_vap;
struct timespec *mtime, *atime;
struct smb_cred scred;
struct smb_cred *scred;
struct smb_share *ssp = np->n_mount->sm_share;
struct smb_vc *vcp = SSTOVC(ssp);
struct thread *td = curthread;
@ -308,18 +315,23 @@ smbfs_setattr(ap)
vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL ||
vap->va_mode != (mode_t)VNOVAL) && isreadonly)
return EROFS;
smb_makescred(&scred, td, ap->a_cred);
scred = smbfs_malloc_scred();
smb_makescred(scred, td, ap->a_cred);
if (vap->va_size != VNOVAL) {
switch (vp->v_type) {
case VDIR:
return EISDIR;
error = EISDIR;
goto out;
case VREG:
break;
default:
return EINVAL;
error = EINVAL;
goto out;
};
if (isreadonly)
return EROFS;
if (isreadonly) {
error = EROFS;
goto out;
}
doclose = 0;
vnode_pager_setsize(vp, (u_long)vap->va_size);
tsize = np->n_size;
@ -327,18 +339,18 @@ smbfs_setattr(ap)
if ((np->n_flag & NOPEN) == 0) {
error = smbfs_smb_open(np,
SMB_SM_DENYNONE|SMB_AM_OPENRW,
&scred);
scred);
if (error == 0)
doclose = 1;
}
if (error == 0)
error = smbfs_smb_setfsize(np, vap->va_size, &scred);
error = smbfs_smb_setfsize(np, vap->va_size, scred);
if (doclose)
smbfs_smb_close(ssp, np->n_fid, NULL, &scred);
smbfs_smb_close(ssp, np->n_fid, NULL, scred);
if (error) {
np->n_size = tsize;
vnode_pager_setsize(vp, (u_long)tsize);
return error;
goto out;
}
}
if (vap->va_mode != (mode_t)VNOVAL) {
@ -348,9 +360,9 @@ smbfs_setattr(ap)
else
np->n_dosattr |= SMB_FA_RDONLY;
if (np->n_dosattr != old_n_dosattr) {
error = smbfs_smb_setpattr(np, np->n_dosattr, NULL, &scred);
error = smbfs_smb_setpattr(np, np->n_dosattr, NULL, scred);
if (error)
return error;
goto out;
}
}
mtime = atime = NULL;
@ -381,25 +393,25 @@ smbfs_setattr(ap)
NULL);
if (!error) {
/* error = smbfs_smb_setfattrNT(np, 0,
mtime, atime, &scred);
mtime, atime, scred);
VOP_GETATTR(vp, &vattr, ap->a_cred); */
if (mtime)
np->n_mtime = *mtime;
VOP_CLOSE(vp, FWRITE, ap->a_cred, td);
}
} else if ((vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS)) {
error = smbfs_smb_setptime2(np, mtime, atime, 0, &scred);
/* error = smbfs_smb_setpattrNT(np, 0, mtime, atime, &scred);*/
error = smbfs_smb_setptime2(np, mtime, atime, 0, scred);
/* error = smbfs_smb_setpattrNT(np, 0, mtime, atime, scred);*/
} else if (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN2_0) {
error = smbfs_smb_setptime2(np, mtime, atime, 0, &scred);
error = smbfs_smb_setptime2(np, mtime, atime, 0, scred);
} else {
error = smbfs_smb_setpattr(np, 0, mtime, &scred);
error = smbfs_smb_setpattr(np, 0, mtime, scred);
}
} else {
if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
error = smbfs_smb_setfattrNT(np, 0, mtime, atime, &scred);
error = smbfs_smb_setfattrNT(np, 0, mtime, atime, scred);
} else if (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN1_0) {
error = smbfs_smb_setftime(np, mtime, atime, &scred);
error = smbfs_smb_setftime(np, mtime, atime, scred);
} else {
/*
* I have no idea how to handle this for core
@ -417,6 +429,8 @@ smbfs_setattr(ap)
smbfs_attr_cacheremove(vp); /* invalidate cache */
VOP_GETATTR(vp, vap, ap->a_cred);
np->n_mtime.tv_sec = vap->va_mtime.tv_sec;
out:
smbfs_free_scred(scred);
return error;
}
/*
@ -482,7 +496,7 @@ smbfs_create(ap)
struct vnode *vp;
struct vattr vattr;
struct smbfattr fattr;
struct smb_cred scred;
struct smb_cred *scred;
char *name = cnp->cn_nameptr;
int nmlen = cnp->cn_namelen;
int error;
@ -494,20 +508,23 @@ smbfs_create(ap)
return EOPNOTSUPP;
if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred)))
return error;
smb_makescred(&scred, cnp->cn_thread, cnp->cn_cred);
scred = smbfs_malloc_scred();
smb_makescred(scred, cnp->cn_thread, cnp->cn_cred);
error = smbfs_smb_create(dnp, name, nmlen, &scred);
error = smbfs_smb_create(dnp, name, nmlen, scred);
if (error)
return error;
error = smbfs_smb_lookup(dnp, name, nmlen, &fattr, &scred);
goto out;
error = smbfs_smb_lookup(dnp, name, nmlen, &fattr, scred);
if (error)
return error;
goto out;
error = smbfs_nget(VTOVFS(dvp), dvp, name, nmlen, &fattr, &vp);
if (error)
return error;
goto out;
*vpp = vp;
if (cnp->cn_flags & MAKEENTRY)
cache_enter(dvp, vp, cnp);
out:
smbfs_free_scred(scred);
return error;
}
@ -524,16 +541,18 @@ smbfs_remove(ap)
/* struct vnode *dvp = ap->a_dvp;*/
struct componentname *cnp = ap->a_cnp;
struct smbnode *np = VTOSMB(vp);
struct smb_cred scred;
struct smb_cred *scred;
int error;
if (vp->v_type == VDIR || (np->n_flag & NOPEN) != 0 || vrefcnt(vp) != 1)
return EPERM;
smb_makescred(&scred, cnp->cn_thread, cnp->cn_cred);
error = smbfs_smb_delete(np, &scred);
scred = smbfs_malloc_scred();
smb_makescred(scred, cnp->cn_thread, cnp->cn_cred);
error = smbfs_smb_delete(np, scred);
if (error == 0)
np->n_flag |= NGONE;
cache_purge(vp);
smbfs_free_scred(scred);
return error;
}
@ -557,19 +576,19 @@ smbfs_rename(ap)
struct vnode *tdvp = ap->a_tdvp;
struct componentname *tcnp = ap->a_tcnp;
/* struct componentname *fcnp = ap->a_fcnp;*/
struct smb_cred scred;
struct smb_cred *scred;
u_int16_t flags = 6;
int error=0;
/* Check for cross-device rename */
if ((fvp->v_mount != tdvp->v_mount) ||
(tvp && (fvp->v_mount != tvp->v_mount))) {
error = EXDEV;
return EXDEV;
goto out;
}
if (tvp && vrefcnt(tvp) > 1) {
error = EBUSY;
return EBUSY;
goto out;
}
flags = 0x10; /* verify all writes */
@ -578,17 +597,17 @@ smbfs_rename(ap)
} else if (fvp->v_type == VREG) {
flags |= 1;
} else {
error = EINVAL;
goto out;
return EINVAL;
}
smb_makescred(&scred, tcnp->cn_thread, tcnp->cn_cred);
scred = smbfs_malloc_scred();
smb_makescred(scred, tcnp->cn_thread, tcnp->cn_cred);
/*
* It seems that Samba doesn't implement SMB_COM_MOVE call...
*/
#ifdef notnow
if (SMB_DIALECT(SSTOCN(smp->sm_share)) >= SMB_DIALECT_LANMAN1_0) {
error = smbfs_smb_move(VTOSMB(fvp), VTOSMB(tdvp),
tcnp->cn_nameptr, tcnp->cn_namelen, flags, &scred);
tcnp->cn_nameptr, tcnp->cn_namelen, flags, scred);
} else
#endif
{
@ -596,13 +615,13 @@ smbfs_rename(ap)
* We have to do the work atomicaly
*/
if (tvp && tvp != fvp) {
error = smbfs_smb_delete(VTOSMB(tvp), &scred);
error = smbfs_smb_delete(VTOSMB(tvp), scred);
if (error)
goto out_cacherem;
VTOSMB(fvp)->n_flag |= NGONE;
}
error = smbfs_smb_rename(VTOSMB(fvp), VTOSMB(tdvp),
tcnp->cn_nameptr, tcnp->cn_namelen, &scred);
tcnp->cn_nameptr, tcnp->cn_namelen, scred);
}
if (fvp->v_type == VDIR) {
@ -615,6 +634,7 @@ smbfs_rename(ap)
smbfs_attr_cacheremove(fdvp);
smbfs_attr_cacheremove(tdvp);
out:
smbfs_free_scred(scred);
if (tdvp == tvp)
vrele(tdvp);
else
@ -685,7 +705,7 @@ smbfs_mkdir(ap)
struct componentname *cnp = ap->a_cnp;
struct smbnode *dnp = VTOSMB(dvp);
struct vattr vattr;
struct smb_cred scred;
struct smb_cred *scred;
struct smbfattr fattr;
char *name = cnp->cn_nameptr;
int len = cnp->cn_namelen;
@ -696,17 +716,20 @@ smbfs_mkdir(ap)
}
if ((name[0] == '.') && ((len == 1) || ((len == 2) && (name[1] == '.'))))
return EEXIST;
smb_makescred(&scred, cnp->cn_thread, cnp->cn_cred);
error = smbfs_smb_mkdir(dnp, name, len, &scred);
scred = smbfs_malloc_scred();
smb_makescred(scred, cnp->cn_thread, cnp->cn_cred);
error = smbfs_smb_mkdir(dnp, name, len, scred);
if (error)
return error;
error = smbfs_smb_lookup(dnp, name, len, &fattr, &scred);
goto out;
error = smbfs_smb_lookup(dnp, name, len, &fattr, scred);
if (error)
return error;
goto out;
error = smbfs_nget(VTOVFS(dvp), dvp, name, len, &fattr, &vp);
if (error)
return error;
goto out;
*ap->a_vpp = vp;
out:
smbfs_free_scred(scred);
return 0;
}
@ -727,20 +750,22 @@ smbfs_rmdir(ap)
/* struct smbmount *smp = VTOSMBFS(vp);*/
struct smbnode *dnp = VTOSMB(dvp);
struct smbnode *np = VTOSMB(vp);
struct smb_cred scred;
struct smb_cred *scred;
int error;
if (dvp == vp)
return EINVAL;
smb_makescred(&scred, cnp->cn_thread, cnp->cn_cred);
error = smbfs_smb_rmdir(np, &scred);
scred = smbfs_malloc_scred();
smb_makescred(scred, cnp->cn_thread, cnp->cn_cred);
error = smbfs_smb_rmdir(np, scred);
if (error == 0)
np->n_flag |= NGONE;
dnp->n_flag |= NMODIFIED;
smbfs_attr_cacheremove(dvp);
/* cache_purge(dvp);*/
cache_purge(vp);
smbfs_free_scred(scred);
return error;
}
@ -936,7 +961,7 @@ smbfs_advlock(ap)
caddr_t id = (caddr_t)1 /* ap->a_id */;
/* int flags = ap->a_flags;*/
struct thread *td = curthread;
struct smb_cred scred;
struct smb_cred *scred;
u_quad_t size;
off_t start, end, oadd;
int error, lkop;
@ -986,7 +1011,8 @@ smbfs_advlock(ap)
return EOVERFLOW;
end = start + oadd;
}
smb_makescred(&scred, td, td->td_ucred);
scred = smbfs_malloc_scred();
smb_makescred(scred, td, td->td_ucred);
switch (ap->a_op) {
case F_SETLK:
switch (fl->l_type) {
@ -1000,13 +1026,14 @@ smbfs_advlock(ap)
lkop = SMB_LOCK_RELEASE;
break;
default:
smbfs_free_scred(scred);
return EINVAL;
}
error = lf_advlock(ap, &vp->v_lockf, size);
if (error)
break;
lkop = SMB_LOCK_EXCL;
error = smbfs_smb_lock(np, lkop, id, start, end, &scred);
error = smbfs_smb_lock(np, lkop, id, start, end, scred);
if (error) {
int oldtype = fl->l_type;
fl->l_type = F_UNLCK;
@ -1017,14 +1044,16 @@ smbfs_advlock(ap)
break;
case F_UNLCK:
lf_advlock(ap, &vp->v_lockf, size);
error = smbfs_smb_lock(np, SMB_LOCK_RELEASE, id, start, end, &scred);
error = smbfs_smb_lock(np, SMB_LOCK_RELEASE, id, start, end, scred);
break;
case F_GETLK:
error = lf_advlock(ap, &vp->v_lockf, size);
break;
default:
smbfs_free_scred(scred);
return EINVAL;
}
smbfs_free_scred(scred);
return error;
}
@ -1091,7 +1120,7 @@ smbfs_lookup(ap)
struct mount *mp = dvp->v_mount;
struct smbnode *dnp;
struct smbfattr fattr, *fap;
struct smb_cred scred;
struct smb_cred *scred;
char *name = cnp->cn_nameptr;
int flags = cnp->cn_flags;
int nameiop = cnp->cn_nameiop;
@ -1182,20 +1211,21 @@ smbfs_lookup(ap)
*/
error = 0;
*vpp = NULLVP;
smb_makescred(&scred, td, cnp->cn_cred);
scred = smbfs_malloc_scred();
smb_makescred(scred, td, cnp->cn_cred);
fap = &fattr;
if (flags & ISDOTDOT) {
error = smbfs_smb_lookup(VTOSMB(dnp->n_parent), NULL, 0, fap,
&scred);
scred);
SMBVDEBUG("result of dotdot lookup: %d\n", error);
} else {
fap = &fattr;
error = smbfs_smb_lookup(dnp, name, nmlen, fap, &scred);
error = smbfs_smb_lookup(dnp, name, nmlen, fap, scred);
/* if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.')*/
SMBVDEBUG("result of smbfs_smb_lookup: %d\n", error);
}
if (error && error != ENOENT)
return error;
goto out;
if (error) { /* entry not found */
/*
* Handle RENAME or CREATE case...
@ -1203,11 +1233,13 @@ smbfs_lookup(ap)
if ((nameiop == CREATE || nameiop == RENAME) && islastcn) {
error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td);
if (error)
return error;
goto out;
cnp->cn_flags |= SAVENAME;
return (EJUSTRETURN);
error = EJUSTRETURN;
goto out;
}
return ENOENT;
error = ENOENT;
goto out;
}/* else {
SMBVDEBUG("Found entry %s with id=%d\n", fap->entryName, fap->dirEntNum);
}*/
@ -1217,38 +1249,40 @@ smbfs_lookup(ap)
if (nameiop == DELETE && islastcn) { /* delete last component */
error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td);
if (error)
return error;
goto out;
if (isdot) {
VREF(dvp);
*vpp = dvp;
return 0;
goto out;
}
error = smbfs_nget(mp, dvp, name, nmlen, fap, &vp);
if (error)
return error;
goto out;
*vpp = vp;
cnp->cn_flags |= SAVENAME;
return 0;
goto out;
}
if (nameiop == RENAME && islastcn) {
error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td);
if (error)
return error;
if (isdot)
return EISDIR;
goto out;
if (isdot) {
error = EISDIR;
goto out;
}
error = smbfs_nget(mp, dvp, name, nmlen, fap, &vp);
if (error)
return error;
goto out;
*vpp = vp;
cnp->cn_flags |= SAVENAME;
return 0;
goto out;
}
if (flags & ISDOTDOT) {
VOP_UNLOCK(dvp, 0);
error = smbfs_nget(mp, dvp, name, nmlen, NULL, &vp);
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
if (error)
return error;
goto out;
*vpp = vp;
} else if (isdot) {
vref(dvp);
@ -1256,7 +1290,7 @@ smbfs_lookup(ap)
} else {
error = smbfs_nget(mp, dvp, name, nmlen, fap, &vp);
if (error)
return error;
goto out;
*vpp = vp;
SMBVDEBUG("lookup: getnewvp!\n");
}
@ -1264,5 +1298,7 @@ smbfs_lookup(ap)
/* VTOSMB(*vpp)->n_ctime = VTOSMB(*vpp)->n_vattr.va_ctime.tv_sec;*/
cache_enter(dvp, *vpp, cnp);
}
return 0;
out:
smbfs_free_scred(scred);
return (error);
}

View file

@ -868,8 +868,6 @@ smb_share_getinfo(struct smb_share *ssp, struct smb_share_info *sip)
static int
smb_sysctl_treedump(SYSCTL_HANDLER_ARGS)
{
struct thread *td = req->td;
struct smb_cred scred;
struct smb_connobj *scp1, *scp2;
struct smb_vc *vcp;
struct smb_share *ssp;
@ -877,7 +875,6 @@ smb_sysctl_treedump(SYSCTL_HANDLER_ARGS)
struct smb_share_info ssi;
int error, itype;
smb_makescred(&scred, td, td->td_ucred);
error = sysctl_wire_old_buffer(req, 0);
if (error)
return (error);

View file

@ -157,22 +157,24 @@ nsmb_dev_close(struct cdev *dev, int flag, int fmt, struct thread *td)
struct smb_dev *sdp;
struct smb_vc *vcp;
struct smb_share *ssp;
struct smb_cred scred;
struct smb_cred *scred;
int s;
scred = malloc(sizeof(struct smb_cred), M_NSMBDEV, M_WAITOK);
SMB_CHECKMINOR(dev);
s = splimp();
if ((sdp->sd_flags & NSMBFL_OPEN) == 0) {
splx(s);
free(scred, M_NSMBDEV);
return EBADF;
}
smb_makescred(&scred, td, NULL);
smb_makescred(scred, td, NULL);
ssp = sdp->sd_share;
if (ssp != NULL)
smb_share_rele(ssp, &scred);
smb_share_rele(ssp, scred);
vcp = sdp->sd_vc;
if (vcp != NULL)
smb_vc_rele(vcp, &scred);
smb_vc_rele(vcp, scred);
/*
smb_flushq(&sdp->sd_rqlist);
smb_flushq(&sdp->sd_rplist);
@ -181,6 +183,7 @@ nsmb_dev_close(struct cdev *dev, int flag, int fmt, struct thread *td)
free(sdp, M_NSMBDEV);
destroy_dev_sched(dev);
splx(s);
free(scred, M_NSMBDEV);
return 0;
}
@ -191,20 +194,23 @@ nsmb_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thre
struct smb_dev *sdp;
struct smb_vc *vcp;
struct smb_share *ssp;
struct smb_cred scred;
struct smb_cred *scred;
int error = 0;
SMB_CHECKMINOR(dev);
if ((sdp->sd_flags & NSMBFL_OPEN) == 0)
return EBADF;
smb_makescred(&scred, td, NULL);
scred = malloc(sizeof(struct smb_cred), M_NSMBDEV, M_WAITOK);
smb_makescred(scred, td, NULL);
switch (cmd) {
case SMBIOC_OPENSESSION:
if (sdp->sd_vc)
return EISCONN;
if (sdp->sd_vc) {
error = EISCONN;
goto out;
}
error = smb_usr_opensession((struct smbioc_ossn*)data,
&scred, &vcp);
scred, &vcp);
if (error)
break;
sdp->sd_vc = vcp;
@ -212,12 +218,16 @@ nsmb_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thre
sdp->sd_level = SMBL_VC;
break;
case SMBIOC_OPENSHARE:
if (sdp->sd_share)
return EISCONN;
if (sdp->sd_vc == NULL)
return ENOTCONN;
if (sdp->sd_share) {
error = EISCONN;
goto out;
}
if (sdp->sd_vc == NULL) {
error = ENOTCONN;
goto out;
}
error = smb_usr_openshare(sdp->sd_vc,
(struct smbioc_oshare*)data, &scred, &ssp);
(struct smbioc_oshare*)data, scred, &ssp);
if (error)
break;
sdp->sd_share = ssp;
@ -225,16 +235,20 @@ nsmb_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thre
sdp->sd_level = SMBL_SHARE;
break;
case SMBIOC_REQUEST:
if (sdp->sd_share == NULL)
return ENOTCONN;
if (sdp->sd_share == NULL) {
error = ENOTCONN;
goto out;
}
error = smb_usr_simplerequest(sdp->sd_share,
(struct smbioc_rq*)data, &scred);
(struct smbioc_rq*)data, scred);
break;
case SMBIOC_T2RQ:
if (sdp->sd_share == NULL)
return ENOTCONN;
if (sdp->sd_share == NULL) {
error = ENOTCONN;
goto out;
}
error = smb_usr_t2request(sdp->sd_share,
(struct smbioc_t2rq*)data, &scred);
(struct smbioc_t2rq*)data, scred);
break;
case SMBIOC_SETFLAGS: {
struct smbioc_flags *fl = (struct smbioc_flags*)data;
@ -243,9 +257,11 @@ nsmb_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thre
if (fl->ioc_level == SMBL_VC) {
if (fl->ioc_mask & SMBV_PERMANENT) {
on = fl->ioc_flags & SMBV_PERMANENT;
if ((vcp = sdp->sd_vc) == NULL)
return ENOTCONN;
error = smb_vc_get(vcp, LK_EXCLUSIVE, &scred);
if ((vcp = sdp->sd_vc) == NULL) {
error = ENOTCONN;
goto out;
}
error = smb_vc_get(vcp, LK_EXCLUSIVE, scred);
if (error)
break;
if (on && (vcp->obj.co_flags & SMBV_PERMANENT) == 0) {
@ -253,17 +269,19 @@ nsmb_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thre
smb_vc_ref(vcp);
} else if (!on && (vcp->obj.co_flags & SMBV_PERMANENT)) {
vcp->obj.co_flags &= ~SMBV_PERMANENT;
smb_vc_rele(vcp, &scred);
smb_vc_rele(vcp, scred);
}
smb_vc_put(vcp, &scred);
smb_vc_put(vcp, scred);
} else
error = EINVAL;
} else if (fl->ioc_level == SMBL_SHARE) {
if (fl->ioc_mask & SMBS_PERMANENT) {
on = fl->ioc_flags & SMBS_PERMANENT;
if ((ssp = sdp->sd_share) == NULL)
return ENOTCONN;
error = smb_share_get(ssp, LK_EXCLUSIVE, &scred);
if ((ssp = sdp->sd_share) == NULL) {
error = ENOTCONN;
goto out;
}
error = smb_share_get(ssp, LK_EXCLUSIVE, scred);
if (error)
break;
if (on && (ssp->obj.co_flags & SMBS_PERMANENT) == 0) {
@ -271,9 +289,9 @@ nsmb_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thre
smb_share_ref(ssp);
} else if (!on && (ssp->obj.co_flags & SMBS_PERMANENT)) {
ssp->obj.co_flags &= ~SMBS_PERMANENT;
smb_share_rele(ssp, &scred);
smb_share_rele(ssp, scred);
}
smb_share_put(ssp, &scred);
smb_share_put(ssp, scred);
} else
error = EINVAL;
break;
@ -282,11 +300,13 @@ nsmb_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thre
break;
}
case SMBIOC_LOOKUP:
if (sdp->sd_vc || sdp->sd_share)
return EISCONN;
if (sdp->sd_vc || sdp->sd_share) {
error = EISCONN;
goto out;
}
vcp = NULL;
ssp = NULL;
error = smb_usr_lookup((struct smbioc_lookup*)data, &scred, &vcp, &ssp);
error = smb_usr_lookup((struct smbioc_lookup*)data, scred, &vcp, &ssp);
if (error)
break;
if (vcp) {
@ -305,8 +325,10 @@ nsmb_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thre
struct uio auio;
struct iovec iov;
if ((ssp = sdp->sd_share) == NULL)
return ENOTCONN;
if ((ssp = sdp->sd_share) == NULL) {
error = ENOTCONN;
goto out;
}
iov.iov_base = rwrq->ioc_base;
iov.iov_len = rwrq->ioc_cnt;
auio.uio_iov = &iov;
@ -317,15 +339,17 @@ nsmb_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thre
auio.uio_rw = (cmd == SMBIOC_READ) ? UIO_READ : UIO_WRITE;
auio.uio_td = td;
if (cmd == SMBIOC_READ)
error = smb_read(ssp, rwrq->ioc_fh, &auio, &scred);
error = smb_read(ssp, rwrq->ioc_fh, &auio, scred);
else
error = smb_write(ssp, rwrq->ioc_fh, &auio, &scred);
error = smb_write(ssp, rwrq->ioc_fh, &auio, scred);
rwrq->ioc_cnt -= auio.uio_resid;
break;
}
default:
error = ENODEV;
}
out:
free(scred, M_NSMBDEV);
return error;
}

View file

@ -192,8 +192,8 @@ nb_connect_in(struct nbpcb *nbp, struct sockaddr_in *to, struct thread *td)
static int
nbssn_rq_request(struct nbpcb *nbp, struct thread *td)
{
struct mbchain mb, *mbp = &mb;
struct mdchain md, *mdp = &md;
struct mbchain *mbp;
struct mdchain *mdp;
struct mbuf *m0;
struct timeval tv;
struct sockaddr_in sin;
@ -201,9 +201,14 @@ nbssn_rq_request(struct nbpcb *nbp, struct thread *td)
u_int8_t rpcode;
int error, rplen;
mbp = malloc(sizeof(struct mbchain), M_NBDATA, M_WAITOK);
mdp = malloc(sizeof(struct mbchain), M_NBDATA, M_WAITOK);
error = mb_init(mbp);
if (error)
if (error) {
free(mbp, M_NBDATA);
free(mdp, M_NBDATA);
return error;
}
mb_put_uint32le(mbp, 0);
nb_put_name(mbp, nbp->nbp_paddr);
nb_put_name(mbp, nbp->nbp_laddr);
@ -214,19 +219,26 @@ nbssn_rq_request(struct nbpcb *nbp, struct thread *td)
}
mb_detach(mbp);
mb_done(mbp);
if (error)
free(mbp, M_NBDATA);
if (error) {
free(mdp, M_NBDATA);
return error;
}
TIMESPEC_TO_TIMEVAL(&tv, &nbp->nbp_timo);
error = selsocket(nbp->nbp_tso, POLLIN, &tv, td);
if (error == EWOULDBLOCK) { /* Timeout */
NBDEBUG("initial request timeout\n");
free(mdp, M_NBDATA);
return ETIMEDOUT;
}
if (error) /* restart or interrupt */
if (error) { /* restart or interrupt */
free(mdp, M_NBDATA);
return error;
}
error = nbssn_recv(nbp, &m0, &rplen, &rpcode, td);
if (error) {
NBDEBUG("recv() error %d\n", error);
free(mdp, M_NBDATA);
return error;
}
/*
@ -264,6 +276,7 @@ nbssn_rq_request(struct nbpcb *nbp, struct thread *td)
} while(0);
if (m0)
md_done(mdp);
free(mdp, M_NBDATA);
return error;
}

View file

@ -127,8 +127,8 @@ smb_usr_lookup(struct smbioc_lookup *dp, struct smb_cred *scred,
struct smb_vc **vcpp, struct smb_share **sspp)
{
struct smb_vc *vcp = NULL;
struct smb_vcspec vspec;
struct smb_sharespec sspec, *sspecp = NULL;
struct smb_vcspec vspec; /* XXX */
struct smb_sharespec sspec, *sspecp = NULL; /* XXX */
int error;
if (dp->ioc_level < SMBL_VC || dp->ioc_level > SMBL_SHARE)
@ -212,7 +212,7 @@ int
smb_usr_simplerequest(struct smb_share *ssp, struct smbioc_rq *dp,
struct smb_cred *scred)
{
struct smb_rq rq, *rqp = &rq;
struct smb_rq *rqp;
struct mbchain *mbp;
struct mdchain *mdp;
u_int8_t wc;
@ -231,9 +231,12 @@ smb_usr_simplerequest(struct smb_share *ssp, struct smbioc_rq *dp,
case SMB_COM_TREE_CONNECT_ANDX:
return EPERM;
}
rqp = malloc(sizeof(struct smb_rq), M_SMBTEMP, M_WAITOK);
error = smb_rq_init(rqp, SSTOCP(ssp), dp->ioc_cmd, scred);
if (error)
if (error) {
free(rqp, M_SMBTEMP);
return error;
}
mbp = &rqp->sr_rq;
smb_rq_wstart(rqp);
error = mb_put_mem(mbp, dp->ioc_twords, dp->ioc_twc * 2, MB_MUSER);
@ -271,6 +274,7 @@ smb_usr_simplerequest(struct smb_share *ssp, struct smbioc_rq *dp,
dp->ioc_serror = rqp->sr_serror;
dp->ioc_error = rqp->sr_error;
smb_rq_done(rqp);
free(rqp, M_SMBTEMP);
return error;
}
@ -292,15 +296,18 @@ int
smb_usr_t2request(struct smb_share *ssp, struct smbioc_t2rq *dp,
struct smb_cred *scred)
{
struct smb_t2rq t2, *t2p = &t2;
struct smb_t2rq *t2p;
struct mdchain *mdp;
int error, len;
if (dp->ioc_setupcnt > 3)
return EINVAL;
t2p = malloc(sizeof(struct smb_t2rq), M_SMBTEMP, M_WAITOK);
error = smb_t2_init(t2p, SSTOCP(ssp), dp->ioc_setup[0], scred);
if (error)
if (error) {
free(t2p, M_SMBTEMP);
return error;
}
len = t2p->t2_setupcount = dp->ioc_setupcnt;
if (len > 1)
t2p->t2_setupdata = dp->ioc_setup;
@ -351,5 +358,6 @@ smb_usr_t2request(struct smb_share *ssp, struct smbioc_t2rq *dp,
if (t2p->t_name)
smb_strfree(t2p->t_name);
smb_t2_done(t2p);
free(t2p, M_SMBTEMP);
return error;
}