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";