forked from Minki/linux
Merge branch 'stackprotector' into core/percpu
This commit is contained in:
commit
7890ba8c87
@ -1340,13 +1340,17 @@ config SECCOMP
|
|||||||
|
|
||||||
If unsure, say Y. Only embedded should say N here.
|
If unsure, say Y. Only embedded should say N here.
|
||||||
|
|
||||||
|
config CC_STACKPROTECTOR_ALL
|
||||||
|
bool
|
||||||
|
|
||||||
config CC_STACKPROTECTOR
|
config CC_STACKPROTECTOR
|
||||||
bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
|
bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
|
||||||
depends on X86_64 && EXPERIMENTAL && BROKEN
|
depends on X86_64
|
||||||
|
select CC_STACKPROTECTOR_ALL
|
||||||
help
|
help
|
||||||
This option turns on the -fstack-protector GCC feature. This
|
This option turns on the -fstack-protector GCC feature. This
|
||||||
feature puts, at the beginning of critical functions, a canary
|
feature puts, at the beginning of functions, a canary value on
|
||||||
value on the stack just before the return address, and validates
|
the stack just before the return address, and validates
|
||||||
the value just before actually returning. Stack based buffer
|
the value just before actually returning. Stack based buffer
|
||||||
overflows (that need to overwrite this return address) now also
|
overflows (that need to overwrite this return address) now also
|
||||||
overwrite the canary, which gets detected and the attack is then
|
overwrite the canary, which gets detected and the attack is then
|
||||||
@ -1354,15 +1358,8 @@ config CC_STACKPROTECTOR
|
|||||||
|
|
||||||
This feature requires gcc version 4.2 or above, or a distribution
|
This feature requires gcc version 4.2 or above, or a distribution
|
||||||
gcc with the feature backported. Older versions are automatically
|
gcc with the feature backported. Older versions are automatically
|
||||||
detected and for those versions, this configuration option is ignored.
|
detected and for those versions, this configuration option is
|
||||||
|
ignored. (and a warning is printed during bootup)
|
||||||
config CC_STACKPROTECTOR_ALL
|
|
||||||
bool "Use stack-protector for all functions"
|
|
||||||
depends on CC_STACKPROTECTOR
|
|
||||||
help
|
|
||||||
Normally, GCC only inserts the canary value protection for
|
|
||||||
functions that use large-ish on-stack buffers. By enabling
|
|
||||||
this option, GCC will be asked to do this for ALL functions.
|
|
||||||
|
|
||||||
source kernel/Kconfig.hz
|
source kernel/Kconfig.hz
|
||||||
|
|
||||||
|
@ -117,6 +117,7 @@ config DEBUG_RODATA
|
|||||||
config DEBUG_RODATA_TEST
|
config DEBUG_RODATA_TEST
|
||||||
bool "Testcase for the DEBUG_RODATA feature"
|
bool "Testcase for the DEBUG_RODATA feature"
|
||||||
depends on DEBUG_RODATA
|
depends on DEBUG_RODATA
|
||||||
|
default y
|
||||||
help
|
help
|
||||||
This option enables a testcase for the DEBUG_RODATA
|
This option enables a testcase for the DEBUG_RODATA
|
||||||
feature as well as for the change_page_attr() infrastructure.
|
feature as well as for the change_page_attr() infrastructure.
|
||||||
|
@ -73,7 +73,7 @@ else
|
|||||||
|
|
||||||
stackp := $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh
|
stackp := $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh
|
||||||
stackp-$(CONFIG_CC_STACKPROTECTOR) := $(shell $(stackp) \
|
stackp-$(CONFIG_CC_STACKPROTECTOR) := $(shell $(stackp) \
|
||||||
"$(CC)" -fstack-protector )
|
"$(CC)" "-fstack-protector -DGCC_HAS_SP" )
|
||||||
stackp-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(stackp) \
|
stackp-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(stackp) \
|
||||||
"$(CC)" -fstack-protector-all )
|
"$(CC)" -fstack-protector-all )
|
||||||
|
|
||||||
|
@ -17,11 +17,9 @@ struct x8664_pda {
|
|||||||
unsigned long unused4;
|
unsigned long unused4;
|
||||||
int unused5;
|
int unused5;
|
||||||
unsigned int unused6; /* 36 was cpunumber */
|
unsigned int unused6; /* 36 was cpunumber */
|
||||||
#ifdef CONFIG_CC_STACKPROTECTOR
|
|
||||||
unsigned long stack_canary; /* 40 stack canary value */
|
unsigned long stack_canary; /* 40 stack canary value */
|
||||||
/* gcc-ABI: this canary MUST be at
|
/* gcc-ABI: this canary MUST be at
|
||||||
offset 40!!! */
|
offset 40!!! */
|
||||||
#endif
|
|
||||||
short in_bootmem; /* pda lives in bootmem */
|
short in_bootmem; /* pda lives in bootmem */
|
||||||
} ____cacheline_aligned_in_smp;
|
} ____cacheline_aligned_in_smp;
|
||||||
|
|
||||||
@ -42,4 +40,6 @@ extern void pda_init(int);
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define refresh_stack_canary() write_pda(stack_canary, current->stack_canary)
|
||||||
|
|
||||||
#endif /* _ASM_X86_PDA_H */
|
#endif /* _ASM_X86_PDA_H */
|
||||||
|
39
arch/x86/include/asm/stackprotector.h
Normal file
39
arch/x86/include/asm/stackprotector.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#ifndef _ASM_STACKPROTECTOR_H
|
||||||
|
#define _ASM_STACKPROTECTOR_H 1
|
||||||
|
|
||||||
|
#include <asm/tsc.h>
|
||||||
|
#include <asm/pda.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
u64 canary;
|
||||||
|
u64 tsc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we're the non-boot CPU, nothing set the PDA stack
|
||||||
|
* canary up for us - and if we are the boot CPU we have
|
||||||
|
* a 0 stack canary. This is a good place for updating
|
||||||
|
* it, as we wont ever return from this function (so the
|
||||||
|
* invalid canaries already on the stack wont ever
|
||||||
|
* trigger).
|
||||||
|
*
|
||||||
|
* We both use the random pool and the current TSC as a source
|
||||||
|
* of randomness. The TSC only matters for very early init,
|
||||||
|
* there it already has some randomness on most systems. Later
|
||||||
|
* on during the bootup the random pool has true entropy too.
|
||||||
|
*/
|
||||||
|
get_random_bytes(&canary, sizeof(canary));
|
||||||
|
tsc = __native_read_tsc();
|
||||||
|
canary += tsc + (tsc << 32UL);
|
||||||
|
|
||||||
|
current->stack_canary = canary;
|
||||||
|
write_pda(stack_canary, canary);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -95,6 +95,8 @@ do { \
|
|||||||
".globl thread_return\n" \
|
".globl thread_return\n" \
|
||||||
"thread_return:\n\t" \
|
"thread_return:\n\t" \
|
||||||
"movq "__percpu_arg([current_task])",%%rsi\n\t" \
|
"movq "__percpu_arg([current_task])",%%rsi\n\t" \
|
||||||
|
"movq %P[task_canary](%%rsi),%%r8\n\t" \
|
||||||
|
"movq %%r8,%%gs:%P[pda_canary]\n\t" \
|
||||||
"movq %P[thread_info](%%rsi),%%r8\n\t" \
|
"movq %P[thread_info](%%rsi),%%r8\n\t" \
|
||||||
LOCK_PREFIX "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \
|
LOCK_PREFIX "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \
|
||||||
"movq %%rax,%%rdi\n\t" \
|
"movq %%rax,%%rdi\n\t" \
|
||||||
@ -106,7 +108,9 @@ do { \
|
|||||||
[ti_flags] "i" (offsetof(struct thread_info, flags)), \
|
[ti_flags] "i" (offsetof(struct thread_info, flags)), \
|
||||||
[tif_fork] "i" (TIF_FORK), \
|
[tif_fork] "i" (TIF_FORK), \
|
||||||
[thread_info] "i" (offsetof(struct task_struct, stack)), \
|
[thread_info] "i" (offsetof(struct task_struct, stack)), \
|
||||||
[current_task] "m" (per_cpu_var(current_task)) \
|
[task_canary] "i" (offsetof(struct task_struct, stack_canary)),\
|
||||||
|
[current_task] "m" (per_cpu_var(current_task)), \
|
||||||
|
[pda_canary] "i" (offsetof(struct x8664_pda, stack_canary))\
|
||||||
: "memory", "cc" __EXTRA_CLOBBER)
|
: "memory", "cc" __EXTRA_CLOBBER)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ nostackp := $(call cc-option, -fno-stack-protector)
|
|||||||
CFLAGS_vsyscall_64.o := $(PROFILING) -g0 $(nostackp)
|
CFLAGS_vsyscall_64.o := $(PROFILING) -g0 $(nostackp)
|
||||||
CFLAGS_hpet.o := $(nostackp)
|
CFLAGS_hpet.o := $(nostackp)
|
||||||
CFLAGS_tsc.o := $(nostackp)
|
CFLAGS_tsc.o := $(nostackp)
|
||||||
|
CFLAGS_paravirt.o := $(nostackp)
|
||||||
|
|
||||||
obj-y := process_$(BITS).o signal.o entry_$(BITS).o
|
obj-y := process_$(BITS).o signal.o entry_$(BITS).o
|
||||||
obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
|
obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include <linux/stackprotector.h>
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
@ -117,6 +118,17 @@ static inline void play_dead(void)
|
|||||||
void cpu_idle(void)
|
void cpu_idle(void)
|
||||||
{
|
{
|
||||||
current_thread_info()->status |= TS_POLLING;
|
current_thread_info()->status |= TS_POLLING;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we're the non-boot CPU, nothing set the PDA stack
|
||||||
|
* canary up for us - and if we are the boot CPU we have
|
||||||
|
* a 0 stack canary. This is a good place for updating
|
||||||
|
* it, as we wont ever return from this function (so the
|
||||||
|
* invalid canaries already on the stack wont ever
|
||||||
|
* trigger):
|
||||||
|
*/
|
||||||
|
boot_init_stack_canary();
|
||||||
|
|
||||||
/* endless idle loop with no priority at all */
|
/* endless idle loop with no priority at all */
|
||||||
while (1) {
|
while (1) {
|
||||||
tick_nohz_stop_sched_tick(1);
|
tick_nohz_stop_sched_tick(1);
|
||||||
@ -627,7 +639,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
|
|||||||
(unsigned long)task_stack_page(next_p) +
|
(unsigned long)task_stack_page(next_p) +
|
||||||
THREAD_SIZE - KERNEL_STACK_OFFSET);
|
THREAD_SIZE - KERNEL_STACK_OFFSET);
|
||||||
#ifdef CONFIG_CC_STACKPROTECTOR
|
#ifdef CONFIG_CC_STACKPROTECTOR
|
||||||
write_pda(stack_canary, next_p->stack_canary);
|
|
||||||
/*
|
/*
|
||||||
* Build time only check to make sure the stack_canary is at
|
* Build time only check to make sure the stack_canary is at
|
||||||
* offset 40 in the pda; this is a gcc ABI requirement
|
* offset 40 in the pda; this is a gcc ABI requirement
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <linux/kprobes.h>
|
#include <linux/kprobes.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/kdebug.h>
|
#include <linux/kdebug.h>
|
||||||
|
#include <linux/magic.h>
|
||||||
|
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/desc.h>
|
#include <asm/desc.h>
|
||||||
@ -589,6 +590,8 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
|||||||
unsigned long address;
|
unsigned long address;
|
||||||
int write, si_code;
|
int write, si_code;
|
||||||
int fault;
|
int fault;
|
||||||
|
unsigned long *stackend;
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int sig;
|
int sig;
|
||||||
@ -841,6 +844,10 @@ no_context:
|
|||||||
|
|
||||||
show_fault_oops(regs, error_code, address);
|
show_fault_oops(regs, error_code, address);
|
||||||
|
|
||||||
|
stackend = end_of_stack(tsk);
|
||||||
|
if (*stackend != STACK_END_MAGIC)
|
||||||
|
printk(KERN_ALERT "Thread overran stack, or stack corrupted\n");
|
||||||
|
|
||||||
tsk->thread.cr2 = address;
|
tsk->thread.cr2 = address;
|
||||||
tsk->thread.trap_no = 14;
|
tsk->thread.trap_no = 14;
|
||||||
tsk->thread.error_code = error_code;
|
tsk->thread.error_code = error_code;
|
||||||
|
@ -47,4 +47,5 @@
|
|||||||
#define FUTEXFS_SUPER_MAGIC 0xBAD1DEA
|
#define FUTEXFS_SUPER_MAGIC 0xBAD1DEA
|
||||||
#define INOTIFYFS_SUPER_MAGIC 0x2BAD1DEA
|
#define INOTIFYFS_SUPER_MAGIC 0x2BAD1DEA
|
||||||
|
|
||||||
|
#define STACK_END_MAGIC 0x57AC6E9D
|
||||||
#endif /* __LINUX_MAGIC_H__ */
|
#endif /* __LINUX_MAGIC_H__ */
|
||||||
|
@ -1157,10 +1157,9 @@ struct task_struct {
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
pid_t tgid;
|
pid_t tgid;
|
||||||
|
|
||||||
#ifdef CONFIG_CC_STACKPROTECTOR
|
|
||||||
/* Canary value for the -fstack-protector gcc feature */
|
/* Canary value for the -fstack-protector gcc feature */
|
||||||
unsigned long stack_canary;
|
unsigned long stack_canary;
|
||||||
#endif
|
|
||||||
/*
|
/*
|
||||||
* pointers to (original) parent process, youngest child, younger sibling,
|
* pointers to (original) parent process, youngest child, younger sibling,
|
||||||
* older sibling, respectively. (p->father can be replaced with
|
* older sibling, respectively. (p->father can be replaced with
|
||||||
@ -2066,6 +2065,19 @@ static inline int object_is_on_stack(void *obj)
|
|||||||
|
|
||||||
extern void thread_info_cache_init(void);
|
extern void thread_info_cache_init(void);
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_STACK_USAGE
|
||||||
|
static inline unsigned long stack_not_used(struct task_struct *p)
|
||||||
|
{
|
||||||
|
unsigned long *n = end_of_stack(p);
|
||||||
|
|
||||||
|
do { /* Skip over canary */
|
||||||
|
n++;
|
||||||
|
} while (!*n);
|
||||||
|
|
||||||
|
return (unsigned long)n - (unsigned long)end_of_stack(p);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* set thread flags in other task's structures
|
/* set thread flags in other task's structures
|
||||||
* - see asm/thread_info.h for TIF_xxxx flags available
|
* - see asm/thread_info.h for TIF_xxxx flags available
|
||||||
*/
|
*/
|
||||||
|
16
include/linux/stackprotector.h
Normal file
16
include/linux/stackprotector.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef _LINUX_STACKPROTECTOR_H
|
||||||
|
#define _LINUX_STACKPROTECTOR_H 1
|
||||||
|
|
||||||
|
#include <linux/compiler.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/random.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_CC_STACKPROTECTOR
|
||||||
|
# include <asm/stackprotector.h>
|
||||||
|
#else
|
||||||
|
static inline void boot_init_stack_canary(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -14,6 +14,7 @@
|
|||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/syscalls.h>
|
#include <linux/syscalls.h>
|
||||||
|
#include <linux/stackprotector.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/ctype.h>
|
#include <linux/ctype.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
@ -539,6 +540,12 @@ asmlinkage void __init start_kernel(void)
|
|||||||
*/
|
*/
|
||||||
lockdep_init();
|
lockdep_init();
|
||||||
debug_objects_early_init();
|
debug_objects_early_init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up the the initial canary ASAP:
|
||||||
|
*/
|
||||||
|
boot_init_stack_canary();
|
||||||
|
|
||||||
cgroup_init_early();
|
cgroup_init_early();
|
||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
|
@ -977,12 +977,9 @@ static void check_stack_usage(void)
|
|||||||
{
|
{
|
||||||
static DEFINE_SPINLOCK(low_water_lock);
|
static DEFINE_SPINLOCK(low_water_lock);
|
||||||
static int lowest_to_date = THREAD_SIZE;
|
static int lowest_to_date = THREAD_SIZE;
|
||||||
unsigned long *n = end_of_stack(current);
|
|
||||||
unsigned long free;
|
unsigned long free;
|
||||||
|
|
||||||
while (*n == 0)
|
free = stack_not_used(current);
|
||||||
n++;
|
|
||||||
free = (unsigned long)n - (unsigned long)end_of_stack(current);
|
|
||||||
|
|
||||||
if (free >= lowest_to_date)
|
if (free >= lowest_to_date)
|
||||||
return;
|
return;
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blkdev.h>
|
||||||
#include <trace/sched.h>
|
#include <trace/sched.h>
|
||||||
|
#include <linux/magic.h>
|
||||||
|
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/pgalloc.h>
|
#include <asm/pgalloc.h>
|
||||||
@ -212,6 +213,8 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
|
|||||||
{
|
{
|
||||||
struct task_struct *tsk;
|
struct task_struct *tsk;
|
||||||
struct thread_info *ti;
|
struct thread_info *ti;
|
||||||
|
unsigned long *stackend;
|
||||||
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
prepare_to_copy(orig);
|
prepare_to_copy(orig);
|
||||||
@ -237,6 +240,8 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
setup_thread_stack(tsk, orig);
|
setup_thread_stack(tsk, orig);
|
||||||
|
stackend = end_of_stack(tsk);
|
||||||
|
*stackend = STACK_END_MAGIC; /* for overflow detection */
|
||||||
|
|
||||||
#ifdef CONFIG_CC_STACKPROTECTOR
|
#ifdef CONFIG_CC_STACKPROTECTOR
|
||||||
tsk->stack_canary = get_random_int();
|
tsk->stack_canary = get_random_int();
|
||||||
|
@ -74,6 +74,9 @@ NORET_TYPE void panic(const char * fmt, ...)
|
|||||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
vsnprintf(buf, sizeof(buf), fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf);
|
printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf);
|
||||||
|
#ifdef CONFIG_DEBUG_BUGVERBOSE
|
||||||
|
dump_stack();
|
||||||
|
#endif
|
||||||
bust_spinlocks(0);
|
bust_spinlocks(0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -355,15 +358,22 @@ EXPORT_SYMBOL(warn_slowpath);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_CC_STACKPROTECTOR
|
#ifdef CONFIG_CC_STACKPROTECTOR
|
||||||
|
|
||||||
|
#ifndef GCC_HAS_SP
|
||||||
|
#warning You have selected the CONFIG_CC_STACKPROTECTOR option, but the gcc used does not support this.
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called when gcc's -fstack-protector feature is used, and
|
* Called when gcc's -fstack-protector feature is used, and
|
||||||
* gcc detects corruption of the on-stack canary value
|
* gcc detects corruption of the on-stack canary value
|
||||||
*/
|
*/
|
||||||
void __stack_chk_fail(void)
|
void __stack_chk_fail(void)
|
||||||
{
|
{
|
||||||
panic("stack-protector: Kernel stack is corrupted");
|
panic("stack-protector: Kernel stack is corrupted in: %p\n",
|
||||||
|
__builtin_return_address(0));
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__stack_chk_fail);
|
EXPORT_SYMBOL(__stack_chk_fail);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
core_param(panic, panic_timeout, int, 0644);
|
core_param(panic, panic_timeout, int, 0644);
|
||||||
|
@ -5939,12 +5939,7 @@ void sched_show_task(struct task_struct *p)
|
|||||||
printk(KERN_CONT " %016lx ", thread_saved_pc(p));
|
printk(KERN_CONT " %016lx ", thread_saved_pc(p));
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_DEBUG_STACK_USAGE
|
#ifdef CONFIG_DEBUG_STACK_USAGE
|
||||||
{
|
free = stack_not_used(p);
|
||||||
unsigned long *n = end_of_stack(p);
|
|
||||||
while (!*n)
|
|
||||||
n++;
|
|
||||||
free = (unsigned long)n - (unsigned long)end_of_stack(p);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
printk(KERN_CONT "%5lu %5d %6d\n", free,
|
printk(KERN_CONT "%5lu %5d %6d\n", free,
|
||||||
task_pid_nr(p), task_pid_nr(p->real_parent));
|
task_pid_nr(p), task_pid_nr(p->real_parent));
|
||||||
|
Loading…
Reference in New Issue
Block a user