Older versions of Linux's client-side NFS implementation uses
different credentials for read/write of a file over NFS than it did
for the open if the euid changes.  This is fixed in the latest Linux
kernels but here is a workaround for older kernels.  This patch
will *not* become a part of the normal sudo distribution.

 - todd

--- parse.c.DIST	Sun Jan 13 16:22:21 2002
+++ parse.c	Sun Jan 13 16:22:00 2002
@@ -111,6 +111,7 @@
  * Prototypes
  */
 static int has_meta	__P((char *));
+static int stat_wrap	__P((char *, struct stat *));
        void init_parser	__P((void));
 
 /*
@@ -140,9 +141,12 @@
     if (pwflag > 0)
 	keepall = TRUE;
 
-    /* Need to be root while stat'ing things in the parser. */
-    set_perms(PERM_ROOT, 0);
+    /*
+     * XXX - Linux's NFS doesn't use the same creds for read/write
+     *       as used for the open so we retain PERM_SUDOERS.
+     */
     error = yyparse();
+    set_perms(PERM_ROOT, 0);
 
     /* Close the sudoers file now that we are done with it. */
     (void) fclose(sudoers_fp);
@@ -267,7 +271,7 @@
 
     /* Only need to stat cmnd once since it never changes */
     if (cst.st_dev == 0) {
-	if (stat(cmnd, &cst) == -1)
+	if (stat_wrap(cmnd, &cst) == -1)
 	    return(FALSE);
 	if ((cmnd_base = strrchr(cmnd, '/')) == NULL)
 	    cmnd_base = cmnd;
@@ -312,7 +316,7 @@
 		p = path;
 	    else
 		p++;
-	    if (strcmp(cmnd_base, p) != 0 || stat(path, &pst) == -1)
+	    if (strcmp(cmnd_base, p) != 0 || stat_wrap(path, &pst) == -1)
 		return(FALSE);
 
 	    /*
@@ -350,7 +354,7 @@
 	    strcat(buf, dent->d_name);
 
 	    /* only stat if basenames are the same */
-	    if (strcmp(cmnd_base, dent->d_name) != 0 || stat(buf, &pst) == -1)
+	    if (strcmp(cmnd_base, dent->d_name) != 0 || stat_wrap(buf, &pst) == -1)
 		continue;
 	    if (cst.st_dev == pst.st_dev && cst.st_ino == pst.st_ino) {
 		if (safe_cmnd)
@@ -525,4 +529,22 @@
 	    return(TRUE);
     }
     return(FALSE);
+}
+
+/*
+ * XXX - this is a hack for broken Linux NFS
+ */
+static int stat_wrap(path, sb)
+    char *path;
+    struct stat *sb;
+{
+    int serrno, retval;
+
+    set_perms(PERM_ROOT, 0);
+    retval = stat(path, sb);
+    serrno = errno;
+    set_perms(PERM_SUDOERS, 0);
+    errno = serrno;
+
+    return(retval);
 }
