Skip to content

Commit

Permalink
MIPS: initial stack protector support
Browse files Browse the repository at this point in the history
Implements basic stack protector support based on ARM version in
c743f38 , with Kconfig option,
constant canary value set at boot time, and script to check if
compiler actually supports stack protector.

Tested by creating a kernel module that writes past end of char[].

Signed-off-by: Gregory Fong <[email protected]>
Cc: [email protected]
Cc: Filippo Arcidiacono <[email protected]>
Cc: Carmelo Amoroso <[email protected]>
Patchwork: https://patchwork.linux-mips.org/patch/5448/
Signed-off-by: Ralf Baechle <[email protected]>
  • Loading branch information
cha5on authored and ralfbaechle committed Jul 1, 2013
1 parent 23df341 commit 36ecafc
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 0 deletions.
13 changes: 13 additions & 0 deletions arch/mips/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2367,6 +2367,19 @@ config SECCOMP

If unsure, say Y. Only embedded should say N here.

config CC_STACKPROTECTOR
bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
help
This option turns on the -fstack-protector GCC feature. This
feature puts, at the beginning of functions, a canary value on
the stack just before the return address, and validates
the value just before actually returning. Stack based buffer
overflows (that need to overwrite this return address) now also
overwrite the canary, which gets detected and the attack is then
neutralized via a kernel panic.

This feature requires gcc version 4.2 or above.

config USE_OF
bool
select OF
Expand Down
4 changes: 4 additions & 0 deletions arch/mips/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@ KBUILD_CPPFLAGS += -DDATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0)

LDFLAGS += -m $(ld-emul)

ifdef CONFIG_CC_STACKPROTECTOR
KBUILD_CFLAGS += -fstack-protector
endif

ifdef CONFIG_MIPS
CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \
egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \
Expand Down
40 changes: 40 additions & 0 deletions arch/mips/include/asm/stackprotector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* GCC stack protector support.
*
* (This is directly adopted from the ARM implementation)
*
* Stack protector works by putting predefined pattern at the start of
* the stack frame and verifying that it hasn't been overwritten when
* returning from the function. The pattern is called stack canary
* and gcc expects it to be defined by a global variable called
* "__stack_chk_guard" on MIPS. This unfortunately means that on SMP
* we cannot have a different canary value per task.
*/

#ifndef _ASM_STACKPROTECTOR_H
#define _ASM_STACKPROTECTOR_H 1

#include <linux/random.h>
#include <linux/version.h>

extern unsigned long __stack_chk_guard;

/*
* Initialize the stackprotector canary value.
*
* NOTE: this must only be called from functions that never return,
* and it must always be inlined.
*/
static __always_inline void boot_init_stack_canary(void)
{
unsigned long canary;

/* Try to get a semi random initial value. */
get_random_bytes(&canary, sizeof(canary));
canary ^= LINUX_VERSION_CODE;

current->stack_canary = canary;
__stack_chk_guard = current->stack_canary;
}

#endif /* _ASM_STACKPROTECTOR_H */
6 changes: 6 additions & 0 deletions arch/mips/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,12 @@ int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr)
return 1;
}

#ifdef CONFIG_CC_STACKPROTECTOR
#include <linux/stackprotector.h>
unsigned long __stack_chk_guard __read_mostly;
EXPORT_SYMBOL(__stack_chk_guard);
#endif

/*
*
*/
Expand Down

0 comments on commit 36ecafc

Please sign in to comment.