From 99afdd5ecd787e40f06473304125eee93139031a Mon Sep 17 00:00:00 2001 From: Michal Ruprich Date: Sun, 12 Apr 2020 22:41:50 +0200 Subject: [PATCH 53/60] telnetd: Fix arbitrary remote code execution via short writes or urgent data Fixes: CVE-2020-10188 Closes: #956084 Bug-RedHat: https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2020-10188 Patch-Origin: Fedora / RedHat Patch-URL: https://src.fedoraproject.org/rpms/telnet/raw/master/f/telnet-0.17-overflow-exploit.patch --- telnetd/telnetd.h | 2 +- telnetd/utility.c | 35 ++++++++++++++++++++++------------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/telnetd/telnetd.h b/telnetd/telnetd.h index 044025d2..fa970e24 100644 --- a/telnetd/telnetd.h +++ b/telnetd/telnetd.h @@ -271,7 +271,7 @@ void io_drain (void); int stilloob (int s); void ptyflush (void); -char *nextitem (char *current); +char *nextitem (char *current, const char *endp); void netclear (void); void netflush (void); diff --git a/telnetd/utility.c b/telnetd/utility.c index db93c205..c9df8a79 100644 --- a/telnetd/utility.c +++ b/telnetd/utility.c @@ -484,10 +484,14 @@ stilloob (int s) * character. */ char * -nextitem (char *current) +nextitem (char *current, const char *endp) { + if (current >= endp) + return NULL; if ((*current & 0xff) != IAC) return current + 1; + if (current + 1 >= endp) + return NULL; switch (*(current + 1) & 0xff) { @@ -495,19 +499,20 @@ nextitem (char *current) case DONT: case WILL: case WONT: - return current + 3; + return current + 3 <= endp ? current + 3 : NULL; case SB: /* loop forever looking for the SE */ { char *look = current + 2; - for (;;) - if ((*look++ & 0xff) == IAC && (*look++ & 0xff) == SE) + while (look < endp) + if ((*look++ & 0xff) == IAC && look < endp && (*look++ & 0xff) == SE) return look; - default: - return current + 2; + return NULL; } + default: + return current + 2 <= endp ? current + 2 : NULL; } } /* end of nextitem */ @@ -529,8 +534,9 @@ nextitem (char *current) * us in any case. */ #define wewant(p) \ - ((nfrontp > p) && ((*p&0xff) == IAC) && \ - ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) + ((nfrontp > p) && ((*p & 0xff) == IAC) && \ + (nfrontp > p + 1 && (((*(p + 1) & 0xff) != EC) && \ + ((*(p + 1)&0xff) != EL)))) void @@ -545,7 +551,7 @@ netclear (void) thisitem = netobuf; #endif /* ENCRYPTION */ - while ((next = nextitem (thisitem)) <= nbackp) + while ((next = nextitem (thisitem, nbackp)) != NULL && next <= nbackp) thisitem = next; /* Now, thisitem is first before/at boundary. */ @@ -556,15 +562,18 @@ netclear (void) good = netobuf; /* where the good bytes go */ #endif /* ENCRYPTION */ - while (nfrontp > thisitem) + while (thisitem != NULL && nfrontp > thisitem) { if (wewant (thisitem)) { int length; - for (next = thisitem; wewant (next) && nfrontp > next; - next = nextitem (next)) + for (next = thisitem; + next != NULL && wewant (next) && nfrontp > next; + next = nextitem (next, nfrontp)) ; + if (next == NULL) + next = nfrontp; length = next - thisitem; memmove (good, thisitem, length); @@ -573,7 +582,7 @@ netclear (void) } else { - thisitem = nextitem (thisitem); + thisitem = nextitem (thisitem, nfrontp); } } -- 2.26.0.292.g33ef6b2f38