On 08/14/2017 04:04 PM, Paul Moore wrote:
> On Mon, Aug 14, 2017 at 4:57 PM, Tyler Hicks <
tyh...@canonical.com> wrote:
>> On 08/14/2017 03:53 PM, Paul Moore wrote:
>>> On Fri, Aug 11, 2017 at 4:31 PM, Tyler Hicks <
tyh...@canonical.com> wrote:
>>>> I had forgotten about an aspect of this problem. We'll want to test new
>>>> return actions in the simulated BPF tests but it won't be possible
>>>> because the seccomp(2) syscall will return ENOSYS under valgrind (under
>>>> both old and new kernels). For example, the following change breaks the
>>>> bpf-valgrind test of 06-sim-actions even when running under a kernel
>>>> that supports the new return action:
>>>>
>>>>
https://github.com/tyhicks/libseccomp/commit/2d0b7648a86a33b983d76b91055b22195887080c
>>>
>>> That's a simulated test, not a live test, why is the seccomp() syscall
>>> being called at all? I think we have a disconnect somewhere ...
>>
>> When would you expect the seccomp() syscall to be used to verify that
>> the action specified in calls to seccomp_init() or seccomp_rule_add()
>> are valid? I have it coded up to verify the action inside of those
>> libseccomp calls. Are you saying that it should be done at some later
>> point such as seccomp_load()?
>
> First, I think some clarification is in order. The only tests that
> are executed using the host kernel's seccomp mechanism are the
> tests/*-live-* tests. All of the tests/*-sim-* tests, which are the
> majority, are run through a seccomp/BPF simulator to avoid
> compatibility problems with the host kernel.
Thanks for the clarification. It matches my understanding. Now I suppose
I should try to clarify the problem that I'm trying to solve. If this
doesn't help, I think it is best to just talk through code via the PR
that I'm preparing. :)
As it stands today, libseccomp validates seccomp actions specified in
seccomp_init(3) and seccomp_rule_add(3) by checking the action against a
known-good list of actions. This is possible because these were the
actions that were available when libseccomp was initially written. Those
libseccomp calls don't have to query the kernel today and that makes it
possible for the simulated tests, which call those two libseccomp
functions, to not rely on the features available in the host kernel.
Two new actions (SECCOMP_RET_LOG, SECCOMP_RET_KILL_PROCESS) are on their
way to being merged into the kernel along with a new seccomp(2)
operation (SECCOMP_GET_ACTION_AVAIL) to validate that the kernel
supports a given action. The action validation code behind
seccomp_init(3) and seccomp_rule_add(3) will need to be changed to use
the new seccomp(2) operation to validate that the kernel supports the
action specified in the action-related parameters of those two
libseccomp functions. The logic will need to look something like this
pseudo code:
func bool db_action_valid(action):
# Is this one of the actions that were implemented from the start?
if action in [RET_KILL, RET_TRAP, RET_ERRNO, RET_TRACE, RET_ALLOW]:
return True
# This is potentially a new action, implemented after libseccomp's
# first release. Ask the kernel if the action is supported. Assume it
# is not supported if the seccomp(2) syscall isn't available.
if seccomp-syscall-is-not-available:
return False
else if seccomp(SECCOMP_GET_ACTION_AVAIL, 0, action) != 0:
return False
return True
With seccomp_init(3) and seccomp_rule_add(3) having to run actions
through this code, you can imagine how the simulated tests are no longer
decoupled from the host kernel's feature set. Their output will vary
depending on the actions that the host kernel supports.
You made the decision that the new/modified tests should pass on newer
kernels that support the new actions and that, while it isn't preferred,
they can be considered expected failures when they fail on old kernels
that don't support the new actions.
Unfortunately, that policy doesn't help with test failures induced by
valgrind. The seccomp-syscall-is-not-available conditional will always
evaluate to true in the bpf-valgrind tests because valgrind doesn't
implement wrapping of seccomp(2) and simply returns ENOSYS in all
situations (even if the host kernel implements the syscall). This means
that it is not possible to run valgrind on the simulated tests that use
new actions because seccomp_rule_add(3) will always fail when a new
action is passed to it.
> I would expect that we would have simulated tests which verify the new
> actions, as well as a live test, if the live test can be done in such
> a way that it is backwards compatible (e.g. doesn't fail/error on
> older kernels, skipping is okay).
Sounds reasonable.
Tyler