On 02/08/2018 07:34 AM, Paul Moore wrote:
On Thu, Feb 8, 2018 at 9:26 AM, Tom Hromatka <[email protected]> wrote:
On 02/07/2018 08:30 PM, Paul Moore wrote:
On Wed, Feb 7, 2018 at 6:12 PM, Tom Hromatka <[email protected]>
wrote:
On 02/07/2018 03:17 PM, Paul Moore wrote:
* Improved performance is always good, but functional equivalency and
compatibility with the existing API/callers is another hard
requirement. I mention this because of your comments regarding
argument filtering and hybrid BPF filters, can you elaborate a bit
more on the possible solutions to ensure this works under EBPF
(including hybrid options)?
Agreed. We cannot afford to break existing seccomp users.
So this is purely theoretical, but I think it should work. We could
utilize seccomp's ability in the kernel to run multiple seccomp filters.
The first filter to run would be the EBPF filter. If it returns an
action to run, we could bail out of the for() loop in
seccomp_run_filters()
early. If not, continue running the cBPF filter(s) as usual. Existing
seccomp users wouldn't even load an EBPF filter so their behavior would
remain unchanged.
On the libseccomp side, I would expect something like this:
int sys_filter_load(struct db_filter_col *col)
{
int rc;
/* load the classic BPF filter first */
rc = sys_bpf_filter_load(col);
if (rc < 0)
return rc;
/* process the EBPF filter. note - it will only load a
* filter if it has been instructed to do so by the user.
* for classic seccomp filters this is effectively a nop
*/
rc = sys_ebpf_filter_load(col);
return rc;
}
One of the gotchas with loading multiple filters is that the first,
and all non-final, filters need to allow the syscalls necessary to
load the additional filter (I'm not 100% on EBPF, but I believe it is
still just seccomp(2)). Generally this is user/caller problem, but if
we are hiding the fact that we are loading two filters instead of one
we are going to need to do some additional work to ensure we can load
the second filter and not allow any syscalls the caller didn't intend.
You are definitely correct. The cBPF filter would have to
(at a minimum) allow __NR_seccomp and __NR_bpf. __NR_bpf is
used to create and populate the EBPF map.
If a user was especially security conscious, they would then
need to block those syscalls in the EBPF map. This is
potentially error prone and slightly cumbersome.
Yes, exactly.
It's also not backwards compatible, you need a new(er) kernel for this
to work. Like I said earlier, it might be easier to look into
improving the existing syscall sorting code in libseccomp; I believe
all the relevant code lives in src/gen_bpf.c:_gen_bpf_arch() and
should be relatively easy to play with ... much easier than the stuff
in src/db.c ;)
It can be made backward compatible if libseccomp only calls __NR_bpf and
__NR_seccomp iff the user has requested EBPF features. But I digress.
Okay, I'll dig into src/gen_bpf.c and try to improve the syscall sorting
code.
I'm intrigued by the binary tree idea. Let me know if there's anything you
would like to see added/changed.
Thanks.
Tom
It might be a better use of time and energy to look into improving
libseccomp's filter generation, e.g. Kees' comments around
sorted-trees/qsort.
--
You received this message because you are subscribed to the Google Groups
"libseccomp" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
For more options, visit https://groups.google.com/d/optout.