]> granicus.if.org Git - sudo/commitdiff
Open sudoedit files with O_NONBLOCK and fail if they are not regular
authorTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 2 Oct 2015 20:45:09 +0000 (14:45 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 2 Oct 2015 20:45:09 +0000 (14:45 -0600)
files.

src/sudo_edit.c

index 95bf8aa0a1dfe58eb517b3c6547568427a37790f..0eb91a89a5990b6b071a7727f1565cd9207b8f5f 100644 (file)
@@ -158,9 +158,22 @@ sudo_edit_mktemp(const char *ofile, char **tfile)
 static int
 sudo_edit_open(const char *path, int oflags, mode_t mode, int sflags)
 {
+    int fd;
+    struct stat sb;
+
     if (!ISSET(sflags, CD_SUDOEDIT_FOLLOW))
        oflags |= O_NOFOLLOW;
-    return open(path, oflags, mode);
+    fd = open(path, oflags|O_NONBLOCK, mode);
+    if (fd != -1) {
+       if (!ISSET(oflags, O_NONBLOCK))
+           (void) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
+       if (fstat(fd, &sb) == -1 || !S_ISREG(sb.st_mode)) {
+           close(fd);
+           fd = -1;
+           errno = EINVAL;
+       }
+    }
+    return fd;
 }
 #else
 static int
@@ -169,9 +182,10 @@ sudo_edit_open(const char *path, int oflags, mode_t mode, int sflags)
     struct stat sb1, sb2;
     int fd;
 
-    fd = open(path, oflags, mode);
-    if (fd == -1 || ISSET(sflags, CD_SUDOEDIT_FOLLOW))
-       return fd;
+    if ((fd = open(path, oflags|O_NONBLOCK, mode)) == -1)
+       return -1;
+    if (!ISSET(oflags, O_NONBLOCK))
+       (void) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
 
     /*
      * Treat [fl]stat() failure like an open() failure.
@@ -184,16 +198,27 @@ sudo_edit_open(const char *path, int oflags, mode_t mode, int sflags)
     }
 
     /*
-     * Make sure we did not open a link and that what we opened
-     * matches what is currently on the file system.
+     * Only open regular files.
      */
-    if (S_ISLNK(sb2.st_mode) ||
-       sb1.st_dev != sb2.st_dev || sb1.st_ino != sb2.st_ino) {
+    if (!S_ISREG(sb1.st_mode)) {
        close(fd);
-       errno = ELOOP;
+       errno = EINVAL;
        return -1;
     }
 
+    /*
+     * Make sure we did not open a link and that what we opened
+     * matches what is currently on the file system.
+     */
+    if (!ISSET(sflags, CD_SUDOEDIT_FOLLOW)) {
+       if (S_ISLNK(sb2.st_mode) ||
+           sb1.st_dev != sb2.st_dev || sb1.st_ino != sb2.st_ino) {
+           close(fd);
+           errno = ELOOP;
+           return -1;
+       }
+    }
+
     return fd;
 }
 #endif /* O_NOFOLLOW */