Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 35943
b: refs/heads/master
c: 78be370
h: refs/heads/master
i:
  35941: 1ad3aec
  35939: 33f03b2
  35935: 40fe9b7
v: v3
  • Loading branch information
Rusty Russell authored and Andi Kleen committed Sep 26, 2006
1 parent 3084bb0 commit 24d0fa3
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 16 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0da5db313317e3195482d3e660a1074857374a89
refs/heads/master: 78be3706b21a232310590fe00258b224177ac05f
9 changes: 5 additions & 4 deletions trunk/arch/i386/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,9 @@ ret_from_intr:
check_userspace:
movl EFLAGS(%esp), %eax # mix EFLAGS and CS
movb CS(%esp), %al
testl $(VM_MASK | 3), %eax
jz resume_kernel
andl $(VM_MASK | SEGMENT_RPL_MASK), %eax
cmpl $USER_RPL, %eax
jb resume_kernel # not returning to v8086 or userspace
ENTRY(resume_userspace)
DISABLE_INTERRUPTS # make sure we don't miss an interrupt
# setting need_resched or sigpending
Expand Down Expand Up @@ -377,8 +378,8 @@ restore_all:
# See comments in process.c:copy_thread() for details.
movb OLDSS(%esp), %ah
movb CS(%esp), %al
andl $(VM_MASK | (4 << 8) | 3), %eax
cmpl $((4 << 8) | 3), %eax
andl $(VM_MASK | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
CFI_REMEMBER_STATE
je ldt_ss # returning to user-space with LDT SS
restore_nocheck:
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/i386/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
regs.xes = __USER_DS;
regs.orig_eax = -1;
regs.eip = (unsigned long) kernel_thread_helper;
regs.xcs = __KERNEL_CS;
regs.xcs = __KERNEL_CS | get_kernel_rpl();
regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;

/* Ok, create the new process.. */
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/i386/mm/extable.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ int fixup_exception(struct pt_regs *regs)
const struct exception_table_entry *fixup;

#ifdef CONFIG_PNPBIOS
if (unlikely((regs->xcs & ~15) == (GDT_ENTRY_PNPBIOS_BASE << 3)))
if (unlikely(SEGMENT_IS_PNP_CODE(regs->xcs)))
{
extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp;
extern u32 pnp_bios_is_utter_crap;
Expand Down
11 changes: 4 additions & 7 deletions trunk/arch/i386/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <asm/uaccess.h>
#include <asm/desc.h>
#include <asm/kdebug.h>
#include <asm/segment.h>

extern void die(const char *,struct pt_regs *,long);

Expand Down Expand Up @@ -113,10 +114,10 @@ static inline unsigned long get_segment_eip(struct pt_regs *regs,
}

/* The standard kernel/user address space limit. */
*eip_limit = (seg & 3) ? USER_DS.seg : KERNEL_DS.seg;
*eip_limit = user_mode(regs) ? USER_DS.seg : KERNEL_DS.seg;

/* By far the most common cases. */
if (likely(seg == __USER_CS || seg == __KERNEL_CS))
if (likely(SEGMENT_IS_FLAT_CODE(seg)))
return eip;

/* Check the segment exists, is within the current LDT/GDT size,
Expand Down Expand Up @@ -430,11 +431,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs,
write = 0;
switch (error_code & 3) {
default: /* 3: write, present */
#ifdef TEST_VERIFY_AREA
if (regs->cs == KERNEL_CS)
printk("WP fault at %08lx\n", regs->eip);
#endif
/* fall through */
/* fall through */
case 2: /* write, not present */
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
Expand Down
5 changes: 3 additions & 2 deletions trunk/include/asm-i386/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ struct pt_regs {
#ifdef __KERNEL__

#include <asm/vm86.h>
#include <asm/segment.h>

struct task_struct;
extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code);
Expand All @@ -73,11 +74,11 @@ extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int erro
*/
static inline int user_mode(struct pt_regs *regs)
{
return (regs->xcs & 3) != 0;
return (regs->xcs & SEGMENT_RPL_MASK) == USER_RPL;
}
static inline int user_mode_vm(struct pt_regs *regs)
{
return ((regs->xcs & 3) | (regs->eflags & VM_MASK)) != 0;
return ((regs->xcs & SEGMENT_RPL_MASK) | (regs->eflags & VM_MASK)) >= USER_RPL;
}
#define instruction_pointer(regs) ((regs)->eip)
extern unsigned long profile_pc(struct pt_regs *regs);
Expand Down
17 changes: 17 additions & 0 deletions trunk/include/asm-i386/segment.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@

#define GDT_SIZE (GDT_ENTRIES * 8)

/* Matches __KERNEL_CS and __USER_CS (they must be 2 entries apart) */
#define SEGMENT_IS_FLAT_CODE(x) (((x) & 0xec) == GDT_ENTRY_KERNEL_CS * 8)
/* Matches PNP_CS32 and PNP_CS16 (they must be consecutive) */
#define SEGMENT_IS_PNP_CODE(x) (((x) & 0xf4) == GDT_ENTRY_PNPBIOS_BASE * 8)

/* Simple and small GDT entries for booting only */

#define GDT_ENTRY_BOOT_CS 2
Expand Down Expand Up @@ -112,4 +117,16 @@
*/
#define IDT_ENTRIES 256

/* Bottom two bits of selector give the ring privilege level */
#define SEGMENT_RPL_MASK 0x3
/* Bit 2 is table indicator (LDT/GDT) */
#define SEGMENT_TI_MASK 0x4

/* User mode is privilege level 3 */
#define USER_RPL 0x3
/* LDT segment has TI set, GDT has it cleared */
#define SEGMENT_LDT 0x4
#define SEGMENT_GDT 0x0

#define get_kernel_rpl() 0
#endif

0 comments on commit 24d0fa3

Please sign in to comment.