[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
|
|
Subscribe / Log in / New account

Seccomp filters for multi-threaded programs

By Jonathan Corbet
May 29, 2014
The secure computing ("seccomp") mechanism helps in the sandboxing of processes by restricting access to system calls. Seccomp works by attaching one or more programs to a process; those programs, written in Berkeley packet filter (BPF) byte code, are invoked for every system call made by the affected process. The BPF filter programs have access to the system call number and arguments; each filter has the option of denying the system call. Seccomp filters can thus restrict access to specific system calls, or, for example, only allow write() to be called on specific file descriptors. This mechanism works well as far as it goes, but it was not designed for use with multi-threaded programs. A set of proposed changes should close that particular functionality gap in the near future, though.

In current kernels, a process can apply a filter program to itself with the prctl() system call:

    prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, filter);

Where filter is a pointer to a sock_fprog structure containing the BPF program to be applied. Multiple programs can be added with multiple prctl() calls; each will be executed in sequence and any can reject a system call. There is no mechanism for removing filters once they have been applied to a process. Adding filters is normally a privileged operation; otherwise there is a real risk of privilege escalation via setuid programs that do not expect some operations to be denied (see this old sendmail vulnerability for an example). But any process may set filters on itself if it has first called:

    prctl(PR_SET_NO_NEW_PRIVS, 1);

to disable the addition of any privileges to the process. In particular, a process marked as "no new privileges" cannot gain capabilities or access to a different user ID by running setuid or setgid programs.

What is lacking in the current interface is any way for a process to apply filters to a different process (or thread). There does not seem to be a use case for the ability to add filters to arbitrary processes; among other things, trying to contain a program that is already off and running would be a recipe for unpleasant race conditions. But it seems that there is value in allowing a thread to apply filters to its sibling threads. In the absence of this ability, it can be hard to ensure that a seccomp filter applies to all threads running as part of a process. Threads inherit their parent's filters when they are created, but any threads created before the filters are applied will remain uncontained. It may not always be practical to set up the filters before any threads are created, so the ability to attach them to threads after creation is a useful way to ensure that no part of a program escapes filtering.

Adding that ability is the object of this patch set from Kees Cook. All Kees really needed to do was to add an "apply this filter to all threads" flag to the PR_SET_SECCOMP operation, but, as so often seems to be the case, that operation was defined without the ability to pass in additional flags to modify its behavior. So, instead, Kees has added a new operation:

    prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_FILTER, flags, filter);

If flags is zero, this operation behaves just like the PR_SET_SECCOMP example above; it attaches filter to the calling process. But if the SECCOMP_FILTER_TSYNC flag is set, the given filter (along with any other filters already applied to the calling process) will be applied to all threads in the process's thread group, thus ensuring that all threads are running with the same set of filters.

There is one other new operation:

    prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0);

This one will apply the calling process's filters to all other threads without making any changes to the filters themselves.

In either case, other threads will only have their filtering changed if whatever filter they currently have applied is an "ancestor" of the filters running on the calling process. Essentially, any filters applied to the target thread must also have been applied to the calling thread; any thread that has a totally unrelated filter will not have its filtering changed. If a thread is not running with a filter at all, it will be put into the seccomp mode and the filters will be applied. Also, if the calling thread has the "no new privileges" mode set, that mode will be set on all other threads as well.

This is the fifth version of this patch set; the previous attempts needed work in response to locking and other issues. Unless another problem turns up, this code should be about ready for merging. There does not appear to be any opposition to the concept, so this feature could find its way into the mainline as early as 3.16.

Index entries for this article
KernelSecurity/seccomp


to post comments

Seccomp filters for multi-threaded programs

Posted May 30, 2014 15:54 UTC (Fri) by felixfix (subscriber, #242) [Link] (1 responses)

I knew nothing of SECCOMP filters before this article, so apologies if I am missing something.
But if the SECCOMP_FILTER_TSYNC flag is set, the given filter (along with any other filters already applied to the calling process) will be applied to all threads in the process's thread group, thus ensuring that all threads are running with the same set of filters.
Is there any way to apply the new filter to all threads without applying all previously applied filters? Maybe that makes no sense; maybe there is no reason to apply arbitrary subsets of filters to individual threads, or maybe it is dangerous, and applying any filter should always apply all previous filters.

Seccomp filters for multi-threaded programs

Posted May 30, 2014 17:17 UTC (Fri) by luto (subscriber, #39314) [Link]

It's both a correctness and efficiency thing.

The correctness issue is that users of sync want every other thread to end up at least as confined as the current thread.

The efficiency issue is that, internally, there's a tree of filters. Adding a filter makes a new child node. If you can share nodes between threads, you save on memory and cache impact.

Seccomp filters for multi-threaded programs

Posted Jun 2, 2014 17:34 UTC (Mon) by jhoblitt (subscriber, #77733) [Link] (1 responses)

Does using seccomp mean paying the cost of checking syscall calls twice? Once by seccomp and then again by SELinux?

Seccomp filters for multi-threaded programs

Posted Jun 2, 2014 19:47 UTC (Mon) by kees (subscriber, #27264) [Link]

LSMs (like SELinux) do not actually check syscalls. They do policy management at a higher level via the various "LSM hooks". The performance impact of the checks would add since they're in different areas of code with very different policy processing.


Copyright © 2014, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds