-
Notifications
You must be signed in to change notification settings - Fork 171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFE: consider removing negative (non-canonical) __NR_xyz defines #27
Comments
@amluto Out of curiosity, in the sandstorm issue you mentioned the following:
Other than the issue you mention here, can you explain the others? We would like to make libseccomp useful for other projects, and if it isn't it would be good to know why. |
IIRC the main issue I had was that filtering on anything other than syscall nr is very inflexible. For example, I couldn't express: Block init_module. unless I inverted it and disallowed families above the largest family number I wanted and also disallowed families in between the ones that are okay. |
@dwrensha is reporting that if he builds a binary on a system whose headers are old and don't define the __NR_blah constant for a syscall, and so instead gets libseccomp's pseudo-number, the result is that the seccomp filter does not filter the syscall. Does this seem correct? If so this seems like a serious security problem. |
Here is an example program: #include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <seccomp.h>
#include <string.h>
#include <fcntl.h>
int main() {
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW);
if (ctx == NULL) return 1;
int result = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(userfaultfd), 0);
if (result < 0) return 1;
result = seccomp_load(ctx);
if (result < 0) return 1;
long result2 = syscall(323, O_NONBLOCK); // 323 = userfaultfd() on x86_64
if (result2 >= 0) {
printf("successfully called userfaultfd()\n"); // should never happen!
} else {
printf("errno %d: %s\n", errno, strerror(errno));
}
return 0;
} I statically compiled this program on the following box:
and it gave me the following output:
There doesn't seem to be any Seccomp filtering happening, but, whatever, the syscall isn't implemented anyway. Then I copied that binary over to the following box:
and it gave me this result:
Which goes completely against my expectation. Shouldn't Seccomp block this call? |
Note that if I compile the program on radon, the box with the newer kernel, then I get
as expected. |
Just to be really clear on the problem here: This implies that binaries built on machines with older kernel headers will fail to actually filter syscalls that the code very clearly is trying to filter. This could be a problem if:
For example, there was recently a CVE in |
As a FYI, I am considering changing some of how we handle non-native ABIs in libseccomp, which is the main reason why libseccomp needs to provide its own __NR_xxx defines; hopefully we'll have something in the next release. |
Related: systemd/systemd#13319 |
Since this is starting to become more of an issue, here is one of the possible solutions I was thinking should solve this problem. We currently need
I believe this should eliminate the need for libseccomp to create it's own |
I need to think about it some more, but this sounds like it meets everyone's needs without breaking backward compatibility. Nice! |
All tests look good on my system, but I'm waiting on the Travis run to come back clean before submitting the PR. In the meantime, my proposed fix is at the link below: |
See PR #172. |
IMO __NR_xyz for syscall xyz should either match the actual kernel-assigned number or should not be defined. This code, for example, can cause confusion:
libseccomp is not the sole user of __NR_xyz defines.
Using LIBSECCOMP_xyz or sticking with __PNR_syz would be fine.
The text was updated successfully, but these errors were encountered: