[Wolves] [Fwd: Hot fix for do_brk bug]
Matt Wright
matt at consultmatt.co.uk
Thu Dec 18 17:01:49 GMT 2003
<delurk>
Am I allowed to go "grrrr" ?? I've just killed my server off for a
2.4.20 -> 2.4.23 upgrade. I'd got 55 days uptime which is impressive as
the ADSL modem usually kills it off within 30 odd days.
Matt
</delurk>
On Thu, 2003-12-18 at 15:26, sparkes wrote:
> you might not have to do a kernel upgrade if you don't want too although
> your milage may vary
>
> sparkes
>
> ______________________________________________________________________
> From: canon at nersc.gov
> To: bugtraq at securityfocus.com
> Subject: Hot fix for do_brk bug
> Date: Thu, 04 Dec 2003 15:41:37 -0800
>
>
> 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 at 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
> ------------------------------------------------------------------------
>
>
>
> ______________________________________________________________________
> _______________________________________________
> Wolves LUG mailing list
> Homepage: http://www.wolveslug.org.uk/
> Mailing list: Wolves at mailman.lug.org.uk
> Mailing list home: http://mailman.lug.org.uk/mailman/listinfo/wolves
More information about the Wolves
mailing list