Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <loom.20140203T214939-590@post.gmane.org>
Date: Mon, 3 Feb 2014 20:55:35 +0000 (UTC)
From: mancha <mancha1@...h.com>
To: oss-security@...ts.openwall.com
Subject: Re: Linux 3.4+: arbitrary write with CONFIG_X86_X32 (CVE-2014-0038)

mancha <mancha1@...> writes:
> 
[SNIP]
> I made a change to the kernel module to minimize the amount of time
> things are rw. Please use this version (not the one attached in my
> first post).
> 
> New version also uploaded to:
> http://sf.net/projects/mancha/file/sec/nox32recvmmsg.tar.bz2.
> 
> --mancha
> 

I made one more change so it works with protected-mode enabled
procs.

SourceForge tarball also updated. Check against this hash:

SHA256(nox32recvmmsg.tar.bz2)=
8c822d55a0a45f0fa994c73921701e2bb035bdaeb169c2355ed8d767414c4f73

========= nox32recvmmsg.c =========
#define _GNU_SOURCE
#include <linux/init.h>
#include <linux/socket.h>
#include <linux/module.h>
#include <linux/kernel.h> 
#include <linux/errno.h> 
#include <linux/types.h>
#include <linux/unistd.h>
#include <asm/cacheflush.h>  
#include <asm/page.h>  
#include <asm/current.h>
#include <linux/sched.h>
#include <linux/kallsyms.h>
#include <linux/syscalls.h>
#include <asm/string.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("mancha <mancha1@...h.com>");
MODULE_DESCRIPTION("disable x32 recvmmsg()");

unsigned long **syscall_table;

#define __NR_x32_recvmmsg 537

asmlinkage int (*orig_recvmmsg)(int sockfd, struct mmsghdr *msgvec, unsigned
int vlen, unsigned int flags, struct timespec *timeout);

static unsigned long **aquire_syscall_table(void)
{
  unsigned long int offset = PAGE_OFFSET;
  unsigned long **sct;

  while (offset < ULLONG_MAX) {
    sct = (unsigned long **)offset;
    if (sct[__NR_close] == (unsigned long *) sys_close) 
      return sct;
    offset += sizeof(void *);
  }
  printk(KERN_ALERT "Unable to get syscall table\n");
  return NULL;
}

void set_addr_rw(long unsigned int _addr)
{
    unsigned int level;
    pte_t *pte = lookup_address(_addr, &level);
    if (pte->pte &~ _PAGE_RW) pte->pte |= _PAGE_RW;
    write_cr0(read_cr0() & (~ 0x10000));
}

void set_addr_ro(long unsigned int _addr)
{
    unsigned int level;
    pte_t *pte = lookup_address(_addr, &level);
    pte->pte = pte->pte &~_PAGE_RW;
    write_cr0(read_cr0() | 0x10000);
}

asmlinkage int norecvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int
vlen, unsigned int flags, struct timespec *timeout) {

    printk(KERN_ALERT "x32 recvmmsg call intercepted\n");
    return -1;
}

static int __init init_recvmmsg(void) {

    if(!(syscall_table = aquire_syscall_table())) {
      printk(KERN_INFO "Unable to acquire syscall table\n");
      return -1;
    }
    printk(KERN_ALERT "x32 recvmmsg disabled\n");
    set_addr_rw((unsigned long)syscall_table);
    orig_recvmmsg = (void*)syscall_table[__NR_x32_recvmmsg];
    syscall_table[__NR_x32_recvmmsg] = (unsigned long*)norecvmmsg;  
    set_addr_ro((unsigned long)syscall_table);
    return 0;
}

static void __exit exit_recvmmsg(void) {

    set_addr_rw((unsigned long)syscall_table);
    syscall_table[__NR_x32_recvmmsg] = (unsigned long*)orig_recvmmsg;  
    set_addr_ro((unsigned long)syscall_table);
    printk(KERN_ALERT "x32 recvmmsg restored\n");
}

module_init(init_recvmmsg);
module_exit(exit_recvmmsg);
=================================== 





Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.