First Last Prev Next    No search results available      Search page      Enter new bug
Bug#: 73210
Alias:
Product:
Component:
Status: RESOLVED
Resolution: DUPLICATE of bug 74384
Assigned To: Gentoo Security <security@gentoo.org>
Hardware:
OS:
Version:
Priority:
Severity:
Reporter: Sune Kloppenborg Jeppesen <jaervosz@gentoo.org>
Add CC:
CC:
URL:
Summary:
Status Whiteboard:
Keywords:
Flags: Requestee:
 
 
  ()

Filename Description Type Creator Created Size Actions
Create a New Attachment (proposed patch, testcase, etc.) View All

Bug 73210 depends on: Show dependency tree
Bug 73210 blocks:

Additional Comments: (this is where you put emerge --info)


Not eligible to see or edit group visibility for this bug.






View Bug Activity   |   Format For Printing   |   XML   |   Clone This Bug


Description:   Opened: 2004-12-03 04:07 0000
Just reported to Vendor-Sec, no patches, PoC provided but not included here. 

There are multiple serious issues with the igmp.c code in recent kernel
versions. Here an incomplete list of bugs:

1) ip_mc_source suffers from a serious kernel deadlock & kernel memory
overwrite problem (see attached code). It is possible to decrement the
psl->sl_count counter to be 0xffffffff == -1 with the consequence that:

- a repeated call will start a loop counting from 0 to UINT_MAX causing a
kernel hang for minutes (depending on the machine speed), then the
whole kernel memory following the kmalloc'ated buffer will be shifted by 4
bytes (LOL) causing an immediate reboot.

- If properly exploited this will lead to elevated privileges.

Btw. the code there is obviously nonsense:


------- Comment #1 From Sune Kloppenborg Jeppesen 2004-12-03 04:07:41 0000 -------
Just reported to Vendor-Sec, no patches, PoC provided but not included here. 

There are multiple serious issues with the igmp.c code in recent kernel
versions. Here an incomplete list of bugs:

1) ip_mc_source suffers from a serious kernel deadlock & kernel memory
overwrite problem (see attached code). It is possible to decrement the
psl->sl_count counter to be 0xffffffff == -1 with the consequence that:

- a repeated call will start a loop counting from 0 to UINT_MAX causing a
kernel hang for minutes (depending on the machine speed), then the
whole kernel memory following the kmalloc'ated buffer will be shifted by 4
bytes (LOL) causing an immediate reboot.

- If properly exploited this will lead to elevated privileges.

Btw. the code there is obviously nonsense:

                rv = !0;
                for (i=0; i<psl->sl_count; i++) {
                        rv = memcmp(&psl->sl_addr, &mreqs->imr_multiaddr,
                                sizeof(__u32));
                        if (rv >= 0)
                                break;
                }
                if (!rv)        /* source not found */
                        goto done;

If we had the 01.04 today I would say some people have keyboards without
the '[' and ']' brackets ;-)


2) because of the bug 1) it is possible to read huge portions of kernel
memory through ip_mc_msfget()


3) igmp_marksources() function is called in the context of an IGMP group
query and suffers from an out of bound access to kernel memory. This is
remotely exploitable if applications have bound a multicast socket.

I'm not sure but I guess that there is a large number of standard apps
that use multicast, eg. some Linux routing packages or videoconferencing,
etc.

You may check for your configuration if you are vulnerable:

/proc/net/igmp
/proc/net/mcfilter

if both files exist and are non-empty you are vulnerable.

This bug allows in the best case to remotely DoS a Linux machine with just
a moderate flow of prepared IGMP packets.

In the worst case (the socket buffer allocated for the packet is at the
end of kernel accessible memory), the Linux machine may be crashed
remotely.

4) I think there are more bugs and more or less subtle races in that code.


And seriously, please save me from the 'I have a patch for X' 'I have a
patch for Y' mentality, I feel like that code or at least parts of it have
been done by people _without_ any elementary C and kernel API & principles
knowledge. It _must_ be completely reaudited. I really wonder, since I
remember that it was mostly clean in .22 or .23 or so, so who the hell is
breaking it again and again and why??

------- Comment #2 From Sune Kloppenborg Jeppesen 2004-12-04 05:39:30 0000 -------
Proposed fix from Chris Wright:

===== net/ipv4/igmp.c 1.58 vs edited =====
--- 1.58/net/ipv4/igmp.c

------- Comment #3 From Sune Kloppenborg Jeppesen 2004-12-04 05:39:30 0000 -------
Proposed fix from Chris Wright:

===== net/ipv4/igmp.c 1.58 vs edited =====
--- 1.58/net/ipv4/igmp.c        2004-11-09 16:44:25 -08:00
+++ edited/net/ipv4/igmp.c      2004-12-04 01:14:53 -08:00
@@ -1774,16 +1774,16 @@ int ip_mc_source(int add, int omode, str
 
        psl = pmc->sflist;
        if (!add) {
-               if (!psl)
+               if (!psl || !psl->sl_count)
                        goto done;
-               rv = !0;
+               rv = 1;
                for (i=0; i<psl->sl_count; i++) {
-                       rv = memcmp(&psl->sl_addr, &mreqs->imr_multiaddr,
+                       rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
                                sizeof(__u32));
-                       if (rv >= 0)
+                       if (rv >= 0)    /* array is sorted */
                                break;
                }
-               if (!rv)        /* source not found */
+               if (rv)         /* source not found */
                        goto done;
 
                /* update the interface filter */
@@ -1825,7 +1825,7 @@ int ip_mc_source(int add, int omode, str
        }
        rv = 1; /* > 0 for insert logic below if sl_count is 0 */
        for (i=0; i<psl->sl_count; i++) {
-               rv = memcmp(&psl->sl_addr, &mreqs->imr_multiaddr,
+               rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
                        sizeof(__u32));
                if (rv >= 0)
                        break;
===== net/ipv6/mcast.c 1.71 vs edited =====
--- 1.71/net/ipv6/mcast.c       2004-11-11 15:07:25 -08:00
+++ edited/net/ipv6/mcast.c     2004-12-04 01:27:20 -08:00
@@ -387,16 +387,16 @@ int ip6_mc_source(int add, int omode, st
 
        psl = pmc->sflist;
        if (!add) {
-               if (!psl)
+               if (!psl || !psl->sl_count)
                        goto done;
-               rv = !0;
+               rv = 1;
                for (i=0; i<psl->sl_count; i++) {
-                       rv = memcmp(&psl->sl_addr, group,
+                       rv = memcmp(&psl->sl_addr[i], source,
                                sizeof(struct in6_addr));
-                       if (rv >= 0)
+                       if (rv >= 0)    /* array is sorted */
                                break;
                }
-               if (!rv)        /* source not found */
+               if (rv)         /* source not found */
                        goto done;
 
                /* update the interface filter */
@@ -437,7 +437,7 @@ int ip6_mc_source(int add, int omode, st
        }
        rv = 1; /* > 0 for insert logic below if sl_count is 0 */
        for (i=0; i<psl->sl_count; i++) {
-               rv = memcmp(&psl->sl_addr, group, sizeof(struct in6_addr));
+               rv = memcmp(&psl->sl_addr[i], source, sizeof(struct in6_addr));
                if (rv >= 0)
                        break;
        }

------- Comment #4 From Sune Kloppenborg Jeppesen 2004-12-06 23:16:56 0000 -------
Minor revision to the last patch. 

------- Comment #5 From Sune Kloppenborg Jeppesen 2004-12-06 23:16:56 0000 -------
Minor revision to the last patch.  Eliminates some no-op changes.

===== net/ipv4/igmp.c 1.58 vs edited =====
--- 1.58/net/ipv4/igmp.c        2004-11-09 16:44:25 -08:00
+++ edited/net/ipv4/igmp.c      2004-12-06 18:43:54 -08:00
@@ -1778,12 +1778,12 @@ int ip_mc_source(int add, int omode, str
                        goto done;
                rv = !0;
                for (i=0; i<psl->sl_count; i++) {
-                       rv = memcmp(&psl->sl_addr, &mreqs->imr_multiaddr,
+                       rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
                                sizeof(__u32));
-                       if (rv >= 0)
+                       if (rv >= 0)    /* array is sorted */
                                break;
                }
-               if (!rv)        /* source not found */
+               if (rv)         /* source not found */
                        goto done;
 
                /* update the interface filter */
@@ -1825,7 +1825,7 @@ int ip_mc_source(int add, int omode, str
        }
        rv = 1; /* > 0 for insert logic below if sl_count is 0 */
        for (i=0; i<psl->sl_count; i++) {
-               rv = memcmp(&psl->sl_addr, &mreqs->imr_multiaddr,
+               rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
                        sizeof(__u32));
                if (rv >= 0)
                        break;
===== net/ipv6/mcast.c 1.71 vs edited =====
--- 1.71/net/ipv6/mcast.c       2004-11-11 15:07:25 -08:00
+++ edited/net/ipv6/mcast.c     2004-12-06 18:43:54 -08:00
@@ -391,12 +391,12 @@ int ip6_mc_source(int add, int omode, st
                        goto done;
                rv = !0;
                for (i=0; i<psl->sl_count; i++) {
-                       rv = memcmp(&psl->sl_addr, group,
+                       rv = memcmp(&psl->sl_addr[i], source,
                                sizeof(struct in6_addr));
-                       if (rv >= 0)
+                       if (rv >= 0)    /* array is sorted */
                                break;
                }
-               if (!rv)        /* source not found */
+               if (rv)         /* source not found */
                        goto done;
 
                /* update the interface filter */
@@ -437,7 +437,7 @@ int ip6_mc_source(int add, int omode, st
        }
        rv = 1; /* > 0 for insert logic below if sl_count is 0 */
        for (i=0; i<psl->sl_count; i++) {
-               rv = memcmp(&psl->sl_addr, group, sizeof(struct in6_addr));
+               rv = memcmp(&psl->sl_addr[i], source, sizeof(struct in6_addr));
                if (rv >= 0)
                        break;
        }

------- Comment #6 From Sune Kloppenborg Jeppesen 2004-12-11 00:47:40 0000 -------
New version:

===== net/ipv4/igmp.c 1.58 vs edited =====
--- 1.58/net/ipv4/igmp.c

------- Comment #7 From Sune Kloppenborg Jeppesen 2004-12-11 00:47:40 0000 -------
New version:

===== net/ipv4/igmp.c 1.58 vs edited =====
--- 1.58/net/ipv4/igmp.c        2004-11-09 16:44:25 -08:00
+++ edited/net/ipv4/igmp.c      2004-12-10 15:16:17 -08:00
@@ -1778,12 +1778,12 @@ int ip_mc_source(int add, int omode, str
                        goto done;
                rv = !0;
                for (i=0; i<psl->sl_count; i++) {
-                       rv = memcmp(&psl->sl_addr, &mreqs->imr_multiaddr,
+                       rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
                                sizeof(__u32));
-                       if (rv >= 0)
+                       if (rv == 0)
                                break;
                }
-               if (!rv)        /* source not found */
+               if (rv)         /* source not found */
                        goto done;
 
                /* update the interface filter */
@@ -1825,9 +1825,9 @@ int ip_mc_source(int add, int omode, str
        }
        rv = 1; /* > 0 for insert logic below if sl_count is 0 */
        for (i=0; i<psl->sl_count; i++) {
-               rv = memcmp(&psl->sl_addr, &mreqs->imr_multiaddr,
+               rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
                        sizeof(__u32));
-               if (rv >= 0)
+               if (rv == 0)
                        break;
        }
        if (rv == 0)            /* address already there is an error */
===== net/ipv6/mcast.c 1.71 vs edited =====
--- 1.71/net/ipv6/mcast.c       2004-11-11 15:07:25 -08:00
+++ edited/net/ipv6/mcast.c     2004-12-10 17:20:46 -08:00
@@ -391,12 +391,12 @@ int ip6_mc_source(int add, int omode, st
                        goto done;
                rv = !0;
                for (i=0; i<psl->sl_count; i++) {
-                       rv = memcmp(&psl->sl_addr, group,
+                       rv = memcmp(&psl->sl_addr[i], source,
                                sizeof(struct in6_addr));
-                       if (rv >= 0)
+                       if (rv == 0)
                                break;
                }
-               if (!rv)        /* source not found */
+               if (rv)         /* source not found */
                        goto done;
 
                /* update the interface filter */
@@ -437,8 +437,8 @@ int ip6_mc_source(int add, int omode, st
        }
        rv = 1; /* > 0 for insert logic below if sl_count is 0 */
        for (i=0; i<psl->sl_count; i++) {
-               rv = memcmp(&psl->sl_addr, group, sizeof(struct in6_addr));
-               if (rv >= 0)
+               rv = memcmp(&psl->sl_addr[i], source, sizeof(struct in6_addr));
+               if (rv == 0)
                        break;
        }
        if (rv == 0)            /* address already there is an error */

------- Comment #8 From Sune Kloppenborg Jeppesen 2004-12-13 00:35:06 0000 -------
IGMP has been assigned  CAN-2004-1137

------- Comment #9 From Thierry Carrez (RETIRED) 2004-12-13 01:24:25 0000 -------
BK changesets :
http://linux.bkbits.net:8080/linux-2.4/cset@41b76e94BsJKm8jhVtyDat9ZM1dXXg
http://linux.bkbits.net:8080/linux-2.6/cset@41b768d1ySHbfa7cUWDle8NjDT_02A
http://linux.bkbits.net:8080/linux-2.6/cset@41b76c07Ee61GkoNwMH-oOvWG2FdxA

------- Comment #10 From Tim Yamin (RETIRED) 2004-12-13 11:21:06 0000 -------
Ok, is this cleared for declassification since it's fixed upstream then...?

------- Comment #11 From Thierry Carrez (RETIRED) 2004-12-14 06:57:40 0000 -------
This bug is and will stay classified (quoting emails sent to v-s and requesting
secret). Another one will be opened to handle the issue when it will be public.

This is however semi-public since the fixes are out there, so we can start
including patches in our trees too. Any publicity about it should however wait
for advisory publication (due Dec 14 20:00 UTC).

------- Comment #12 From Thierry Carrez (RETIRED) 2004-12-14 06:59:54 0000 -------
*** Bug 73802 has been marked as a duplicate of this bug. ***

------- Comment #13 From Thierry Carrez (RETIRED) 2004-12-14 09:03:35 0000 -------
This bug will stay closed. Public followup to bug 74384

*** This bug has been marked as a duplicate of 74384 ***

First Last Prev Next    No search results available      Search page      Enter new bug