From cdff5660514a8ed99e7076bcf6824a126f2fcabb Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Mon, 17 Jun 2019 15:21:06 -0700 Subject: [PATCH] [Pal/Linux] enable stack protector enable stack protector for Pal/Linux. for other Pal, enabling stack protector results in error. Signed-off-by: Isaku Yamahata --- Makefile.configs | 3 + Pal/lib/Makefile | 5 ++ Pal/src/Makefile | 21 ++++++ Pal/src/db_main.c | 9 +++ Pal/src/host/FreeBSD/Makefile | 4 ++ Pal/src/host/Linux-SGX/Makefile | 4 ++ Pal/src/host/Linux/.gitignore | 2 + Pal/src/host/Linux/Makefile | 21 +++++- Pal/src/host/Linux/Makefile.am | 2 +- Pal/src/host/Linux/db_main.c | 5 ++ Pal/src/host/Linux/db_stack_protector.c | 86 +++++++++++++++++++++++++ Pal/src/host/Linux/db_threading.c | 42 ++---------- Pal/src/host/Linux/generated-offsets.c | 14 ++++ Pal/src/host/Linux/pal_linux.h | 4 ++ Pal/src/host/Skeleton/Makefile | 4 ++ Pal/src/host/Skeleton/db_main.c | 4 -- 16 files changed, 189 insertions(+), 41 deletions(-) create mode 100644 Pal/src/host/Linux/.gitignore create mode 100644 Pal/src/host/Linux/db_stack_protector.c create mode 100644 Pal/src/host/Linux/generated-offsets.c diff --git a/Makefile.configs b/Makefile.configs index 71c491a7..2064845e 100644 --- a/Makefile.configs +++ b/Makefile.configs @@ -11,3 +11,6 @@ ifeq ($(origin LD),default) LD = ld endif OBJCOPY ?= objcopy + +CONFIG_PAL_STACK_PROTECTOR = n +# CONFIG_PAL_STACK_PROTECTOR = y diff --git a/Pal/lib/Makefile b/Pal/lib/Makefile index e3f35e4c..7e6394b2 100644 --- a/Pal/lib/Makefile +++ b/Pal/lib/Makefile @@ -12,6 +12,11 @@ include ../src/host/$(PAL_HOST)/Makefile.am CFLAGS += -I. -I../include -I../src +# TODO: enable stack protector pal/lib. security/Linux/libpal_sec.so is blocker. +# Makefile.am overwrites CFLAGS. defining CFLAGS before Makefile.am +# may not have effects. +CFLAGS += -fno-stack-protector + # Include host_endian.h from either the host-specific directory, # or directly under the target directory. ifeq ($(target),) diff --git a/Pal/src/Makefile b/Pal/src/Makefile index 8febc574..e3fca642 100644 --- a/Pal/src/Makefile +++ b/Pal/src/Makefile @@ -56,6 +56,27 @@ CFLAGS += -DDEBUG endif export DEBUG + +$(HOST_DIR)/asm-offsets.h: + $(MAKE) -C $(HOST_DIR) $(notdir $@) + +$(HOST_DIR)/.Makefile.stack-protector: $(HOST_DIR)/asm-offsets.h + $(call cmd,makefile_stack_protector) + +ifeq ($(CONFIG_PAL_STACK_PROTECTOR),y) +include $(HOST_DIR)/.Makefile.stack-protector +$(addsuffix .o,$(objs)): $(HOST_DIR)/.Makefile.stack-protector +ASFLAGS += -DENABLE_STACK_PROTECTOR=1 +CFLAGS += -DENABLE_STACK_PROTECTOR=1 +ifneq ($(CONFIG_STACK_PROTECTOR_GUARD_OFFSET),) +CFLAGS += -mstack-protector-guard-offset=$(CONFIG_STACK_PROTECTOR_GUARD_OFFSET) +endif +CFLAGS += -mstack-protector-guard-reg=%gs +else +CFLAGS += -fno-stack-protector +endif + + # Install Targets (all in RUNTIME_DIR): # pal-{Host Name}: loader for PAL (as an executable) # libpal-{Host Name}.so: dynamic-linking library diff --git a/Pal/src/db_main.c b/Pal/src/db_main.c index 63a9b36e..2115017d 100644 --- a/Pal/src/db_main.c +++ b/Pal/src/db_main.c @@ -32,6 +32,15 @@ #include #include +#ifdef ENABLE_STACK_PROTECTOR +void __stack_chk_fail(void) +{ + printf("stack protector: Pal stack is corrupted in %p\n", + __builtin_return_address(0)); + _DkThreadExit(); +} +#endif + PAL_CONTROL __pal_control; PAL_CONTROL * pal_control_addr (void) diff --git a/Pal/src/host/FreeBSD/Makefile b/Pal/src/host/FreeBSD/Makefile index 34bc3088..2ff3c105 100644 --- a/Pal/src/host/FreeBSD/Makefile +++ b/Pal/src/host/FreeBSD/Makefile @@ -25,6 +25,10 @@ CFLAGS += -DDEBUG export DEBUG endif +ifeq ($(CONFIG_PAL_STACK_PROTECTOR),y) +$(error CONFIG_PAL_STACK_PROTECTOR is not supported) +endif + pal-gdb: pal-gdb.template sed -e 's:\$$(PAL_DIR):$(PWD):g' $< > $@ chmod 755 $@ diff --git a/Pal/src/host/Linux-SGX/Makefile b/Pal/src/host/Linux-SGX/Makefile index ef117bbf..927831c1 100644 --- a/Pal/src/host/Linux-SGX/Makefile +++ b/Pal/src/host/Linux-SGX/Makefile @@ -30,6 +30,10 @@ ASFLAGS += -DDEBUG export DEBUG endif +ifeq ($(CONFIG_PAL_STACK_PROTECTOR),y) +$(error CONFIG_PAL_STACK_PROTECTOR is not supported) +endif + ../../host_endian.h: host_endian.h $(MAKE) -C ../../ $< diff --git a/Pal/src/host/Linux/.gitignore b/Pal/src/host/Linux/.gitignore new file mode 100644 index 00000000..aca284ec --- /dev/null +++ b/Pal/src/host/Linux/.gitignore @@ -0,0 +1,2 @@ +/.Makefile.stack-protector +/asm-offsets.h diff --git a/Pal/src/host/Linux/Makefile b/Pal/src/host/Linux/Makefile index 8e2738b3..d5d04747 100644 --- a/Pal/src/host/Linux/Makefile +++ b/Pal/src/host/Linux/Makefile @@ -16,7 +16,7 @@ defs = -DIN_PAL -DPAL_DIR=$(PAL_DIR) -DRUNTIME_DIR=$(RUNTIME_DIR) CFLAGS += $(defs) ASFLAGS += $(defs) objs = $(addprefix db_,files devices pipes sockets streams memory threading \ - mutex events process object main rtld misc ipc \ + mutex events process object main rtld misc ipc stack_protector \ exception) manifest clone-x86_64 gettimeofday-x86_64 graphene_lib = .lib/graphene-lib.a headers = $(wildcard *.h) $(wildcard ../../*.h) $(wildcard ../../../lib/*.h) @@ -30,6 +30,25 @@ CFLAGS += -DDEBUG export DEBUG endif +.Makefile.stack-protector: asm-offsets.h + $(call cmd,makefile_stack_protector) + +CFLAGS-db_stack_protector.o += -fno-stack-protector + +ifeq ($(CONFIG_PAL_STACK_PROTECTOR),y) +include .Makefile.stack-protector +$(addsuffix .o,$(objs)): .Makefile.stack-protector +ASFLAGS += -DENABLE_STACK_PROTECTOR=1 +CFLAGS += -DENABLE_STACK_PROTECTOR=1 +ifneq ($(CONFIG_STACK_PROTECTOR_GUARD_OFFSET),) +CFLAGS += -mstack-protector-guard-offset=$(CONFIG_STACK_PROTECTOR_GUARD_OFFSET) +endif +CFLAGS += -mstack-protector-guard-reg=%gs +else +CFLAGS += -fno-stack-protector +endif + + libpal-Linux.a: $(addsuffix .o,$(objs)) $(graphene_lib) $(call cmd,ar_a_o) diff --git a/Pal/src/host/Linux/Makefile.am b/Pal/src/host/Linux/Makefile.am index 2fb519e9..a6f76aff 100644 --- a/Pal/src/host/Linux/Makefile.am +++ b/Pal/src/host/Linux/Makefile.am @@ -3,7 +3,7 @@ HOST_DIR = host/$(PAL_HOST) SEC_DIR = security/$(PAL_HOST) CFLAGS = -Wall -fPIC -O2 -std=c11 -U_FORTIFY_SOURCE \ - -fno-stack-protector -fno-builtin + -fno-builtin EXTRAFLAGS = -Wextra $(call cc-option,-Wnull-dereference) diff --git a/Pal/src/host/Linux/db_main.c b/Pal/src/host/Linux/db_main.c index 5a36e3c6..18e654f7 100644 --- a/Pal/src/host/Linux/db_main.c +++ b/Pal/src/host/Linux/db_main.c @@ -37,6 +37,7 @@ #include #include +#ifndef ENABLE_STACK_PROTECTOR /* At the begining of entry point, rsp starts at argc, then argvs, envps and auxvs. Here we store rsp to rdi, so it will not be messed up by function calls */ @@ -45,6 +46,7 @@ __asm__ (".global pal_start \n" "pal_start: \n" " movq %rsp, %rdi \n" " call pal_linux_main \n"); +#endif #define RTLD_BOOTSTRAP @@ -245,6 +247,9 @@ void pal_linux_main (void * args) tcb->alt_stack = alt_stack; // Stack bottom tcb->callback = NULL; tcb->param = NULL; +#if ENABLE_STACK_PROTECTOR + tcb->stack_protector_canary = STACK_PROTECTOR_CANARY_DEFAULT; +#endif pal_thread_init(tcb); setup_pal_map(&pal_map); diff --git a/Pal/src/host/Linux/db_stack_protector.c b/Pal/src/host/Linux/db_stack_protector.c new file mode 100644 index 00000000..4ecca9e4 --- /dev/null +++ b/Pal/src/host/Linux/db_stack_protector.c @@ -0,0 +1,86 @@ +/* Copyright 2019 Intel Corporation. + * Copyright 2019 Isaku Yamahata + * + * This file is part of Graphene Library OS. + * + * Graphene Library OS is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Graphene Library OS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#include "pal_linux.h" +#include "pal_internal.h" + +#include +#include + +#ifdef ENABLE_STACK_PROTECTOR +/* At the begining of entry point, rsp starts at argc, then argvs, + envps and auxvs. Here we store rsp to rdi, so it will not be + messed up by function calls */ +__asm__ ( + ".global pal_start \n" + ".type pal_start,@function \n" + "pal_start: \n" + " movq %rsp, %rdi \n" + " call __pal_linux_main \n"); + +void __pal_linux_main (void * args) +{ + static PAL_TCB tcb = { + .stack_protector_canary = STACK_PROTECTOR_CANARY_DEFAULT + }; + + int ret = INLINE_SYSCALL(arch_prctl, 2, ARCH_SET_GS, &tcb); + if (IS_ERR(ret)) { + while (true) { + /* do nothing */ + } + } + pal_linux_main(args); +} +#endif + +/* + * pal_thread_init(): An initialization wrapper of a newly-created thread (including + * the first thread). This function accepts a TCB pointer to be set to the GS register + * of the thread. The rest of the TCB is used as the alternative stack for signal + * handling. + */ +int pal_thread_init (void * tcbptr) +{ + PAL_TCB * tcb = tcbptr; + int ret; + + ret = INLINE_SYSCALL(arch_prctl, 2, ARCH_SET_GS, tcb); + if (IS_ERR(ret)) + return -ERRNO(ret); + + if (tcb->alt_stack) { + // Align stack to 16 bytes + void * alt_stack_top = (void *) ((uint64_t) tcb & ~15); + assert(alt_stack_top > tcb->alt_stack); + stack_t ss; + ss.ss_sp = alt_stack_top; + ss.ss_flags = 0; + ss.ss_size = alt_stack_top - tcb->alt_stack; + + ret = INLINE_SYSCALL(sigaltstack, 2, &ss, NULL); + if (IS_ERR(ret)) + return -ERRNO(ret); + } + + if (tcb->callback) + return (*tcb->callback) (tcb->param); + + return 0; +} diff --git a/Pal/src/host/Linux/db_threading.c b/Pal/src/host/Linux/db_threading.c index 79de6686..c0cf7b28 100644 --- a/Pal/src/host/Linux/db_threading.c +++ b/Pal/src/host/Linux/db_threading.c @@ -42,41 +42,6 @@ #include #endif -/* - * pal_thread_init(): An initialization wrapper of a newly-created thread (including - * the first thread). This function accepts a TCB pointer to be set to the GS register - * of the thread. The rest of the TCB is used as the alternative stack for signal - * handling. - */ -int pal_thread_init (void * tcbptr) -{ - PAL_TCB * tcb = tcbptr; - int ret; - - ret = INLINE_SYSCALL(arch_prctl, 2, ARCH_SET_GS, tcb); - if (IS_ERR(ret)) - return -ERRNO(ret); - - if (tcb->alt_stack) { - // Align stack to 16 bytes - void * alt_stack_top = (void *) ((uint64_t) tcb & ~15); - assert(alt_stack_top > tcb->alt_stack); - stack_t ss; - ss.ss_sp = alt_stack_top; - ss.ss_flags = 0; - ss.ss_size = alt_stack_top - tcb->alt_stack; - - ret = INLINE_SYSCALL(sigaltstack, 2, &ss, NULL); - if (IS_ERR(ret)) - return -ERRNO(ret); - } - - if (tcb->callback) - return (*tcb->callback) (tcb->param); - - return 0; -} - /* _DkThreadCreate for internal use. Create an internal thread inside the current process. The arguments callback and param specify the starting function and parameters */ @@ -105,6 +70,13 @@ int _DkThreadCreate (PAL_HANDLE * handle, int (*callback) (void *), tcb->alt_stack = child_stack; // Stack bottom tcb->callback = callback; tcb->param = (void *) param; +#ifdef ENABLE_STACK_PROTECTOR + uint64_t canary; + ret = _DkRandomBitsRead(&canary, sizeof(canary)); + if (ret < 0) + canary = STACK_PROTECTOR_CANARY_DEFAULT; + tcb->stack_protector_canary = canary; +#endif /* align child_stack to 16 */ child_stack = ALIGN_DOWN_PTR(child_stack, 16); diff --git a/Pal/src/host/Linux/generated-offsets.c b/Pal/src/host/Linux/generated-offsets.c new file mode 100644 index 00000000..b3c4f026 --- /dev/null +++ b/Pal/src/host/Linux/generated-offsets.c @@ -0,0 +1,14 @@ +#include + +#include + +#include "pal_linux.h" + +void dummy(void) +{ + /* pal_linux.h */ +#ifdef ENABLE_STACK_PROTECTOR + OFFSET_T(STACK_PROTECTOR_CANARY, PAL_TCB, stack_protector_canary); +#endif +} + diff --git a/Pal/src/host/Linux/pal_linux.h b/Pal/src/host/Linux/pal_linux.h index dbb16f8a..83f57454 100644 --- a/Pal/src/host/Linux/pal_linux.h +++ b/Pal/src/host/Linux/pal_linux.h @@ -187,6 +187,10 @@ struct event_queue { DEFINE_LISTP(event_queue); typedef struct pal_tcb { struct pal_tcb * self; +#ifdef ENABLE_STACK_PROTECTOR +#define STACK_PROTECTOR_CANARY_DEFAULT 0x2bad2bad2bad2badUL + uint64_t stack_protector_canary; +#endif int pending_event; LISTP_TYPE(event_queue) pending_queue; PAL_HANDLE handle; diff --git a/Pal/src/host/Skeleton/Makefile b/Pal/src/host/Skeleton/Makefile index 1c1e59c4..29e03e05 100644 --- a/Pal/src/host/Skeleton/Makefile +++ b/Pal/src/host/Skeleton/Makefile @@ -23,6 +23,10 @@ CFLAGS += -DDEBUG export DEBUG endif +ifeq ($(CONFIG_PAL_STACK_PROTECTOR),y) +$(error CONFIG_PAL_STACK_PROTECTOR is not supported) +endif + ../../host_endian.h: host_endian.h $(MAKE) -C ../../ $< diff --git a/Pal/src/host/Skeleton/db_main.c b/Pal/src/host/Skeleton/db_main.c index d9c3d424..b5f0777b 100644 --- a/Pal/src/host/Skeleton/db_main.c +++ b/Pal/src/host/Skeleton/db_main.c @@ -28,10 +28,6 @@ #include "pal_error.h" #include "api.h" -void __stack_chk_fail(void) -{ -} - /* must implement "pal_start", and call "pal_main" inside */ void pal_start (void);