记录下一次欧拉容器内sudo无法使用的排查过程。
由来
实施反馈客户环境上我们部署容器内无法使用 sudo:
排查
部署容器是基于 openeuler/openeuler:22.03 制作的,之前是实施和另一个同事发现基于 ubuntu 的基础镜像制作的部署镜像内 sudo 可以使用,后面升级后又变成欧拉的,让我排查下。
权限?
远程上去后:
1 2 3
| $ docker run --rm -ti --entrypoint bash xxx $ sudo ls -l 已杀死
|
想着是不是 seccomp 之类的导致的,用特权启动下试试:
1 2 3
| $ docker run --rm -ti --privileged --entrypoint bash xxx $ sudo ls -l 已杀死
|
依旧这样,换基于 ubuntu 制作的发现没问题,但是这个欧拉镜像内无 strace 命令。
制作验证
本地制作了下基于欧拉和其他一些镜像增加 sudo 和 strace 的镜像:
1 2 3 4 5 6 7 8 9 10
| FROM openeuler/openeuler:22.03
RUN set -eux; \ sed -ri 's|://repo.openeuler.org/|://repo.huaweicloud.com/openeuler/|g' /etc/yum.repos.d/openEuler.repo; \ sed -ri 's|https://mirrors.openeuler.org|https://repo.huaweicloud.com/openeuler/|g' /etc/yum.repos.d/openEuler.repo; \ yum makecache; \ dnf install -y --setopt=install_weak_deps=False \ sudo \ strace \ ;
|
然后几个镜像构建完成后:
1
| docker save sudo:oe sudo:xxx | gzip -> sudo-docker.tar.gz
|
客户环境上导入测试:
1 2 3 4 5 6 7 8 9
| $ docker load -i sudo-docker.tar.gz $ docker run --rm -ti --entrypoint bash sudo:oe [root@71ec45b79f63 /]# sudo ls -l Killed $ docker run --rm -ti --privileged --entrypoint bash sudo:oe [root@fea66e40292f /]# sudo -V Sudo version 1.9.8p2 Configure options: --build=x86_64-openEuler-linux-gnu --host=x86_64-openEuler-linux-gnu --program-prefix= --disable-dependency-tracking --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --sysconfdir=/etc --datadir=/usr/share --includedir=/usr/include --libdir=/usr/lib64 --libexecdir=/usr/libexec --localstatedir=/var --sharedstatedir=/var/lib --mandir=/usr/share/man --infodir=/usr/share/info --prefix=/usr --sbindir=/usr/sbin --libdir=/usr/lib64 --docdir=/usr/share/doc/sudo --disable-root-mailer --disable-intercept --disable-log-server --disable-log-client --with-logging=syslog --with-logfac=authpriv --with-pam --with-pam-login --with-editor=/bin/vi --with-env-editor --with-ignore-dot --with-tty-tickets --with-ldap --with-selinux --with-passprompt=[sudo] password for %p: --with-linux-audit --with-sssd Killed
|
发现 -V 都报错,没办法了,strace 看看调用过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| [root@fea66e40292f /]# strace sudo -V .... mprotect(0x7f605d240000, 4096, PROT_READ) = 0 mprotect(0x7f605d2bf000, 4096, PROT_READ) = 0 openat(AT_FDCWD, "/proc/sys/crypto/fips_enabled", O_RDONLY) = 3 read(3, "0\n", 2) = 2 close(3) = 0 access("/etc/system-fips", F_OK) = -1 ENOENT (No such file or directory) munmap(0x7f605d5eb000, 10235) = 0 newfstatat(AT_FDCWD, "/usr/libexec/sudo/sudoers.so", {st_mode=S_IFREG|0644, st_size=525888, ...}, 0) = 0 newfstatat(AT_FDCWD, "/usr/libexec/sudo/sudoers.so", {st_mode=S_IFREG|0644, st_size=525888, ...}, 0) = 0 pipe2([3, 4], O_NONBLOCK|O_CLOEXEC) = 0 getpid() = 80 getrandom(0x7fff8e404980, 40, 0) = -1 ENOSYS (Function not implemented) gettid() = 80 getpid() = 80 tgkill(80, 80, SIGKILL) = ? +++ killed by SIGKILL +++ Killed
|
看着是 getrandom 的 syscall 报错没实现,欧拉镜像是类似 rhel 的,自带 python,用 python 调用它试试:
1 2 3 4
| [root@fea66e40292f /]# python3 -c 'import os;os.getrandom(3)' Traceback (most recent call last): File "<string>", line 1, in <module> OSError: [Errno 38] Function not implemented
|
明确是 getrandom syscall 问题,再试下 Linux shuf 随机数命令:
1 2 3 4 5 6 7
| [root@fea66e40292f /]# shuf -i 1-10 -n 1 shuf: getrandom: Function not implemented [root@fea66e40292f /]# uname -a Linux fea66e40292f 3.10.0-514.el7.x86_64 #1 SMP Tue Nov 22 16:42:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux [root@fea66e40292f /]# rpm -qa | grep glibc glibc-common-2.34-170.oe2203sp4.x86_64 glibc-2.34-170.oe2203sp4.x86_64
|
结论和验证
客户机器是 CentOS 7.3,内核 3.10.0-514.el7.x86_64 ,推测欧拉的 glibc 对 getrandom syscall 强依赖没有 fallback 回退到 openat(/dev/urandom) 机制,客户这套环境还有其他 CentOS 7.9的,上面去测试了下没问题,其他 7.3 的机器上也复现了:
1 2 3 4 5 6
| # 其他 7.9 机器上 [root@fea66e40292f /]# shuf -i 1-10 -n 1 4 # 其他 7.3 机器上 [root@fea66e40292f /]# shuf -i 1-10 -n 1 shuf: getrandom: Function not implemented
|
因为还有其他业务服务使用欧拉基础镜像,如果从 glibc 层面修改解决这个问题成本太大了:
- 客户现场要针对每个容器镜像单独更新下 glibc
- 后续我们也要维护一份 glibc 代码编译成欧拉的 rpm 包
让客户使用 CentOS 7.9 的最稳妥,同时该问题已经反馈给欧拉仓库 https://atomgit.com/openeuler/openeuler-docker-images/issues/60