[exim-cvs] taint enforce: file access backstops

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] taint enforce: file access backstops
Gitweb: https://git.exim.org/exim.git/commitdiff/9e21ce8fc41aea068996e0a22093dfae33f542c7
Commit:     9e21ce8fc41aea068996e0a22093dfae33f542c7
Parent:     ed1620555d261c5e970dbbe873bf4b19026b0e48
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Sat Jan 11 21:52:24 2020 +0000
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Sat Jan 11 21:52:24 2020 +0000


    taint enforce: file access backstops
---
 src/src/expand.c               |  2 +-
 src/src/functions.h            | 47 ++++++++++++++++++++++++++++++++++++++++++
 src/src/malware.c              | 13 +++++-------
 src/src/mytypes.h              | 14 +++++++------
 src/src/parse.c                |  4 ++--
 src/src/transports/queuefile.c |  4 ++--
 6 files changed, 65 insertions(+), 19 deletions(-)


diff --git a/src/src/expand.c b/src/src/expand.c
index fe5384a..55aaf53 100644
--- a/src/src/expand.c
+++ b/src/src/expand.c
@@ -8550,7 +8550,7 @@ expand_file_big_buffer(const uschar * filename)
{
int fd, off = 0, len;

-if ((fd = open(CS filename, O_RDONLY)) < 0)
+if ((fd = exim_open2(CS filename, O_RDONLY)) < 0)
   {
   log_write(0, LOG_MAIN | LOG_PANIC, "unable to open file for reading: %s",
          filename);
diff --git a/src/src/functions.h b/src/src/functions.h
index d5df987..fe15cc5 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -930,6 +930,8 @@ subdir_str[1] = '\0';
 }


/******************************************************************************/
+/* Time calculations */
+
static inline void
timesince(struct timeval * diff, const struct timeval * then)
{
@@ -983,6 +985,51 @@ if (f.running_in_test_harness) millisleep(millisec);
#endif
}

+/******************************************************************************/
+/* Taint-checked file opens */
+
+static inline int
+exim_open2(const char *pathname, int flags)
+{
+if (!is_tainted(pathname)) return open(pathname, flags);
+log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'\n", pathname);
+errno = EACCES;
+return -1;
+}
+static inline int
+exim_open(const char *pathname, int flags, mode_t mode)
+{
+if (!is_tainted(pathname)) return open(pathname, flags, mode);
+log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'\n", pathname);
+errno = EACCES;
+return -1;
+}
+static inline int
+exim_openat(int dirfd, const char *pathname, int flags)
+{
+if (!is_tainted(pathname)) return openat(dirfd, pathname, flags);
+log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'\n", pathname);
+errno = EACCES;
+return -1;
+}
+static inline int
+exim_openat4(int dirfd, const char *pathname, int flags, mode_t mode)
+{
+if (!is_tainted(pathname)) return openat(dirfd, pathname, flags, mode);
+log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'\n", pathname);
+errno = EACCES;
+return -1;
+}
+
+static inline FILE *
+exim_fopen(const char *pathname, const char *mode)
+{
+if (!is_tainted(pathname)) return fopen(pathname, mode);
+log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'\n", pathname);
+errno = EACCES;
+return NULL;
+}
+
 #endif    /* !MACRO_PREDEF */


 #endif  /* _FUNCTIONS_H_ */
diff --git a/src/src/malware.c b/src/src/malware.c
index ef27daf..ec2f7c1 100644
--- a/src/src/malware.c
+++ b/src/src/malware.c
@@ -791,7 +791,7 @@ if (!malware_ok)
       if (*scanner_options != '/')
     {
     /* calc file size */
-    if ((drweb_fd = open(CCS eml_filename, O_RDONLY)) == -1)
+    if ((drweb_fd = exim_open(CCS eml_filename, O_RDONLY)) == -1)
       return m_panic_defer_3(scanent, NULL,
         string_sprintf("can't open spool file %s: %s",
           eml_filename, strerror(errno)),
@@ -1362,13 +1362,10 @@ badseek:  err = errno;
     malware_name = US"unknown";


     /* re-open the scanner output file, look for name match */
-    scanner_record = fopen(CS file_name, "rb");
-    while (fgets(CS linebuffer, sizeof(linebuffer), scanner_record))
-      {
-      /* try match */
-      if ((s = m_pcre_exec(cmdline_regex_re, linebuffer)))
+    scanner_record = Ufopen(file_name, "rb");
+    while (Ufgets(linebuffer, sizeof(linebuffer), scanner_record))
+      if ((s = m_pcre_exec(cmdline_regex_re, linebuffer))) /* try match */
         malware_name = s;
-      }
     (void)fclose(scanner_record);
     }
       else /* no virus found */
@@ -1638,7 +1635,7 @@ badseek:  err = errno;
           malware_daemon_ctx.sock);


     /* calc file size */
-    if ((clam_fd = open(CS eml_filename, O_RDONLY)) < 0)
+    if ((clam_fd = exim_open2(CS eml_filename, O_RDONLY)) < 0)
       {
       int err = errno;
       return m_panic_defer_3(scanent, NULL,
diff --git a/src/src/mytypes.h b/src/src/mytypes.h
index eba3f7e..d652dae 100644
--- a/src/src/mytypes.h
+++ b/src/src/mytypes.h
@@ -89,15 +89,17 @@ functions that are called quite often; for other calls to external libraries
 #define Uchdir(s)          chdir(CCS(s))
 #define Uchmod(s,n)        chmod(CCS(s),n)
 #define Ufgets(b,n,f)      fgets(CS(b),n,f)
-#define Ufopen(s,t)        fopen(CCS(s),CCS(t))
+#define Ufopen(s,t)        exim_fopen(CCS(s),CCS(t))
 #define Ulink(s,t)         link(CCS(s),CCS(t))
 #define Ulstat(s,t)        lstat(CCS(s),t)


-#ifdef O_BINARY                                        /* This is for Cygwin,  */
-#define Uopen(s,n,m)       open(CCS(s),(n)|O_BINARY,m) /* where all files must */
-#else                                                  /* be opened as binary  */
-#define Uopen(s,n,m)       open(CCS(s),n,m)            /* to avoid problems    */
-#endif                                                 /* with CRLF endings.   */
+#ifdef O_BINARY                            /* This is for Cygwin,  */
+#define Uopen(s,n,m)       exim_open(CCS(s),(n)|O_BINARY,m)    /* where all files must */
+#define Uopen2(s,n)        exim_open2(CCS(s),(n)|O_BINARY)
+#else                                /* be opened as binary  */
+#define Uopen(s,n,m)       exim_open(CCS(s),n,m)        /* to avoid problems    */
+#define Uopen2(s,n)        exim_open2(CCS(s),n)    
+#endif                                /* with CRLF endings.   */
 #define Uread(f,b,l)       read(f,CS(b),l)
 #define Urename(s,t)       rename(CCS(s),CCS(t))
 #define Ustat(s,t)         stat(CCS(s),t)
diff --git a/src/src/parse.c b/src/src/parse.c
index be70eff..71f48f3 100644
--- a/src/src/parse.c
+++ b/src/src/parse.c
@@ -1454,7 +1454,7 @@ for (;;)
       with a flag that fails symlinks. */


       {
-      int fd = open(CS directory, O_RDONLY);
+      int fd = exim_open2(CS directory, O_RDONLY);
       if (fd < 0)
     {
     *error = string_sprintf("failed to open directory %s", directory);
@@ -1470,7 +1470,7 @@ for (;;)
     temp = *p;
     *p = '\0';


-    fd2 = openat(fd, CS q, O_RDONLY|O_NOFOLLOW);
+    fd2 = exim_openat(fd, CS q, O_RDONLY|O_NOFOLLOW);
     close(fd);
     *p = temp;
     if (fd2 < 0)
diff --git a/src/src/transports/queuefile.c b/src/src/transports/queuefile.c
index bb2b9b9..4339d1f 100644
--- a/src/src/transports/queuefile.c
+++ b/src/src/transports/queuefile.c
@@ -134,11 +134,11 @@ else                    /* use data copy */
     tb->name, srcpath, dstpath);


   if (  (s = dstpath,
-     (dstfd = openat(ddfd, CCS filename, O_RDWR|O_CREAT|O_EXCL, SPOOL_MODE))
+     (dstfd = exim_openat4(ddfd, CCS filename, O_RDWR|O_CREAT|O_EXCL, SPOOL_MODE))
      < 0
     )
      ||    is_hdr_file
-    && (s = srcpath, (srcfd = openat(sdfd, CCS filename, O_RDONLY)) < 0)
+    && (s = srcpath, (srcfd = exim_openat(sdfd, CCS filename, O_RDONLY)) < 0)
      )
     op = US"opening";