[From nobody Thu Dec 18 15:26:53 2003 Return-path: <bugtraq-return-12106-sparkes=westmids.biz@securityfocus.com> Envelope-to: sparkes@westmids.biz Received: from outgoing3.securityfocus.com ([205.206.231.27]) by lappy.westmids.biz with esmtp (Exim 3.36 #1 (Debian)) id 1ASLVM-0003t1-00 for <sparkes@westmids.biz>; Fri, 05 Dec 2003 19:20:44 +0000 Received: from lists2.securityfocus.com (lists2.securityfocus.com [205.206.231.20]) by outgoing3.securityfocus.com (Postfix) with QMQP id BA719A311F; Fri, 5 Dec 2003 11:00:06 -0700 (MST) Mailing-List: contact bugtraq-help@securityfocus.com; run by ezmlm Precedence: bulk List-Id: <bugtraq.list-id.securityfocus.com> List-Post: <mailto:bugtraq@securityfocus.com> List-Help: <mailto:bugtraq-help@securityfocus.com> List-Unsubscribe: <mailto:bugtraq-unsubscribe@securityfocus.com> List-Subscribe: <mailto:bugtraq-subscribe@securityfocus.com> Delivered-To: mailing list bugtraq@securityfocus.com Delivered-To: moderator for bugtraq@securityfocus.com Received: (qmail 2978 invoked from network); 4 Dec 2003 23:38:18 -0000 Message-Id: <200312042341.hB4Nfbmd005154@pookie.nersc.gov> X-Mailer: exmh version 2.5 01/15/2001 with nmh-1.0.4 To: bugtraq@securityfocus.com Subject: Hot fix for do_brk bug Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Date: Thu, 04 Dec 2003 15:41:37 -0800 From: canon@nersc.gov Greetings, I've written a linux kernel module that can be used to hot fix a Linux system for the bug in do_brk. It scans the kernel space and replaces jmp and calls to do_brk to point to a wrapper routine instead. It also maps the symbol table to point to the wrapper. This only works on x86 and it has only been tested with RH kernels 2.4.18-27.7.xsmp and 2.4.20-20.7smp. It is quite possible this could crash or screw-up a system, so use at your own risk. I've tested the module against the proof of concept code written and posted by Christophe Devine. The module catches the exploit and logs the attempt. --Shane Canon ------brk_fix.c------------ #define MODULE #define __KERNEL__ /* some constants used in our module */ #define MODULE_NAME "brk_fix" #define MODULE_VERSION "0.01" /* brk_fix * Verions: 0.01 * * WARNING WARNING WARNING * This module intentionally modifies kernel memory. * This module could potentially crash or damage your system. * Use at your own risks. * * Hot fix for integer overflow in do_brk * * This module scans kernel code space looking for jumps and calls * to do_brk. It then changes these calls to instead call my_brk, * which is a wrapper routine that does some checks before calling do_brk. * The module also scans for the address of do_brk and replaces it * with my_brk. This would mainly occur in the exported symbols table. * * This has been tested with RH 2.4.20-20.7smp and RH 2.4.18-27.7.xsmp on i686 * * Sample use... * gcc -O3 -I/lib/modules/`uname -r`/build/include -c -o brk_fix.o brk_fix.c * insmod ./brk_fix.o * * Written by Shane Canon <canon@nersc.gov> * (c) Copyright 2003 Regents of the University of California * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <linux/kernel.h> #include <linux/errno.h> #include <linux/version.h> #include <linux/module.h> #include <linux/slab.h> extern void * __start___kallsyms; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9) #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif #endif unsigned long my_brk(unsigned long addr, unsigned long len); int init_module(void) { unsigned char *ptr; unsigned char *newptr; long *lptr; unsigned char *cptr; long diff; int count=0; unsigned char *start=(unsigned char *) (TASK_SIZE); /* Start at the beginning of kernel space */ unsigned char *end=(unsigned char *)&__start___kallsyms; /* Want something that is well past the kernel test */ /* This seems to fit the bill */ ptr=(unsigned char *)(do_brk); /* We are looking for calls/jumps to this function */ newptr=(unsigned char *)(my_brk); /* This is what we will change it to */ for (cptr=start;cptr<end;cptr++){ /* Lets scan all of kernel space */ if (*cptr==0xe8||*cptr==0xe9){ /* Look for calls or jumps */ cptr++; /* If you find one look at the next dword */ lptr=(long *)cptr; cptr+=4; if ((cptr+*lptr)==(ptr)){ /* See if the offset would point to do_brk */ printk("fixing 0x%08lx\n",lptr); /* If so, change it to our new routine */ *lptr=(newptr-cptr); count++; } } else{ lptr=(long *)cptr; /* Look for the address as well. This would show */ if ((unsigned char*)(*lptr)==ptr){ /* up in the symbol table. */ printk("Fixing address at 0x%08lx\n",lptr); *lptr=(long)(newptr); } } } printk ("Fix brk installed..\n"); /* All done. */ MOD_INC_USE_COUNT; /* We can't unload this one. So lets inc the mod */ /* count and leave it there. */ return 0; /* success */ } void cleanup_module(void) { /* Can't remove it */ } /* These are the first couple of lines from the patched mmap.c */ /* Do the new checks and then call the original do_brk */ unsigned long my_brk(unsigned long addr, unsigned long len) { len = PAGE_ALIGN(len); if (!len) return addr; if ((addr + len) > TASK_SIZE || (addr + len) < addr){ /* Let's make sure its in bounds */ printk("caught do_brk exploit!!!\n"); return -EINVAL; } return do_brk(addr,len); /* Call the real do_brk */ } -------end--------- ------------------------------------------------------------------------ Shane Canon National Energy Research Scientific Computing Center ------------------------------------------------------------------------ ]