Subject: kern/3701: olstat can't stat "/"
To: None <gnats-bugs@gnats.netbsd.org>
From: None <arnej@math.ntnu.no>
List: netbsd-bugs
Date: 06/03/1997 19:34:49
>Number:         3701
>Category:       kern
>Synopsis:       olstat can't stat "/"
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Jun  3 10:50:02 1997
>Last-Modified:
>Originator:     Arne H. Juul
>Organization:
	Norwegian University of Technology and Science
>Release:        NetBSD-current as of Jun 3, 1997
>Environment:
	
System: NetBSD leon.math.ntnu.no 1.2E NetBSD 1.2E (NIKITA) #2: Tue Jun 3 18:48:24 CEST 1997 arnej@leon.math.ntnu.no:/usr/src/sys/arch/i386/compile/NIKITA i386


>Description:
	We had problems with an IBCS2 program doing lstat("/") failing
	with errno=EISDIR.  This was traced to the common BSD 4.3
	compatibility lstat() routine.  The problem seems to have
	been activated because of the recent namei() changes, but
	in reality it was caused by the hack to get lstat() to return
	the attributes of the parent directory.  This was removed
	from normal lstat() between 1.1 and 1.2, but the 4.3 compat
	call was neglected.
>How-To-Repeat:
	Easiest done by running the following test program,
	which calls first normal lstat and then compat_43_sys_lstat
	via syscall:

extern int errno;
int main(void) {
        char buf[1000];
        int i;

        i=syscall(190,"/",buf);
        printf("lstat /:  returns %d errno %d\n", i, errno);
        i=syscall(40,"/",buf);
        printf("olstat /: returns %d errno %d\n", i, errno);
}
>Fix:
	Apply this fix.  Also applies to 1.2 sources.

--- src/sys/compat/common/vfs_syscalls_43.c.orig	Fri Mar 15 13:41:06 1996
+++ src/sys/compat/common/vfs_syscalls_43.c	Tue Jun  3 19:18:00 1997
@@ -140,50 +140,21 @@
 		syscallarg(char *) path;
 		syscallarg(struct ostat *) ub;
 	} */ *uap = v;
-	struct vnode *vp, *dvp;
-	struct stat sb, sb1;
+	struct stat sb;
 	struct ostat osb;
 	int error;
 	struct nameidata nd;
 
-	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
+	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
 	    SCARG(uap, path), p);
 	if ((error = namei(&nd)) != 0)
 		return (error);
-	/*
-	 * For symbolic links, always return the attributes of its
-	 * containing directory, except for mode, size, and links.
-	 */
-	vp = nd.ni_vp;
-	dvp = nd.ni_dvp;
-	if (vp->v_type != VLNK) {
-		if (dvp == vp)
-			vrele(dvp);
-		else
-			vput(dvp);
-		error = vn_stat(vp, &sb, p);
-		vput(vp);
-		if (error)
-			return (error);
-	} else {
-		error = vn_stat(dvp, &sb, p);
-		vput(dvp);
-		if (error) {
-			vput(vp);
-			return (error);
-		}
-		error = vn_stat(vp, &sb1, p);
-		vput(vp);
-		if (error)
-			return (error);
-		sb.st_mode &= ~S_IFDIR;
-		sb.st_mode |= S_IFLNK;
-		sb.st_nlink = sb1.st_nlink;
-		sb.st_size = sb1.st_size;
-		sb.st_blocks = sb1.st_blocks;
-	}
+	error = vn_stat(nd.ni_vp, &sb, p);
+	vput(nd.ni_vp);
+	if (error)
+		return (error);
 	cvtstat(&sb, &osb);
-	error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb));
+	error = copyout(&osb, SCARG(uap, ub), sizeof (osb));
 	return (error);
 }
 
>Audit-Trail:
>Unformatted: