我正在开发一个嵌入式系统(基于 Cortex-A8 CPU),运行 Linux 内核 4.19、OpenSSH_8.3p1、OpenSSL 1.1.1h、glibc 2.32,并使用 buildroot 使用 GCC 10.2 进行编译。
当客户端尝试通过 ssh 连接时,控制台会记录以下消息,并且客户端会断开连接:
[ 120.954119] audit: type=1326 audit(1599913110.890:2): auid=4294967295 uid=1001 gid=1001 ses=4294967295 pid=430 comm="sshd" exe="/usr/sbin/sshd" sig=31 arch=40000028 syscall=407 compat=0 ip=0xb6b5b080 code=0x0
[ 120.979667] audit: type=1701 audit(1599913110.910:3): auid=4294967295 uid=1001 gid=1001 ses=4294967295 pid=430 comm="sshd" exe="/usr/sbin/sshd" sig=31 res=1
添加审计包后,ausearch -i
有以下输出:
type=SECCOMP msg=audit(09/12/20 12:32:13.500:4) : auid=unset uid=sshd gid=sshd ses=unset pid=369 comm=sshd exe=/usr/sbin/sshd sig=SIGSYS arch=armeb syscall=unknown-syscall(407) compat=0 ip=0xb6b3f080 code=kill
----
type=ANOM_ABEND msg=audit(09/12/20 12:32:13.510:5) : auid=unset uid=sshd gid=sshd ses=unset pid=369 comm=sshd exe=/usr/sbin/sshd sig=SIGSYS res=yes
当我通过 running附加strace
到正在运行的进程时,我得到以下输出:sshd
strace -y -p $(pgrep sshd)
[pid 2248] write(5<socket:[8970]>, "\0\0\0\16ssh-connection\0\0\0\0", 22 <unfinished ...>
[pid 2244] read(6<socket:[8971]>, <unfinished ...>
[pid 2248] <... write resumed>) = 22
[pid 2244] <... read resumed>"\0\0\0\27", 4) = 4
[pid 2248] clock_gettime(CLOCK_BOOTTIME, <unfinished ...>
[pid 2244] read(6<socket:[8971]>, <unfinished ...>
[pid 2248] <... clock_gettime resumed>{tv_sec=1838, tv_nsec=947294512}) = 0
[pid 2244] <... read resumed>"\4\0\0\0\16ssh-connection\0\0\0\0", 23) = 23
[pid 2248] clock_nanosleep_time64(CLOCK_REALTIME, 0, {tv_sec=0, tv_nsec=22439932944646645}, <unfinished ...>
[pid 2244] poll([{fd=6<socket:[8971]>, events=POLLIN}, {fd=7<pipe:[8972]>, events=POLLIN}], 2, -1 <unfinished ...>
[pid 2248] <... clock_nanosleep_time64 resumed> <unfinished ...>) = ?
[pid 2244] <... poll resumed>) = 1 ([{fd=7, revents=POLLHUP}])
[pid 2244] read(7<pipe:[8972]>, <unfinished ...>
[pid 2248] +++ killed by SIGSYS +++
当我使用 GCC 9.3 和 glibc 2.31 构建系统时也存在此问题。
有没有办法找出这个未知的系统调用是什么?内核中是否缺少某些内容?
答案1
作为用户414777 评论,缺少的系统调用是时钟_nanosleep_time64。这最初是添加到内核中的5.6 分支作为解决方案的一部分2038 年问题,并且从 5.1 开始向后移植到每个分支。
GNU C 库在 v2.31 中开始使用这些 64 位时间函数,我在 OpenSSH 中遇到的问题在发行说明:
time 系统调用的系统调用包装器现在使用新的 time64 系统调用(如果可用)。在 32 位目标上,这些包装器尝试首先调用新的系统调用,如果不存在,则回退到旧的 32 位时间系统调用。在无法通过返回 -ENOSYS 正常处理不受支持的系统调用的环境中,这可能会导致问题。 Seccomp 沙箱受此问题影响。
要解决我的问题,我可以:
- 将内核更新到至少 5.1
- 将 glibc 降级到 2.30
- 修补 glibc 2.32 以省略 time64 系统调用
- 使用不同的沙箱编译 OpenSSH
我决定采用内核更新路径,因为这似乎是最面向未来的。
答案2
我遇到了同样的问题,并选择了 glibc 补丁方法,因为我们的客户坚持使用 4.19 LTS 内核
以下补丁修复了我的系统的此问题(glibc 2.32、linux 4.19.178、openssh 8.4p1)
diff --git a/sysdeps/unix/sysv/linux/time64-support.h b/sysdeps/unix/sysv/linux/time64-support.h
index 8466d37f8f..35bf73f5ee 100644
--- a/sysdeps/unix/sysv/linux/time64-support.h
+++ b/sysdeps/unix/sysv/linux/time64-support.h
@@ -54,6 +54,7 @@ extern int __time64_support attribute_hidden;
static inline bool
supports_time64 (void)
{
+ return false;
#ifdef __ASSUME_TIME64_SYSCALLS
return true;
#else
和
diff --git a/sysdeps/unix/sysv/linux/arm/arch-syscall.h b/sysdeps/unix/sysv/linux/arm/arch-syscall.h
index 9352319740..7b73ec2a95 100644
--- a/sysdeps/unix/sysv/linux/arm/arch-syscall.h
+++ b/sysdeps/unix/sysv/linux/arm/arch-syscall.h
@@ -29,7 +29,9 @@
#define __NR_clock_gettime 263
#define __NR_clock_gettime64 403
#define __NR_clock_nanosleep 265
+#if 0
#define __NR_clock_nanosleep_time64 407
+#endif
#define __NR_clock_settime 262
#define __NR_clock_settime64 404
#define __NR_clone 120