Linux,全称GNU/Linux,是一种免费使用和自由传播的类UNIX操作系统,其内核由林纳斯·本纳第克特·托瓦兹于1991年10月5日首次发布,它主要受到Minix和Unix思想的启发,是一个基于POSIX的多用户、多任务、支持多线程和多CPU的操作系统。 背景 Android模拟器运行于virtualbox中,而virtualbox运行于x86架构的pc端,所以android及其Linux内核都编译成x86架构。当virtualbox的vt未开启的情况下android系统会出现各种问题,如arm库游戏不能运行,桌面平凡挂死重启。通过查看日志,都奔溃在了#00 pc 000183c6 /system/lib/libc.so (__get_thread+6)这个点。 问题 在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未定义错误的修复patch diff --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) +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) + __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 + +#ifdef CONFIG_CC_STACKPROTECTOR +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 + +#ifdef CONFIG_CC_STACKPROTECTOR +#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) + __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来提交修复,福泽大众的,但本人从来没有提交过,限于水平有限,暂且记录,以备后忘。 Linux是一套免费使用和自由传播的类Unix操作系统 |
温馨提示:喜欢本站的话,请收藏一下本站!