- sys___getfh30:
- restructure code so that it doesn't try to allocate user-specified unbound amount of memory. - don't ignore copyout failure in the case of E2BIG. - rename vfs_copyinfh to vfs_copyinfh_alloc for consistency.
This commit is contained in:
parent
e19a48dbd2
commit
cf80fa09d3
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: vfs_syscalls.c,v 1.248 2006/07/14 15:59:29 yamt Exp $ */
|
||||
/* $NetBSD: vfs_syscalls.c,v 1.249 2006/07/14 18:29:40 yamt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.248 2006/07/14 15:59:29 yamt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.249 2006/07/14 18:29:40 yamt Exp $");
|
||||
|
||||
#include "opt_compat_netbsd.h"
|
||||
#include "opt_compat_43.h"
|
||||
|
@ -1203,6 +1203,18 @@ sys_open(struct lwp *l, void *v, register_t *retval)
|
|||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
vfs__fhfree(fhandle_t *fhp)
|
||||
{
|
||||
size_t fhsize;
|
||||
|
||||
if (fhp == NULL) {
|
||||
return;
|
||||
}
|
||||
fhsize = FHANDLE_SIZE(fhp);
|
||||
kmem_free(fhp, fhsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* vfs_composefh: compose a filehandle.
|
||||
*/
|
||||
|
@ -1232,6 +1244,53 @@ vfs_composefh(struct vnode *vp, fhandle_t *fhp, size_t *fh_size)
|
|||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
vfs_composefh_alloc(struct vnode *vp, fhandle_t **fhpp)
|
||||
{
|
||||
struct mount *mp;
|
||||
fhandle_t *fhp;
|
||||
size_t fhsize;
|
||||
size_t fidsize;
|
||||
int error;
|
||||
|
||||
*fhpp = NULL;
|
||||
mp = vp->v_mount;
|
||||
if (mp->mnt_op->vfs_vptofh == NULL) {
|
||||
error = EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
fhsize = 0;
|
||||
error = VFS_VPTOFH(vp, NULL, &fidsize);
|
||||
KASSERT(error != 0);
|
||||
if (error != E2BIG) {
|
||||
goto out;
|
||||
}
|
||||
fhsize = offsetof(fhandle_t, fh_fid) + fidsize;
|
||||
fhp = kmem_zalloc(fhsize, KM_SLEEP);
|
||||
if (fhp == NULL) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
fhp->fh_fsid = mp->mnt_stat.f_fsidx;
|
||||
error = VFS_VPTOFH(vp, &fhp->fh_fid, &fidsize);
|
||||
if (error == 0) {
|
||||
KASSERT((FHANDLE_SIZE(fhp) == fhsize &&
|
||||
FHANDLE_FILEID(fhp)->fid_len == fidsize));
|
||||
*fhpp = fhp;
|
||||
} else {
|
||||
kmem_free(fhp, fhsize);
|
||||
}
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
||||
void
|
||||
vfs_composefh_free(fhandle_t *fhp)
|
||||
{
|
||||
|
||||
vfs__fhfree(fhp);
|
||||
}
|
||||
|
||||
/*
|
||||
* vfs_fhtovp: lookup a vnode by a filehandle.
|
||||
*/
|
||||
|
@ -1262,7 +1321,7 @@ out:
|
|||
*/
|
||||
|
||||
int
|
||||
vfs_copyinfh(const void *ufhp, fhandle_t **fhpp)
|
||||
vfs_copyinfh_alloc(const void *ufhp, fhandle_t **fhpp)
|
||||
{
|
||||
fhandle_t *fhp;
|
||||
fhandle_t tempfh;
|
||||
|
@ -1291,13 +1350,8 @@ vfs_copyinfh(const void *ufhp, fhandle_t **fhpp)
|
|||
void
|
||||
vfs_copyinfh_free(fhandle_t *fhp)
|
||||
{
|
||||
size_t fhsize;
|
||||
|
||||
if (fhp == NULL) {
|
||||
return;
|
||||
}
|
||||
fhsize = FHANDLE_SIZE(fhp);
|
||||
kmem_free(fhp, fhsize);
|
||||
vfs__fhfree(fhp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1317,6 +1371,7 @@ sys___getfh30(struct lwp *l, void *v, register_t *retval)
|
|||
int error;
|
||||
struct nameidata nd;
|
||||
size_t sz;
|
||||
size_t usz;
|
||||
|
||||
/*
|
||||
* Must be super user
|
||||
|
@ -1325,29 +1380,33 @@ sys___getfh30(struct lwp *l, void *v, register_t *retval)
|
|||
&p->p_acflag);
|
||||
if (error)
|
||||
return (error);
|
||||
fh = NULL;
|
||||
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
|
||||
SCARG(uap, fname), l);
|
||||
error = namei(&nd);
|
||||
if (error)
|
||||
return (error);
|
||||
vp = nd.ni_vp;
|
||||
error = copyin(SCARG(uap, fh_size), &sz, sizeof(size_t));
|
||||
error = vfs_composefh_alloc(vp, &fh);
|
||||
vput(vp);
|
||||
if (!error) {
|
||||
fh = malloc(sz, M_TEMP, M_WAITOK);
|
||||
if (fh == NULL)
|
||||
return EINVAL;
|
||||
error = vfs_composefh(vp, fh, &sz);
|
||||
if (error != 0) {
|
||||
goto out;
|
||||
}
|
||||
if (error == E2BIG)
|
||||
copyout(&sz, SCARG(uap, fh_size), sizeof(size_t));
|
||||
if (error == 0) {
|
||||
error = copyout(&sz, SCARG(uap, fh_size), sizeof(size_t));
|
||||
if (!error)
|
||||
error = copyout(fh, SCARG(uap, fhp), sz);
|
||||
error = copyin(SCARG(uap, fh_size), &usz, sizeof(size_t));
|
||||
if (error != 0) {
|
||||
goto out;
|
||||
}
|
||||
free(fh, M_TEMP);
|
||||
sz = FHANDLE_SIZE(fh);
|
||||
error = copyout(&sz, SCARG(uap, fh_size), sizeof(size_t));
|
||||
if (error != 0) {
|
||||
goto out;
|
||||
}
|
||||
if (usz >= sz) {
|
||||
error = copyout(fh, SCARG(uap, fhp), sz);
|
||||
} else {
|
||||
error = E2BIG;
|
||||
}
|
||||
out:
|
||||
vfs_composefh_free(fh);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
@ -1393,7 +1452,7 @@ sys_fhopen(struct lwp *l, void *v, register_t *retval)
|
|||
if ((error = falloc(p, &nfp, &indx)) != 0)
|
||||
return (error);
|
||||
fp = nfp;
|
||||
error = vfs_copyinfh(SCARG(uap, fhp), &fh);
|
||||
error = vfs_copyinfh_alloc(SCARG(uap, fhp), &fh);
|
||||
if (error != 0) {
|
||||
goto bad;
|
||||
}
|
||||
|
@ -1511,7 +1570,7 @@ sys___fhstat30(struct lwp *l, void *v, register_t *retval)
|
|||
&p->p_acflag)))
|
||||
return (error);
|
||||
|
||||
error = vfs_copyinfh(SCARG(uap, fhp), &fh);
|
||||
error = vfs_copyinfh_alloc(SCARG(uap, fhp), &fh);
|
||||
if (error != 0) {
|
||||
goto bad;
|
||||
}
|
||||
|
@ -1553,7 +1612,7 @@ sys_fhstatvfs1(struct lwp *l, void *v, register_t *retval)
|
|||
&p->p_acflag)) != 0)
|
||||
return error;
|
||||
|
||||
error = vfs_copyinfh(SCARG(uap, fhp), &fh);
|
||||
error = vfs_copyinfh_alloc(SCARG(uap, fhp), &fh);
|
||||
if (error != 0) {
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: mount.h,v 1.145 2006/07/14 15:59:29 yamt Exp $ */
|
||||
/* $NetBSD: mount.h,v 1.146 2006/07/14 18:29:40 yamt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1991, 1993
|
||||
|
@ -272,7 +272,9 @@ MALLOC_DECLARE(M_MOUNT);
|
|||
* exported VFS interface (see vfssubr(9))
|
||||
*/
|
||||
struct mount *vfs_getvfs(fsid_t *); /* return vfs given fsid */
|
||||
int vfs_composefh(struct vnode *, fhandle_t *, size_t *fh_size);
|
||||
int vfs_composefh(struct vnode *, fhandle_t *, size_t *);
|
||||
int vfs_composefh_alloc(struct vnode *, fhandle_t **);
|
||||
void vfs_composefh_free(fhandle_t *);
|
||||
int vfs_fhtovp(fhandle_t *, struct vnode **);
|
||||
int vfs_mountedon(struct vnode *);/* is a vfs mounted on vp */
|
||||
int vfs_mountroot(void);
|
||||
|
@ -307,7 +309,7 @@ void vfs_bufstats(void);
|
|||
* syscall helpers
|
||||
*/
|
||||
|
||||
int vfs_copyinfh(const void *, fhandle_t **);
|
||||
int vfs_copyinfh_alloc(const void *, fhandle_t **);
|
||||
void vfs_copyinfh_free(fhandle_t *);
|
||||
|
||||
LIST_HEAD(vfs_list_head, vfsops);
|
||||
|
|
Loading…
Reference in New Issue