Hotfix for the latest Kernel exploit. (setsockopt integer overflow)

From: nolife
Date: Sun Apr 25 2004 - 18:17:56 EST


Hi,
Thought i publish the code so it has more use than idling on a single box.
It should patch against the latest bug in setsockopt without the need of a
new kernel/reboot.
It logs process and id if someone tries to exploit the system.

I've tested it against the public POC, seems to work fine.

It can be downloaded here: http://sigsegv.cc/setsockopt.c

Or copy/paste from here:
----------------------------------------------------------------------------
------------
/* setsockopt hotfix by nolife.
* gcc -c -O3 -fomit-frame-pointer setsockopt.c
This is a hotfix against the latest kernel vulnerability (integer
overflow in memory size calculation)
It protects against the POC and should protect against upcoming exploits.
*/

#include <linux/autoconf.h>
#ifdef CONFIG_SMP
#define __SMP__
#endif
#define MODULE
#define __KERNEL__
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mman.h>
#include <linux/in.h>
#include <linux/net.h>
#include <asm/unistd.h>
#include <asm/uaccess.h>
#include <sys/syscall.h>
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif

#ifndef MCAST_MSFILTER // you probably do not even have multicast
support .....
#define MCAST_MSFILTER 48
#endif
#ifndef SYS_SOCKETCALL
#define SYS_SOCKETCALL 102
#endif
#ifndef SYS_SETSOCKOPT
#define SYS_SETSOCKOPT 14
#endif

#define AL(x) ((x) * sizeof(unsigned long))
static unsigned char nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
#undef AL

extern void *sys_call_table[];
const int optmem_max = sizeof(unsigned long)*(2*UIO_MAXIOV + 512);

static long (*old_socketcall)(int call, unsigned long *args);
static long new_socketcall(int call,unsigned long *args)
{
unsigned long a[6];
unsigned long a0,a1;

if (call == SYS_SETSOCKOPT)
{
if (copy_from_user(a, args, nargs[call]))
return -EFAULT;
a0=a[0];
a1=a[1];
//printk("setsockopt called with optlen= %d by
%s\n",(int)a[4],current->comm);
if ((int)a[2] == MCAST_MSFILTER)
{
// Multicast option
if ((int)a[4] > optmem_max)
{
printk(KERN_ALERT "setsockopt exploit halted. abused by uid %d with
process %.32s\n",current->uid, current->comm);
return(-ENOBUFS);
}
}


}
return old_socketcall(call,args);
}


int init_module()
{
unsigned long flags;

save_flags(flags);
cli();

old_socketcall = sys_call_table[SYS_SOCKETCALL];
sys_call_table[SYS_SOCKETCALL] = new_socketcall;

restore_flags(flags);
printk(KERN_NOTICE "\"setsockopt\" hotfix loaded (c)nolife\n");
return 0;
}

void cleanup_module()
{
unsigned long flags;

save_flags(flags);
cli();

sys_call_table[SYS_SOCKETCALL] = old_socketcall;
printk(KERN_NOTICE "\"setsockopt\" hotfix unloaded\n");
restore_flags(flags);
}
----------------------------------------------------------------------------
------------

best regards,
nolife ;)

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/