From owner-svn-src-head@FreeBSD.ORG Wed Oct 22 21:55:49 2008 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 387471065679; Wed, 22 Oct 2008 21:55:49 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 2652F8FC18; Wed, 22 Oct 2008 21:55:49 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9MLtmBs039896; Wed, 22 Oct 2008 21:55:48 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9MLtmVa039892; Wed, 22 Oct 2008 21:55:48 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <200810222155.m9MLtmVa039892@svn.freebsd.org> From: John Baldwin Date: Wed, 22 Oct 2008 21:55:48 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184183 - in head/sys: compat/freebsd32 kern sys X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 22 Oct 2008 21:55:49 -0000 Author: jhb Date: Wed Oct 22 21:55:48 2008 New Revision: 184183 URL: http://svn.freebsd.org/changeset/base/184183 Log: Split the copyout of *base at the end of getdirentries() out leaving the rest in kern_getdirentries(). Use kern_getdirentries() to implement freebsd32_getdirentries(). This fixes a bug where calls to getdirentries() in 32-bit binaries would trash the 4 bytes after the 'long base' in userland. Submitted by: ups MFC after: 1 week Modified: head/sys/compat/freebsd32/freebsd32_misc.c head/sys/compat/freebsd32/syscalls.master head/sys/kern/vfs_syscalls.c head/sys/sys/syscallsubr.h Modified: head/sys/compat/freebsd32/freebsd32_misc.c ============================================================================== --- head/sys/compat/freebsd32/freebsd32_misc.c Wed Oct 22 21:46:59 2008 (r184182) +++ head/sys/compat/freebsd32/freebsd32_misc.c Wed Oct 22 21:55:48 2008 (r184183) @@ -1762,6 +1762,24 @@ freebsd32_ftruncate(struct thread *td, s return (ftruncate(td, &ap)); } +int +freebsd32_getdirentries(struct thread *td, + struct freebsd32_getdirentries_args *uap) +{ + long base; + int32_t base32; + int error; + + error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base); + if (error) + return (error); + if (uap->basep != NULL) { + base32 = base; + error = copyout(&base32, uap->basep, sizeof(int32_t)); + } + return (error); +} + #ifdef COMPAT_FREEBSD6 /* versions with the 'int pad' argument */ int Modified: head/sys/compat/freebsd32/syscalls.master ============================================================================== --- head/sys/compat/freebsd32/syscalls.master Wed Oct 22 21:46:59 2008 (r184182) +++ head/sys/compat/freebsd32/syscalls.master Wed Oct 22 21:55:48 2008 (r184183) @@ -350,8 +350,8 @@ 195 AUE_SETRLIMIT NOPROTO { int setrlimit(u_int which, \ struct rlimit *rlp); } setrlimit \ __setrlimit_args int -196 AUE_GETDIRENTRIES NOPROTO { int getdirentries(int fd, char *buf, \ - u_int count, long *basep); } +196 AUE_GETDIRENTRIES STD { int freebsd32_getdirentries(int fd, \ + char *buf, u_int count, int32_t *basep); } 197 AUE_MMAP COMPAT6 { caddr_t freebsd32_mmap(caddr_t addr, \ size_t len, int prot, int flags, int fd, \ int pad, u_int32_t poslo, \ Modified: head/sys/kern/vfs_syscalls.c ============================================================================== --- head/sys/kern/vfs_syscalls.c Wed Oct 22 21:46:59 2008 (r184182) +++ head/sys/kern/vfs_syscalls.c Wed Oct 22 21:55:48 2008 (r184183) @@ -4016,6 +4016,21 @@ getdirentries(td, uap) long *basep; } */ *uap; { + long base; + int error; + + error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base); + if (error) + return (error); + if (uap->basep != NULL) + error = copyout(&base, uap->basep, sizeof(long)); + return (error); +} + +int +kern_getdirentries(struct thread *td, int fd, char *buf, u_int count, + long *basep) +{ struct vnode *vp; struct file *fp; struct uio auio; @@ -4024,8 +4039,8 @@ getdirentries(td, uap) long loff; int error, eofflag; - AUDIT_ARG(fd, uap->fd); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) + AUDIT_ARG(fd, fd); + if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0) return (error); if ((fp->f_flag & FREAD) == 0) { fdrop(fp, td); @@ -4039,14 +4054,14 @@ unionread: error = EINVAL; goto fail; } - aiov.iov_base = uap->buf; - aiov.iov_len = uap->count; + aiov.iov_base = buf; + aiov.iov_len = count; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_USERSPACE; auio.uio_td = td; - auio.uio_resid = uap->count; + auio.uio_resid = count; /* vn_lock(vp, LK_SHARED | LK_RETRY); */ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); AUDIT_ARG(vnode, vp, ARG_VNODE1); @@ -4063,7 +4078,7 @@ unionread: VFS_UNLOCK_GIANT(vfslocked); goto fail; } - if (uap->count == auio.uio_resid && + if (count == auio.uio_resid && (vp->v_vflag & VV_ROOT) && (vp->v_mount->mnt_flag & MNT_UNION)) { struct vnode *tvp = vp; @@ -4078,10 +4093,8 @@ unionread: } VOP_UNLOCK(vp, 0); VFS_UNLOCK_GIANT(vfslocked); - if (uap->basep != NULL) { - error = copyout(&loff, uap->basep, sizeof(long)); - } - td->td_retval[0] = uap->count - auio.uio_resid; + *basep = loff; + td->td_retval[0] = count - auio.uio_resid; fail: fdrop(fp, td); return (error); Modified: head/sys/sys/syscallsubr.h ============================================================================== --- head/sys/sys/syscallsubr.h Wed Oct 22 21:46:59 2008 (r184182) +++ head/sys/sys/syscallsubr.h Wed Oct 22 21:55:48 2008 (r184183) @@ -91,6 +91,8 @@ int kern_fstatfs(struct thread *td, int int kern_ftruncate(struct thread *td, int fd, off_t length); int kern_futimes(struct thread *td, int fd, struct timeval *tptr, enum uio_seg tptrseg); +int kern_getdirentries(struct thread *td, int fd, char *buf, u_int count, + long *basep); int kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize, enum uio_seg bufseg, int flags); int kern_getgroups(struct thread *td, u_int *ngrp, gid_t *groups);