All of lore.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.