Skip site navigation (1)Skip section navigation (2)
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>