[HOTFIX] setsockopt kernel vulnerability
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 uid 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 ;)