svn commit: r184469 - in stable/7/sys: . compat/freebsd32 kern sys

John Baldwin jhb at FreeBSD.org
Thu Oct 30 13:14:46 UTC 2008


Author: jhb
Date: Thu Oct 30 13:14:45 2008
New Revision: 184469
URL: http://svn.freebsd.org/changeset/base/184469

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.
  
  Approved by:	re (kib)

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/compat/freebsd32/freebsd32_misc.c
  stable/7/sys/compat/freebsd32/syscalls.master
  stable/7/sys/kern/vfs_syscalls.c
  stable/7/sys/sys/syscallsubr.h

Modified: stable/7/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- stable/7/sys/compat/freebsd32/freebsd32_misc.c	Thu Oct 30 13:10:33 2008	(r184468)
+++ stable/7/sys/compat/freebsd32/freebsd32_misc.c	Thu Oct 30 13:14:45 2008	(r184469)
@@ -1724,6 +1724,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: stable/7/sys/compat/freebsd32/syscalls.master
==============================================================================
--- stable/7/sys/compat/freebsd32/syscalls.master	Thu Oct 30 13:10:33 2008	(r184468)
+++ stable/7/sys/compat/freebsd32/syscalls.master	Thu Oct 30 13:14:45 2008	(r184469)
@@ -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: stable/7/sys/kern/vfs_syscalls.c
==============================================================================
--- stable/7/sys/kern/vfs_syscalls.c	Thu Oct 30 13:10:33 2008	(r184468)
+++ stable/7/sys/kern/vfs_syscalls.c	Thu Oct 30 13:14:45 2008	(r184469)
@@ -3761,6 +3761,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;
@@ -3769,8 +3784,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);
@@ -3784,14 +3799,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);
@@ -3808,7 +3823,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;
@@ -3823,10 +3838,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/7/sys/sys/syscallsubr.h
==============================================================================
--- stable/7/sys/sys/syscallsubr.h	Thu Oct 30 13:10:33 2008	(r184468)
+++ stable/7/sys/sys/syscallsubr.h	Thu Oct 30 13:14:45 2008	(r184469)
@@ -84,6 +84,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_getgroups(struct thread *td, u_int *ngrp, gid_t *groups);


More information about the svn-src-stable-7 mailing list