概述
背景
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 …… ,卷起褲管跑,擼起袖子干!
最后
以上就是傻傻裙子为你收集整理的linux 内核裁剪不当 死机,Linux編譯x86架構內核出現_stack_chk_guard未定義錯誤的全部内容,希望文章能够帮你解决linux 内核裁剪不当 死机,Linux編譯x86架構內核出現_stack_chk_guard未定義錯誤所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复