Closed maravtdm closed 2 years ago
Looks like we need to add a define for __NR_getrandom in privsep-linux.c
I can prepare a patch when I get back from holiday next week unless someone else can beat me to it.
This might be a byproduct of getrandom()
moving to a vDSO/vsyscall64. More information here: https://lore.kernel.org/lkml/20220729145525.1729066-1-Jason@zx2c4.com/
Hi Roy, Hi Ido,
yes, there seems to be an issue with getrandom(). Find attached some logs i captured. The 000-build-dhcpcd shows how i built it, the other next two (001 and 005) are captures of the error and finally a normal working client in 010.
To get it work, just a small sed has been used:
case "$(uname -m)" in i?86) sed -e '/Deny everything else/i SECCOMP_ALLOW(__NR_getrandom),' -i src/privsep-linux.c ;; esac
It does the patch just for i686, but that was just for testing. If applies to i686 and x86_64. I should mention that the command i used to test was
dhcpcd -B -d -4 eth0
Some of us (@lfs-book) can reproduce the issue on x86_64, but some cannot. We are not sure how to "100%" reproduce the issue, but I can tell what's happening here.
dhcpcd building system checks if <stdlib.h>
provides arc4random
function and its friends. If they are provided, dhcpcd will use it. Otherwise, dhcpcd will use an internal shipped version as fallback.
Glibc-2.36 added arc4random
into <stdlib.h>
, so dhcpcd will use the arc4random
-family functions in Glibc. Currently these functions are simple wrappers around getrandom
system call (Glibc developers have considered a pure user-space implementation, but the conclusion was there is no way to determine if the RNG should be reseeded without some information only known by the kernel). But dhcpcd's seccomp filter does not allow getrandom
, causing the crash.
sed -e '/Deny everything else/i SECCOMP_ALLOW(__NR_getrandom),' -i src/privsep-linux.c
does the job for both 32-bit x86 and x86_64.
To me use a system call allowlist (rejecting anything you unexpect) is almost always wrong in nature. We depend on external libraries (libc, at least) and we can't control what system call the library will invoke. Sometimes libc (and other libraries) invokes a system call in a manner we cannot expect. (For example, glibc invokes sysinfo
in qsort
implementation to improve performance, did you expect it? :)
If you want to use an allowlist, either (1) program everything yourself, don't use libc and invoke system calls with assembly code; (2) at least, don't kill the program if some system call you cannot expect is invoked, return ENOSYS
(via SECCOMP_RET_ERRNO
) instead. Then the libraries (if they are programmed carefully) will manage to work around the issue, just like how they are running on a relatively old kernel.
OTOH, use a denylist for some really dangerous thing (pciconfig_write
for example) is mostly OK.
To me use a system call allowlist (rejecting anything you unexpect) is almost always wrong in nature. We depend on external libraries (libc, at least) and we can't control what system call the library will invoke. Sometimes libc (and other libraries) invokes a system call in a manner we cannot expect. (For example, glibc invokes
sysinfo
inqsort
implementation to improve performance, did you expect it? :)If you want to use an allowlist, either (1) program everything yourself, don't use libc and invoke system calls with assembly code; (2) at least, don't kill the program if some system call you cannot expect is invoked, return
ENOSYS
(viaSECCOMP_RET_ERRNO
) instead. Then the libraries (if they are programmed carefully) will manage to work around the issue, just like how they are running on a relatively old kernel.OTOH, use a denylist for some really dangerous thing (
pciconfig_write
for example) is mostly OK.
This is a design issue with SECCOMP which I noted here: https://github.com/NetworkConfiguration/dhcpcd/blob/e307ec2c58d6beb0c48d34253c19eac3b9851f07/src/privsep-linux.c#L393
Sadly the capsicum port to Linux stalled.
Thank you Roy
Hi Xi,
I think you have the balance of harms wrong, or aren’t considering the real risk to security of a denylist approach.
It’s reasonable to assume your language runtime (libc) will remain stable, and use the same syscalls, and to handle exceptions as they arise. In this case, about twice a decade. Denylists defeat the purpose of the security mechanism, because nearly every syscall you miss - including newly introduced ones across every kernel/kernel version in existence - will be impossible to enumerate and often present an unreasonably large attack surface.
It’s super easy to enumerate syscalls we do use - both through static analysis and at runtime using tools like strace.
On Thu, Aug 25, 2022 at 19:40 Xi Ruoyao @.***> wrote:
To me use a system call allowlist (rejecting anything you unexpect) is almost always wrong in nature. We depends on external libraries (libc, at least) and we can't control what system call the library will invoke. Sometimes libc (and other libraries) invokes a system call in a manner we cannot expect. (For example, glibc invokes sysinfo in qsort implementation to improve performance, did you expect it? :)
If you want to use an allowlist, either (1) program everything yourself, don't use libc and invoke system calls with assembly code; (2) at least, don't kill the program if some system call you cannot expect is invoked, return ENOSYS (via SECCOMP_RET_ERRNO) instead. Then the libraries (if they are programmed carefully) will manage to work around the issue, just like how they are running on a relatively old kernel.
OTOH, use a denylist for some really dangerous thing (pciconfig_write for example) is mostly OK.
— Reply to this email directly, view it on GitHub https://github.com/NetworkConfiguration/dhcpcd/issues/120#issuecomment-1227980583, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAU4RXI3GXOFZFVMYYPSVDV3AVCTANCNFSM56VVOIBA . You are receiving this because you commented.Message ID: @.***>
On Tue, 2022-10-11 at 00:28 -0700, Ido Rosen wrote:
It’s reasonable to assume your language runtime (libc) will remain stable, and use the same syscalls
It's not only language runtime, but also other libraries.
We keep using Glibc for 20 years, but not the same version of Glibc. And "what syscall Glibc uses" is definitely not a part of its public ABI.
and to handle exceptions as they arise.
Then you should use SECCOMP_RET_ERRNO instead of SECCOMP_RETKILL{PROCESS,THREAD} or SECCOMP_RET_TRAP, to give the runtime a chance to handle the exceptions.
-- Xi Ruoyao @.***> School of Aerospace Science and Technology, Xidian University
Then you should use SECCOMP_RET_ERRNO instead of SECCOMP_RETKILL{PROCESS,THREAD} or SECCOMP_RET_TRAP, to give the runtime a chance to handle the exceptions.
If you compile dhcpcd with SECCOMP_FILTER_DEBUG then SECCOMP_RET_TRAP is used instead. https://github.com/NetworkConfiguration/dhcpcd/blob/master/src/privsep-linux.c#L143
We also install a signal handler to log a suitable diagnostic before exiting. https://github.com/NetworkConfiguration/dhcpcd/blob/master/src/privsep-linux.c#L446
If dhcpcd detects a security issue the only correct action is to exit.
Hi Roy,
OS: Slackware current glibc: 2.36 kernel : 5.19.1
I have an issue with dhcpcd ( 9.4.1 and the master branch) Attached: /var/log/messages when I restarted NetworkManager (with dhcpcd 9.99.0)
Let me know if you need anything more dhcpcd_messages.txt