Bug 961721 (CVE-2015-7547) - VUL-0: CVE-2015-7547: glibc getaddrinfo stack-based buffer overflow
Summary: VUL-0: CVE-2015-7547: glibc getaddrinfo stack-based buffer overflow
Status: RESOLVED FIXED
Alias: CVE-2015-7547
Product: SUSE Security Incidents
Classification: Novell Products
Component: Incidents (show other bugs)
Version: unspecified
Hardware: Other Other
: P3 - Medium : Major
Target Milestone: ---
Assignee: Andreas Schwab
QA Contact: Security Team bot
URL:
Whiteboard: CVSSv2:SUSE:CVE-2015-7547:5.8:(AV:N/A...
Keywords:
Depends on:
Blocks:
 
Reported: 2016-01-13 14:55 UTC by Johannes Segitz
Modified: 2017-10-24 18:07 UTC (History)
16 users (show)

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---


Attachments
Patch for getaddrinfo stack-based buffer overflow (11.55 KB, patch)
2016-01-13 16:01 UTC, Andreas Schwab
Details | Diff
Patch for getaddrinfo stack-based buffer overflow (17.05 KB, patch)
2016-01-14 13:04 UTC, Andreas Schwab
Details | Diff
Patch for getaddrinfo stack-based buffer overflow (22.51 KB, patch)
2016-01-18 09:23 UTC, Andreas Schwab
Details | Diff
Tests from Florian Weimer (21.95 KB, application/x-gzip)
2016-02-01 16:14 UTC, Andreas Schwab
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Johannes Segitz 2016-01-13 14:55:19 UTC
Summary
=======

During upstream review of the public open bug 18665 for glibc,
it was discovered that the bug could lead to a stack-based buffer
overlow.

https://sourceware.org/bugzilla/show_bug.cgi?id=18665

The buffer overflow occurs in the function send_dg (UDP) and
send_vc (TCP) for the NSS module libnss_dns.so.2 when calling
getaddrinfo with AF_UNSPEC family.

The use of AF_UNSPEC triggers the low-level resolver code to send
out two parallel queries for A and AAAA. A mismanagement of the
buffers used for those queries could result in the response of a
query writing beyond the alloca allocated buffer created by
__res_nquery.

Main conclusions:

- Via getaddrinfo with family AF_UNSPEC the overflowed buffer
  is located on the stack via alloca (a 2048 byte fixed size
  buffer for DNS responses).

- At most 65535 bytes (MAX_PACKET) may be written to the
  alloca buffer of 2048 bytes. Overflowing bytes are entirely
  under the control of the attacker and are the result of a
  crafted DNS response.

- Local testing shows that we have been able to control at
  least the execution of one free() call with the buffer
  overflow and gained control of EIP. Further exploitation
  was not attempted, only this single attempt to show that
  it is very likely that execution control can be gained
  without much more effort. We know of no known attacks that
  use this specific vulnerability.

- Mitigating factors for UDP include:
  - A firewall that drops UDP DNS packets > 512 bytes.
  - A local validating resolver.
  - No IPv6 AAAA queries (avoids buffer management error).
    e.g. Do not use AF_UNSPEC.
  - No use of `options edns0` in /etc/resolv.conf since
    EDNS0 allows responses larger than 512 bytes and can
    lead to valid DNS responses that overflow.
  - No use of `RES_USE_EDNS0` or `RES_USE_DNSSEC` since they
    can both lead to valid large EDNS0-based DNS responses
    that can overflow.

- Mitigating factors for TCP include:
  - Nothing.

- Mitigations that don't work:
  - Setting `options single-request` does not change buffer
    management and does not prevent the exploit.
  - Setting `options single-request-reopen` does not change
    buffer management and does not prevent the exploit.
  - Disabling IPv6 does not disable AAAA queries. The use of
    AF_UNSPEC unconditionally enables the dual query.
    - The use of `sysctl -w net.ipv6.conf.all.disable_ipv6=1`
      will not protect your system from the exploit.

- The code is only present in glibc's copy of libresolv which
  has enhancements to carry out parallel A and AAAA queries.
  A quick review shows Fedora 10 with bind-9.5.2 was the last
  bind in Fedora to have common code in lib/bind/reolv/res_send.c,
  but the bind implementation is much simpler and does not suffer
  from the buffer overflow. Therefore only programs using glibc's
  copy of the code have this problem.
  The code in question was introduced in May 2008 as part of
  glibc 2.9, which means it is present in RHEL6, and RHEL7 but
  not RHEL5 (verified not present in RHEL5, and verified present
  in RHEL6 and RHEL7).

High-level Analysis:
====================

The defect is located in the glibc package in the following file:

- resolv/res_send.c

as part of the send_dg and send_vc functions which are part
of the __libc_res_nsend (res_nsend) interface which  is used
by many of the higher level interfaces including getaddrinfo
indirectly via the DNS NSS module.

The easiest way to trigger the buffer mismanagement is like
this:

* Have the target attempt a DNS resolution for a domain you control.
  - Need to get A and AAAA queries.
* First response is 2048 bytes.
  - Fills the alloca buffer entirely with 0 left over.
  - send_dg attemps to reuse the user buffer but can't.
  - New buffer created but due to bug old alloca buffer is used
    with new size of 65535.
  - Response should be valid.
* Send second response.
  - This response should be flawed in such a way that it forces
    __libc_res_nsend to retry the query. It is sufficient for example
    to pick any of the listed failure modes in the code which return
    0 as a way to create a malformed response.
* Send third response.
  - The third response can contain 2048 bytes of valid response.
  - The remaining 63487 bytes of the response are the attack payload
    and the recvfrom smashes the stack with it.

The real work required is to craft a payload that won't crash the
target, but control one function, like our example free() where the
stack contents allow control flow modification.

Please note that there are other ways to trigger the buffer management
flaw, but they require slightly more control over the timing of the
responses and use poll timeout to carry out the exploit with just two
responses from the attacker (as opposed to three).

A similar exploit is possible with TCP, but requires resetting the
TCP connection to force send_vc to exit and be retried with the wrong
buffer size, similar to the send_dg failure.

Detailed Analysis:
==================

>From getaddrinfo we call into the NSS DNS module.

First in resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname4_r):

 307   host_buffer.buf = orig_host_buffer = (querybuf *) alloca (2048);
...
 315   int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC,
 316                               host_buffer.buf->buf, 2048, &host_buffer.ptr,
 317                               &ans2p, &nans2p, &resplen2, &ans2p_malloced);

We have the alloca which is the root cause of the stack smash.

Then in resolv/res_send.c (send_dg):

We are in POLLIN reading the server response to our request:

1151         } else if (pfd[0].revents & POLLIN) {
1152                 int *thisanssizp;
1153                 u_char **thisansp;
1154                 int *thisresplenp;
1155 
1156                 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
1157                         thisanssizp = anssizp;
1158                         thisansp = anscp ?: ansp;
1159                         assert (anscp != NULL || ansp2 == NULL);
1160                         thisresplenp = &resplen;

Neither reply is received yet so thisanssizp is anssizp e.g. 2048, matching
the user supplied buffer (from _nss_dns_gethostbyname4_r).

1189                 if (*thisanssizp < MAXPACKET
1190                     /* Yes, we test ANSCP here.  If we have two buffers
1191                        both will be allocatable.  */
1192                     && anscp
1193 #ifdef FIONREAD
1194                     && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
1195                         || *thisanssizp < *thisresplenp)
1196 #endif

The buffer is sufficient and `thisresplenp` is 2048 and that fits in the user buffer.

1357                 /* Mark which reply we received.  */
1358                 if (recvresp1 == 0 && hp->id == anhp->id)
1359                         recvresp1 = 1;

We mark the first response as received, and go back to `wait:`

1362                 /* Repeat waiting if we have a second answer to arrive.  */
1363                 if ((recvresp1 & recvresp2) == 0) {
...
1374                         goto wait;

This time around though we have already received one reply, and buf2 is non-NULL
so we trigger this:

1162                         if (*anssizp != MAXPACKET) {
1163                                 /* No buffer allocated for the first
1164                                    reply.  We can try to use the rest
1165                                    of the user-provided buffer.  */
1166 #if _STRING_ARCH_unaligned
1167                                 *anssizp2 = orig_anssizp - resplen;
1168                                 *ansp2 = *ansp + resplen;

The use of MAXPACKET is a value/boolean-style check. The send_dg internal
logic uses a value of *anssizp of MAXPACKET to indicate an internal buffer
was allocated for the response. It does not contemplate a user might pass in
a buffer that big, but let us ignore that for now.

The above code, noting it has not allocated an malloc'd buffer, attempts to use
the remainder of the user buffer to store the second response to avoid malloc.

However, the user buffer of 2048 was fully used by the 2048 response, and
the value of `orig_anssizp - resplen` is zero, so `*anssizp2` is zero.

None of this is important really, but it sets the stage for the next failures.

1169 #else
...
1184                         thisanssizp = anssizp2;
1185                         thisansp = ansp2;
1186                         thisresplenp = resplen2;

Then `thisansp` points also just beyond the stack, but because the size is
zero we'll never use this pointer.

1189                 if (*thisanssizp < MAXPACKET
1190                     /* Yes, we test ANSCP here.  If we have two buffers
1191                        both will be allocatable.  */
1192                     && anscp
1193 #ifdef FIONREAD
1194                     && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
1195                         || *thisanssizp < *thisresplenp)

This is all true. We are reusing the user buffer so it's size is less than
MAXPACKET, yes we have `anscp` non-NULL pointer (allowed to modify callers
storage pointers), and the ioctl shows we have 10000 bytes arriving.

1196 #endif
1197                     ) {
1198                         u_char *newp = malloc (MAXPACKET);
1199                         if (newp != NULL) {
1200                                 *anssizp = MAXPACKET;
1201                                 *thisansp = ans = newp;
1202                                 if (thisansp == ansp2)
1203                                   *ansp2_malloced = 1;
1204                         }
1205                 }

So we allocate a new buffer, set *anssizp to MAXPACKET, but fail to set
*ansp to the new buffer, and fail to update *thisanssizp to the new size.

1209                 *thisresplenp = recvfrom(pfd[0].fd, (char*)*thisansp,
1210                                          *thisanssizp, 0,
1211                                         (struct sockaddr *)&from, &fromlen);

Then in recvfrom we read zero bytes because *thisanssizp is zero.

Which means we error out:

1212                 if (__glibc_unlikely (*thisresplenp <= 0))       {
...
1218                         goto err_out;

However, we return to __libc_res_nsend, and we have manipulated the callers
state (they are all pointers-to-pointers) incorrectly.

Firstly:

1167                                 *anssizp2 = orig_anssizp - resplen;

... this sets the size of answer buffer #2 to 0.


1185                         thisansp = ansp2;
...
1201                                 *thisansp = ans = newp;

... but then we set the answer buffer #2 pointer to the malloced block.

So now in __libc_res_nsend the second answer buffer has size 0, but is
malloced and points to a valid block of MAXPACKET bytes of memory.

Secondly:

1200                                 *anssizp = MAXPACKET;

... this sets the size of the answer buffer #1 to MAXPACKET bytes, but
does nothing else to change *ansp to the new malloc'd buffer.

So now in __libc_res_nsend the first answer buffer has size MAXPACKET,
but is still the same alloca'd 2048 byte space.

The send_dg function exits, and we loop in __libc_res_nsend looking for
an answer with the next resolver. The buffers are reused and send_dg is
called again and this time it results in `MAXPACKET - 2048` bytes being
overflowed from the response directly onto the stack.

Playing with the attack buffer slightly and the timing gives another
way to trigger the stack smash.

Set the response buffer to 2049 or larger to trigger malloc buffer
reallocation right away.

1182                 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
1183                         thisanssizp = anssizp;
1184                         thisansp = anscp ?: ansp;
1185                         assert (anscp != NULL || ansp2 == NULL);
1186                         thisresplenp = &resplen;

this executes and we assign `thisansp` to `anscp` which is a pointer
that is non-null if the caller intends to allow us to change the allocation
of the answer buffer.

At this point the astute reader realizes that:

    In __libc_res_nsend the variable `&ans` has distinct storage from
    `ansp`, but that `ans` and `*ansp` point to the same location.
    The res_nquery caller intends this because they want the underlying
    res_nsend to be able to change the buffer if the size is insufficient.

Then we go on to allocate the new buffer:

1224                         u_char *newp = malloc (MAXPACKET);
1225                         if (newp != NULL) {
1226                                 *thisanssizp = MAXPACKET;
1227                                 *thisansp = ans = newp;
1228                                 if (thisansp == ansp2)
1229                                   *ansp2_malloced = 1;

We update `ans` (our cached copy of `ansp` or `&ans` in res_nsend), and we
update `*thisansp` which is `anscp` (`ansp` in res_nsend), but nowhere
do we update `ansp` which means that in res_nsend the two pointers
`&ans` and `ansp` point to two different buffers, but only have one
size `*anssizp` which is now MAXPACKET, but the original `ansp` is still
pointing at the 2048 alloca buffer.

Everything is OK for now since this works:

1235                 *thisresplenp = recvfrom(pfd[0].fd, (char*)*thisansp,
1236                                          *thisanssizp, 0,
1237                                         (struct sockaddr *)&from, &fromlen);

We point at the new buffer, and read the new length at most.

But if you delay the application enough to timeout the retry loop (perhaps load
induced in real life) and that causes us to exit send_dg with 0 to indicate
we should retry.

When we restart send_dg, we now have `&ans` pointing at the 2048 alloca buffer
but `&anssiz` is MAXPACKET now and doesn't match. This is OK for the first
answer because:

1184                 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
1185                         thisanssizp = anssizp;
1186                         thisansp = anscp ?: ansp;
1187                         assert (anscp != NULL || ansp2 == NULL);
1188                         thisresplenp = &resplen;

... this again selects anscp (malloc'd storage) over ansp (alloca).

However, if we are quick this time and don't timeout, we flip over to trying
to make the second query and setup an ansp2 buffer:

1204                         } else {
1205                                 /* The first reply did not fit into the
1206                                    user-provided buffer.  Maybe the second
1207                                    answer will.  */
1208                                 *anssizp2 = orig_anssizp;
1209                                 *ansp2 = *ansp;
1210                         }

Here we assign ansp2 to ansp (alloca) with an orig_anssizp size which is
wrong (MAXPACKET).

The next time we do a recvfrom we will smash the stack again.

The same problems exist in send_vc.

Prototype patch to fix glibc master attached (lots of comments).

Prototype self-contained test cases attached for UDP and TCP.
These are rough and would need more cleanup for inclusion in glibc.

Cheers,
Carlos.

P.S.

The test cases showed 2 uninitialized uses in getaddrinfo under valgrind:

==4917== Conditional jump or move depends on uninitialised value(s)
==4917==    at 0x512674E: gaih_inet (getaddrinfo.c:870)
==4917==    by 0x512866D: getaddrinfo (getaddrinfo.c:2417)
==4917==    by 0x400D0B: main (bug18665.c:166)
==4917==  Uninitialised value was created by a stack allocation
==4917==    at 0x5125850: gaih_inet (getaddrinfo.c:275)
==4917== 
==4917== Conditional jump or move depends on uninitialised value(s)
==4917==    at 0x5126584: gaih_inet (getaddrinfo.c:1079)
==4917==    by 0x512866D: getaddrinfo (getaddrinfo.c:2417)
==4917==    by 0x400D0B: main (bug18665.c:166)
==4917==  Uninitialised value was created by a stack allocation
==4917==    at 0x5125850: gaih_inet (getaddrinfo.c:275)

Which are caused by failure to set *h_errnop in 
resolv/nss_dns/dns-host.c (gaih_getanswer_slice) which results
in gaih_inet jump/move depends on uninitialized value here:

 862                       status = DL_CALL_FCT (fct4, (name, pat, tmpbuf,
 863                                                    tmpbuflen, &rc, &herrno,
 864                                                    NULL));
 865                       if (status == NSS_STATUS_SUCCESS)
 866                         break;
 867                       if (status != NSS_STATUS_TRYAGAIN
 868                           || rc != ERANGE || herrno != NETDB_INTERNAL)
 869                         {
 870                           if (herrno == TRY_AGAIN)
                                   ^^^^^^
 871                             no_data = EAI_AGAIN;
 872                           else
 873                             no_data = herrno == NO_DATA;
 874                           break;

All paths through _nss_dns_gethostbyname4_r and called functions
must correctly set *h_errnop or we have an uninitialized use of the
stack allocated herrno variable.

Fix attached as valgrind-uninit.patch.

P.P.S 

Analysis by Florian indicates also that send_vc suffers
from a potential TCP issue. The function sends both A and AAAA
queries back-to-back on the same socket and this could result in
failure to get any response back from the server. The scenarios is
as follows: server receives query, server reads query header and
determines query length, server reads full query length, server
responds to query and closes socket. The server closing the socket
is an implementation detail that is allowed by the server and may
be done to switch to another client. The consequence of closing the
socket with data still pending (the AAAA query) will result in an
RST being sent to the client. That RST is unordered and when it
arrives at the client kernel will cause an asynchronous teardown
of the entire socket and buffers. Any unread data by the client
is lost and the client may see less than the full response (it
might see no response). This issue is orthogonal to what we're dealing
with, but it should be mentioned because in the event it impacts
your analysis.
Comment 1 Andreas Schwab 2016-01-13 16:01:50 UTC
Created attachment 661635 [details]
Patch for getaddrinfo stack-based buffer overflow
Comment 2 Johannes Segitz 2016-01-13 16:39:17 UTC
CRD: unknown
Comment 3 Swamp Workflow Management 2016-01-13 23:00:37 UTC
bugbot adjusting priority
Comment 4 Andreas Schwab 2016-01-14 13:04:08 UTC
Created attachment 661760 [details]
Patch for getaddrinfo stack-based buffer overflow
Comment 5 Andreas Schwab 2016-01-18 08:54:15 UTC
CRD: 2016-02-08
Comment 6 Andreas Schwab 2016-01-18 09:23:34 UTC
Created attachment 662028 [details]
Patch for getaddrinfo stack-based buffer overflow
Comment 15 Andreas Schwab 2016-02-01 16:14:54 UTC
Created attachment 664035 [details]
Tests from Florian Weimer
Comment 16 Alexander Bergmann 2016-02-16 15:05:11 UTC
Public now.
Comment 17 Sebastian Krahmer 2016-02-16 15:39:15 UTC
Crasher PoC: https://github.com/fjserna/CVE-2015-7547
Comment 18 Andreas Stieger 2016-02-16 16:29:21 UTC
Andreas, we would now like to process the openSUSE submission.
Comment 19 Swamp Workflow Management 2016-02-16 19:18:11 UTC
SUSE-SU-2016:0470-1: An update that solves 10 vulnerabilities and has four fixes is now available.

Category: security (important)
Bug References: 830257,847227,863499,892065,918187,920338,927080,945779,950944,961721,962736,962737,962738,962739
CVE References: CVE-2013-2207,CVE-2013-4458,CVE-2014-8121,CVE-2014-9761,CVE-2015-1781,CVE-2015-7547,CVE-2015-8776,CVE-2015-8777,CVE-2015-8778,CVE-2015-8779
Sources used:
SUSE Linux Enterprise Server 11-SP2-LTSS (src):    glibc-2.11.3-17.45.66.1
SUSE Linux Enterprise Debuginfo 11-SP2 (src):    glibc-2.11.3-17.45.66.1
Comment 20 Swamp Workflow Management 2016-02-16 19:23:49 UTC
SUSE-SU-2016:0471-1: An update that solves 6 vulnerabilities and has three fixes is now available.

Category: security (important)
Bug References: 950944,955647,956716,958315,961721,962736,962737,962738,962739
CVE References: CVE-2014-9761,CVE-2015-7547,CVE-2015-8776,CVE-2015-8777,CVE-2015-8778,CVE-2015-8779
Sources used:
SUSE Linux Enterprise Software Development Kit 12-SP1 (src):    glibc-2.19-35.1
SUSE Linux Enterprise Server 12-SP1 (src):    glibc-2.19-35.1
SUSE Linux Enterprise Desktop 12-SP1 (src):    glibc-2.19-35.1
Comment 21 Swamp Workflow Management 2016-02-16 19:29:47 UTC
SUSE-SU-2016:0472-1: An update that solves 6 vulnerabilities and has three fixes is now available.

Category: security (important)
Bug References: 930721,942317,950944,956988,961721,962736,962737,962738,962739
CVE References: CVE-2014-9761,CVE-2015-7547,CVE-2015-8776,CVE-2015-8777,CVE-2015-8778,CVE-2015-8779
Sources used:
SUSE Linux Enterprise Software Development Kit 11-SP4 (src):    glibc-2.11.3-17.95.2
SUSE Linux Enterprise Software Development Kit 11-SP3 (src):    glibc-2.11.3-17.95.2
SUSE Linux Enterprise Server for VMWare 11-SP3 (src):    glibc-2.11.3-17.95.2
SUSE Linux Enterprise Server 11-SP4 (src):    glibc-2.11.3-17.95.2
SUSE Linux Enterprise Server 11-SP3 (src):    glibc-2.11.3-17.95.2
SUSE Linux Enterprise Desktop 11-SP4 (src):    glibc-2.11.3-17.95.2
SUSE Linux Enterprise Desktop 11-SP3 (src):    glibc-2.11.3-17.95.2
SUSE Linux Enterprise Debuginfo 11-SP4 (src):    glibc-2.11.3-17.95.2
SUSE Linux Enterprise Debuginfo 11-SP3 (src):    glibc-2.11.3-17.95.2
Comment 22 Swamp Workflow Management 2016-02-16 19:31:35 UTC
SUSE-SU-2016:0473-1: An update that solves 6 vulnerabilities and has three fixes is now available.

Category: security (important)
Bug References: 950944,955647,956716,958315,961721,962736,962737,962738,962739
CVE References: CVE-2014-9761,CVE-2015-7547,CVE-2015-8776,CVE-2015-8777,CVE-2015-8778,CVE-2015-8779
Sources used:
SUSE Linux Enterprise Software Development Kit 12 (src):    glibc-2.19-22.13.1
SUSE Linux Enterprise Server 12 (src):    glibc-2.19-22.13.1
SUSE Linux Enterprise Desktop 12 (src):    glibc-2.19-22.13.1
Comment 27 Sascha Weber 2016-02-17 10:32:11 UTC
Another question. I can see that patches for SLES/D 11 SP3 have been released but it does not say LTSS. But both products are only available in LTSS now. Or has this patch been released to the regular Updates channel?
Comment 29 Marcus Meissner 2016-02-17 10:39:53 UTC
This update was started before the LTSS of 11-SP3, so it was still released into the regular SP3 channels. So it was "late", but only 1 or 2 more will be coming there.
Comment 30 Sascha Weber 2016-02-17 10:58:44 UTC
As per Michal Koutny I have requested the SLES 11 SP1 Mass-PTF on internal Bug#967023. L3 has been created there.
Comment 31 Sascha Weber 2016-02-17 10:59:23 UTC
Also, TID has been created here: https://www.suse.com/support/kb/doc.php?id=7017265

^^ It is marked as INTERNAL for now until I get a go either here or on the HIV Mailinglist.
Comment 32 Swamp Workflow Management 2016-02-17 11:12:46 UTC
openSUSE-SU-2016:0490-1: An update that solves 6 vulnerabilities and has three fixes is now available.

Category: security (important)
Bug References: 950944,955647,956716,958315,961721,962736,962737,962738,962739
CVE References: CVE-2014-9761,CVE-2015-7547,CVE-2015-8776,CVE-2015-8777,CVE-2015-8778,CVE-2015-8779
Sources used:
openSUSE Leap 42.1 (src):    glibc-2.19-19.1, glibc-testsuite-2.19-19.2, glibc-utils-2.19-19.1
Comment 34 Marcus Meissner 2016-02-17 12:54:03 UTC
Please note that SLES 10 all service packs have an older version of glibc which is NOT affected.
Comment 37 Martin Jedamzik 2016-02-17 14:21:47 UTC
Do we have an update for rhel expanded support planned ?
Comment 38 Forgotten User SK4BVlRiaA 2016-02-17 14:32:06 UTC
any ETA for tumbleweed? or even the older opensuse releases still receiving updates?
Comment 39 Andreas Stieger 2016-02-17 14:44:19 UTC
(In reply to Matthias Subik from comment #38)
> any ETA for tumbleweed? or even the older opensuse releases still receiving
> updates?

openSUSE Tumbleweed was submitted right now.
https://build.opensuse.org/request/show/359990

openSUSE Leap 42.1 is patched
openSUSE 13.2 update is building
openSUSE 13.1 update... it's EOL/evergreen: community effort
Comment 43 Richard Thompson 2016-02-18 10:51:51 UTC
Sorry to dump this here as is but one of my customer has the following question.

---
Whether a SLES11SP4 bind – configured as caching proxy – will
a)	forward the maliciously forged DNS replies from DNS servers in the internet 1:1 to out DNS clients behind the DNS proxies, or 
b)	drop / rewrite the DNS information, rendering the potential attack impossible.
---
I guess it will make a difference to which machines they need to update and when.
Can someone help answer it please
Comment 44 Roger Whittaker 2016-02-18 13:24:42 UTC
Richard's question (comment #43) is exactly what I would like to understand also.  The discussions I have seen of this bug so far don't explain this point but it's rather crucial for people trying to understand how exposed they are.
Comment 45 Forgotten User 0wt-W6srW9 2016-02-18 13:36:38 UTC
(In reply to Andreas Stieger from comment #39)
> openSUSE Leap 42.1 is patched
> openSUSE 13.2 update is building
> openSUSE 13.1 update... it's EOL/evergreen: community effort

I do not see that the package is built for 13.2 anywhere. Could you check if building for this platform is enabled?

It's marked as "disabled" here for example:

https://build.opensuse.org/request/show/359990

and there is no open request for it here:

https://build.opensuse.org/package/show/openSUSE:13.2:Update/glibc

Am I looking in the wrong place?
Comment 46 Marcus Meissner 2016-02-18 13:45:50 UTC
yes, you are.

it is building in a staging incident: openSUSE:Maintenance:4693
Comment 47 Marcus Meissner 2016-02-18 17:18:37 UTC
openSUSE Factory is released via the Tumbleweed Update repository.
Comment 48 Swamp Workflow Management 2016-02-18 23:12:22 UTC
openSUSE-SU-2016:0510-1: An update that solves 5 vulnerabilities and has two fixes is now available.

Category: security (important)
Bug References: 956716,958315,961721,962736,962737,962738,962739
CVE References: CVE-2014-9761,CVE-2015-7547,CVE-2015-8776,CVE-2015-8778,CVE-2015-8779
Sources used:
openSUSE 13.2 (src):    glibc-2.19-16.22.2, glibc-testsuite-2.19-16.22.4, glibc-utils-2.19-16.22.2
Comment 49 Florian BONIN 2016-02-19 13:29:51 UTC
Hi all,

Could you tell me if a reboot of the server is needed after the Patch has been applied ? 

Thanks
Regards,
Comment 50 Michal Koutný 2016-02-19 14:14:31 UTC
Hi, Florian.

(In reply to Florian BONIN from comment #49)
> Could you tell me if a reboot of the server is needed after the Patch has
> been applied ? 
The problem is not in kernel, so the reboot is theoretically not needed. However, the fixed code is in libc, which is linked to... like everything? So you'd need to restart most of the userspace anyway (`zypper ps` might help), i.e. solution is either to reboot or restart ("only") all daemons that use the libc resolver.

This is my theoretical POV, someone more experienced can add more.
Comment 51 Forgotten User SK4BVlRiaA 2016-02-19 14:17:43 UTC
(In reply to Florian BONIN from comment #49)

ldd /bin/systemd clearly shows ...

...
        libc.so.6 => /lib64/libc.so.6 (0x00007f19fb594000)
...

So your PID 1 is affected, you need to reboot.
Comment 52 Michal Koutný 2016-02-19 14:19:34 UTC
(In reply to Matthias Subik from comment #51)
> ldd /bin/systemd clearly shows ...
systemctl daemon-reexec ;-)
Comment 54 Forgotten User Cjyjh0cmPE 2016-02-19 14:44:48 UTC
Today a patch for 13.1 has been released. Can we also expect patches for older versions like 11.1, 12.1?
Comment 55 Andreas Stieger 2016-02-19 14:54:15 UTC
(In reply to dsgn dsgn from comment #54)
> Today a patch for 13.1 has been released. Can we also expect patches for
> older versions like 11.1, 12.1?

No. The 13.1 patch was provided through Evergreen:
https://en.opensuse.org/openSUSE:Evergreen

There is no Evergreen effort underway for 11.1, 12.1. The patch is open source so you could build it.

https://en.opensuse.org/Lifetime
Comment 58 Forgotten User SK4BVlRiaA 2016-02-19 17:44:56 UTC
(In reply to Michal Koutny from comment #52)
> (In reply to Matthias Subik from comment #51)
> > ldd /bin/systemd clearly shows ...
> systemctl daemon-reexec ;-)

I stand corrected, thank you.
Comment 60 Andreas Schwab 2016-02-22 08:11:23 UTC
The patch only changes libresolv and libnss_dns, so only processes using these libraries are affected.
Comment 62 Sebastian Krahmer 2016-02-22 09:26:57 UTC
(In reply to Andreas Schwab from comment #60)
> The patch only changes libresolv and libnss_dns, so only processes using
> these libraries are affected.

The problem is that the vuln code is reachable via getaddrinfo(),
which is a symbol of glibc. You dont immediately see via ldd
if a program is affected. Missing libresolv/libnss_dns libs
in ldd output dont mean anything.
You'd need to dump /proc/pid/maps at runtime
to find libnss_dns dynamically loaded.

However, in most scenarios, you probably only need to restart nscd,
as in nscd setups (which should be default for most of our dists?)
the getaddrinfo() calls are routed to nscd which is turn is doing
the real 'vulnerable' lookup.
Comment 64 Andreas Schwab 2016-02-22 09:41:36 UTC
> The problem is that the vuln code is reachable via getaddrinfo(),
> which is a symbol of glibc.

No, this is not the problem.  The code of getaddrinfo (or any other part of libc.so) didn't change due to that patch in any way whatsoever.

> You'd need to dump /proc/pid/maps at runtime
> to find libnss_dns dynamically loaded.

That is exactly what "using a library" is all about.
Comment 65 Sebastian Krahmer 2016-02-22 09:52:55 UTC
(In reply to Andreas Schwab from comment #64)
> > The problem is that the vuln code is reachable via getaddrinfo(),
> > which is a symbol of glibc.
> 
> No, this is not the problem.  The code of getaddrinfo (or any other part of
> libc.so) didn't change due to that patch in any way whatsoever.

I didnt say the opposite. The problem remains. Your program may
still needs to be restarted, even if it "just" links to libc.so,
as its the case with nscd.
Comment 66 Andreas Schwab 2016-02-22 10:23:27 UTC
> I didnt say the opposite. The problem remains. Your program may
> still needs to be restarted, even if it "just" links to libc.so,

Only once it has used libresolv or libnss_dns.  ldd isn't the answer to that question.

> as its the case with nscd

Of course, nscd is using libnss_dns as soon as it tries to do a DNS lookup.
Comment 67 Sebastian Krahmer 2016-02-22 10:28:17 UTC
(In reply to Andreas Schwab from comment #66)
> > I didnt say the opposite. The problem remains. Your program may
> > still needs to be restarted, even if it "just" links to libc.so,
> 
> Only once it has used libresolv or libnss_dns.  ldd isn't the answer to that
> question.

That was my whole point, that "ldd systemd" and alike dont
tell you anything :)
Comment 68 Marcus Meissner 2016-02-23 14:28:57 UTC
I currently can not add more than already written.

A lot of mitigations are there, like stack is usually randomized, our services facing the network are built with ASLR.

I general dont handle this as PANIC! update, but more as important for next possible maintenance window.

We have currently not heard of working exploits in the wild.
      

Updates were released, tumbleweed glibc is in final integration.