Skip to content

Commit

Permalink
libsgxstep: support for call gates.
Browse files Browse the repository at this point in the history
  • Loading branch information
jovanbulck committed Jan 10, 2020
1 parent 8060bb4 commit dbf5400
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 31 deletions.
2 changes: 1 addition & 1 deletion app/idt/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ LDFLAGS += -lsgx-step -lsgx_urts \
-lsgx_uae_service -pthread $(SUBDIRS:%=-L %) -L$(SGX_SDK)/lib64/

SOURCES = $(shell ls *.c)
OBJECTS = $(SOURCES:.c=.o)
OBJECTS = $(SOURCES:.c=.o) asm.o
OUTPUT = app

BUILDDIRS = $(SUBDIRS:%=build-%)
Expand Down
5 changes: 5 additions & 0 deletions app/idt/asm.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.text
.global call_gate_func
call_gate_func:
call say_hi
lretq
12 changes: 12 additions & 0 deletions app/idt/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ void hello_world(uint8_t *rsp)
irq_fired = 1;
}

void call_gate_func(void);
void say_hi(void)
{
info("hello world from call gate!");
}

int main( int argc, char **argv )
{
idt_t idt = {0};
Expand All @@ -66,6 +72,12 @@ int main( int argc, char **argv )
#endif
dump_gdt(&gdt);

info_event("Installing call gate @%p", call_gate_func);
install_user_call_gate(&gdt, call_gate_func, GDT_VECTOR);
dump_gate(get_gate_desc(&gdt, GDT_VECTOR), GDT_VECTOR);
do_far_user_call(GDT_VECTOR);
info("back from call gate!");

info_event("Establishing user space IDT mapping");
map_idt(&idt);
install_user_irq_handler(&idt, hello_world, IRQ_VECTOR);
Expand Down
1 change: 1 addition & 0 deletions libsgxstep/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#define SINGLE_STEP_ENABLE 1
#define USER_IDT_ENABLE 1
#define IRQ_VECTOR 45
#define GDT_VECTOR 13
#if (M32 != 1)
#define APIC_CONFIG_MSR 1
#else
Expand Down
29 changes: 29 additions & 0 deletions libsgxstep/desc.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,35 @@

#include <stdint.h>

/* IA-64: 16-byte gate (from Linux kernel arch/x86/include/asm/desc_defs.h) */
typedef struct {
uint16_t offset_low;
uint16_t segment;
unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
uint16_t offset_middle;
uint32_t offset_high;
uint32_t zero1;
} __attribute__((packed)) gate_desc_t;

enum {
GATE_INTERRUPT = 0xE,
GATE_TRAP = 0xF,
GATE_CALL = 0xC,
GATE_TASK = 0x5,
};

typedef struct {
uint32_t offset;
uint16_t segment;
} __attribute__((packed)) call_gate_pt_t;

#define PTR_LOW(x) ((unsigned long long)(x) & 0xFFFF)
#define PTR_MIDDLE(x) (((unsigned long long)(x) >> 16) & 0xFFFF)
#define PTR_HIGH(x) ((unsigned long long)(x) >> 32)

#define gate_offset(g) ((g)->offset_low | ((unsigned long)(g)->offset_middle << 16) | ((unsigned long)(g)->offset_high << 32))
#define gate_ptr(base, idx) ((gate_desc_t*) (((void*) base) + idx*sizeof(gate_desc_t)))

/*
* From Linux kernel arch/x86/include/asm/segment.h
* arch/x86/include/asm/desc_defs.h
Expand Down
32 changes: 32 additions & 0 deletions libsgxstep/gdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,35 @@ desc_t *get_desc(gdt_t *gdt, int idx)

return desc_ptr(gdt->base, idx);
}

gate_desc_t *get_gate_desc(gdt_t *gdt, int idx)
{
/* System descriptors are expanded to 16 bytes (occupying the space of two entries). */
ASSERT(idx >= 0 && idx < (gdt->entries-1));

return (gate_desc_t*) (desc_ptr(gdt->base, idx));
}

void install_user_call_gate(gdt_t *gdt, call_gate_cb_t handler, int vector)
{
ASSERT(vector >= 0 && vector < (gdt->entries-1));
ASSERT( !get_desc(gdt, vector)->p && !get_desc(gdt, vector+1)->p );

gate_desc_t *g = get_gate_desc(gdt, vector);
g->offset_low = PTR_LOW(handler);
g->offset_middle = PTR_MIDDLE(handler);
g->offset_high = PTR_HIGH(handler);
g->p = 1;
g->segment = USER_CS;
g->dpl = USER_DPL;
g->type = GATE_CALL;
g->ist = 0;
}

void do_far_user_call(int gdt_idx)
{
call_gate_pt_t p = {
.segment = (gdt_idx*8+USER_DPL)
};
asm("lcall *%0\n\t"::"m"(p):);
}
5 changes: 5 additions & 0 deletions libsgxstep/gdt.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,15 @@ typedef struct {
size_t entries;
} gdt_t;

typedef void (*call_gate_cb_t)(void);

void map_gdt(gdt_t *gdt);
void dump_gdt(gdt_t *gdt);
void dump_desc(desc_t *desc, int idx);
void install_user_call_gate(gdt_t *gdt, call_gate_cb_t handler, int vector);
void do_far_user_call(int call_gate_idx);

desc_t *get_desc(gdt_t *gdt, int idx);
gate_desc_t *get_gate_desc(gdt_t *gdt, int idx);

#endif
8 changes: 4 additions & 4 deletions libsgxstep/idt.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ extern void sgx_step_irq_entry(void);
irq_cb_t sgx_step_irq_cb_table[256] = {0};
uint8_t sgx_step_vector_hack = 0;

void dump_gate(idt_gate_t *gate, int idx)
void dump_gate(gate_desc_t *gate, int idx)
{
info("IDT[%3d] @%p = %p (seg sel 0x%x); p=%d; dpl=%d; type=%02d; ist=%d",
idx, gate, (void*) gate_offset(gate), gate->segment, gate->p, gate->dpl, gate->type, gate->ist);
Expand All @@ -31,15 +31,15 @@ void map_idt(idt_t *idt)

asm volatile ("sidt %0\n\t"
:"=m"(idtr) :: );
entries = (idtr.size+1)/sizeof(idt_gate_t);
entries = (idtr.size+1)/sizeof(gate_desc_t);
dump_dtr(&idtr, entries);

ASSERT( idtr.base );
idt_base = remap_page_table_level((void*) idtr.base, PAGE);
libsgxstep_info("established user space IDT mapping at %p", idt_base);
ASSERT(idt_base);

idt->base = (idt_gate_t*) idt_base;
idt->base = (gate_desc_t*) idt_base;
idt->entries = entries;
}

Expand All @@ -55,7 +55,7 @@ void install_user_irq_handler(idt_t *idt, irq_cb_t handler, int vector)
{
ASSERT(vector >= 0 && vector < idt->entries);

idt_gate_t *gate = gate_ptr(idt->base, vector);
gate_desc_t *gate = gate_ptr(idt->base, vector);
gate->offset_low = PTR_LOW(sgx_step_irq_entry);
gate->offset_middle = PTR_MIDDLE(sgx_step_irq_entry);
gate->offset_high = PTR_HIGH(sgx_step_irq_entry);
Expand Down
28 changes: 2 additions & 26 deletions libsgxstep/idt.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,40 +24,16 @@
#include "desc.h"
#include "debug.h"

/* IA-64: 16-byte gate (from Linux kernel arch/x86/include/asm/desc_defs.h) */
typedef struct {
uint16_t offset_low;
uint16_t segment;
unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
uint16_t offset_middle;
uint32_t offset_high;
uint32_t zero1;
} __attribute__((packed)) idt_gate_t;

enum {
GATE_INTERRUPT = 0xE,
GATE_TRAP = 0xF,
GATE_CALL = 0xC,
GATE_TASK = 0x5,
};

#define PTR_LOW(x) ((unsigned long long)(x) & 0xFFFF)
#define PTR_MIDDLE(x) (((unsigned long long)(x) >> 16) & 0xFFFF)
#define PTR_HIGH(x) ((unsigned long long)(x) >> 32)

#define gate_offset(g) ((g)->offset_low | ((unsigned long)(g)->offset_middle << 16) | ((unsigned long)(g)->offset_high << 32))
#define gate_ptr(idt_base, idx) ((idt_gate_t*) (((void*) idt_base) + idx*sizeof(idt_gate_t)))

typedef struct {
idt_gate_t *base;
gate_desc_t *base;
size_t entries;
} idt_t;

typedef void (*irq_cb_t)(uint8_t *rsp);

void map_idt(idt_t *idt);
void dump_idt(idt_t *idt);
void dump_gate(idt_gate_t *gate, int idx);
void dump_gate(gate_desc_t *gate, int idx);

void install_user_irq_handler(idt_t *idt, irq_cb_t handler, int vector);

Expand Down

0 comments on commit dbf5400

Please sign in to comment.