Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 15 Nov 1999 23:55:12 -0500 (EST)
From:      Kelly Yancey <kbyanc@posi.net>
To:        freebsd-hackers@freebsd.org
Subject:   Portable way to compare struct stat's?
Message-ID:  <Pine.BSF.4.05.9911152339050.74677-100000@kronos.alcnet.com>

next in thread | raw e-mail | index | archive | help

  Is there a portable method for determining if the contents of two struct
stat's are identical? I believe there is not. The problem is that while
Posix defines a base set of fields for the stat structure, it appears that
most implementations (including FreeBSD's) extend the structure with
additional fields. Comparing all of the Posix fields will only determine
the relationship between the Posix subset of the structures.
  My first inclination was to do a memcmp() which in theory should work
across all stat structure definitions. But being that my development box
runs FreeBSD, I quickly discovered that at least on FreeBSD, memcmp won't
work.
  The reason? Because the FreeBSD struct stat defines 2 spare fields:
st_lspare and st_qspare. The kernel never initializes the values of these
fields when returning structures back to userland. So the values are more
or less random contents that were on the kernel stack.

  Besides the possible security implications of passing random kernel
stack contents into userland (I am no security expert, so there may not be
any problem with this, it just doesn't seem right), there is the nasty
side effect the memcmp cannot be used to compare 2 stat structures for
equality.

  I have made a small set of changes to my local kernel source which
addresses the problem by bzero'ing the struct stat memory in the kernel
before filling it (which ensures that the spare fields get reset to a
known state). I've attached the patches below (they need to be applied in 
the /sys/kern directory).

  So, back to my original question: is there a better way for comparing
stat structures? Or, should memcmp work on other platforms (as well as
FreeBSD given the attached patch)?


--
Kelly Yancey  -  kbyanc@posi.net  -  Richmond, VA
Director of Technical Services, ALC Communications  http://www.alcnet.com/
Maintainer, BSD Driver Database       http://www.posi.net/freebsd/drivers/
Coordinator, Team FreeBSD        http://www.posi.net/freebsd/Team-FreeBSD/


--- kern_descrip.c.orig	Mon Nov 15 22:11:57 1999
+++ kern_descrip.c	Mon Nov 15 22:27:43 1999
@@ -548,9 +548,11 @@
 		panic("ofstat");
 		/*NOTREACHED*/
 	}
-	cvtstat(&ub, &oub);
-	if (error == 0)
+	if (error == 0) {
+		bzero(&oub, sizeof (oub));
+		cvtstat(&ub, &oub);
 		error = copyout((caddr_t)&oub, (caddr_t)uap->sb, sizeof (oub));
+	}
 	return (error);
 }
 #endif /* COMPAT_43 || COMPAT_SUNOS */
@@ -578,6 +580,7 @@
 	if ((unsigned)uap->fd >= fdp->fd_nfiles ||
 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
 		return (EBADF);
+	bzero(&ub, sizeof (ub));
 	switch (fp->f_type) {
 
 	case DTYPE_FIFO:
@@ -646,6 +649,7 @@
 		/*NOTREACHED*/
 	}
 	if (error == 0) {
+		bzero(&nub, sizeof (nub));
 		cvtnstat(&ub, &nub);
 		error = copyout((caddr_t)&nub, (caddr_t)uap->sb, sizeof (nub));
 	}
--- vfs_syscalls.c.orig	Mon Nov 15 23:25:48 1999
+++ vfs_syscalls.c	Mon Nov 15 23:29:08 1999
@@ -1514,6 +1514,7 @@
 	vput(nd.ni_vp);
 	if (error)
 		return (error);
+	bzero(&osb, sizeof (osb));
 	cvtstat(&sb, &osb);
 	error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
 	return (error);
@@ -1552,6 +1553,7 @@
 	vput(vp);
 	if (error)
 		return (error);
+	bzero(&osb, sizeof (osb));
 	cvtstat(&sb, &osb);
 	error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
 	return (error);
@@ -1613,6 +1615,7 @@
 	    SCARG(uap, path), p);
 	if (error = namei(&nd))
 		return (error);
+	bzero(&sb, sizeof (sb));
 	error = vn_stat(nd.ni_vp, &sb, p);
 	vput(nd.ni_vp);
 	if (error)
@@ -1648,6 +1651,7 @@
 	    SCARG(uap, path), p);
 	if (error = namei(&nd))
 		return (error);
+	bzero(&sb, sizeof (sb));
 	vp = nd.ni_vp;
 	error = vn_stat(vp, &sb, p);
 	vput(vp);
@@ -1707,6 +1711,7 @@
 	vput(nd.ni_vp);
 	if (error)
 		return (error);
+	bzero(&nsb, sizeof (nsb));
 	cvtnstat(&sb, &nsb);
 	error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
 	return (error);
@@ -1745,6 +1750,7 @@
 	vput(vp);
 	if (error)
 		return (error);
+	bzero(&nsb, sizeof (nsb));
 	cvtnstat(&sb, &nsb);
 	error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb));
 	return (error);



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.05.9911152339050.74677-100000>