[exim-cvs] Fix IP SRR parsing. Bug 3124

Góra strony
Delete this message
Reply to this message
Autor: Exim Git Commits Mailing List
Data:  
Dla: exim-cvs
Temat: [exim-cvs] Fix IP SRR parsing. Bug 3124
Gitweb: https://git.exim.org/exim.git/commitdiff/8b8667503b5248524dbe94fa11be312fca5b380c
Commit:     8b8667503b5248524dbe94fa11be312fca5b380c
Parent:     e2725fc0da9c39d279a883cbd184cf3243026dd3
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Tue Dec 3 00:13:43 2024 +0000
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Tue Dec 3 00:18:12 2024 +0000


    Fix IP SRR parsing.  Bug 3124
---
 doc/doc-txt/ChangeLog |  7 +++++
 src/src/smtp_in.c     | 71 +++++++++++++++++++++++++--------------------------
 2 files changed, 42 insertions(+), 36 deletions(-)


diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 37cc3b77d..cf9420b19 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -80,6 +80,13 @@ JH/15 Disallow tainted metadata in lists.
       - Exclamation-marks ("!" signifying negation) are not checked for taint
       at this time.


+JH/16 Bug 3124: Fix theoretical crash in received connection, triggerable by a
+      crafted packet with massive count of IP options.  A buffer overflow was
+      detected, but a null-deref results.  In practice, IP packets with options
+      are rare (to non-existent).  Exim refuses connections having any, but this
+      issue was in the coding for logging preceding that refusal.  If coredumps
+      were enabled (not common), an attack could cause filesystem space usage.
+
 Exim version 4.98
 -----------------


diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
index fd28c4454..be065eafb 100644
--- a/src/src/smtp_in.c
+++ b/src/src/smtp_in.c
@@ -2317,10 +2317,9 @@ if (!f.sender_host_unknown)

     else if (optlen > 0)
       {
-      uschar * p = big_buffer;
-      uschar * pend = big_buffer + big_buffer_size;
+      uschar * p = big_buffer, * pend = big_buffer + big_buffer_size;
       uschar * adptr;
-      int optcount;
+      int optcount, sprint_len;
       struct in_addr addr;


 # if OPTSTYLE == 1
@@ -2351,57 +2350,57 @@ if (!f.sender_host_unknown)
           case IPOPT_LSRR:
         if (!
 # if OPTSTYLE == 1
-             string_format(p, pend-p, " %s [@%s",
-         (*opt == IPOPT_SSRR)? "SSRR" : "LSRR",
-         inet_ntoa(*((struct in_addr *)(&(ipopt->faddr)))))
+         string_format(p, pend-p, " %s [@%s%n",
+           *opt == IPOPT_SSRR ? "SSRR" : "LSRR",
+           inet_ntoa(*(struct in_addr *)&ipopt->faddr),
+           &sprint_len)
 # elif OPTSTYLE == 2
-             string_format(p, pend-p, " %s [@%s",
-         (*opt == IPOPT_SSRR)? "SSRR" : "LSRR",
-         inet_ntoa(ipopt->ip_dst))
+         string_format(p, pend-p, " %s [@%s%n",
+           *opt == IPOPT_SSRR ? "SSRR" : "LSRR",
+           inet_ntoa(ipopt->ip_dst),
+           &sprint_len)
 # else
-             string_format(p, pend-p, " %s [@%s",
-         (*opt == IPOPT_SSRR)? "SSRR" : "LSRR",
-         inet_ntoa(ipopt->ipopt_dst))
+         string_format(p, pend-p, " %s [@%s%n",
+           *opt == IPOPT_SSRR ? "SSRR" : "LSRR",
+           inet_ntoa(ipopt->ipopt_dst),
+           &sprint_len)
 # endif
-          )
-          {
+            )
           opt = NULL;
-          break;
-          }
-
-        p += Ustrlen(p);
-        optcount = (opt[1] - 3) / sizeof(struct in_addr);
-        adptr = opt + 3;
-        while (optcount-- > 0)
+        else
           {
-          memcpy(&addr, adptr, sizeof(addr));
-          if (!string_format(p, pend - p - 1, "%s%s",
-            (optcount == 0)? ":" : "@", inet_ntoa(addr)))
+          p += sprint_len;
+          optcount = (opt[1] - 3) / sizeof(struct in_addr);
+          adptr = opt + 3;
+          while (optcount-- > 0)
         {
-        opt = NULL;
-        break;
+        memcpy(&addr, adptr, sizeof(addr));
+        if (!string_format(p, pend - p - 1, "%s%s%n",
+              optcount == 0 ? ":" : "@", inet_ntoa(addr), &sprint_len))
+          { opt = NULL; goto bad_srr; }
+        p += sprint_len;
+        adptr += sizeof(struct in_addr);
         }
-          p += Ustrlen(p);
-          adptr += sizeof(struct in_addr);
+          *p++ = ']';
+          opt += opt[1];
           }
-        *p++ = ']';
-        opt += opt[1];
-        break;
+bad_srr:    break;


           default:
+        if (pend - p < 4 + 3*opt[1])
+          opt = NULL;
+        else
           {
-          if (pend - p < 4 + 3*opt[1]) { opt = NULL; break; }
-          Ustrcat(p, "[ ");
-          p += 2;
+          p = Ustpcpy(p, "[ ");
           for (int i = 0; i < opt[1]; i++)
         p += sprintf(CS p, "%2.2x ", opt[i]);
           *p++ = ']';
+          opt += opt[1];
           }
-        opt += opt[1];
         break;
           }


-      *p = 0;
+      *p = '\0';
       log_write(0, LOG_MAIN, "%s", big_buffer);


       /* Refuse any call with IP options. This is what tcpwrappers 7.5 does. */


--
## subscription configuration (requires account):
## https://lists.exim.org/mailman3/postorius/lists/exim-cvs.lists.exim.org/
## unsubscribe (doesn't require an account):
## exim-cvs-unsubscribe@???
## Exim details at http://www.exim.org/
## Please use the Wiki with this list - http://wiki.exim.org/