【运维案例】容器内执行shell结果返回值异常(centos宿主机openEuler容器)

产品:openEuler

版本:openEuler22.03 LTS

分类:云原生/容器

来源:现网

[背景及现象描述]

客户使用centos 7.9物理机和openEuler 22.03的容器执行test -x / 后echo $?,发现结果为1,而使用openEuler 22.03的宿主机和22.03的容器则结果为0,正常。

[问题根因]

由于19.03的docker seccomp中没有faccessat2系统调用白名单,seccomp直接返回错误给glibc,glibc上报错误


返回值为1的原因是:由于19.03的docker seccomp中没有faccessat2系统调用白名单,seccomp直接返回错误给glibc,glibc上报错误

客户问题:为什么同版本docker,都没有seccomp 白名单,为什么返回值不同?
原因:runc版本在1.0.0-rc93中修复了一个系统调用问题:低runc版本如果跑在高版本内核中,可能新增许多系统调用为runc低版本不支持的,为了兼容这个现象runc作出如下改动:
设置当前runc支持最大系统调用号(一般新增系统调用号是递增的),在seccomp过滤时,如果不在白名单内,会再去检查此时的系统调用号是否大于当前runc版本支持的最大系统调用号,如果大于,则认为该系统调用为新增的,返回NOSYS错误码。
在上述客户场景中,虽然seccomp白名单中没有faccessat2系统调用,但由于faccessat2系统调用号大于1.1.4版本设置的最大系统调用号,则返回NOSYS,在glibc2.34版本中,会接着调用faccessat系统调用,最终返回成功。
验证:将runc版本分别回退到此补丁与此补丁前一个补丁版本,合入此补丁的能正常返回0,前一步补丁版本的返回1。

[解决方法]

1.docker profiles/seccomp/seccomp_default.go代码中添加faccessat2系统调用白名单即可解决
2. 升级contianerd版本至1.6.8,借助高版本runc的兼容功能解决这个问题
3. 使用openEuler社区22.03版本的docker

3 Likes

老哥做什么工作的,能接触这么多有趣的栗子

目前在做运维工作哈

:+1: