Here it is what POSIX says about lseek():
[EINVAL]
The whence argument is not a proper value, or the resulting file offset
would be negative for a regular file, block special file, or directory.
[EOVERFLOW]
The resulting file offset would be a value which cannot be represented
correctly in an object of type off_t.
The patch below adds both cases, i.e. disallow negative seeks for VREG,
VDIR, VBLK and add off_t overflow checks.
I plan to commit this, please review.
--- vfs_syscalls.c.old Wed Aug 15 04:45:30 2001
+++ vfs_syscalls.c Wed Aug 15 12:46:12 2001
@@ -1614,29 +1614,44 @@
register struct filedesc *fdp = p->p_fd;
register struct file *fp;
struct vattr vattr;
- int error;
+ off_t offset;
+ int error, no_neg_seek;
if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
(fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
return (EBADF);
if (fp->f_type != DTYPE_VNODE)
return (ESPIPE);
+ error = VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p);
+ no_neg_seek = (!error &&
+ (vattr.va_type == VREG ||
+ vattr.va_type == VDIR ||
+ vattr.va_type == VBLK));
+ offset = SCARG(uap, offset);
switch (SCARG(uap, whence)) {
case L_INCR:
- fp->f_offset += SCARG(uap, offset);
+ if ((fp->f_offset > 0 && offset > 0 &&
+ offset + fp->f_offset < 0) ||
+ (fp->f_offset < 0 && offset < 0 &&
+ offset + fp->f_offset > 0))
+ return (EOVERFLOW);
+ offset += fp->f_offset;
break;
case L_XTND:
- error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p);
if (error)
return (error);
- fp->f_offset = SCARG(uap, offset) + vattr.va_size;
+ if (offset > 0 && (off_t)(offset + vattr.va_size) < 0)
+ return (EOVERFLOW);
+ offset += vattr.va_size;
break;
case L_SET:
- fp->f_offset = SCARG(uap, offset);
break;
default:
return (EINVAL);
}
+ if (no_neg_seek && offset < 0)
+ return (EINVAL);
+ fp->f_offset = offset;
*(off_t *)(p->p_retval) = fp->f_offset;
return (0);
}
--
Andrey A. Chernov
http://ache.pp.ru/
To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message