From 5e33e384dc5d19f8aa63ecd4a157e7acbaed579f Mon Sep 17 00:00:00 2001 From: Pierre Imai Date: Fri, 8 Jan 2016 13:20:54 +0900 Subject: Fix buffer overflow and null pointer dereference in mDNSResponder (CVE-2015-7988). BUG: 25852056 Test: None (cherry-picked from 5cb016d58af2cdc40c20fa435b8143a72ddf01a2) Change-Id: I67a8262caf48b42ccb2f41adae63c22f7f4ee4c8 --- mDNSCore/mDNSEmbeddedAPI.h | 5 +++-- mDNSPosix/mDNSPosix.c | 8 ++++++++ mDNSShared/uds_daemon.c | 18 +++++++++++++----- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/mDNSCore/mDNSEmbeddedAPI.h b/mDNSCore/mDNSEmbeddedAPI.h index 3d6c12a..5c3115c 100755 --- a/mDNSCore/mDNSEmbeddedAPI.h +++ b/mDNSCore/mDNSEmbeddedAPI.h @@ -2548,8 +2548,9 @@ mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, mDNSIPPort dst extern void mDNSPlatformLock (const mDNS *const m); extern void mDNSPlatformUnlock (const mDNS *const m); -extern void mDNSPlatformStrCopy ( void *dst, const void *src); -extern mDNSu32 mDNSPlatformStrLen ( const void *src); +mDNSexport void mDNSPlatformStrCopy( void *dst, const void *src); +mDNSexport mDNSu32 mDNSPlatformStrLCopy( void *dst, const void *src, mDNSu32 dstlen); +mDNSexport mDNSu32 mDNSPlatformStrLen ( const void *src); extern void mDNSPlatformMemCopy ( void *dst, const void *src, mDNSu32 len); extern mDNSBool mDNSPlatformMemSame (const void *dst, const void *src, mDNSu32 len); extern void mDNSPlatformMemZero ( void *dst, mDNSu32 len); diff --git a/mDNSPosix/mDNSPosix.c b/mDNSPosix/mDNSPosix.c index 8a46c6f..a8ac88a 100644 --- a/mDNSPosix/mDNSPosix.c +++ b/mDNSPosix/mDNSPosix.c @@ -1357,6 +1357,14 @@ mDNSexport void mDNSPlatformStrCopy(void *dst, const void *src) strcpy((char *)dst, (char *)src); } +// mDNS core calls this routine to copy C strings while taking the destination +// buffer size into account. +// On the Posix platform this maps directly to the ANSI C strncpy. +mDNSexport mDNSu32 mDNSPlatformStrLCopy(void *dst, const void *src, mDNSu32 dstlen) + { + return (strlcpy((char *)dst, (const char *)src, dstlen)); + } + // mDNS core calls this routine to get the length of a C string. // On the Posix platform this maps directly to the ANSI C strlen. mDNSexport mDNSu32 mDNSPlatformStrLen (const void *src) diff --git a/mDNSShared/uds_daemon.c b/mDNSShared/uds_daemon.c index ad5f943..e269be6 100644 --- a/mDNSShared/uds_daemon.c +++ b/mDNSShared/uds_daemon.c @@ -21,6 +21,7 @@ #else #include #include +#include #include #include #include @@ -1594,6 +1595,7 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) char type_as_string[MAX_ESCAPED_DOMAIN_NAME]; domainname d, srv; mStatus err; + const char *msgTXTData; DNSServiceFlags flags = get_flags(&request->msgptr, request->msgend); mDNSu32 interfaceIndex = get_uint32(&request->msgptr, request->msgend); @@ -1612,7 +1614,7 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) request->u.servicereg.instances = NULL; request->u.servicereg.txtlen = 0; request->u.servicereg.txtdata = NULL; - mDNSPlatformStrCopy(request->u.servicereg.type_as_string, type_as_string); + mDNSPlatformStrLCopy(request->u.servicereg.type_as_string, type_as_string, sizeof(request->u.servicereg.type_as_string)); if (request->msgptr + 2 > request->msgend) request->msgptr = NULL; else @@ -1622,15 +1624,21 @@ mDNSlocal mStatus handle_regservice_request(request_state *request) } request->u.servicereg.txtlen = get_uint16(&request->msgptr, request->msgend); + msgTXTData = get_rdata(&request->msgptr, request->msgend, request->u.servicereg.txtlen); + if (!request->msgptr) + { + LogMsg("%3d: DNSServiceRegister(unreadable parameters)", request->sd); + android_errorWriteWithInfoLog(0x534e4554, "25852056", -1, NULL, 0); + return(mStatus_BadParamErr); + } + if (request->u.servicereg.txtlen) { request->u.servicereg.txtdata = mallocL("service_info txtdata", request->u.servicereg.txtlen); if (!request->u.servicereg.txtdata) FatalError("ERROR: handle_regservice_request - malloc"); - mDNSPlatformMemCopy(request->u.servicereg.txtdata, get_rdata(&request->msgptr, request->msgend, request->u.servicereg.txtlen), request->u.servicereg.txtlen); + mDNSPlatformMemCopy(request->u.servicereg.txtdata, msgTXTData, request->u.servicereg.txtlen); } - if (!request->msgptr) { LogMsg("%3d: DNSServiceRegister(unreadable parameters)", request->sd); return(mStatus_BadParamErr); } - // Check for sub-types after the service type request->u.servicereg.num_subtypes = ChopSubTypes(request->u.servicereg.type_as_string); // Note: Modifies regtype string to remove trailing subtypes if (request->u.servicereg.num_subtypes < 0) @@ -2169,7 +2177,7 @@ mDNSlocal mStatus handle_browse_request(request_state *request) if (!MakeDomainNameFromDNSNameString(&temp, regtype)) return(mStatus_BadParamErr); // For over-long service types, we only allow domain "local" - if (temp.c[0] > 15 && domain[0] == 0) mDNSPlatformStrCopy(domain, "local."); + if (temp.c[0] > 15 && domain[0] == 0) mDNSPlatformStrLCopy(domain, "local.", sizeof(domain)); // Set up browser info request->u.browser.ForceMCast = (flags & kDNSServiceFlagsForceMulticast) != 0; -- cgit v1.2.3