From owner-freebsd-current Wed Aug 15 1:53: 5 2001 Delivered-To: freebsd-current@freebsd.org Received: from hermes.dialup.ru (hermes.dialup.ru [194.87.16.230]) by hub.freebsd.org (Postfix) with ESMTP id 2BE6D37B405; Wed, 15 Aug 2001 01:52:51 -0700 (PDT) (envelope-from ache@hermes.dialup.ru) Received: (from ache@localhost) by hermes.dialup.ru (8.11.5/8.11.5) id f7F8qm702600; Wed, 15 Aug 2001 12:52:48 +0400 (MSD) (envelope-from ache) Date: Wed, 15 Aug 2001 12:52:48 +0400 From: "Andrey A. Chernov" To: arch@freebsd.org, current@freebsd.org Subject: CFR: lseek() POSIXed patch Message-ID: <20010815125248.A2588@nagual.pp.ru> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5i Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG 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 majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message