Home
Reading
Searching
Subscribe
Sponsors
Statistics
Posting
Contact
Spam
Lists
Links
About
Hosting
Filtering
Features Download
Marketing
Archives
FAQ
Blog
 
Gmane
From: mancha <mancha1-yx4YqRIVDag <at> public.gmane.org>
Subject: Re: Linux 3.4+: arbitrary write with =?utf-8?b?Q09ORklHX1g4Nl9YMzI=?= (CVE-2014-0038)
Newsgroups: gmane.comp.security.oss.general
Date: Monday 3rd February 2014 20:55:35 UTC (over 3 years ago)
mancha  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 
#include 
#include 
#include  
#include  
#include 
#include 
#include   
#include   
#include 
#include 
#include 
#include 
#include 

MODULE_LICENSE("GPL");
MODULE_AUTHOR("mancha ");
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);
===================================
 
CD: 3ms