public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* i386 / sysenter safety test case
@ 2005-03-09  0:23 Zachary Amsden
  0 siblings, 0 replies; only message in thread
From: Zachary Amsden @ 2005-03-09  0:23 UTC (permalink / raw)
  To: linux-kernel, ltp-list

[-- Attachment #1: Type: text/plain, Size: 1046 bytes --]

Code inspection of entry.S on i386 showed a potential problem - load 
through segment without verifying "flatness" on the sysenter path.  
Turns out this code is safe, but only by a thread ..

ENTRY(sysenter_entry)
        movl TSS_sysenter_esp0(%esp),%esp
sysenter_past_esp:
        sti
        pushl $(__USER_DS)
        pushl %ebp
        pushfl
        pushl $(__USER_CS)
        pushl $SYSENTER_RETURN

/*
 * Load the potential sixth argument from user stack.
 * Careful about security.
 */
        cmpl $__PAGE_OFFSET-3,%ebp
        jae syscall_fault
1:      movl (%ebp),%ebp

If it weren't for the fact that %ebp relative addresses default to using 
the SS segment, we could have loaded through a user segment here to read 
arbitrary memory (sysenter does nothing to DS segment).  Perhaps this 
was considered before, but because of the implications, I thought this 
might be worth annotating in the source.   Also provided a test case.  
Obviously only works on sysenter capable processors.  Tested on 2.6.8.

Zach Amsden
zach@vmware.com

[-- Attachment #2: sysenter.S --]
[-- Type: text/plain, Size: 804 bytes --]

#include <sys/syscall.h>

.text
.global sysenter_call
.global sysenter_call_2

/* void sysenter_call(pid_t pid, int signo, short ds, void *addr) */

sysenter_call:
	push %ebx
	push %edi
	push %ebp
        push %ds
	movl %esp, %edi
	movl 20(%esp), %ebx   /* pid */
	movl 24(%esp), %ecx   /* signo */
	movl 28(%esp), %ds    /* exploit DS */
	movl 32(%esp), %ebp
	movl %ebp, %esp
        push $sysenter_return
	push %ecx
	push %edx
	subl $16, %ebp
	push $0xbaadf00d
	movl $SYS_kill, %eax
	sysenter

/* vsyscall page will ret to us here */
sysenter_return:
        mov %edi, %esp
	pop %ds
	pop %ebp
	pop %edi
	pop %ebx	
	ret

sysenter_call_2:
	push %ebx
	push %ebp
	movl 20(%esp), %ebx   /* pid */
	movl 24(%esp), %ecx   /* signo */
	movl 28(%esp), %ebp
	movl $SYS_kill, %eax
	sysenter

.data
test: .long 0 

[-- Attachment #3: sysenter.c --]
[-- Type: text/plain, Size: 1506 bytes --]

/*
 * Copyright (c) 2005, Zachary Amsden (zach@vmware.com)
 * This is licensed under the GPL.
 */

#include <stdio.h>
#include <signal.h>
#include <asm/ldt.h>
#include <asm/segment.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/mman.h>
#define __KERNEL__
#include <asm/page.h>

extern void sysenter_call(pid_t pid, int signo, short ds, void *addr);
extern void sysenter_call_2(pid_t pid, int signo, void *addr);
void catch_sig(int signo, struct sigcontext ctx)
{
	__asm__ __volatile__("mov %0, %%ds" : : "r" (__USER_DS));
	printf("interrupted %%ebp = 0x%x\n", ctx.ebp);
	if (ctx.ebp == 0xbaadf00d)
		printf("phew\n");
}

void main(void)
{
	struct user_desc desc;
	short ds;
	unsigned long addr;
	unsigned *stack;
	unsigned long offset;

	stack = (unsigned *)mmap(0, 4096, PROT_EXEC|PROT_READ|PROT_WRITE,
				 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
	stack = &stack[1024];
	addr = 0xf0000; /* Try to read BIOS */
	offset = __PAGE_OFFSET-(unsigned)stack+addr+16;
	signal(SIGUSR1, catch_sig);
	desc.entry_number = 0;
	desc.base_addr = offset;
	desc.limit = 0xffffff;
	desc.seg_32bit = 1;
	desc.contents = MODIFY_LDT_CONTENTS_DATA;
	desc.read_exec_only = 0;
	desc.limit_in_pages = 1;
	desc.seg_not_present = 0;
	desc.useable = 1;
	if (modify_ldt(1, &desc, sizeof(desc)) != 0) {
		perror("modify_ldt");
	}
	ds = 0x7; /* TI | RPL 3 */
	sysenter_call(getpid(), SIGUSR1, ds, stack);
	sysenter_call_2(getpid(), SIGSTOP, __PAGE_OFFSET+4096);
	printf("not reached - core should show %%eax == -EFAULT\n");
}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-03-09  0:29 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-03-09  0:23 i386 / sysenter safety test case Zachary Amsden

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox