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);
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to