Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 305225
b: refs/heads/master
c: 5d920bb
h: refs/heads/master
i:
  305223: 575056a
v: v3
  • Loading branch information
Filippo Arcidiacono authored and Paul Mundt committed Apr 19, 2012
1 parent 22dc439 commit c0ecfa6
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 78 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: 9e7f60a37d1817460ffcdfc2001a00861ac3e121
refs/heads/master: 5d920bb929a99446062a48cf90867bbca57b8e77
14 changes: 14 additions & 0 deletions trunk/arch/sh/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,20 @@ config SECCOMP

If unsure, say N.

config CC_STACKPROTECTOR
bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
depends on SUPERH32 && 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 SMP
bool "Symmetric multi-processing support"
depends on SYS_SUPPORTS_SMP
Expand Down
4 changes: 4 additions & 0 deletions trunk/arch/sh/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ ifeq ($(CONFIG_DWARF_UNWINDER),y)
KBUILD_CFLAGS += -fasynchronous-unwind-tables
endif

ifeq ($(CONFIG_CC_STACKPROTECTOR),y)
KBUILD_CFLAGS += -fstack-protector
endif

libs-$(CONFIG_SUPERH32) := arch/sh/lib/ $(libs-y)
libs-$(CONFIG_SUPERH64) := arch/sh/lib64/ $(libs-y)

Expand Down
4 changes: 2 additions & 2 deletions trunk/arch/sh/boards/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,8 @@ config SH_APSH4AD0A
help
Select AP-SH4AD-0A if configuring for an ALPHAPROJECT AP-SH4AD-0A.

endmenu

source "arch/sh/boards/mach-r2d/Kconfig"
source "arch/sh/boards/mach-highlander/Kconfig"
source "arch/sh/boards/mach-sdk7780/Kconfig"
Expand All @@ -357,5 +359,3 @@ config SH_MAGIC_PANEL_R2_VERSION
endmenu

endif

endmenu
27 changes: 27 additions & 0 deletions trunk/arch/sh/include/asm/stackprotector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef __ASM_SH_STACKPROTECTOR_H
#define __ASM_SH_STACKPROTECTOR_H

#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_SH_STACKPROTECTOR_H */
7 changes: 7 additions & 0 deletions trunk/arch/sh/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/export.h>
#include <linux/stackprotector.h>

struct kmem_cache *task_xstate_cachep = NULL;
unsigned int xstate_size;

#ifdef CONFIG_CC_STACKPROTECTOR
unsigned long __stack_chk_guard __read_mostly;
EXPORT_SYMBOL(__stack_chk_guard);
#endif

int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
{
*dst = *src;
Expand Down
5 changes: 5 additions & 0 deletions trunk/arch/sh/kernel/process_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <linux/ftrace.h>
#include <linux/hw_breakpoint.h>
#include <linux/prefetch.h>
#include <linux/stackprotector.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
#include <asm/fpu.h>
Expand Down Expand Up @@ -220,6 +221,10 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
{
struct thread_struct *next_t = &next->thread;

#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
__stack_chk_guard = next->stack_canary;
#endif

unlazy_fpu(prev, task_pt_regs(prev));

/* we're going to use this soon, after a few expensive things */
Expand Down
99 changes: 24 additions & 75 deletions trunk/arch/sh/mm/fault_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,74 +35,6 @@ static inline int notify_page_fault(struct pt_regs *regs, int trap)
return ret;
}

/*
* This is useful to dump out the page tables associated with
* 'addr' in mm 'mm'.
*/
static void show_pte(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pgd;

if (mm)
pgd = mm->pgd;
else
pgd = get_TTB();

printk(KERN_ALERT "pgd = %p\n", pgd);
pgd += pgd_index(addr);
printk(KERN_ALERT "[%08lx] *pgd=%0*Lx", addr,
sizeof(*pgd) * 2, (u64)pgd_val(*pgd));

do {
pud_t *pud;
pmd_t *pmd;
pte_t *pte;

if (pgd_none(*pgd))
break;

if (pgd_bad(*pgd)) {
printk("(bad)");
break;
}

pud = pud_offset(pgd, addr);
if (PTRS_PER_PUD != 1)
printk(", *pud=%0*Lx", sizeof(*pud) * 2,
(u64)pud_val(*pud));

if (pud_none(*pud))
break;

if (pud_bad(*pud)) {
printk("(bad)");
break;
}

pmd = pmd_offset(pud, addr);
if (PTRS_PER_PMD != 1)
printk(", *pmd=%0*Lx", sizeof(*pmd) * 2,
(u64)pmd_val(*pmd));

if (pmd_none(*pmd))
break;

if (pmd_bad(*pmd)) {
printk("(bad)");
break;
}

/* We must not map this if we have highmem enabled */
if (PageHighMem(pfn_to_page(pmd_val(*pmd) >> PAGE_SHIFT)))
break;

pte = pte_offset_kernel(pmd, addr);
printk(", *pte=%0*Lx", sizeof(*pte) * 2, (u64)pte_val(*pte));
} while (0);

printk("\n");
}

static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
{
unsigned index = pgd_index(address);
Expand Down Expand Up @@ -154,7 +86,7 @@ static noinline int vmalloc_fault(unsigned long address)
pte_t *pte_k;

/* Make sure we are in vmalloc/module/P3 area: */
if (!(address >= P3SEG && address < P3_ADDR_MAX))
if (!(address >= VMALLOC_START && address < P3_ADDR_MAX))
return -1;

/*
Expand Down Expand Up @@ -322,12 +254,29 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
bust_spinlocks(1);

if (oops_may_print()) {
printk(KERN_ALERT
"Unable to handle kernel %s at virtual address %08lx\n",
(address < PAGE_SIZE) ? "NULL pointer dereference" :
"paging request", address);

show_pte(mm, address);
unsigned long page;

if (address < PAGE_SIZE)
printk(KERN_ALERT "Unable to handle kernel NULL "
"pointer dereference");
else
printk(KERN_ALERT "Unable to handle kernel paging "
"request");
printk(" at virtual address %08lx\n", address);
printk(KERN_ALERT "pc = %08lx\n", regs->pc);
page = (unsigned long)get_TTB();
if (page) {
page = ((__typeof__(page) *)page)[address >> PGDIR_SHIFT];
printk(KERN_ALERT "*pde = %08lx\n", page);
if (page & _PAGE_PRESENT) {
page &= PAGE_MASK;
address &= 0x003ff000;
page = ((__typeof__(page) *)
__va(page))[address >>
PAGE_SHIFT];
printk(KERN_ALERT "*pte = %08lx\n", page);
}
}
}

die("Oops", regs, writeaccess);
Expand Down

0 comments on commit c0ecfa6

Please sign in to comment.