searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

containerd运行时报符号溢出错误根因分析

2024-07-31 09:49:44
58
0

containerd-shim-runc-v2程序在运行时发生了异常,stderr符号引起了R_X86_64_PC32符号表溢出,报错内容为:Symbol `stderr' causes overflow in R_X86_64_PC32 relocation。是因为程序文件containerd-shim-runc-v2内的符号表过大,导致使用-fPIE编译参数会导致符号表溢出,引起程序无法正常运行,改为-fPIC可以有效解决此问题。

问题描述:

运行打包好的docker时,发现containerd程序报错,导致容器无法正常启动运行,报错内容为:Symbol `stderr' causes overflow in R_X86_64_PC32 relocation。

根因分析:

一、故障分析

这里,上图中的报错信息,意思是containerd-shim-runc-v2程序在运行时发生了异常,stderr符号引起了R_X86_64_PC32符号表溢出,导致程序abort退出。继而引起k8s等软件无法启动用户容器,从而报错。
这里的R_X86_64_PC32符号表,其实是由-fPIE参数引入的,它的大小是受限的,当程序里的函数符号过多时,就会引起符号表溢出。并且,该符号表多用于static局部静态函数,实现快速短跳转,因为该符号表里是有直接记录了函数跳转的地址指针值。
但改为使用-fPIC编译参数后,就会在二进制文件中引入重定位表PLT表和GOT表。并且在进行某子函数的第一次函数跳转时,则是改为利用动态链接器先进行函数查找。具体为:通过PLT表拉起dynamic-loader(ld-linux.so) 来查找目标跳转函数的地址,然后再跳转到该函数里。
这两者的区别是:
1. 动态链接器的执行很复杂,所以比静态链接的情况下,程序的执行时间长;
2. 动态链接可以极大的节省二进制程序文件的 size 大小,并且没有符号表大小限制;

这里-fPIE由于符号表的限制,引起了符号表溢出,改为-fPIC采用动态链接方式执行,就能有效避免此故障。

二、官方修复方法:

检查开源打包Makefile,发现开源已修复此问题,修改方法为:

官方这里针对异常进程containerd-shim-runc-v2的修复方法为:
1. 修改-fPIE为-fPIC;
2. 修改编译参数-fstack-protector-strong为-fstack-protector-all;

官方的patch中,还修改了-fstack-protector-strong参数,改成了-fstack-protector-all。gcc在4.2版本中添加了-fstack-protector-all编译参数以支持栈保护功能,gcc4.9新增了-fstack-protector-strong编译参数让保护的范围更广。相比all参数,strong参数除了会保护函数的堆栈,还会保护函数内部定义的数组,以及对局部栈上的地址引用的保护。因为目前暂未发现有栈溢出的故障截图,应该是华为欧拉那边运行时发现了有存在栈溢出的故障,所以才调整该该编译参数得以解决栈溢出的问题。正常情况下,golang是可动态自动扩展的栈,是不会有发生栈溢出的情况的。

总结:

程序文件containerd-shim-runc-v2内的符号表过大,导致使用-fPIE编译参数会导致符号表溢出,引起程序无法正常运行,改为-fPIC可以有效解决此问题。官方的patch中,还同时修改了栈保护参数,应该是华为欧拉那边运行时发现了有存在栈溢出的故障,所以才调整该该编译参数得以解决栈溢出的问题。

 

 

 

0条评论
0 / 1000
吴****衡
1文章数
0粉丝数
吴****衡
1 文章 | 0 粉丝
吴****衡
1文章数
0粉丝数
吴****衡
1 文章 | 0 粉丝
原创

containerd运行时报符号溢出错误根因分析

2024-07-31 09:49:44
58
0

containerd-shim-runc-v2程序在运行时发生了异常,stderr符号引起了R_X86_64_PC32符号表溢出,报错内容为:Symbol `stderr' causes overflow in R_X86_64_PC32 relocation。是因为程序文件containerd-shim-runc-v2内的符号表过大,导致使用-fPIE编译参数会导致符号表溢出,引起程序无法正常运行,改为-fPIC可以有效解决此问题。

问题描述:

运行打包好的docker时,发现containerd程序报错,导致容器无法正常启动运行,报错内容为:Symbol `stderr' causes overflow in R_X86_64_PC32 relocation。

根因分析:

一、故障分析

这里,上图中的报错信息,意思是containerd-shim-runc-v2程序在运行时发生了异常,stderr符号引起了R_X86_64_PC32符号表溢出,导致程序abort退出。继而引起k8s等软件无法启动用户容器,从而报错。
这里的R_X86_64_PC32符号表,其实是由-fPIE参数引入的,它的大小是受限的,当程序里的函数符号过多时,就会引起符号表溢出。并且,该符号表多用于static局部静态函数,实现快速短跳转,因为该符号表里是有直接记录了函数跳转的地址指针值。
但改为使用-fPIC编译参数后,就会在二进制文件中引入重定位表PLT表和GOT表。并且在进行某子函数的第一次函数跳转时,则是改为利用动态链接器先进行函数查找。具体为:通过PLT表拉起dynamic-loader(ld-linux.so) 来查找目标跳转函数的地址,然后再跳转到该函数里。
这两者的区别是:
1. 动态链接器的执行很复杂,所以比静态链接的情况下,程序的执行时间长;
2. 动态链接可以极大的节省二进制程序文件的 size 大小,并且没有符号表大小限制;

这里-fPIE由于符号表的限制,引起了符号表溢出,改为-fPIC采用动态链接方式执行,就能有效避免此故障。

二、官方修复方法:

检查开源打包Makefile,发现开源已修复此问题,修改方法为:

官方这里针对异常进程containerd-shim-runc-v2的修复方法为:
1. 修改-fPIE为-fPIC;
2. 修改编译参数-fstack-protector-strong为-fstack-protector-all;

官方的patch中,还修改了-fstack-protector-strong参数,改成了-fstack-protector-all。gcc在4.2版本中添加了-fstack-protector-all编译参数以支持栈保护功能,gcc4.9新增了-fstack-protector-strong编译参数让保护的范围更广。相比all参数,strong参数除了会保护函数的堆栈,还会保护函数内部定义的数组,以及对局部栈上的地址引用的保护。因为目前暂未发现有栈溢出的故障截图,应该是华为欧拉那边运行时发现了有存在栈溢出的故障,所以才调整该该编译参数得以解决栈溢出的问题。正常情况下,golang是可动态自动扩展的栈,是不会有发生栈溢出的情况的。

总结:

程序文件containerd-shim-runc-v2内的符号表过大,导致使用-fPIE编译参数会导致符号表溢出,引起程序无法正常运行,改为-fPIC可以有效解决此问题。官方的patch中,还同时修改了栈保护参数,应该是华为欧拉那边运行时发现了有存在栈溢出的故障,所以才调整该该编译参数得以解决栈溢出的问题。

 

 

 

文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0