Date: Wed, 21 Jan 2009 17:03:55 +0000 (UTC) From: John Baldwin <jhb@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-6@freebsd.org Subject: svn commit: r187537 - in stable/6/sys: . compat/freebsd32 kern sys Message-ID: <200901211703.n0LH3t0a083886@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jhb Date: Wed Jan 21 17:03:55 2009 New Revision: 187537 URL: http://svn.freebsd.org/changeset/base/187537 Log: MFC: Split most of getdirentries() out into a kern_getdirentries() and add a freebsd32 frontend to fix a data corruption bug with 32-bit binaries. Modified: stable/6/sys/ (props changed) stable/6/sys/compat/freebsd32/freebsd32_misc.c stable/6/sys/compat/freebsd32/syscalls.master stable/6/sys/kern/vfs_syscalls.c stable/6/sys/sys/syscallsubr.h Modified: stable/6/sys/compat/freebsd32/freebsd32_misc.c ============================================================================== --- stable/6/sys/compat/freebsd32/freebsd32_misc.c Wed Jan 21 16:28:15 2009 (r187536) +++ stable/6/sys/compat/freebsd32/freebsd32_misc.c Wed Jan 21 17:03:55 2009 (r187537) @@ -1702,6 +1702,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); +} + struct sf_hdtr32 { uint32_t headers; int hdr_cnt; Modified: stable/6/sys/compat/freebsd32/syscalls.master ============================================================================== --- stable/6/sys/compat/freebsd32/syscalls.master Wed Jan 21 16:28:15 2009 (r187536) +++ stable/6/sys/compat/freebsd32/syscalls.master Wed Jan 21 17:03:55 2009 (r187537) @@ -355,8 +355,8 @@ 195 AUE_SETRLIMIT MNOPROTO { int setrlimit(u_int which, \ struct rlimit *rlp); } setrlimit \ __setrlimit_args int -196 AUE_GETDIRENTRIES MNOPROTO { int getdirentries(int fd, char *buf, \ - u_int count, long *basep); } +196 AUE_GETDIRENTRIES MSTD { int freebsd32_getdirentries(int fd, \ + char *buf, u_int count, int32_t *basep); } 197 AUE_MMAP MSTD { caddr_t freebsd32_mmap(caddr_t addr, \ size_t len, int prot, int flags, int fd, \ int pad, u_int32_t poslo, \ Modified: stable/6/sys/kern/vfs_syscalls.c ============================================================================== --- stable/6/sys/kern/vfs_syscalls.c Wed Jan 21 16:28:15 2009 (r187536) +++ stable/6/sys/kern/vfs_syscalls.c Wed Jan 21 17:03:55 2009 (r187537) @@ -3688,6 +3688,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; @@ -3696,10 +3711,10 @@ getdirentries(td, uap) long loff; int error, eofflag; - AUDIT_ARG(fd, uap->fd); + AUDIT_ARG(fd, fd); if (uap->count > INT_MAX) return (EINVAL); - if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) + if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0) return (error); if ((fp->f_flag & FREAD) == 0) { fdrop(fp, td); @@ -3713,14 +3728,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, td); */ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); AUDIT_ARG(vnode, vp, ARG_VNODE1); @@ -3737,7 +3752,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; @@ -3752,10 +3767,8 @@ unionread: } VOP_UNLOCK(vp, 0, td); 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: stable/6/sys/sys/syscallsubr.h ============================================================================== --- stable/6/sys/sys/syscallsubr.h Wed Jan 21 16:28:15 2009 (r187536) +++ stable/6/sys/sys/syscallsubr.h Wed Jan 21 17:03:55 2009 (r187537) @@ -79,6 +79,8 @@ int kern_fstat(struct thread *td, int fd int kern_fstatfs(struct thread *td, int fd, struct statfs *buf); 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_getitimer(struct thread *, u_int, struct itimerval *);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901211703.n0LH3t0a083886>