背景

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=yCONFIG_HAVE_INTEL_TXT=yCONFIG_X86_32_SMP=yCONFIG_X86_HT=y
-CONFIG_X86_32_LAZY_GS=yCONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-ecx -fcall-saved-edx"CONFIG_ARCH_SUPPORTS_UPROBES=yCONFIG_FIX_EARLYCON_MEM=y
@@ -249,10 +248,10 @@ CONFIG_HAVE_CMPXCHG_DOUBLE=yCONFIG_ARCH_WANT_IPC_PARSE_VERSION=yCONFIG_HAVE_ARCH_SECCOMP_FILTER=yCONFIG_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=yCONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=yCONFIG_HAVE_IRQ_TIME_ACCOUNTING=yCONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y

开启3.18内核栈保护配置后内核编译x86架构错误如下:

  CHK     include/generated/compile.hUPD     include/generated/compile.hCC      init/version.oLD      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 <asm/desc.h>#include <linux/random.h>+#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)#elsethis_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 <asm/debugreg.h>#include <asm/nmi.h>+
+#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 <asm/pgtable.h>#include <asm/ldt.h>#include <asm/processor.h>
+
+#if (defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP))
+#include <linux/stackprotector.h>
+#endif
+#include <asm/i387.h>#include <asm/fpu-internal.h>#include <asm/desc.h>
@@ -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来提交修复,福泽大众的,但本人从来没有提交过,限于水平有限,暂且记录,以备后忘。

【注:关于内核栈保护原理,可以参考文章:CC_STACKPROTECTOR防内核堆栈溢出补丁分析】


感谢

2017 …… ,卷起裤管跑,撸起袖子干!

yanxiangyfg的专栏 : “忠于实践,记录点滴”


Linux编译x86架构内核出现_stack_chk_guard未定义错误相关推荐

  1. 编译内核发现wireless_send_event未定义错误

    主要出现下面类似的错误: ERROR: "wireless_send_event" [drivers/net/wireless/realtek/rtl8723BU/8723bu.k ...

  2. linux内核未定义的引用,变异内核,出现“未定义的引用”问题

    drivers/built-in.o:在函数'mmc_blk_drm_part_get'中: /home/zouxf/project/rk3399/rk_linux_sdk/kernel/driver ...

  3. AjaxPro 未定义错误

    问题:      "本机测试一切正常,传到服务器上浏览器提示我的AjaxPro 未定义"-->这是我在网上找的原话也是我的问题. 原因和解决:     1.没有将AjaxPr ...

  4. 关于页面出现未定义错误的解决

    页面报xxxxx未定义错误时: 1.首先先定义它: var xx=xxxxx: 2.如果不行: 试着加 ' 号试试如: var str='<div οnclick="sqtd('+ro ...

  5. Robotstudio出现未定义错误解决办法

    问题描述:Robotstudio出现未定义错误,如下图所示 问题分析:前几天使用360安全卫士杀毒时删除了一些组件 解决办法一:在恢复区内恢复已删除组件 解决方法二:控制面板-程序-修复 ,(修复时间 ...

  6. 代码操作 ACCESS时为什么老出现XXX函数未定义错误?

    为什么老出现XXX函数未定义错误? 问题: 1.为什么以前运行正常的Access数据库,搬到另一台电脑上老出现XXXX函数未定义错误? 2.为什么我在Access中调试通过的sql语句,在VB/ASP ...

  7. IE浏览器下报“xxx“方法未定义错误

    IE浏览器下报"xxx"方法未定义错误 问题描述 在Chrome浏览器下正常运行,而在IE浏览器报错,外部js文件的方法未定义,js文件引入没有问题 原因 可能导致这样报错的原因有 ...

  8. 编译x86架构的openwrt系统,让笔记本从u盘启动openwrt

    2019独角兽企业重金招聘Python工程师标准>>> 下载openwrt源码,  参考:  http://blog.csdn.net/u011641885/article/deta ...

  9. linux 编译指cpu内核,linux内核编译与配置

    linux是如何组成的? 答:linux是由用户空间和内核空间组成的 为什么要划分用户空间和内核空间? 答:有关CPU体系结构,各处理器可以有多种模式,而LInux这样的划分是考虑到系统的 安全性,比 ...

最新文章

  1. python xlrd 的merged_cells 里面四个参数的含义
  2. Linux内核分析——可执行程序的装载
  3. 用PHP计算个税,PHP计算个人所得税示例【不使用速算扣除数】
  4. 单例模式和多例模式的区别(转)
  5. 在ump系统的那半个多月-jqGrid
  6. vue router 参数_Vue.js项目开发技术解析
  7. Redis 3.0.2集群搭建以及相关问题汇总
  8. Trick(十五)—— 树结构如何判断一个节点是内部节点(internal node)还是叶子节点(leaf node)
  9. php中使用PHPExcel读写excel(xls)文件的方法
  10. SAO Utils 添加白色参考线
  11. MySQL中以日期为查询条件的方法
  12. 机智云发布机智云5.0 实现物联网应用协同开发
  13. 《精通git》笔记之九(储藏与清理、签署工作、搜索)
  14. JVM调优前置知识-深堆Retained Heap和浅堆Shallow Heap
  15. ubuntu16.04对比工具Meld安装和使用
  16. python下载迅雷资源_PYTHON实现迅雷、FLASHGET、QQ旋风转真实链接、磁链转种子文件、迅雷快传链接抓取 | 学步园...
  17. Philosopher’s Walk ICPC 2017 Daejeon F dfs 分治
  18. 博客上怎么根据搜索ID搜索其它人
  19. Windows版本,OS内核版本,Windows SDK之间的关系(附 :Windows纯净系统下载以及更新)
  20. [AHU2021校内赛] ez-injection

热门文章

  1. wdcp mysql configure error_install Error: mysql configure err
  2. Ubuntu桌面不见了,桌面找回
  3. 常用的十种算法:二分查找,分治,动态规划,KMP
  4. 怎么用python读取excel图_如何用Python读取Excel中图片?
  5. Android webview和HTML的JS交互
  6. 一个转来的简单T9输入法
  7. pandas取出特定行列数据
  8. 骞云数据库DBaaS解决方案深度解析
  9. 均方误差——MSE 和标准差 的区别
  10. Flyway-数据库迁移工具