diff options
author | alfred <alfred@FreeBSD.org> | 1999-09-11 00:46:08 +0000 |
---|---|---|
committer | alfred <alfred@FreeBSD.org> | 1999-09-11 00:46:08 +0000 |
commit | b9136a6115cbac97ab114f16b1aacf4eb20ad2c1 (patch) | |
tree | 783daf81f8570ef14570d4a5a6fc45f15ec1cbf5 /sys/kern | |
parent | a9f7b5ee698afe56d1167bfa395f23b1fff1730c (diff) | |
download | FreeBSD-src-b9136a6115cbac97ab114f16b1aacf4eb20ad2c1.zip FreeBSD-src-b9136a6115cbac97ab114f16b1aacf4eb20ad2c1.tar.gz |
Seperate the export check in VFS_FHTOVP, exports are now checked via
VFS_CHECKEXP.
Add fh(open|stat|stafs) syscalls to allow userland to query filesystems
based on (network) filehandle.
Obtained from: NetBSD
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/init_sysent.c | 7 | ||||
-rw-r--r-- | sys/kern/syscalls.c | 7 | ||||
-rw-r--r-- | sys/kern/syscalls.master | 7 | ||||
-rw-r--r-- | sys/kern/vfs_default.c | 13 | ||||
-rw-r--r-- | sys/kern/vfs_extattr.c | 293 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 293 |
6 files changed, 604 insertions, 16 deletions
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index e37f1f0..592cd14 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -2,6 +2,7 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. + * $FreeBSD$ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.63 1999/08/28 00:46:19 peter Exp */ @@ -316,9 +317,9 @@ struct sysent sysent[] = { { 0, (sy_call_t *)nosys }, /* 294 = nosys */ { 0, (sy_call_t *)nosys }, /* 295 = nosys */ { 0, (sy_call_t *)nosys }, /* 296 = nosys */ - { 0, (sy_call_t *)nosys }, /* 297 = nosys */ - { 0, (sy_call_t *)nosys }, /* 298 = nosys */ - { 0, (sy_call_t *)nosys }, /* 299 = nosys */ + { 2, (sy_call_t *)fhstatfs }, /* 297 = fhstatfs */ + { 2, (sy_call_t *)fhopen }, /* 298 = fhopen */ + { 2, (sy_call_t *)fhstat }, /* 299 = fhstat */ { 1, (sy_call_t *)modnext }, /* 300 = modnext */ { 2, (sy_call_t *)modstat }, /* 301 = modstat */ { 1, (sy_call_t *)modfnext }, /* 302 = modfnext */ diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 3a1cd36..8f99132 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -2,6 +2,7 @@ * System call names. * * DO NOT EDIT-- this file is automatically generated. + * $FreeBSD$ * created from FreeBSD: src/sys/kern/syscalls.master,v 1.63 1999/08/28 00:46:19 peter Exp */ @@ -303,9 +304,9 @@ char *syscallnames[] = { "#294", /* 294 = nosys */ "#295", /* 295 = nosys */ "#296", /* 296 = nosys */ - "#297", /* 297 = nosys */ - "#298", /* 298 = nosys */ - "#299", /* 299 = nosys */ + "fhstatfs", /* 297 = fhstatfs */ + "fhopen", /* 298 = fhopen */ + "fhstat", /* 299 = fhstat */ "modnext", /* 300 = modnext */ "modstat", /* 301 = modstat */ "modfnext", /* 302 = modfnext */ diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 843cc9d..a0d1457 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -428,9 +428,10 @@ 294 UNIMPL NOHIDE nosys 295 UNIMPL NOHIDE nosys 296 UNIMPL NOHIDE nosys -297 UNIMPL NOHIDE nosys -298 UNIMPL NOHIDE nosys -299 UNIMPL NOHIDE nosys +; XXX 297 is 300 in NetBSD +297 STD BSD { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } +298 STD BSD { int fhopen(const struct fhandle *u_fhp, int flags); } +299 STD BSD { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } ; syscall numbers for FreeBSD 300 STD BSD { int modnext(int modid); } 301 STD BSD { int modstat(int modid, struct module_stat* stat); } diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index f089298..1d3e27d 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -580,12 +580,19 @@ vfs_stdvget (mp, ino, vpp) } int -vfs_stdfhtovp (mp, fhp, nam, vpp, exflagsp, credanonp) +vfs_stdfhtovp (mp, fhp, vpp) struct mount *mp; struct fid *fhp; - struct sockaddr *nam; struct vnode **vpp; - int *exflagsp; +{ + return (EOPNOTSUPP); +} + +int +vfs_stdcheckexp (mp, nam, extflagsp, credanonp) + struct mount *mp; + struct sockaddr *nam; + int *extflagsp; struct ucred **credanonp; { return (EOPNOTSUPP); diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index ae7aeeb4..e5354f6 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -46,6 +46,8 @@ #include <sys/systm.h> #include <sys/buf.h> #include <sys/sysent.h> +#include <sys/malloc.h> +#include <sys/mount.h> #include <sys/sysproto.h> #include <sys/namei.h> #include <sys/filedesc.h> @@ -56,8 +58,6 @@ #include <sys/stat.h> #include <sys/unistd.h> #include <sys/vnode.h> -#include <sys/malloc.h> -#include <sys/mount.h> #include <sys/proc.h> #include <sys/dirent.h> @@ -3130,3 +3130,292 @@ __getcwd(p, uap) free(buf, M_TEMP); return (error); } + +/* + * Get (NFS) file handle + */ +#ifndef _SYS_SYSPROTO_H_ +struct getfh_args { + char *fname; + fhandle_t *fhp; +}; +#endif +int +getfh(p, uap) + struct proc *p; + register struct getfh_args *uap; +{ + struct nameidata nd; + fhandle_t fh; + register struct vnode *vp; + int error; + + /* + * Must be super user + */ + error = suser(p); + if (error) + return (error); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); + error = namei(&nd); + if (error) + return (error); + vp = nd.ni_vp; + bzero(&fh, sizeof(fh)); + fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; + error = VFS_VPTOFH(vp, &fh.fh_fid); + vput(vp); + if (error) + return (error); + error = copyout(&fh, uap->fhp, sizeof (fh)); + return (error); +} + +/* + * syscall for the rpc.lockd to use to translate a NFS file handle into + * an open descriptor. + * + * warning: do not remove the suser() call or this becomes one giant + * security hole. + */ +#ifndef _SYS_SYSPROTO_H_ +struct fhopen_args { + const struct fhandle *u_fhp; + int flags; +}; +#endif +int +fhopen(p, uap) + struct proc *p; + struct fhopen_args /* { + syscallarg(const struct fhandle *) u_fhp; + syscallarg(int) flags; + } */ *uap; +{ + struct mount *mp; + struct vnode *vp; + struct fhandle fhp; + struct vattr vat; + struct vattr *vap = &vat; + struct flock lf; + struct file *fp; + register struct filedesc *fdp = p->p_fd; + int fmode, mode, error, type; + struct file *nfp; + int indx; + + /* + * Must be super user + */ + error = suser(p); + if (error) + return (error); + + fmode = FFLAGS(SCARG(uap, flags)); + /* why not allow a non-read/write open for our lockd? */ + if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT)) + return (EINVAL); + error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp)); + if (error) + return(error); + /* find the mount point */ + mp = vfs_getvfs(&fhp.fh_fsid); + if (mp == NULL) + return (ESTALE); + /* now give me my vnode, it gets returned to me locked */ + error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp); + if (error) + return (error); + /* + * from now on we have to make sure not + * to forget about the vnode + * any error that causes an abort must vput(vp) + * just set error = err and 'goto bad;'. + */ + + /* + * from vn_open + */ + if (vp->v_type == VLNK) { + error = EMLINK; + goto bad; + } + if (vp->v_type == VSOCK) { + error = EOPNOTSUPP; + goto bad; + } + mode = 0; + if (fmode & (FWRITE | O_TRUNC)) { + if (vp->v_type == VDIR) { + error = EISDIR; + goto bad; + } + error = vn_writechk(vp); + if (error) + goto bad; + mode |= VWRITE; + } + if (fmode & FREAD) + mode |= VREAD; + if (mode) { + error = VOP_ACCESS(vp, mode, p->p_ucred, p); + if (error) + goto bad; + } + if (fmode & O_TRUNC) { + VOP_UNLOCK(vp, 0, p); /* XXX */ + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */ + VATTR_NULL(vap); + vap->va_size = 0; + error = VOP_SETATTR(vp, vap, p->p_ucred, p); + if (error) + goto bad; + } + error = VOP_OPEN(vp, fmode, p->p_ucred, p); + if (error) + goto bad; + /* + * Make sure that a VM object is created for VMIO support. + */ + if (vn_canvmio(vp) == TRUE) { + if ((error = vfs_object_create(vp, p, p->p_ucred)) != 0) + goto bad; + } + if (fmode & FWRITE) + vp->v_writecount++; + + /* + * end of vn_open code + */ + + if ((error = falloc(p, &nfp, &indx)) != 0) + goto bad; + fp = nfp; + nfp->f_data = (caddr_t)vp; + nfp->f_flag = fmode & FMASK; + nfp->f_ops = &vnops; + nfp->f_type = DTYPE_VNODE; + if (fmode & (O_EXLOCK | O_SHLOCK)) { + lf.l_whence = SEEK_SET; + lf.l_start = 0; + lf.l_len = 0; + if (fmode & O_EXLOCK) + lf.l_type = F_WRLCK; + else + lf.l_type = F_RDLCK; + type = F_FLOCK; + if ((fmode & FNONBLOCK) == 0) + type |= F_WAIT; + VOP_UNLOCK(vp, 0, p); + if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) { + (void) vn_close(vp, fp->f_flag, fp->f_cred, p); + ffree(fp); + fdp->fd_ofiles[indx] = NULL; + return (error); + } + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + fp->f_flag |= FHASLOCK; + } + if ((vp->v_type == VREG) && (vp->v_object == NULL)) + vfs_object_create(vp, p, p->p_ucred); + + VOP_UNLOCK(vp, 0, p); + p->p_retval[0] = indx; + return (0); + +bad: + vput(vp); + return (error); +} + +#ifndef _SYS_SYSPROTO_H_ +struct fhstat_args { + struct fhandle *u_fhp; + struct stat *sb; +}; +#endif +int +fhstat(p, uap) + struct proc *p; + register struct fhstat_args /* { + syscallarg(struct fhandle *) u_fhp; + syscallarg(struct stat *) sb; + } */ *uap; +{ + struct stat sb; + fhandle_t fh; + struct mount *mp; + struct vnode *vp; + int error; + + /* + * Must be super user + */ + error = suser(p); + if (error) + return (error); + + error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t)); + if (error) + return (error); + + if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) + return (ESTALE); + if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) + return (error); + error = vn_stat(vp, &sb, p); + vput(vp); + if (error) + return (error); + error = copyout(&sb, SCARG(uap, sb), sizeof(sb)); + return (error); +} + +#ifndef _SYS_SYSPROTO_H_ +struct fhstatfs_args { + struct fhandle *u_fhp; + struct statfs *buf; +}; +#endif +int +fhstatfs(p, uap) + struct proc *p; + struct fhstatfs_args /* { + syscallarg(struct fhandle) *u_fhp; + syscallarg(struct statfs) *buf; + } */ *uap; +{ + struct statfs *sp; + struct mount *mp; + struct vnode *vp; + struct statfs sb; + fhandle_t fh; + int error; + + /* + * Must be super user + */ + if ((error = suser(p))) + return (error); + + if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0) + return (error); + + if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) + return (ESTALE); + if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) + return (error); + mp = vp->v_mount; + sp = &mp->mnt_stat; + vput(vp); + if ((error = VFS_STATFS(mp, sp, p)) != 0) + return (error); + sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; + if (suser_xxx(p->p_ucred, 0, 0)) { + bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); + sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; + sp = &sb; + } + return (copyout(sp, SCARG(uap, buf), sizeof(*sp))); +} diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index ae7aeeb4..e5354f6 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -46,6 +46,8 @@ #include <sys/systm.h> #include <sys/buf.h> #include <sys/sysent.h> +#include <sys/malloc.h> +#include <sys/mount.h> #include <sys/sysproto.h> #include <sys/namei.h> #include <sys/filedesc.h> @@ -56,8 +58,6 @@ #include <sys/stat.h> #include <sys/unistd.h> #include <sys/vnode.h> -#include <sys/malloc.h> -#include <sys/mount.h> #include <sys/proc.h> #include <sys/dirent.h> @@ -3130,3 +3130,292 @@ __getcwd(p, uap) free(buf, M_TEMP); return (error); } + +/* + * Get (NFS) file handle + */ +#ifndef _SYS_SYSPROTO_H_ +struct getfh_args { + char *fname; + fhandle_t *fhp; +}; +#endif +int +getfh(p, uap) + struct proc *p; + register struct getfh_args *uap; +{ + struct nameidata nd; + fhandle_t fh; + register struct vnode *vp; + int error; + + /* + * Must be super user + */ + error = suser(p); + if (error) + return (error); + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); + error = namei(&nd); + if (error) + return (error); + vp = nd.ni_vp; + bzero(&fh, sizeof(fh)); + fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; + error = VFS_VPTOFH(vp, &fh.fh_fid); + vput(vp); + if (error) + return (error); + error = copyout(&fh, uap->fhp, sizeof (fh)); + return (error); +} + +/* + * syscall for the rpc.lockd to use to translate a NFS file handle into + * an open descriptor. + * + * warning: do not remove the suser() call or this becomes one giant + * security hole. + */ +#ifndef _SYS_SYSPROTO_H_ +struct fhopen_args { + const struct fhandle *u_fhp; + int flags; +}; +#endif +int +fhopen(p, uap) + struct proc *p; + struct fhopen_args /* { + syscallarg(const struct fhandle *) u_fhp; + syscallarg(int) flags; + } */ *uap; +{ + struct mount *mp; + struct vnode *vp; + struct fhandle fhp; + struct vattr vat; + struct vattr *vap = &vat; + struct flock lf; + struct file *fp; + register struct filedesc *fdp = p->p_fd; + int fmode, mode, error, type; + struct file *nfp; + int indx; + + /* + * Must be super user + */ + error = suser(p); + if (error) + return (error); + + fmode = FFLAGS(SCARG(uap, flags)); + /* why not allow a non-read/write open for our lockd? */ + if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT)) + return (EINVAL); + error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp)); + if (error) + return(error); + /* find the mount point */ + mp = vfs_getvfs(&fhp.fh_fsid); + if (mp == NULL) + return (ESTALE); + /* now give me my vnode, it gets returned to me locked */ + error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp); + if (error) + return (error); + /* + * from now on we have to make sure not + * to forget about the vnode + * any error that causes an abort must vput(vp) + * just set error = err and 'goto bad;'. + */ + + /* + * from vn_open + */ + if (vp->v_type == VLNK) { + error = EMLINK; + goto bad; + } + if (vp->v_type == VSOCK) { + error = EOPNOTSUPP; + goto bad; + } + mode = 0; + if (fmode & (FWRITE | O_TRUNC)) { + if (vp->v_type == VDIR) { + error = EISDIR; + goto bad; + } + error = vn_writechk(vp); + if (error) + goto bad; + mode |= VWRITE; + } + if (fmode & FREAD) + mode |= VREAD; + if (mode) { + error = VOP_ACCESS(vp, mode, p->p_ucred, p); + if (error) + goto bad; + } + if (fmode & O_TRUNC) { + VOP_UNLOCK(vp, 0, p); /* XXX */ + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */ + VATTR_NULL(vap); + vap->va_size = 0; + error = VOP_SETATTR(vp, vap, p->p_ucred, p); + if (error) + goto bad; + } + error = VOP_OPEN(vp, fmode, p->p_ucred, p); + if (error) + goto bad; + /* + * Make sure that a VM object is created for VMIO support. + */ + if (vn_canvmio(vp) == TRUE) { + if ((error = vfs_object_create(vp, p, p->p_ucred)) != 0) + goto bad; + } + if (fmode & FWRITE) + vp->v_writecount++; + + /* + * end of vn_open code + */ + + if ((error = falloc(p, &nfp, &indx)) != 0) + goto bad; + fp = nfp; + nfp->f_data = (caddr_t)vp; + nfp->f_flag = fmode & FMASK; + nfp->f_ops = &vnops; + nfp->f_type = DTYPE_VNODE; + if (fmode & (O_EXLOCK | O_SHLOCK)) { + lf.l_whence = SEEK_SET; + lf.l_start = 0; + lf.l_len = 0; + if (fmode & O_EXLOCK) + lf.l_type = F_WRLCK; + else + lf.l_type = F_RDLCK; + type = F_FLOCK; + if ((fmode & FNONBLOCK) == 0) + type |= F_WAIT; + VOP_UNLOCK(vp, 0, p); + if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) { + (void) vn_close(vp, fp->f_flag, fp->f_cred, p); + ffree(fp); + fdp->fd_ofiles[indx] = NULL; + return (error); + } + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + fp->f_flag |= FHASLOCK; + } + if ((vp->v_type == VREG) && (vp->v_object == NULL)) + vfs_object_create(vp, p, p->p_ucred); + + VOP_UNLOCK(vp, 0, p); + p->p_retval[0] = indx; + return (0); + +bad: + vput(vp); + return (error); +} + +#ifndef _SYS_SYSPROTO_H_ +struct fhstat_args { + struct fhandle *u_fhp; + struct stat *sb; +}; +#endif +int +fhstat(p, uap) + struct proc *p; + register struct fhstat_args /* { + syscallarg(struct fhandle *) u_fhp; + syscallarg(struct stat *) sb; + } */ *uap; +{ + struct stat sb; + fhandle_t fh; + struct mount *mp; + struct vnode *vp; + int error; + + /* + * Must be super user + */ + error = suser(p); + if (error) + return (error); + + error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t)); + if (error) + return (error); + + if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) + return (ESTALE); + if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) + return (error); + error = vn_stat(vp, &sb, p); + vput(vp); + if (error) + return (error); + error = copyout(&sb, SCARG(uap, sb), sizeof(sb)); + return (error); +} + +#ifndef _SYS_SYSPROTO_H_ +struct fhstatfs_args { + struct fhandle *u_fhp; + struct statfs *buf; +}; +#endif +int +fhstatfs(p, uap) + struct proc *p; + struct fhstatfs_args /* { + syscallarg(struct fhandle) *u_fhp; + syscallarg(struct statfs) *buf; + } */ *uap; +{ + struct statfs *sp; + struct mount *mp; + struct vnode *vp; + struct statfs sb; + fhandle_t fh; + int error; + + /* + * Must be super user + */ + if ((error = suser(p))) + return (error); + + if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0) + return (error); + + if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) + return (ESTALE); + if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) + return (error); + mp = vp->v_mount; + sp = &mp->mnt_stat; + vput(vp); + if ((error = VFS_STATFS(mp, sp, p)) != 0) + return (error); + sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; + if (suser_xxx(p->p_ucred, 0, 0)) { + bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); + sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; + sp = &sb; + } + return (copyout(sp, SCARG(uap, buf), sizeof(*sp))); +} |