summaryrefslogtreecommitdiff
path: root/sys/kern/vfs_syscalls.c
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>2006-11-24 17:04:21 +0000
committerArtur Grabowski <art@cvs.openbsd.org>2006-11-24 17:04:21 +0000
commit56285a1cd929f62c7bdeb22f32c57362c9ee5fe3 (patch)
tree6a2da2d88beccaeea08dcd62fd36e0481877f8d7 /sys/kern/vfs_syscalls.c
parent7fbffbaf7e3799b9cd7a8945cea919cc091ca8d1 (diff)
When copying out struct statfs to userland, we need to zero out the fsid
field unless it's root that's asking. This far, this has been done by putting a struct statfs on the stack and modifying it. struct statfs is large. Large things on the stack are bad. Create copyout_statfs() that copies out a struct statfs to userland, does the necessary root check and gives userland what it needs withtout wasting stack space. pedro@, deraadt@ ok.
Diffstat (limited to 'sys/kern/vfs_syscalls.c')
-rw-r--r--sys/kern/vfs_syscalls.c67
1 files changed, 39 insertions, 28 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 27c06b5ed8e..6e734e3cdd9 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_syscalls.c,v 1.137 2006/06/25 15:01:54 sturm Exp $ */
+/* $OpenBSD: vfs_syscalls.c,v 1.138 2006/11/24 17:04:20 art Exp $ */
/* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */
/*
@@ -64,6 +64,8 @@ static int change_dir(struct nameidata *, struct proc *);
void checkdirs(struct vnode *);
+int copyout_statfs(struct statfs *, void *, struct proc *);
+
/*
* Virtual File System System Calls
*/
@@ -520,6 +522,34 @@ sys_quotactl(struct proc *p, void *v, register_t *retval)
SCARG(uap, arg), p));
}
+int
+copyout_statfs(struct statfs *sp, void *uaddr, struct proc *p)
+{
+ size_t co_sz1 = offsetof(struct statfs, f_fsid);
+ size_t co_off2 = co_sz1 + sizeof(fsid_t);
+ size_t co_sz2 = sizeof(struct statfs) - co_off2;
+ char *s, *d;
+ int error;
+
+ /* Don't let non-root see filesystem id (for NFS security) */
+ if (suser(p, 0)) {
+ fsid_t fsid;
+
+ s = (char *)sp;
+ d = (char *)uaddr;
+
+ memset(&fsid, 0, sizeof(fsid));
+
+ if ((error = copyout(s, d, co_sz1)) != 0)
+ return (error);
+ if ((error = copyout(&fsid, d + co_sz1, sizeof(fsid))) != 0)
+ return (error);
+ return (copyout(s + co_off2, d + co_off2, co_sz2));
+ }
+
+ return (copyout(sp, uaddr, sizeof(*sp)));
+}
+
/*
* Get filesystem statistics.
*/
@@ -535,7 +565,6 @@ sys_statfs(struct proc *p, void *v, register_t *retval)
struct statfs *sp;
int error;
struct nameidata nd;
- struct statfs sb;
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
if ((error = namei(&nd)) != 0)
@@ -550,13 +579,7 @@ sys_statfs(struct proc *p, void *v, register_t *retval)
if (mp->mnt_flag & MNT_SOFTDEP)
sp->f_eflags = STATFS_SOFTUPD;
#endif
- /* Don't let non-root see filesystem id (for NFS security) */
- if (suser(p, 0)) {
- bcopy(sp, &sb, sizeof(sb));
- sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
- sp = &sb;
- }
- return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
+ return (copyout_statfs(sp, SCARG(uap, buf), p));
}
/*
@@ -574,7 +597,6 @@ sys_fstatfs(struct proc *p, void *v, register_t *retval)
struct mount *mp;
struct statfs *sp;
int error;
- struct statfs sb;
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
return (error);
@@ -593,13 +615,7 @@ sys_fstatfs(struct proc *p, void *v, register_t *retval)
if (mp->mnt_flag & MNT_SOFTDEP)
sp->f_eflags = STATFS_SOFTUPD;
#endif
- /* Don't let non-root see filesystem id (for NFS security) */
- if (suser(p, 0)) {
- bcopy(sp, &sb, sizeof(sb));
- sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
- sp = &sb;
- }
- return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
+ return (copyout_statfs(sp, SCARG(uap, buf), p));
}
/*
@@ -615,7 +631,6 @@ sys_getfsstat(struct proc *p, void *v, register_t *retval)
} */ *uap = v;
struct mount *mp, *nmp;
struct statfs *sp;
- struct statfs sb;
struct statfs *sfsp;
size_t count, maxcount;
int error, flags = SCARG(uap, flags);
@@ -649,12 +664,7 @@ sys_getfsstat(struct proc *p, void *v, register_t *retval)
if (mp->mnt_flag & MNT_SOFTDEP)
sp->f_eflags = STATFS_SOFTUPD;
#endif
- if (suser(p, 0)) {
- bcopy(sp, &sb, sizeof(sb));
- sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
- sp = &sb;
- }
- error = copyout(sp, sfsp, sizeof(*sp));
+ error = (copyout_statfs(sp, sfsp, p));
if (error) {
vfs_unbusy(mp);
return (error);
@@ -1121,7 +1131,7 @@ sys_fhstatfs(struct proc *p, void *v, register_t *retval)
syscallarg(const fhandle_t *) fhp;
syscallarg(struct statfs *) buf;
} */ *uap = v;
- struct statfs sp;
+ struct statfs *sp;
fhandle_t fh;
struct mount *mp;
struct vnode *vp;
@@ -1141,11 +1151,12 @@ sys_fhstatfs(struct proc *p, void *v, register_t *retval)
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)
+ if ((error = VFS_STATFS(mp, sp, p)) != 0)
return (error);
- sp.f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
- return (copyout(&sp, SCARG(uap, buf), sizeof(sp)));
+ sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ return (copyout(sp, SCARG(uap, buf), sizeof(sp)));
}
/*