sshd 在未知系统调用后断开连接

sshd 在未知系统调用后断开连接

我正在开发一个嵌入式系统(基于 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到正在运行的进程时,我得到以下输出:sshdstrace -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 沙箱受此问题影响。

要解决我的问题,我可以:

  1. 将内核更新到至少 5.1
  2. 将 glibc 降级到 2.30
  3. 修补 glibc 2.32 以省略 time64 系统调用
  4. 使用不同的沙箱编译 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

相关内容