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); }