File CVE-2020-10188.patch of Package krb5-appl.26157
From f89fba350fff7a2e675b7b846c50e3ac00288daf Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Thu, 26 Mar 2020 15:19:43 -0400
Subject: [PATCH] Fix CVE-2020-10188 (netclear()/nextitem() buffer overrun)
Modify nextitem() to always take a end bound and return NULL when it
would pass that bound. Simplify the loop for picking items in
netclear() and add NULL checks.
This fixes an issue where a malicious stream could cause writes beyond
the end of netobuf (or nclearto, if ENCRYPT).
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
[rschiron@redhat.com: adjusted bounds checks]
[rharwood@redhat.com: backported from telnet to krb5-appl]
---
telnet/telnetd/utility.c | 43 ++++++++++++++++++++++++----------------
1 file changed, 26 insertions(+), 17 deletions(-)
diff --git a/telnet/telnetd/utility.c b/telnet/telnetd/utility.c
index 087eecb..a210375 100644
--- a/telnet/telnetd/utility.c
+++ b/telnet/telnetd/utility.c
@@ -212,33 +212,40 @@ ptyflush()
* if the current address is a TELNET IAC ("I Am a Command")
* character.
*/
-static char *
-nextitem(current)
- char *current;
+static
+char *
+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) {
case DO:
case DONT:
case WILL:
case WONT:
- return current+3;
+ return current+3 <= endp ? current+3 : NULL;
case SB: /* loop forever looking for the SE */
{
register char *look = current+2;
- for (;;) {
+ while (look < endp) {
if ((*look++&0xff) == IAC) {
- if ((*look++&0xff) == SE) {
+ if (look < endp && (*look++&0xff) == SE) {
return look;
}
}
}
+ return NULL;
}
default:
- return current+2;
+ return current+2 <= endp ? current+2 : NULL;
}
} /* end of nextitem */
@@ -259,13 +266,12 @@ nextitem(current)
* caller should be setting the urgent data pointer AFTER calling
* us in any case.
*/
- void
-netclear()
+void netclear(void)
{
register char *thisitem, *next;
char *good;
#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
- ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
+ (nfrontp > p+1 && (((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))))
#ifdef ENCRYPTION
thisitem = nclearto > netobuf ? nclearto : netobuf;
@@ -273,7 +279,7 @@ netclear()
thisitem = netobuf;
#endif /* ENCRYPTION */
- while ((next = nextitem(thisitem)) <= nbackp) {
+ while ((next = nextitem(thisitem, nbackp)) != NULL && next <= nbackp) {
thisitem = next;
}
@@ -285,20 +291,23 @@ netclear()
good = netobuf; /* where the good bytes go */
#endif /* ENCRYPTION */
- while (nfrontp > thisitem) {
+ while (thisitem != NULL && nfrontp > thisitem) {
if (wewant(thisitem)) {
- unsigned int length;
+ int length;
next = thisitem;
do {
- next = nextitem(next);
- } while (wewant(next) && (nfrontp > next));
+ next = nextitem(next, nfrontp);
+ } while (next != NULL && wewant(next) && (nfrontp > next));
+ if (next == NULL) {
+ next = nfrontp;
+ }
length = next-thisitem;
- memcpy(good, thisitem, length);
+ bcopy(thisitem, good, length);
good += length;
thisitem = next;
} else {
- thisitem = nextitem(thisitem);
+ thisitem = nextitem(thisitem, nfrontp);
}
}
--
2.26.2