linux 内核裁剪不当 死机,Linux編譯x86架構內核出現_stack_chk_guard未定義錯誤

背景

android模擬器運行於virtualbox中,而virtualbox運行於x86架構的pc端,所以android及其Linux內核都編譯成x86架構。當virtualbox的vt未開啟的情況下android系統會出現各種問題,如arm庫游戲不能運行,桌面平凡掛死重啟。通過查看日志,都奔潰在了#00 pc 000183c6 /system/lib/libc.so (__get_thread+6)這個點。關於此點的日志分析過程請查看本人的另一篇文章的分析: Linux系統調用__get_thread獲取TLS失敗導致應用程序奔潰.

問題

在android內核為3.10時選擇CONFIG_CC_STACKPROTECTOR=y(開啟內核棧保護功能),在x86架構下能正常編譯解決vt下桌面重復掛死、arm庫游戲不能玩的問題。但是如果升級android內核為3.18,內核開啟棧保護功能時,交叉編譯x86架構下的linux內核就會出現編譯錯誤。具體看如下開啟內核配置和出錯日志:

開啟3.18棧保護的內核配置選項如下:@@ -41,7 +41,6 @@ CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y

CONFIG_HAVE_INTEL_TXT=y

CONFIG_X86_32_SMP=y

CONFIG_X86_HT=y

-CONFIG_X86_32_LAZY_GS=y

CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-ecx -fcall-saved-edx"

CONFIG_ARCH_SUPPORTS_UPROBES=y

CONFIG_FIX_EARLYCON_MEM=y

@@ -249,10 +248,10 @@ CONFIG_HAVE_CMPXCHG_DOUBLE=y

CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y

CONFIG_HAVE_ARCH_SECCOMP_FILTER=y

CONFIG_HAVE_CC_STACKPROTECTOR=y

-# CONFIG_CC_STACKPROTECTOR is not set

-CONFIG_CC_STACKPROTECTOR_NONE=y

+CONFIG_CC_STACKPROTECTOR=y

+# CONFIG_CC_STACKPROTECTOR_NONE is not set

# CONFIG_CC_STACKPROTECTOR_REGULAR is not set

-# CONFIG_CC_STACKPROTECTOR_STRONG is not set

+CONFIG_CC_STACKPROTECTOR_STRONG=y

CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y

CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y

CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y

開啟3.18內核棧保護配置后內核編譯x86架構錯誤如下:CHK include/generated/compile.h

UPD include/generated/compile.h

CC init/version.o

LD init/built-in.o

android-4.4.4/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.6/bin/i686-linux-android-ld: init/built-in.o: in function do_one_initcall:init_task.c(.text+0x7f): error: undefined reference to '__stack_chk_guard'

android-4.4.4/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.6/bin/i686-linux-android-ld: init/built-in.o: in function do_one_initcall:init_task.c(.text+0x1c6): error: undefined reference to '__stack_chk_guard'

android-4.4.4/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.6/bin/i686-linux-android-ld: init/built-in.o: in function name_to_dev_t:init_task.c(.text+0x261): error: undefined reference to '__stack_chk_guard'

android-4.4.4/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.6/bin/i686-linux-android-ld: init/built-in.o: in function name_to_dev_t:init_task.c(.text+0x517): error: undefined reference to '__stack_chk_guard'

make: *** [vmlinux] Error 1

arch/x86/Makefile:116: stack-protector enabled but compiler support broken

分析解決

上述error: undefined reference to '__stack_chk_guard'錯誤通過各種google也沒有找到正解,有的說是gcc需要4.9及以上,然而用交叉編譯工具4.9也不行。還查看了android源碼關於stack protector的相關修復,都沒有啥卵用。最后通過查看__stack_chk_guard字段發現,x86架構沒有定義此字段,而sh,arm,mips等架構確定義了。在窮途末路時只能自己動手依葫蘆畫瓢,期待有所進展。如下patch為本人添加,不僅能解決編譯錯誤,還確實解決了vt未開啟時,virtualbox下運行android鏡像出現的各種問題。

Linux編譯x86架構時__stack_chk_guard未定義錯誤的修復patchdiff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h

index 6a99859..3e2d812 100644

--- a/arch/x86/include/asm/stackprotector.h

+++ b/arch/x86/include/asm/stackprotector.h

@@ -41,6 +41,10 @@

#include

#include

+#if (defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP))

+extern unsigned long __stack_chk_guard;

+#endif

+

/*

* 24 byte read-only segment initializer for stack canary. Linker

* can't handle the address bit shifting. Address will be set in

@@ -79,6 +83,10 @@ static __always_inline void boot_init_stack_canary(void)

#else

this_cpu_write(stack_canary.canary, canary);

#endif

+

+#if (defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP))

+ __stack_chk_guard = current->stack_canary;

+#endif

}

static inline void setup_stack_canary_segment(int cpu)

diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c

index 4eb204c..5ad8ab2 100644

--- a/arch/x86/kernel/process.c

+++ b/arch/x86/kernel/process.c

@@ -29,6 +29,12 @@

#include

#include

+

+#if (defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP))

+ unsigned long __stack_chk_guard __read_mostly;

+/* 配置打開SMP時,會出現此__stack_chk_guard變量重復定義問題,所有只能在無SMP下生效 */

+//static DEFINE_PER_CPU(unsigned long,__stack_chk_guard) __read_mostly;

+EXPORT_SYMBOL(__stack_chk_guard);

+#endif

+

/*

* per-CPU TSS segments. Threads are completely 'soft' on Linux,

* no more per-task TSS's. The TSS size is kept cacheline-aligned

diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c

index 8f3ebfe..f027d25 100644

--- a/arch/x86/kernel/process_32.c

+++ b/arch/x86/kernel/process_32.c

@@ -39,6 +39,11 @@

#include

#include

#include

+

+#if (defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP))

+#include

+#endif

+

#include

#include

#include

@@ -249,6 +254,11 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)

*next = &next_p->thread;

int cpu = smp_processor_id();

struct tss_struct *tss = &per_cpu(init_tss, cpu);

+

+ #if (defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP))

+ __stack_chk_guard = next_p->stack_canary;

+ #endif

+

fpu_switch_t fpu;

/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */

為啥內核能正常選擇打開棧保護功能但卻無法編譯通過呢,后面想了想,可能有如下原因:

一是godlfish內核主要對移動手機設備使用的內核,手機一般使用的是arm芯片,對於x86架構官方關注的也許並不多。

二是默認此棧保護功能是關閉的,只有對運行穩定性有特殊需求的產品,如航天,太空類高穩定產品才需要考慮打開,打開后會稍微降低性能。

此patch應該是可以作為官網的patch來提交修復,福澤大眾的,但本人從來沒有提交過,限於水平有限,暫且記錄,以備后忘。

感謝

2017 …… ,卷起褲管跑,擼起袖子干!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值