diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2007-06-14 20:36:35 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2007-06-14 20:36:35 +0000 |
commit | 6b09d4aa7f9f0d587f99b245eee31227516e5ee6 (patch) | |
tree | 871f8f2abf34a80e4bd169bed7bc044883e43214 /sys/kern | |
parent | c021e13518192dacd9b5058248c6d5da2cf18137 (diff) |
Forgotten hackton diff: bounds check for seek on special devices
with a disklabel. Original diff from pedro@; ok pedro@ deraadt@
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/vfs_syscalls.c | 37 | ||||
-rw-r--r-- | sys/kern/vfs_vnops.c | 3 |
2 files changed, 27 insertions, 13 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 7c309acf9b4..5b425a0bb21 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_syscalls.c,v 1.139 2007/01/16 17:52:18 thib Exp $ */ +/* $OpenBSD: vfs_syscalls.c,v 1.140 2007/06/14 20:36:34 otto Exp $ */ /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ /* @@ -51,6 +51,8 @@ #include <sys/malloc.h> #include <sys/pool.h> #include <sys/dirent.h> +#include <sys/dkio.h> +#include <sys/disklabel.h> #include <sys/syscallargs.h> @@ -1397,6 +1399,7 @@ sys_lseek(struct proc *p, void *v, register_t *retval) struct file *fp; struct vattr vattr; struct vnode *vp; + off_t offarg, newoff; int error, special; if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL) @@ -1410,30 +1413,42 @@ sys_lseek(struct proc *p, void *v, register_t *retval) special = 1; else special = 0; + offarg = SCARG(uap, offset); + switch (SCARG(uap, whence)) { case SEEK_CUR: - if (!special && fp->f_offset + SCARG(uap, offset) < 0) - return (EINVAL); - fp->f_offset += SCARG(uap, offset); + newoff = fp->f_offset + offarg;; break; case SEEK_END: error = VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p); if (error) return (error); - if (!special && (off_t)vattr.va_size + SCARG(uap, offset) < 0) - return (EINVAL); - fp->f_offset = SCARG(uap, offset) + vattr.va_size; + newoff = offarg + (off_t)vattr.va_size; break; case SEEK_SET: - if (!special && SCARG(uap, offset) < 0) - return (EINVAL); - fp->f_offset = SCARG(uap, offset); + newoff = offarg; break; default: return (EINVAL); } - *(off_t *)retval = fp->f_offset; + if (!special) { + if (newoff < 0) + return (EINVAL); + } else { + /* + * Make sure the user don't seek beyond the end of the + * partition. + */ + struct partinfo dpart; + error = vn_ioctl(fp, DIOCGPART, (void *)&dpart, p); + if (!error) { + if (newoff >= DL_GETPSIZE(dpart.part) * + dpart.disklab->d_secsize) + return (EINVAL); + } + } + *(off_t *)retval = fp->f_offset = newoff; fp->f_seek++; return (0); } diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 79778f113ce..ab92846c193 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_vnops.c,v 1.57 2007/06/01 22:30:46 deraadt Exp $ */ +/* $OpenBSD: vfs_vnops.c,v 1.58 2007/06/14 20:36:34 otto Exp $ */ /* $NetBSD: vfs_vnops.c,v 1.20 1996/02/04 02:18:41 christos Exp $ */ /* @@ -61,7 +61,6 @@ int vn_write(struct file *, off_t *, struct uio *, struct ucred *); int vn_poll(struct file *, int, struct proc *); int vn_kqfilter(struct file *, struct knote *); int vn_closefile(struct file *, struct proc *); -int vn_ioctl(struct file *, u_long, caddr_t, struct proc *); struct fileops vnops = { vn_read, vn_write, vn_ioctl, vn_poll, vn_kqfilter, vn_statfile, |