-
Notifications
You must be signed in to change notification settings - Fork 187
Description
This issue came up while investigating a problem in the seccomp filters generated by snapd using libseccomp. We had a filter set up to allow calling the copy_file_range syscall provided that the sixth argument was 0. This was done through the Go binding with a condition equivalent to seccomp.MakeCondition(5, seccomp.CompareEqual, 0). The filter worked fine for some programs using the syscall, but failed for others.
Running the failing programs under strace showed that they were passing 0 as the flags argument, and the kernel wasn't complaining about the calls when not run under the filter (it will currently return EINVAL for any value of flags != 0). The underlying cause is that the sixth argument is an unsigned int, which is 32-bits wide on x86-64 systems, so the top half of the register used to pass the argument is unused, and may contain garbage data from whatever the register was previously being used for. This garbage data is seen by seccomp, so the filter program needs to know to ignore the high 32 bits of that argument.
I was able to work around this in canonical/snapd#11760 by converting the condition to seccomp.MakeCondition(5, seccomp.CompareMaskedEqual, 0xFFFFFFFF, 0), but would have been out of luck if I was using any of the other comparison operators. And while this worked, it generates a less efficient program: it's loading all 8 bytes of the argument, apply a mask, and perform 2 comparisons. Instead, it could load just 4 bytes and perform a single comparison.
One possible way to implement this in an ABI compatible fashion would be to use some high bits of enum scmp_compare to indicate that a 32-bit comparison is being requested. This would require the high half of struct scmp_arg_cmp's datum_a and datum_b fields to be clear, and to only perform the comparison against the low half of the chosen argument.
The same approach could maybe be used to add support for signed comparisons (mostly an issue for the less than/greater than comparisons).