[exim-cvs] malware: avoid partial packets, sending to ClamAV

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] malware: avoid partial packets, sending to ClamAV
Gitweb: https://git.exim.org/exim.git/commitdiff/17427537cf5a55f952bad37067f0801b66bf7c08
Commit:     17427537cf5a55f952bad37067f0801b66bf7c08
Parent:     3eb0bcd7a112a70bbdd61bedde4878ceae4e1297
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Fri Jan 1 14:31:14 2021 +0000
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Fri Jan 1 14:31:14 2021 +0000


    malware: avoid partial packets, sending to ClamAV
---
 src/src/malware.c | 31 ++++++++++++++++++++++---------
 1 file changed, 22 insertions(+), 9 deletions(-)


diff --git a/src/src/malware.c b/src/src/malware.c
index dfa8e2b..a42e39a 100644
--- a/src/src/malware.c
+++ b/src/src/malware.c
@@ -132,6 +132,11 @@ static const uschar * malware_regex_default = US ".+";
static const pcre * malware_default_re = NULL;


+#ifdef TCP_CORK
+# define EXIM_TCP_CORK TCP_CORK
+#elif defined(TCP_NOPUSH)
+# define EXIM_TCP_CORK TCP_NOPUSH
+#endif

 #ifndef DISABLE_MAL_CLAM
 /* The maximum number of clamd servers that are supported in the configuration */
@@ -1570,8 +1575,8 @@ badseek:  err = errno;
       if (num_servers)
     {
     /* Confirmed in ClamAV source (0.95.3) that the TCPAddr option of clamd
-     * only supports AF_INET, but we should probably be looking to the
-     * future and rewriting this to be protocol-independent anyway. */
+    only supports AF_INET, but we should probably be looking to the
+    future and rewriting this to be protocol-independent anyway. */


     while (num_servers > 0)
       {
@@ -1582,7 +1587,7 @@ badseek:  err = errno;
              cd->hostspec, cd->tcp_port);


       /* Lookup the host. This is to ensure that we connect to the same IP
-       * on both connections (as one host could resolve to multiple ips) */
+      on both connections (as one host could resolve to multiple ips) */
       for (;;)
         {
         /*XXX we trust that the cmd_str is ideempotent */
@@ -1625,9 +1630,9 @@ badseek:  err = errno;
       }


       /* have socket in variable "sock"; command to use is semi-independent of
-       * the socket protocol.  We use SCAN if is local (either Unix/local
-       * domain socket, or explicitly told local) else we stream the data.
-       * How we stream the data depends upon how we were built.  */
+      the socket protocol.  We use SCAN if is local (either Unix/local
+      domain socket, or explicitly told local) else we stream the data.
+      How we stream the data depends upon how we were built.  */


       if (!use_scan_command)
     {
@@ -1674,13 +1679,17 @@ badseek:  err = errno;
         malware_daemon_ctx.sock);
       }


-    /* send file body to socket */
+    /* send file size */
+#ifdef EXIM_TCP_CORK
+    (void) setsockopt(clam_fd, IPPROTO_TCP, EXIM_TCP_CORK, US &on, sizeof(on));
+#endif
     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 send file size to socket (%s)", hostname),
         malware_daemon_ctx.sock);


+    /* send file body */
     while (fsize_uint)
       {
       unsigned n = MIN(fsize_uint, big_buffer_size);
@@ -1701,6 +1710,9 @@ badseek:  err = errno;
       return m_panic_defer_3(scanent, NULL,
         string_sprintf("unable to send file terminator to socket (%s)", hostname),
         malware_daemon_ctx.sock);
+#ifdef EXIM_TCP_CORK
+    (void) setsockopt(clam_fd, IPPROTO_TCP, EXIM_TCP_CORK, US &off, sizeof(off));
+#endif
     }
       else
     { /* use scan command */
@@ -1730,10 +1742,10 @@ badseek:  err = errno;
           malware_daemon_ctx.sock);


     /* Do not shut down the socket for writing; a user report noted that
-     * clamd 0.70 does not react well to this. */
+    clamd 0.70 does not react well to this. */
     }
       /* Commands have been sent, no matter which scan method or connection
-       * type we're using; now just read the result, independent of method. */
+      type we're using; now just read the result, independent of method. */


       /* Read the result */
       memset(av_buffer, 0, sizeof(av_buffer));
@@ -1779,6 +1791,7 @@ badseek:  err = errno;
       /* strip newline at the end (won't be present for zINSTREAM)
       (also any trailing whitespace, which shouldn't exist, but we depend upon
       this below, so double-check) */
+
       p = av_buffer + Ustrlen(av_buffer) - 1;
       if (*p == '\n') *p = '\0';