[exim-cvs] malware: avoid slurping entire spoolfile for send…

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] malware: avoid slurping entire spoolfile for sending to ClamAV
Gitweb: https://git.exim.org/exim.git/commitdiff/62a4137ec452ff0a6801923930b003e954ec09aa
Commit:     62a4137ec452ff0a6801923930b003e954ec09aa
Parent:     996a98d33f790a1e6af927c02318649feec6061b
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Thu Dec 31 22:18:30 2020 +0000
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Thu Dec 31 22:18:30 2020 +0000


    malware: avoid slurping entire spoolfile for sending to ClamAV
---
 src/src/malware.c | 61 +++++++++++++++++++++++--------------------------------
 1 file changed, 25 insertions(+), 36 deletions(-)


diff --git a/src/src/malware.c b/src/src/malware.c
index 03bb832..2883f22 100644
--- a/src/src/malware.c
+++ b/src/src/malware.c
@@ -1445,7 +1445,6 @@ badseek:  err = errno;
       host_item connhost;
       uschar *clamav_fbuf;
       int clam_fd, result;
-      off_t fsize;
       unsigned int fsize_uint;
       BOOL use_scan_command = FALSE;
       clamd_address * cv[MAX_CLAMD_SERVERS];
@@ -1621,6 +1620,7 @@ badseek:  err = errno;


       if (!use_scan_command)
     {
+    struct stat st;
     /* New protocol: "zINSTREAM\n" followed by a sequence of <length><data>
     chunks, <n> a 4-byte number (network order), terminated by a zero-length
     chunk. */
@@ -1637,7 +1637,6 @@ badseek:  err = errno;
         strerror(errno)),
           malware_daemon_ctx.sock);


-    /* calc file size */
     if ((clam_fd = exim_open2(CS eml_filename, O_RDONLY)) < 0)
       {
       int err = errno;
@@ -1646,61 +1645,51 @@ badseek:  err = errno;
           eml_filename, strerror(err)),
         malware_daemon_ctx.sock);
       }
-    if ((fsize = lseek(clam_fd, 0, SEEK_END)) < 0)
+    if (fstat(clam_fd, &st) < 0)
       {
-      int err;
-b_seek:   err = errno;
+      int err = errno;
       (void)close(clam_fd);
       return m_panic_defer_3(scanent, NULL,
-        string_sprintf("can't seek spool file %s: %s",
+        string_sprintf("can't stat spool file %s: %s",
           eml_filename, strerror(err)),
         malware_daemon_ctx.sock);
       }
-    fsize_uint = (unsigned int) fsize;
-    if ((off_t)fsize_uint != fsize)
+    fsize_uint = (unsigned int) st.st_size;
+    if ((off_t)fsize_uint != st.st_size)
       {
       (void)close(clam_fd);
       return m_panic_defer_3(scanent, NULL,
-        string_sprintf("seeking spool file %s, size overflow",
-          eml_filename),
+        string_sprintf("stat spool file %s, size overflow", eml_filename),
         malware_daemon_ctx.sock);
       }
-    if (lseek(clam_fd, 0, SEEK_SET) < 0)
-      goto b_seek;


-    if (!(clamav_fbuf = store_malloc(fsize_uint)))
-      {
-      (void)close(clam_fd);
+    /* send file body to socket */
+    send_size = htonl(fsize_uint);
+    if (send(malware_daemon_ctx.sock, &send_size, sizeof(send_size), 0) < 0)
       return m_panic_defer_3(scanent, NULL,
-        string_sprintf("unable to allocate memory %u for file (%s)",
-          fsize_uint, eml_filename),
+        string_sprintf("unable to send file size to socket (%s)", hostname),
         malware_daemon_ctx.sock);
-      }


-    if ((result = read(clam_fd, clamav_fbuf, fsize_uint)) < 0)
+    while (fsize_uint)
       {
-      int err = errno;
-      store_free(clamav_fbuf); (void)close(clam_fd);
-      return m_panic_defer_3(scanent, NULL,
-        string_sprintf("can't read spool file %s: %s",
-          eml_filename, strerror(err)),
-        malware_daemon_ctx.sock);
+      unsigned n = MIN(fsize_uint, big_buffer_size);
+      if ((n = read(clam_fd, big_buffer, n)) < 0)
+        return m_panic_defer_3(scanent, NULL,
+          string_sprintf("can't read spool file %s: %s",
+        eml_filename, strerror(errno)),
+          malware_daemon_ctx.sock);
+      if ((n = send(malware_daemon_ctx.sock, clamav_fbuf, n, 0)) < 0)
+        return m_panic_defer_3(scanent, NULL,
+          string_sprintf("unable to send file body to socket (%s)", hostname),
+          malware_daemon_ctx.sock);
+      fsize_uint -= n;
       }
-    (void)close(clam_fd);


-    /* send file body to socket */
-    send_size = htonl(fsize_uint);
     send_final_zeroblock = 0;
-    if ((send(malware_daemon_ctx.sock, &send_size, sizeof(send_size), 0) < 0) ||
-        (send(malware_daemon_ctx.sock, clamav_fbuf, fsize_uint, 0) < 0) ||
-        (send(malware_daemon_ctx.sock, &send_final_zeroblock, sizeof(send_final_zeroblock), 0) < 0))
-      {
-      store_free(clamav_fbuf);
+    if (send(malware_daemon_ctx.sock, &send_final_zeroblock, sizeof(send_final_zeroblock), 0) < 0)
       return m_panic_defer_3(scanent, NULL,
-        string_sprintf("unable to send file body to socket (%s)", hostname),
+        string_sprintf("unable to send file terminator to socket (%s)", hostname),
         malware_daemon_ctx.sock);
-      }
-    store_free(clamav_fbuf);
     }
       else
     { /* use scan command */