From: Jeremy Harris Date: Fri, 1 Jan 2021 14:31:14 +0000 (+0000) Subject: malware: avoid partial packets, sending to ClamAV X-Git-Tag: exim-4.95-RC0~168 X-Git-Url: https://git.exim.org/exim.git/commitdiff_plain/17427537cf5a55f952bad37067f0801b66bf7c08 malware: avoid partial packets, sending to ClamAV --- diff --git a/src/src/malware.c b/src/src/malware.c index dfa8e2b4b..a42e39a57 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';