Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-06-03 Thread Kees Cook
On Mon, Jun 2, 2014 at 6:15 PM, Andy Lutomirski  wrote:
> On Mon, Jun 2, 2014 at 6:09 PM, Kees Cook  wrote:
>> On Mon, Jun 2, 2014 at 5:29 PM, Andy Lutomirski  wrote:
>>> On Mon, Jun 2, 2014 at 5:14 PM, Kees Cook  wrote:
 On Mon, Jun 2, 2014 at 1:53 PM, Andy Lutomirski  
 wrote:
> On Tue, May 27, 2014 at 12:55 PM, Kees Cook  wrote:
>> On Tue, May 27, 2014 at 12:27 PM, Andy Lutomirski  
>> wrote:
>>> On Tue, May 27, 2014 at 12:23 PM, Kees Cook  
>>> wrote:
 On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski 
  wrote:
> On Tue, May 27, 2014 at 11:45 AM, Kees Cook  
> wrote:
>> On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski 
>>  wrote:
>>> On Tue, May 27, 2014 at 11:24 AM, Kees Cook  
>>> wrote:
 On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski 
  wrote:
> On Fri, May 23, 2014 at 10:05 AM, Kees Cook 
>  wrote:
>> On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski 
>>  wrote:
>>> On Thu, May 22, 2014 at 4:05 PM, Kees Cook 
>>>  wrote:
 Applying restrictive seccomp filter programs to large or 
 diverse
 codebases often requires handling threads which may be started 
 early in
 the process lifetime (e.g., by code that is linked in). While 
 it is
 possible to apply permissive programs prior to process start 
 up, it is
 difficult to further restrict the kernel ABI to those threads 
 after that
 point.

 This change adds a new seccomp extension action for 
 synchronizing thread
 group seccomp filters and a prctl() for accessing that 
 functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync 
 at filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
 SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or 
 when calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 
 0, 0), it
 will attempt to synchronize all threads in current's 
 threadgroup to its
 seccomp filter program. This is possible iff all threads are 
 using a filter
 that is an ancestor to the filter current is attempting to 
 synchronize to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) 
 are also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has 
 been set on the
 calling thread, no_new_privs will be set for all synchronized 
 threads too.
 On success, 0 is returned. On failure, the pid of one of the 
 failing threads
 will be returned, with as many filters installed as possible.
>>>
>>> Is there a use case for adding a filter and synchronizing 
>>> filters
>>> being separate operations?  If not, I think this would be 
>>> easier to
>>> understand and to use if there was just a single operation.
>>
>> Yes: if the other thread's lifetime is not well controlled, it's 
>> good
>> to be able to have a distinct interface to retry the thread sync 
>> that
>> doesn't require adding "no-op" filters.
>
> Wouldn't this still be solved by:
>
> seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);
>
> the idea would be that, if seccomp_add_filter fails, then you 
> give up
> and, if it succeeds, then you're done.  It shouldn't fail unless 
> out
> of memory or you've nested too deeply.

 I wanted to keep the case of being able to to wait for non-ancestor
 threads to finish. For example, 2 threads start and set separate
 filters. 1 does work and exits, 2 starts another thread (3) which 
 adds
 filters, does work, and then waits for 1 to finish by calling 
 TSYNC.
 Once 1 dies, TSYNC succeeds. In the case of not having direct 
 control
 over thread lifetime (say, when using third-party libraries), I'd 
 like
 to retain the flexibility of being able to do TSYNC without 
 needing a
 filter being attached 

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-06-03 Thread Kees Cook
On Mon, Jun 2, 2014 at 6:15 PM, Andy Lutomirski l...@amacapital.net wrote:
 On Mon, Jun 2, 2014 at 6:09 PM, Kees Cook keesc...@chromium.org wrote:
 On Mon, Jun 2, 2014 at 5:29 PM, Andy Lutomirski l...@amacapital.net wrote:
 On Mon, Jun 2, 2014 at 5:14 PM, Kees Cook keesc...@chromium.org wrote:
 On Mon, Jun 2, 2014 at 1:53 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 12:55 PM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 12:27 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 12:23 PM, Kees Cook keesc...@chromium.org 
 wrote:
 On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski 
 l...@amacapital.net wrote:
 On Tue, May 27, 2014 at 11:45 AM, Kees Cook keesc...@chromium.org 
 wrote:
 On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski 
 l...@amacapital.net wrote:
 On Tue, May 27, 2014 at 11:24 AM, Kees Cook keesc...@chromium.org 
 wrote:
 On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski 
 l...@amacapital.net wrote:
 On Fri, May 23, 2014 at 10:05 AM, Kees Cook 
 keesc...@chromium.org wrote:
 On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski 
 l...@amacapital.net wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook 
 keesc...@chromium.org wrote:
 Applying restrictive seccomp filter programs to large or 
 diverse
 codebases often requires handling threads which may be started 
 early in
 the process lifetime (e.g., by code that is linked in). While 
 it is
 possible to apply permissive programs prior to process start 
 up, it is
 difficult to further restrict the kernel ABI to those threads 
 after that
 point.

 This change adds a new seccomp extension action for 
 synchronizing thread
 group seccomp filters and a prctl() for accessing that 
 functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync 
 at filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
 SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or 
 when calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 
 0, 0), it
 will attempt to synchronize all threads in current's 
 threadgroup to its
 seccomp filter program. This is possible iff all threads are 
 using a filter
 that is an ancestor to the filter current is attempting to 
 synchronize to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) 
 are also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has 
 been set on the
 calling thread, no_new_privs will be set for all synchronized 
 threads too.
 On success, 0 is returned. On failure, the pid of one of the 
 failing threads
 will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing 
 filters
 being separate operations?  If not, I think this would be 
 easier to
 understand and to use if there was just a single operation.

 Yes: if the other thread's lifetime is not well controlled, it's 
 good
 to be able to have a distinct interface to retry the thread sync 
 that
 doesn't require adding no-op filters.

 Wouldn't this still be solved by:

 seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

 the idea would be that, if seccomp_add_filter fails, then you 
 give up
 and, if it succeeds, then you're done.  It shouldn't fail unless 
 out
 of memory or you've nested too deeply.

 I wanted to keep the case of being able to to wait for non-ancestor
 threads to finish. For example, 2 threads start and set separate
 filters. 1 does work and exits, 2 starts another thread (3) which 
 adds
 filters, does work, and then waits for 1 to finish by calling 
 TSYNC.
 Once 1 dies, TSYNC succeeds. In the case of not having direct 
 control
 over thread lifetime (say, when using third-party libraries), I'd 
 like
 to retain the flexibility of being able to do TSYNC without 
 needing a
 filter being attached to it.

 I must admit this strikes me as odd.  What's the point of having a
 thread set a filter if it intends to be a short-lived thread?

 I was illustrating the potential insanity of third-party libraries.
 There isn't much sense in that behavior, but if it exists, working
 around it is harder without the separate TSYNC-only call.

 In any case, I must have missed the ability for TSYNC to block.  
 Hmm.
 That seems complicated, albeit potentially useful.

 Oh, no, I didn't mean to imply TSYNC should block. I meant that 
 thread
 3 could do:

 while (TSYNC-fails)
wait-on-or-kill-unexpected-thread


 Ok.

 I'm still not seeing the need for a separate TSYNC option, though --
 just add-a-filter-across-all-threads would work if it failed
 harmlessly on error.  FWIW, TSYNC is probably equivalent to adding an
 always-accept filter across all threads, although no one should really
 do the latter for efficiency reasons.

 Given the complexity of the locking, fail means I applied the
 change to all threads except for at least this one: *error 

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-06-02 Thread Andy Lutomirski
On Mon, Jun 2, 2014 at 6:09 PM, Kees Cook  wrote:
> On Mon, Jun 2, 2014 at 5:29 PM, Andy Lutomirski  wrote:
>> On Mon, Jun 2, 2014 at 5:14 PM, Kees Cook  wrote:
>>> On Mon, Jun 2, 2014 at 1:53 PM, Andy Lutomirski  wrote:
 On Tue, May 27, 2014 at 12:55 PM, Kees Cook  wrote:
> On Tue, May 27, 2014 at 12:27 PM, Andy Lutomirski  
> wrote:
>> On Tue, May 27, 2014 at 12:23 PM, Kees Cook  
>> wrote:
>>> On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski  
>>> wrote:
 On Tue, May 27, 2014 at 11:45 AM, Kees Cook  
 wrote:
> On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski 
>  wrote:
>> On Tue, May 27, 2014 at 11:24 AM, Kees Cook  
>> wrote:
>>> On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski 
>>>  wrote:
 On Fri, May 23, 2014 at 10:05 AM, Kees Cook 
  wrote:
> On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski 
>  wrote:
>> On Thu, May 22, 2014 at 4:05 PM, Kees Cook 
>>  wrote:
>>> Applying restrictive seccomp filter programs to large or diverse
>>> codebases often requires handling threads which may be started 
>>> early in
>>> the process lifetime (e.g., by code that is linked in). While 
>>> it is
>>> possible to apply permissive programs prior to process start 
>>> up, it is
>>> difficult to further restrict the kernel ABI to those threads 
>>> after that
>>> point.
>>>
>>> This change adds a new seccomp extension action for 
>>> synchronizing thread
>>> group seccomp filters and a prctl() for accessing that 
>>> functionality,
>>> as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at 
>>> filter
>>> installation time.
>>>
>>> When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
>>> SECCOMP_EXT_ACT_FILTER,
>>> flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or 
>>> when calling
>>> prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 
>>> 0, 0), it
>>> will attempt to synchronize all threads in current's 
>>> threadgroup to its
>>> seccomp filter program. This is possible iff all threads are 
>>> using a filter
>>> that is an ancestor to the filter current is attempting to 
>>> synchronize to.
>>> NULL filters (where the task is running as SECCOMP_MODE_NONE) 
>>> are also
>>> treated as ancestors allowing threads to be transitioned into
>>> SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has 
>>> been set on the
>>> calling thread, no_new_privs will be set for all synchronized 
>>> threads too.
>>> On success, 0 is returned. On failure, the pid of one of the 
>>> failing threads
>>> will be returned, with as many filters installed as possible.
>>
>> Is there a use case for adding a filter and synchronizing filters
>> being separate operations?  If not, I think this would be easier 
>> to
>> understand and to use if there was just a single operation.
>
> Yes: if the other thread's lifetime is not well controlled, it's 
> good
> to be able to have a distinct interface to retry the thread sync 
> that
> doesn't require adding "no-op" filters.

 Wouldn't this still be solved by:

 seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

 the idea would be that, if seccomp_add_filter fails, then you give 
 up
 and, if it succeeds, then you're done.  It shouldn't fail unless 
 out
 of memory or you've nested too deeply.
>>>
>>> I wanted to keep the case of being able to to wait for non-ancestor
>>> threads to finish. For example, 2 threads start and set separate
>>> filters. 1 does work and exits, 2 starts another thread (3) which 
>>> adds
>>> filters, does work, and then waits for 1 to finish by calling TSYNC.
>>> Once 1 dies, TSYNC succeeds. In the case of not having direct 
>>> control
>>> over thread lifetime (say, when using third-party libraries), I'd 
>>> like
>>> to retain the flexibility of being able to do TSYNC without needing 
>>> a
>>> filter being attached to it.
>>
>> I must admit this strikes me as odd.  What's the point of having a
>> thread set a filter if it intends to be a short-lived thread?
>
> I was illustrating the 

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-06-02 Thread Kees Cook
On Mon, Jun 2, 2014 at 5:29 PM, Andy Lutomirski  wrote:
> On Mon, Jun 2, 2014 at 5:14 PM, Kees Cook  wrote:
>> On Mon, Jun 2, 2014 at 1:53 PM, Andy Lutomirski  wrote:
>>> On Tue, May 27, 2014 at 12:55 PM, Kees Cook  wrote:
 On Tue, May 27, 2014 at 12:27 PM, Andy Lutomirski  
 wrote:
> On Tue, May 27, 2014 at 12:23 PM, Kees Cook  wrote:
>> On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski  
>> wrote:
>>> On Tue, May 27, 2014 at 11:45 AM, Kees Cook  
>>> wrote:
 On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski 
  wrote:
> On Tue, May 27, 2014 at 11:24 AM, Kees Cook  
> wrote:
>> On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski 
>>  wrote:
>>> On Fri, May 23, 2014 at 10:05 AM, Kees Cook  
>>> wrote:
 On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski 
  wrote:
> On Thu, May 22, 2014 at 4:05 PM, Kees Cook 
>  wrote:
>> Applying restrictive seccomp filter programs to large or diverse
>> codebases often requires handling threads which may be started 
>> early in
>> the process lifetime (e.g., by code that is linked in). While it 
>> is
>> possible to apply permissive programs prior to process start up, 
>> it is
>> difficult to further restrict the kernel ABI to those threads 
>> after that
>> point.
>>
>> This change adds a new seccomp extension action for 
>> synchronizing thread
>> group seccomp filters and a prctl() for accessing that 
>> functionality,
>> as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at 
>> filter
>> installation time.
>>
>> When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
>> SECCOMP_EXT_ACT_FILTER,
>> flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or 
>> when calling
>> prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 
>> 0), it
>> will attempt to synchronize all threads in current's threadgroup 
>> to its
>> seccomp filter program. This is possible iff all threads are 
>> using a filter
>> that is an ancestor to the filter current is attempting to 
>> synchronize to.
>> NULL filters (where the task is running as SECCOMP_MODE_NONE) 
>> are also
>> treated as ancestors allowing threads to be transitioned into
>> SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has 
>> been set on the
>> calling thread, no_new_privs will be set for all synchronized 
>> threads too.
>> On success, 0 is returned. On failure, the pid of one of the 
>> failing threads
>> will be returned, with as many filters installed as possible.
>
> Is there a use case for adding a filter and synchronizing filters
> being separate operations?  If not, I think this would be easier 
> to
> understand and to use if there was just a single operation.

 Yes: if the other thread's lifetime is not well controlled, it's 
 good
 to be able to have a distinct interface to retry the thread sync 
 that
 doesn't require adding "no-op" filters.
>>>
>>> Wouldn't this still be solved by:
>>>
>>> seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);
>>>
>>> the idea would be that, if seccomp_add_filter fails, then you give 
>>> up
>>> and, if it succeeds, then you're done.  It shouldn't fail unless out
>>> of memory or you've nested too deeply.
>>
>> I wanted to keep the case of being able to to wait for non-ancestor
>> threads to finish. For example, 2 threads start and set separate
>> filters. 1 does work and exits, 2 starts another thread (3) which 
>> adds
>> filters, does work, and then waits for 1 to finish by calling TSYNC.
>> Once 1 dies, TSYNC succeeds. In the case of not having direct control
>> over thread lifetime (say, when using third-party libraries), I'd 
>> like
>> to retain the flexibility of being able to do TSYNC without needing a
>> filter being attached to it.
>
> I must admit this strikes me as odd.  What's the point of having a
> thread set a filter if it intends to be a short-lived thread?

 I was illustrating the potential insanity of third-party libraries.
 There isn't much sense in that behavior, but if it exists, working
 around it is harder without the separate TSYNC-only call.


Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-06-02 Thread Andy Lutomirski
On Mon, Jun 2, 2014 at 5:14 PM, Kees Cook  wrote:
> On Mon, Jun 2, 2014 at 1:53 PM, Andy Lutomirski  wrote:
>> On Tue, May 27, 2014 at 12:55 PM, Kees Cook  wrote:
>>> On Tue, May 27, 2014 at 12:27 PM, Andy Lutomirski  
>>> wrote:
 On Tue, May 27, 2014 at 12:23 PM, Kees Cook  wrote:
> On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski  
> wrote:
>> On Tue, May 27, 2014 at 11:45 AM, Kees Cook  
>> wrote:
>>> On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski  
>>> wrote:
 On Tue, May 27, 2014 at 11:24 AM, Kees Cook  
 wrote:
> On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski 
>  wrote:
>> On Fri, May 23, 2014 at 10:05 AM, Kees Cook  
>> wrote:
>>> On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski 
>>>  wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook  
 wrote:
> Applying restrictive seccomp filter programs to large or diverse
> codebases often requires handling threads which may be started 
> early in
> the process lifetime (e.g., by code that is linked in). While it 
> is
> possible to apply permissive programs prior to process start up, 
> it is
> difficult to further restrict the kernel ABI to those threads 
> after that
> point.
>
> This change adds a new seccomp extension action for synchronizing 
> thread
> group seccomp filters and a prctl() for accessing that 
> functionality,
> as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at 
> filter
> installation time.
>
> When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
> SECCOMP_EXT_ACT_FILTER,
> flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or 
> when calling
> prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 
> 0), it
> will attempt to synchronize all threads in current's threadgroup 
> to its
> seccomp filter program. This is possible iff all threads are 
> using a filter
> that is an ancestor to the filter current is attempting to 
> synchronize to.
> NULL filters (where the task is running as SECCOMP_MODE_NONE) are 
> also
> treated as ancestors allowing threads to be transitioned into
> SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been 
> set on the
> calling thread, no_new_privs will be set for all synchronized 
> threads too.
> On success, 0 is returned. On failure, the pid of one of the 
> failing threads
> will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing filters
 being separate operations?  If not, I think this would be easier to
 understand and to use if there was just a single operation.
>>>
>>> Yes: if the other thread's lifetime is not well controlled, it's 
>>> good
>>> to be able to have a distinct interface to retry the thread sync 
>>> that
>>> doesn't require adding "no-op" filters.
>>
>> Wouldn't this still be solved by:
>>
>> seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);
>>
>> the idea would be that, if seccomp_add_filter fails, then you give up
>> and, if it succeeds, then you're done.  It shouldn't fail unless out
>> of memory or you've nested too deeply.
>
> I wanted to keep the case of being able to to wait for non-ancestor
> threads to finish. For example, 2 threads start and set separate
> filters. 1 does work and exits, 2 starts another thread (3) which adds
> filters, does work, and then waits for 1 to finish by calling TSYNC.
> Once 1 dies, TSYNC succeeds. In the case of not having direct control
> over thread lifetime (say, when using third-party libraries), I'd like
> to retain the flexibility of being able to do TSYNC without needing a
> filter being attached to it.

 I must admit this strikes me as odd.  What's the point of having a
 thread set a filter if it intends to be a short-lived thread?
>>>
>>> I was illustrating the potential insanity of third-party libraries.
>>> There isn't much sense in that behavior, but if it exists, working
>>> around it is harder without the separate TSYNC-only call.
>>>
 In any case, I must have missed the ability for TSYNC to block.  Hmm.
 That seems complicated, albeit potentially useful.
>>>
>>> Oh, no, I didn't mean to imply TSYNC should block. I 

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-06-02 Thread Kees Cook
On Mon, Jun 2, 2014 at 1:53 PM, Andy Lutomirski  wrote:
> On Tue, May 27, 2014 at 12:55 PM, Kees Cook  wrote:
>> On Tue, May 27, 2014 at 12:27 PM, Andy Lutomirski  
>> wrote:
>>> On Tue, May 27, 2014 at 12:23 PM, Kees Cook  wrote:
 On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski  
 wrote:
> On Tue, May 27, 2014 at 11:45 AM, Kees Cook  wrote:
>> On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski  
>> wrote:
>>> On Tue, May 27, 2014 at 11:24 AM, Kees Cook  
>>> wrote:
 On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski 
  wrote:
> On Fri, May 23, 2014 at 10:05 AM, Kees Cook  
> wrote:
>> On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski 
>>  wrote:
>>> On Thu, May 22, 2014 at 4:05 PM, Kees Cook  
>>> wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started 
 early in
 the process lifetime (e.g., by code that is linked in). While it is
 possible to apply permissive programs prior to process start up, 
 it is
 difficult to further restrict the kernel ABI to those threads 
 after that
 point.

 This change adds a new seccomp extension action for synchronizing 
 thread
 group seccomp filters and a prctl() for accessing that 
 functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at 
 filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
 SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when 
 calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 
 0), it
 will attempt to synchronize all threads in current's threadgroup 
 to its
 seccomp filter program. This is possible iff all threads are using 
 a filter
 that is an ancestor to the filter current is attempting to 
 synchronize to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) are 
 also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been 
 set on the
 calling thread, no_new_privs will be set for all synchronized 
 threads too.
 On success, 0 is returned. On failure, the pid of one of the 
 failing threads
 will be returned, with as many filters installed as possible.
>>>
>>> Is there a use case for adding a filter and synchronizing filters
>>> being separate operations?  If not, I think this would be easier to
>>> understand and to use if there was just a single operation.
>>
>> Yes: if the other thread's lifetime is not well controlled, it's good
>> to be able to have a distinct interface to retry the thread sync that
>> doesn't require adding "no-op" filters.
>
> Wouldn't this still be solved by:
>
> seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);
>
> the idea would be that, if seccomp_add_filter fails, then you give up
> and, if it succeeds, then you're done.  It shouldn't fail unless out
> of memory or you've nested too deeply.

 I wanted to keep the case of being able to to wait for non-ancestor
 threads to finish. For example, 2 threads start and set separate
 filters. 1 does work and exits, 2 starts another thread (3) which adds
 filters, does work, and then waits for 1 to finish by calling TSYNC.
 Once 1 dies, TSYNC succeeds. In the case of not having direct control
 over thread lifetime (say, when using third-party libraries), I'd like
 to retain the flexibility of being able to do TSYNC without needing a
 filter being attached to it.
>>>
>>> I must admit this strikes me as odd.  What's the point of having a
>>> thread set a filter if it intends to be a short-lived thread?
>>
>> I was illustrating the potential insanity of third-party libraries.
>> There isn't much sense in that behavior, but if it exists, working
>> around it is harder without the separate TSYNC-only call.
>>
>>> In any case, I must have missed the ability for TSYNC to block.  Hmm.
>>> That seems complicated, albeit potentially useful.
>>
>> Oh, no, I didn't mean to imply TSYNC should block. I meant that thread
>> 3 could do:
>>
>> while (TSYNC-fails)
>>wait-on-or-kill-unexpected-thread
>>
>
> Ok.
>
> I'm still not seeing the need for a separate 

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-06-02 Thread Andy Lutomirski
On Tue, May 27, 2014 at 12:55 PM, Kees Cook  wrote:
> On Tue, May 27, 2014 at 12:27 PM, Andy Lutomirski  wrote:
>> On Tue, May 27, 2014 at 12:23 PM, Kees Cook  wrote:
>>> On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski  
>>> wrote:
 On Tue, May 27, 2014 at 11:45 AM, Kees Cook  wrote:
> On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski  
> wrote:
>> On Tue, May 27, 2014 at 11:24 AM, Kees Cook  
>> wrote:
>>> On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski  
>>> wrote:
 On Fri, May 23, 2014 at 10:05 AM, Kees Cook  
 wrote:
> On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski 
>  wrote:
>> On Thu, May 22, 2014 at 4:05 PM, Kees Cook  
>> wrote:
>>> Applying restrictive seccomp filter programs to large or diverse
>>> codebases often requires handling threads which may be started 
>>> early in
>>> the process lifetime (e.g., by code that is linked in). While it is
>>> possible to apply permissive programs prior to process start up, it 
>>> is
>>> difficult to further restrict the kernel ABI to those threads after 
>>> that
>>> point.
>>>
>>> This change adds a new seccomp extension action for synchronizing 
>>> thread
>>> group seccomp filters and a prctl() for accessing that 
>>> functionality,
>>> as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at 
>>> filter
>>> installation time.
>>>
>>> When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
>>> SECCOMP_EXT_ACT_FILTER,
>>> flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when 
>>> calling
>>> prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 
>>> 0), it
>>> will attempt to synchronize all threads in current's threadgroup to 
>>> its
>>> seccomp filter program. This is possible iff all threads are using 
>>> a filter
>>> that is an ancestor to the filter current is attempting to 
>>> synchronize to.
>>> NULL filters (where the task is running as SECCOMP_MODE_NONE) are 
>>> also
>>> treated as ancestors allowing threads to be transitioned into
>>> SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been 
>>> set on the
>>> calling thread, no_new_privs will be set for all synchronized 
>>> threads too.
>>> On success, 0 is returned. On failure, the pid of one of the 
>>> failing threads
>>> will be returned, with as many filters installed as possible.
>>
>> Is there a use case for adding a filter and synchronizing filters
>> being separate operations?  If not, I think this would be easier to
>> understand and to use if there was just a single operation.
>
> Yes: if the other thread's lifetime is not well controlled, it's good
> to be able to have a distinct interface to retry the thread sync that
> doesn't require adding "no-op" filters.

 Wouldn't this still be solved by:

 seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

 the idea would be that, if seccomp_add_filter fails, then you give up
 and, if it succeeds, then you're done.  It shouldn't fail unless out
 of memory or you've nested too deeply.
>>>
>>> I wanted to keep the case of being able to to wait for non-ancestor
>>> threads to finish. For example, 2 threads start and set separate
>>> filters. 1 does work and exits, 2 starts another thread (3) which adds
>>> filters, does work, and then waits for 1 to finish by calling TSYNC.
>>> Once 1 dies, TSYNC succeeds. In the case of not having direct control
>>> over thread lifetime (say, when using third-party libraries), I'd like
>>> to retain the flexibility of being able to do TSYNC without needing a
>>> filter being attached to it.
>>
>> I must admit this strikes me as odd.  What's the point of having a
>> thread set a filter if it intends to be a short-lived thread?
>
> I was illustrating the potential insanity of third-party libraries.
> There isn't much sense in that behavior, but if it exists, working
> around it is harder without the separate TSYNC-only call.
>
>> In any case, I must have missed the ability for TSYNC to block.  Hmm.
>> That seems complicated, albeit potentially useful.
>
> Oh, no, I didn't mean to imply TSYNC should block. I meant that thread
> 3 could do:
>
> while (TSYNC-fails)
>wait-on-or-kill-unexpected-thread
>

 Ok.

 I'm still not seeing the need for a separate TSYNC option, though --
 just add-a-filter-across-all-threads would work if it failed
 harmlessly on error.  FWIW, TSYNC is probably equivalent to adding an

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-06-02 Thread Andy Lutomirski
On Tue, May 27, 2014 at 12:55 PM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 12:27 PM, Andy Lutomirski l...@amacapital.net wrote:
 On Tue, May 27, 2014 at 12:23 PM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 11:45 AM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 11:24 AM, Kees Cook keesc...@chromium.org 
 wrote:
 On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Fri, May 23, 2014 at 10:05 AM, Kees Cook keesc...@chromium.org 
 wrote:
 On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski 
 l...@amacapital.net wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook keesc...@chromium.org 
 wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started 
 early in
 the process lifetime (e.g., by code that is linked in). While it is
 possible to apply permissive programs prior to process start up, it 
 is
 difficult to further restrict the kernel ABI to those threads after 
 that
 point.

 This change adds a new seccomp extension action for synchronizing 
 thread
 group seccomp filters and a prctl() for accessing that 
 functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at 
 filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
 SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when 
 calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 
 0), it
 will attempt to synchronize all threads in current's threadgroup to 
 its
 seccomp filter program. This is possible iff all threads are using 
 a filter
 that is an ancestor to the filter current is attempting to 
 synchronize to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) are 
 also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been 
 set on the
 calling thread, no_new_privs will be set for all synchronized 
 threads too.
 On success, 0 is returned. On failure, the pid of one of the 
 failing threads
 will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing filters
 being separate operations?  If not, I think this would be easier to
 understand and to use if there was just a single operation.

 Yes: if the other thread's lifetime is not well controlled, it's good
 to be able to have a distinct interface to retry the thread sync that
 doesn't require adding no-op filters.

 Wouldn't this still be solved by:

 seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

 the idea would be that, if seccomp_add_filter fails, then you give up
 and, if it succeeds, then you're done.  It shouldn't fail unless out
 of memory or you've nested too deeply.

 I wanted to keep the case of being able to to wait for non-ancestor
 threads to finish. For example, 2 threads start and set separate
 filters. 1 does work and exits, 2 starts another thread (3) which adds
 filters, does work, and then waits for 1 to finish by calling TSYNC.
 Once 1 dies, TSYNC succeeds. In the case of not having direct control
 over thread lifetime (say, when using third-party libraries), I'd like
 to retain the flexibility of being able to do TSYNC without needing a
 filter being attached to it.

 I must admit this strikes me as odd.  What's the point of having a
 thread set a filter if it intends to be a short-lived thread?

 I was illustrating the potential insanity of third-party libraries.
 There isn't much sense in that behavior, but if it exists, working
 around it is harder without the separate TSYNC-only call.

 In any case, I must have missed the ability for TSYNC to block.  Hmm.
 That seems complicated, albeit potentially useful.

 Oh, no, I didn't mean to imply TSYNC should block. I meant that thread
 3 could do:

 while (TSYNC-fails)
wait-on-or-kill-unexpected-thread


 Ok.

 I'm still not seeing the need for a separate TSYNC option, though --
 just add-a-filter-across-all-threads would work if it failed
 harmlessly on error.  FWIW, TSYNC is probably equivalent to adding an
 always-accept filter across all threads, although no one should really
 do the latter for efficiency reasons.

 Given the complexity of the locking, fail means I applied the
 change to all threads except for at least this one: *error code*,
 which means looping with the add-a-filter method means all the other
 threads keep getting filters added until there is full success. I
 don't want that overhead, so this keeps TSYNC distinctly separate.

 Ugh, right.


 Because of the filter addition, when using add_filter-TSYNC, it's not
 sensible to continue after a failure. However, using just-TSYNC allows
 sensible re-trying. Since the 

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-06-02 Thread Kees Cook
On Mon, Jun 2, 2014 at 1:53 PM, Andy Lutomirski l...@amacapital.net wrote:
 On Tue, May 27, 2014 at 12:55 PM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 12:27 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 12:23 PM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 11:45 AM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 11:24 AM, Kees Cook keesc...@chromium.org 
 wrote:
 On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski 
 l...@amacapital.net wrote:
 On Fri, May 23, 2014 at 10:05 AM, Kees Cook keesc...@chromium.org 
 wrote:
 On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski 
 l...@amacapital.net wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook keesc...@chromium.org 
 wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started 
 early in
 the process lifetime (e.g., by code that is linked in). While it is
 possible to apply permissive programs prior to process start up, 
 it is
 difficult to further restrict the kernel ABI to those threads 
 after that
 point.

 This change adds a new seccomp extension action for synchronizing 
 thread
 group seccomp filters and a prctl() for accessing that 
 functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at 
 filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
 SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when 
 calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 
 0), it
 will attempt to synchronize all threads in current's threadgroup 
 to its
 seccomp filter program. This is possible iff all threads are using 
 a filter
 that is an ancestor to the filter current is attempting to 
 synchronize to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) are 
 also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been 
 set on the
 calling thread, no_new_privs will be set for all synchronized 
 threads too.
 On success, 0 is returned. On failure, the pid of one of the 
 failing threads
 will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing filters
 being separate operations?  If not, I think this would be easier to
 understand and to use if there was just a single operation.

 Yes: if the other thread's lifetime is not well controlled, it's good
 to be able to have a distinct interface to retry the thread sync that
 doesn't require adding no-op filters.

 Wouldn't this still be solved by:

 seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

 the idea would be that, if seccomp_add_filter fails, then you give up
 and, if it succeeds, then you're done.  It shouldn't fail unless out
 of memory or you've nested too deeply.

 I wanted to keep the case of being able to to wait for non-ancestor
 threads to finish. For example, 2 threads start and set separate
 filters. 1 does work and exits, 2 starts another thread (3) which adds
 filters, does work, and then waits for 1 to finish by calling TSYNC.
 Once 1 dies, TSYNC succeeds. In the case of not having direct control
 over thread lifetime (say, when using third-party libraries), I'd like
 to retain the flexibility of being able to do TSYNC without needing a
 filter being attached to it.

 I must admit this strikes me as odd.  What's the point of having a
 thread set a filter if it intends to be a short-lived thread?

 I was illustrating the potential insanity of third-party libraries.
 There isn't much sense in that behavior, but if it exists, working
 around it is harder without the separate TSYNC-only call.

 In any case, I must have missed the ability for TSYNC to block.  Hmm.
 That seems complicated, albeit potentially useful.

 Oh, no, I didn't mean to imply TSYNC should block. I meant that thread
 3 could do:

 while (TSYNC-fails)
wait-on-or-kill-unexpected-thread


 Ok.

 I'm still not seeing the need for a separate TSYNC option, though --
 just add-a-filter-across-all-threads would work if it failed
 harmlessly on error.  FWIW, TSYNC is probably equivalent to adding an
 always-accept filter across all threads, although no one should really
 do the latter for efficiency reasons.

 Given the complexity of the locking, fail means I applied the
 change to all threads except for at least this one: *error code*,
 which means looping with the add-a-filter method means all the other
 threads keep getting filters added until there is full success. I
 don't want that overhead, so this keeps TSYNC distinctly separate.

 Ugh, right.


 Because of the filter addition, when using add_filter-TSYNC, it's not
 sensible to continue after a 

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-06-02 Thread Andy Lutomirski
On Mon, Jun 2, 2014 at 5:14 PM, Kees Cook keesc...@chromium.org wrote:
 On Mon, Jun 2, 2014 at 1:53 PM, Andy Lutomirski l...@amacapital.net wrote:
 On Tue, May 27, 2014 at 12:55 PM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 12:27 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 12:23 PM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 11:45 AM, Kees Cook keesc...@chromium.org 
 wrote:
 On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 11:24 AM, Kees Cook keesc...@chromium.org 
 wrote:
 On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski 
 l...@amacapital.net wrote:
 On Fri, May 23, 2014 at 10:05 AM, Kees Cook keesc...@chromium.org 
 wrote:
 On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski 
 l...@amacapital.net wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook keesc...@chromium.org 
 wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started 
 early in
 the process lifetime (e.g., by code that is linked in). While it 
 is
 possible to apply permissive programs prior to process start up, 
 it is
 difficult to further restrict the kernel ABI to those threads 
 after that
 point.

 This change adds a new seccomp extension action for synchronizing 
 thread
 group seccomp filters and a prctl() for accessing that 
 functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at 
 filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
 SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or 
 when calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 
 0), it
 will attempt to synchronize all threads in current's threadgroup 
 to its
 seccomp filter program. This is possible iff all threads are 
 using a filter
 that is an ancestor to the filter current is attempting to 
 synchronize to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) are 
 also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been 
 set on the
 calling thread, no_new_privs will be set for all synchronized 
 threads too.
 On success, 0 is returned. On failure, the pid of one of the 
 failing threads
 will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing filters
 being separate operations?  If not, I think this would be easier to
 understand and to use if there was just a single operation.

 Yes: if the other thread's lifetime is not well controlled, it's 
 good
 to be able to have a distinct interface to retry the thread sync 
 that
 doesn't require adding no-op filters.

 Wouldn't this still be solved by:

 seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

 the idea would be that, if seccomp_add_filter fails, then you give up
 and, if it succeeds, then you're done.  It shouldn't fail unless out
 of memory or you've nested too deeply.

 I wanted to keep the case of being able to to wait for non-ancestor
 threads to finish. For example, 2 threads start and set separate
 filters. 1 does work and exits, 2 starts another thread (3) which adds
 filters, does work, and then waits for 1 to finish by calling TSYNC.
 Once 1 dies, TSYNC succeeds. In the case of not having direct control
 over thread lifetime (say, when using third-party libraries), I'd like
 to retain the flexibility of being able to do TSYNC without needing a
 filter being attached to it.

 I must admit this strikes me as odd.  What's the point of having a
 thread set a filter if it intends to be a short-lived thread?

 I was illustrating the potential insanity of third-party libraries.
 There isn't much sense in that behavior, but if it exists, working
 around it is harder without the separate TSYNC-only call.

 In any case, I must have missed the ability for TSYNC to block.  Hmm.
 That seems complicated, albeit potentially useful.

 Oh, no, I didn't mean to imply TSYNC should block. I meant that thread
 3 could do:

 while (TSYNC-fails)
wait-on-or-kill-unexpected-thread


 Ok.

 I'm still not seeing the need for a separate TSYNC option, though --
 just add-a-filter-across-all-threads would work if it failed
 harmlessly on error.  FWIW, TSYNC is probably equivalent to adding an
 always-accept filter across all threads, although no one should really
 do the latter for efficiency reasons.

 Given the complexity of the locking, fail means I applied the
 change to all threads except for at least this one: *error code*,
 which means looping with the add-a-filter method means all the other
 threads keep getting filters added until there is full success. I
 don't want that overhead, so this keeps TSYNC distinctly separate.

 Ugh, right.


 Because of the filter 

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-06-02 Thread Kees Cook
On Mon, Jun 2, 2014 at 5:29 PM, Andy Lutomirski l...@amacapital.net wrote:
 On Mon, Jun 2, 2014 at 5:14 PM, Kees Cook keesc...@chromium.org wrote:
 On Mon, Jun 2, 2014 at 1:53 PM, Andy Lutomirski l...@amacapital.net wrote:
 On Tue, May 27, 2014 at 12:55 PM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 12:27 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 12:23 PM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 11:45 AM, Kees Cook keesc...@chromium.org 
 wrote:
 On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski 
 l...@amacapital.net wrote:
 On Tue, May 27, 2014 at 11:24 AM, Kees Cook keesc...@chromium.org 
 wrote:
 On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski 
 l...@amacapital.net wrote:
 On Fri, May 23, 2014 at 10:05 AM, Kees Cook keesc...@chromium.org 
 wrote:
 On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski 
 l...@amacapital.net wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook 
 keesc...@chromium.org wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started 
 early in
 the process lifetime (e.g., by code that is linked in). While it 
 is
 possible to apply permissive programs prior to process start up, 
 it is
 difficult to further restrict the kernel ABI to those threads 
 after that
 point.

 This change adds a new seccomp extension action for 
 synchronizing thread
 group seccomp filters and a prctl() for accessing that 
 functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at 
 filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
 SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or 
 when calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 
 0), it
 will attempt to synchronize all threads in current's threadgroup 
 to its
 seccomp filter program. This is possible iff all threads are 
 using a filter
 that is an ancestor to the filter current is attempting to 
 synchronize to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) 
 are also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has 
 been set on the
 calling thread, no_new_privs will be set for all synchronized 
 threads too.
 On success, 0 is returned. On failure, the pid of one of the 
 failing threads
 will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing filters
 being separate operations?  If not, I think this would be easier 
 to
 understand and to use if there was just a single operation.

 Yes: if the other thread's lifetime is not well controlled, it's 
 good
 to be able to have a distinct interface to retry the thread sync 
 that
 doesn't require adding no-op filters.

 Wouldn't this still be solved by:

 seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

 the idea would be that, if seccomp_add_filter fails, then you give 
 up
 and, if it succeeds, then you're done.  It shouldn't fail unless out
 of memory or you've nested too deeply.

 I wanted to keep the case of being able to to wait for non-ancestor
 threads to finish. For example, 2 threads start and set separate
 filters. 1 does work and exits, 2 starts another thread (3) which 
 adds
 filters, does work, and then waits for 1 to finish by calling TSYNC.
 Once 1 dies, TSYNC succeeds. In the case of not having direct control
 over thread lifetime (say, when using third-party libraries), I'd 
 like
 to retain the flexibility of being able to do TSYNC without needing a
 filter being attached to it.

 I must admit this strikes me as odd.  What's the point of having a
 thread set a filter if it intends to be a short-lived thread?

 I was illustrating the potential insanity of third-party libraries.
 There isn't much sense in that behavior, but if it exists, working
 around it is harder without the separate TSYNC-only call.

 In any case, I must have missed the ability for TSYNC to block.  Hmm.
 That seems complicated, albeit potentially useful.

 Oh, no, I didn't mean to imply TSYNC should block. I meant that thread
 3 could do:

 while (TSYNC-fails)
wait-on-or-kill-unexpected-thread


 Ok.

 I'm still not seeing the need for a separate TSYNC option, though --
 just add-a-filter-across-all-threads would work if it failed
 harmlessly on error.  FWIW, TSYNC is probably equivalent to adding an
 always-accept filter across all threads, although no one should really
 do the latter for efficiency reasons.

 Given the complexity of the locking, fail means I applied the
 change to all threads except for at least this one: *error code*,
 which means looping with the add-a-filter method means all the other
 threads keep getting filters added until there is full success. I
 don't want that 

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-06-02 Thread Andy Lutomirski
On Mon, Jun 2, 2014 at 6:09 PM, Kees Cook keesc...@chromium.org wrote:
 On Mon, Jun 2, 2014 at 5:29 PM, Andy Lutomirski l...@amacapital.net wrote:
 On Mon, Jun 2, 2014 at 5:14 PM, Kees Cook keesc...@chromium.org wrote:
 On Mon, Jun 2, 2014 at 1:53 PM, Andy Lutomirski l...@amacapital.net wrote:
 On Tue, May 27, 2014 at 12:55 PM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 12:27 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 12:23 PM, Kees Cook keesc...@chromium.org 
 wrote:
 On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 11:45 AM, Kees Cook keesc...@chromium.org 
 wrote:
 On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski 
 l...@amacapital.net wrote:
 On Tue, May 27, 2014 at 11:24 AM, Kees Cook keesc...@chromium.org 
 wrote:
 On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski 
 l...@amacapital.net wrote:
 On Fri, May 23, 2014 at 10:05 AM, Kees Cook 
 keesc...@chromium.org wrote:
 On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski 
 l...@amacapital.net wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook 
 keesc...@chromium.org wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started 
 early in
 the process lifetime (e.g., by code that is linked in). While 
 it is
 possible to apply permissive programs prior to process start 
 up, it is
 difficult to further restrict the kernel ABI to those threads 
 after that
 point.

 This change adds a new seccomp extension action for 
 synchronizing thread
 group seccomp filters and a prctl() for accessing that 
 functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at 
 filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
 SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or 
 when calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 
 0, 0), it
 will attempt to synchronize all threads in current's 
 threadgroup to its
 seccomp filter program. This is possible iff all threads are 
 using a filter
 that is an ancestor to the filter current is attempting to 
 synchronize to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) 
 are also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has 
 been set on the
 calling thread, no_new_privs will be set for all synchronized 
 threads too.
 On success, 0 is returned. On failure, the pid of one of the 
 failing threads
 will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing filters
 being separate operations?  If not, I think this would be easier 
 to
 understand and to use if there was just a single operation.

 Yes: if the other thread's lifetime is not well controlled, it's 
 good
 to be able to have a distinct interface to retry the thread sync 
 that
 doesn't require adding no-op filters.

 Wouldn't this still be solved by:

 seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

 the idea would be that, if seccomp_add_filter fails, then you give 
 up
 and, if it succeeds, then you're done.  It shouldn't fail unless 
 out
 of memory or you've nested too deeply.

 I wanted to keep the case of being able to to wait for non-ancestor
 threads to finish. For example, 2 threads start and set separate
 filters. 1 does work and exits, 2 starts another thread (3) which 
 adds
 filters, does work, and then waits for 1 to finish by calling TSYNC.
 Once 1 dies, TSYNC succeeds. In the case of not having direct 
 control
 over thread lifetime (say, when using third-party libraries), I'd 
 like
 to retain the flexibility of being able to do TSYNC without needing 
 a
 filter being attached to it.

 I must admit this strikes me as odd.  What's the point of having a
 thread set a filter if it intends to be a short-lived thread?

 I was illustrating the potential insanity of third-party libraries.
 There isn't much sense in that behavior, but if it exists, working
 around it is harder without the separate TSYNC-only call.

 In any case, I must have missed the ability for TSYNC to block.  Hmm.
 That seems complicated, albeit potentially useful.

 Oh, no, I didn't mean to imply TSYNC should block. I meant that thread
 3 could do:

 while (TSYNC-fails)
wait-on-or-kill-unexpected-thread


 Ok.

 I'm still not seeing the need for a separate TSYNC option, though --
 just add-a-filter-across-all-threads would work if it failed
 harmlessly on error.  FWIW, TSYNC is probably equivalent to adding an
 always-accept filter across all threads, although no one should really
 do the latter for efficiency reasons.

 Given the complexity of the locking, fail means I applied the
 change to all threads except for at least this one: *error code*,
 which means looping with the add-a-filter method means all the other
 threads 

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-27 Thread Kees Cook
On Tue, May 27, 2014 at 12:27 PM, Andy Lutomirski  wrote:
> On Tue, May 27, 2014 at 12:23 PM, Kees Cook  wrote:
>> On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski  
>> wrote:
>>> On Tue, May 27, 2014 at 11:45 AM, Kees Cook  wrote:
 On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski  
 wrote:
> On Tue, May 27, 2014 at 11:24 AM, Kees Cook  wrote:
>> On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski  
>> wrote:
>>> On Fri, May 23, 2014 at 10:05 AM, Kees Cook  
>>> wrote:
 On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski  
 wrote:
> On Thu, May 22, 2014 at 4:05 PM, Kees Cook  
> wrote:
>> Applying restrictive seccomp filter programs to large or diverse
>> codebases often requires handling threads which may be started early 
>> in
>> the process lifetime (e.g., by code that is linked in). While it is
>> possible to apply permissive programs prior to process start up, it 
>> is
>> difficult to further restrict the kernel ABI to those threads after 
>> that
>> point.
>>
>> This change adds a new seccomp extension action for synchronizing 
>> thread
>> group seccomp filters and a prctl() for accessing that functionality,
>> as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at 
>> filter
>> installation time.
>>
>> When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
>> SECCOMP_EXT_ACT_FILTER,
>> flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when 
>> calling
>> prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), 
>> it
>> will attempt to synchronize all threads in current's threadgroup to 
>> its
>> seccomp filter program. This is possible iff all threads are using a 
>> filter
>> that is an ancestor to the filter current is attempting to 
>> synchronize to.
>> NULL filters (where the task is running as SECCOMP_MODE_NONE) are 
>> also
>> treated as ancestors allowing threads to be transitioned into
>> SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been 
>> set on the
>> calling thread, no_new_privs will be set for all synchronized 
>> threads too.
>> On success, 0 is returned. On failure, the pid of one of the failing 
>> threads
>> will be returned, with as many filters installed as possible.
>
> Is there a use case for adding a filter and synchronizing filters
> being separate operations?  If not, I think this would be easier to
> understand and to use if there was just a single operation.

 Yes: if the other thread's lifetime is not well controlled, it's good
 to be able to have a distinct interface to retry the thread sync that
 doesn't require adding "no-op" filters.
>>>
>>> Wouldn't this still be solved by:
>>>
>>> seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);
>>>
>>> the idea would be that, if seccomp_add_filter fails, then you give up
>>> and, if it succeeds, then you're done.  It shouldn't fail unless out
>>> of memory or you've nested too deeply.
>>
>> I wanted to keep the case of being able to to wait for non-ancestor
>> threads to finish. For example, 2 threads start and set separate
>> filters. 1 does work and exits, 2 starts another thread (3) which adds
>> filters, does work, and then waits for 1 to finish by calling TSYNC.
>> Once 1 dies, TSYNC succeeds. In the case of not having direct control
>> over thread lifetime (say, when using third-party libraries), I'd like
>> to retain the flexibility of being able to do TSYNC without needing a
>> filter being attached to it.
>
> I must admit this strikes me as odd.  What's the point of having a
> thread set a filter if it intends to be a short-lived thread?

 I was illustrating the potential insanity of third-party libraries.
 There isn't much sense in that behavior, but if it exists, working
 around it is harder without the separate TSYNC-only call.

> In any case, I must have missed the ability for TSYNC to block.  Hmm.
> That seems complicated, albeit potentially useful.

 Oh, no, I didn't mean to imply TSYNC should block. I meant that thread
 3 could do:

 while (TSYNC-fails)
wait-on-or-kill-unexpected-thread

>>>
>>> Ok.
>>>
>>> I'm still not seeing the need for a separate TSYNC option, though --
>>> just add-a-filter-across-all-threads would work if it failed
>>> harmlessly on error.  FWIW, TSYNC is probably equivalent to adding an
>>> always-accept filter across all threads, although no one should really
>>> do the latter for efficiency reasons.
>>
>> Given the complexity of the locking, "fail" means "I 

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-27 Thread Andy Lutomirski
On Tue, May 27, 2014 at 12:23 PM, Kees Cook  wrote:
> On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski  wrote:
>> On Tue, May 27, 2014 at 11:45 AM, Kees Cook  wrote:
>>> On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski  
>>> wrote:
 On Tue, May 27, 2014 at 11:24 AM, Kees Cook  wrote:
> On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski  
> wrote:
>> On Fri, May 23, 2014 at 10:05 AM, Kees Cook  
>> wrote:
>>> On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski  
>>> wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook  
 wrote:
> Applying restrictive seccomp filter programs to large or diverse
> codebases often requires handling threads which may be started early 
> in
> the process lifetime (e.g., by code that is linked in). While it is
> possible to apply permissive programs prior to process start up, it is
> difficult to further restrict the kernel ABI to those threads after 
> that
> point.
>
> This change adds a new seccomp extension action for synchronizing 
> thread
> group seccomp filters and a prctl() for accessing that functionality,
> as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
> installation time.
>
> When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
> SECCOMP_EXT_ACT_FILTER,
> flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when 
> calling
> prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), 
> it
> will attempt to synchronize all threads in current's threadgroup to 
> its
> seccomp filter program. This is possible iff all threads are using a 
> filter
> that is an ancestor to the filter current is attempting to 
> synchronize to.
> NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
> treated as ancestors allowing threads to be transitioned into
> SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set 
> on the
> calling thread, no_new_privs will be set for all synchronized threads 
> too.
> On success, 0 is returned. On failure, the pid of one of the failing 
> threads
> will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing filters
 being separate operations?  If not, I think this would be easier to
 understand and to use if there was just a single operation.
>>>
>>> Yes: if the other thread's lifetime is not well controlled, it's good
>>> to be able to have a distinct interface to retry the thread sync that
>>> doesn't require adding "no-op" filters.
>>
>> Wouldn't this still be solved by:
>>
>> seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);
>>
>> the idea would be that, if seccomp_add_filter fails, then you give up
>> and, if it succeeds, then you're done.  It shouldn't fail unless out
>> of memory or you've nested too deeply.
>
> I wanted to keep the case of being able to to wait for non-ancestor
> threads to finish. For example, 2 threads start and set separate
> filters. 1 does work and exits, 2 starts another thread (3) which adds
> filters, does work, and then waits for 1 to finish by calling TSYNC.
> Once 1 dies, TSYNC succeeds. In the case of not having direct control
> over thread lifetime (say, when using third-party libraries), I'd like
> to retain the flexibility of being able to do TSYNC without needing a
> filter being attached to it.

 I must admit this strikes me as odd.  What's the point of having a
 thread set a filter if it intends to be a short-lived thread?
>>>
>>> I was illustrating the potential insanity of third-party libraries.
>>> There isn't much sense in that behavior, but if it exists, working
>>> around it is harder without the separate TSYNC-only call.
>>>
 In any case, I must have missed the ability for TSYNC to block.  Hmm.
 That seems complicated, albeit potentially useful.
>>>
>>> Oh, no, I didn't mean to imply TSYNC should block. I meant that thread
>>> 3 could do:
>>>
>>> while (TSYNC-fails)
>>>wait-on-or-kill-unexpected-thread
>>>
>>
>> Ok.
>>
>> I'm still not seeing the need for a separate TSYNC option, though --
>> just add-a-filter-across-all-threads would work if it failed
>> harmlessly on error.  FWIW, TSYNC is probably equivalent to adding an
>> always-accept filter across all threads, although no one should really
>> do the latter for efficiency reasons.
>
> Given the complexity of the locking, "fail" means "I applied the
> change to all threads except for at least this one: *error code*",
> which means looping with the "add-a-filter" method means all the other
> threads keep getting filters added until there is 

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-27 Thread Kees Cook
On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski  wrote:
> On Tue, May 27, 2014 at 11:45 AM, Kees Cook  wrote:
>> On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski  
>> wrote:
>>> On Tue, May 27, 2014 at 11:24 AM, Kees Cook  wrote:
 On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski  
 wrote:
> On Fri, May 23, 2014 at 10:05 AM, Kees Cook  wrote:
>> On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski  
>> wrote:
>>> On Thu, May 22, 2014 at 4:05 PM, Kees Cook  
>>> wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started early in
 the process lifetime (e.g., by code that is linked in). While it is
 possible to apply permissive programs prior to process start up, it is
 difficult to further restrict the kernel ABI to those threads after 
 that
 point.

 This change adds a new seccomp extension action for synchronizing 
 thread
 group seccomp filters and a prctl() for accessing that functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
 SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when 
 calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
 will attempt to synchronize all threads in current's threadgroup to its
 seccomp filter program. This is possible iff all threads are using a 
 filter
 that is an ancestor to the filter current is attempting to synchronize 
 to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set 
 on the
 calling thread, no_new_privs will be set for all synchronized threads 
 too.
 On success, 0 is returned. On failure, the pid of one of the failing 
 threads
 will be returned, with as many filters installed as possible.
>>>
>>> Is there a use case for adding a filter and synchronizing filters
>>> being separate operations?  If not, I think this would be easier to
>>> understand and to use if there was just a single operation.
>>
>> Yes: if the other thread's lifetime is not well controlled, it's good
>> to be able to have a distinct interface to retry the thread sync that
>> doesn't require adding "no-op" filters.
>
> Wouldn't this still be solved by:
>
> seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);
>
> the idea would be that, if seccomp_add_filter fails, then you give up
> and, if it succeeds, then you're done.  It shouldn't fail unless out
> of memory or you've nested too deeply.

 I wanted to keep the case of being able to to wait for non-ancestor
 threads to finish. For example, 2 threads start and set separate
 filters. 1 does work and exits, 2 starts another thread (3) which adds
 filters, does work, and then waits for 1 to finish by calling TSYNC.
 Once 1 dies, TSYNC succeeds. In the case of not having direct control
 over thread lifetime (say, when using third-party libraries), I'd like
 to retain the flexibility of being able to do TSYNC without needing a
 filter being attached to it.
>>>
>>> I must admit this strikes me as odd.  What's the point of having a
>>> thread set a filter if it intends to be a short-lived thread?
>>
>> I was illustrating the potential insanity of third-party libraries.
>> There isn't much sense in that behavior, but if it exists, working
>> around it is harder without the separate TSYNC-only call.
>>
>>> In any case, I must have missed the ability for TSYNC to block.  Hmm.
>>> That seems complicated, albeit potentially useful.
>>
>> Oh, no, I didn't mean to imply TSYNC should block. I meant that thread
>> 3 could do:
>>
>> while (TSYNC-fails)
>>wait-on-or-kill-unexpected-thread
>>
>
> Ok.
>
> I'm still not seeing the need for a separate TSYNC option, though --
> just add-a-filter-across-all-threads would work if it failed
> harmlessly on error.  FWIW, TSYNC is probably equivalent to adding an
> always-accept filter across all threads, although no one should really
> do the latter for efficiency reasons.

Given the complexity of the locking, "fail" means "I applied the
change to all threads except for at least this one: *error code*",
which means looping with the "add-a-filter" method means all the other
threads keep getting filters added until there is full success. I
don't want that overhead, so this keeps TSYNC distinctly separate.

Because of the filter addition, when using add_filter-TSYNC, it's not
sensible to continue after a failure. 

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-27 Thread Andy Lutomirski
On Tue, May 27, 2014 at 11:45 AM, Kees Cook  wrote:
> On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski  wrote:
>> On Tue, May 27, 2014 at 11:24 AM, Kees Cook  wrote:
>>> On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski  
>>> wrote:
 On Fri, May 23, 2014 at 10:05 AM, Kees Cook  wrote:
> On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski  
> wrote:
>> On Thu, May 22, 2014 at 4:05 PM, Kees Cook  wrote:
>>> Applying restrictive seccomp filter programs to large or diverse
>>> codebases often requires handling threads which may be started early in
>>> the process lifetime (e.g., by code that is linked in). While it is
>>> possible to apply permissive programs prior to process start up, it is
>>> difficult to further restrict the kernel ABI to those threads after that
>>> point.
>>>
>>> This change adds a new seccomp extension action for synchronizing thread
>>> group seccomp filters and a prctl() for accessing that functionality,
>>> as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
>>> installation time.
>>>
>>> When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
>>> SECCOMP_EXT_ACT_FILTER,
>>> flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when 
>>> calling
>>> prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
>>> will attempt to synchronize all threads in current's threadgroup to its
>>> seccomp filter program. This is possible iff all threads are using a 
>>> filter
>>> that is an ancestor to the filter current is attempting to synchronize 
>>> to.
>>> NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
>>> treated as ancestors allowing threads to be transitioned into
>>> SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set 
>>> on the
>>> calling thread, no_new_privs will be set for all synchronized threads 
>>> too.
>>> On success, 0 is returned. On failure, the pid of one of the failing 
>>> threads
>>> will be returned, with as many filters installed as possible.
>>
>> Is there a use case for adding a filter and synchronizing filters
>> being separate operations?  If not, I think this would be easier to
>> understand and to use if there was just a single operation.
>
> Yes: if the other thread's lifetime is not well controlled, it's good
> to be able to have a distinct interface to retry the thread sync that
> doesn't require adding "no-op" filters.

 Wouldn't this still be solved by:

 seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

 the idea would be that, if seccomp_add_filter fails, then you give up
 and, if it succeeds, then you're done.  It shouldn't fail unless out
 of memory or you've nested too deeply.
>>>
>>> I wanted to keep the case of being able to to wait for non-ancestor
>>> threads to finish. For example, 2 threads start and set separate
>>> filters. 1 does work and exits, 2 starts another thread (3) which adds
>>> filters, does work, and then waits for 1 to finish by calling TSYNC.
>>> Once 1 dies, TSYNC succeeds. In the case of not having direct control
>>> over thread lifetime (say, when using third-party libraries), I'd like
>>> to retain the flexibility of being able to do TSYNC without needing a
>>> filter being attached to it.
>>
>> I must admit this strikes me as odd.  What's the point of having a
>> thread set a filter if it intends to be a short-lived thread?
>
> I was illustrating the potential insanity of third-party libraries.
> There isn't much sense in that behavior, but if it exists, working
> around it is harder without the separate TSYNC-only call.
>
>> In any case, I must have missed the ability for TSYNC to block.  Hmm.
>> That seems complicated, albeit potentially useful.
>
> Oh, no, I didn't mean to imply TSYNC should block. I meant that thread
> 3 could do:
>
> while (TSYNC-fails)
>wait-on-or-kill-unexpected-thread
>

Ok.

I'm still not seeing the need for a separate TSYNC option, though --
just add-a-filter-across-all-threads would work if it failed
harmlessly on error.  FWIW, TSYNC is probably equivalent to adding an
always-accept filter across all threads, although no one should really
do the latter for efficiency reasons.

--Andy

> -Kees
>
> --
> Kees Cook
> Chrome OS Security



-- 
Andy Lutomirski
AMA Capital Management, LLC
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-27 Thread Kees Cook
On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski  wrote:
> On Tue, May 27, 2014 at 11:24 AM, Kees Cook  wrote:
>> On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski  
>> wrote:
>>> On Fri, May 23, 2014 at 10:05 AM, Kees Cook  wrote:
 On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski  
 wrote:
> On Thu, May 22, 2014 at 4:05 PM, Kees Cook  wrote:
>> Applying restrictive seccomp filter programs to large or diverse
>> codebases often requires handling threads which may be started early in
>> the process lifetime (e.g., by code that is linked in). While it is
>> possible to apply permissive programs prior to process start up, it is
>> difficult to further restrict the kernel ABI to those threads after that
>> point.
>>
>> This change adds a new seccomp extension action for synchronizing thread
>> group seccomp filters and a prctl() for accessing that functionality,
>> as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
>> installation time.
>>
>> When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
>> SECCOMP_EXT_ACT_FILTER,
>> flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when 
>> calling
>> prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
>> will attempt to synchronize all threads in current's threadgroup to its
>> seccomp filter program. This is possible iff all threads are using a 
>> filter
>> that is an ancestor to the filter current is attempting to synchronize 
>> to.
>> NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
>> treated as ancestors allowing threads to be transitioned into
>> SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set on 
>> the
>> calling thread, no_new_privs will be set for all synchronized threads 
>> too.
>> On success, 0 is returned. On failure, the pid of one of the failing 
>> threads
>> will be returned, with as many filters installed as possible.
>
> Is there a use case for adding a filter and synchronizing filters
> being separate operations?  If not, I think this would be easier to
> understand and to use if there was just a single operation.

 Yes: if the other thread's lifetime is not well controlled, it's good
 to be able to have a distinct interface to retry the thread sync that
 doesn't require adding "no-op" filters.
>>>
>>> Wouldn't this still be solved by:
>>>
>>> seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);
>>>
>>> the idea would be that, if seccomp_add_filter fails, then you give up
>>> and, if it succeeds, then you're done.  It shouldn't fail unless out
>>> of memory or you've nested too deeply.
>>
>> I wanted to keep the case of being able to to wait for non-ancestor
>> threads to finish. For example, 2 threads start and set separate
>> filters. 1 does work and exits, 2 starts another thread (3) which adds
>> filters, does work, and then waits for 1 to finish by calling TSYNC.
>> Once 1 dies, TSYNC succeeds. In the case of not having direct control
>> over thread lifetime (say, when using third-party libraries), I'd like
>> to retain the flexibility of being able to do TSYNC without needing a
>> filter being attached to it.
>
> I must admit this strikes me as odd.  What's the point of having a
> thread set a filter if it intends to be a short-lived thread?

I was illustrating the potential insanity of third-party libraries.
There isn't much sense in that behavior, but if it exists, working
around it is harder without the separate TSYNC-only call.

> In any case, I must have missed the ability for TSYNC to block.  Hmm.
> That seems complicated, albeit potentially useful.

Oh, no, I didn't mean to imply TSYNC should block. I meant that thread
3 could do:

while (TSYNC-fails)
   wait-on-or-kill-unexpected-thread

-Kees

-- 
Kees Cook
Chrome OS Security
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-27 Thread Andy Lutomirski
On Tue, May 27, 2014 at 11:24 AM, Kees Cook  wrote:
> On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski  wrote:
>> On Fri, May 23, 2014 at 10:05 AM, Kees Cook  wrote:
>>> On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski  
>>> wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook  wrote:
> Applying restrictive seccomp filter programs to large or diverse
> codebases often requires handling threads which may be started early in
> the process lifetime (e.g., by code that is linked in). While it is
> possible to apply permissive programs prior to process start up, it is
> difficult to further restrict the kernel ABI to those threads after that
> point.
>
> This change adds a new seccomp extension action for synchronizing thread
> group seccomp filters and a prctl() for accessing that functionality,
> as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
> installation time.
>
> When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
> SECCOMP_EXT_ACT_FILTER,
> flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when calling
> prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
> will attempt to synchronize all threads in current's threadgroup to its
> seccomp filter program. This is possible iff all threads are using a 
> filter
> that is an ancestor to the filter current is attempting to synchronize to.
> NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
> treated as ancestors allowing threads to be transitioned into
> SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set on 
> the
> calling thread, no_new_privs will be set for all synchronized threads too.
> On success, 0 is returned. On failure, the pid of one of the failing 
> threads
> will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing filters
 being separate operations?  If not, I think this would be easier to
 understand and to use if there was just a single operation.
>>>
>>> Yes: if the other thread's lifetime is not well controlled, it's good
>>> to be able to have a distinct interface to retry the thread sync that
>>> doesn't require adding "no-op" filters.
>>
>> Wouldn't this still be solved by:
>>
>> seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);
>>
>> the idea would be that, if seccomp_add_filter fails, then you give up
>> and, if it succeeds, then you're done.  It shouldn't fail unless out
>> of memory or you've nested too deeply.
>
> I wanted to keep the case of being able to to wait for non-ancestor
> threads to finish. For example, 2 threads start and set separate
> filters. 1 does work and exits, 2 starts another thread (3) which adds
> filters, does work, and then waits for 1 to finish by calling TSYNC.
> Once 1 dies, TSYNC succeeds. In the case of not having direct control
> over thread lifetime (say, when using third-party libraries), I'd like
> to retain the flexibility of being able to do TSYNC without needing a
> filter being attached to it.

I must admit this strikes me as odd.  What's the point of having a
thread set a filter if it intends to be a short-lived thread?

In any cast, I must have missed the ability for TSYNC to block.  Hmm.
That seems complicated, albeit potentially useful.

>
 If you did that, you'd have to decide whether to continue requiring
 that all the other threads have a filter that's an ancestor of the
 current thread's filter.
>>>
>>> This is required no matter what to make sure there is no way to
>>> replace a filter tree with a different one (allowing accidental
>>> bypasses, misbehavior, etc).
>>
>> What I mean is:  should the add-new-filter-to-all-threads operation
>> add the new filter to all threads, regardless of what their current
>> state is, or should it fail if any thread has a filter that isn't an
>> ancestor of the current thread's filter?  Either version should be
>> safe.
>
> It should fail -- we don't want to run the risk of effectively
> replacing a filter out from under a thread. Adding additional
> restrictions is safe as long as we retain the nnp from the caller .

The other option would be to add the new filter.  The threads wouldn't
end up being ancestors of each other, but that could still be okay.

In any case, I don't have a strong feeling about this particular issue.

--Andy
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-27 Thread Kees Cook
On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski  wrote:
> On Fri, May 23, 2014 at 10:05 AM, Kees Cook  wrote:
>> On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski  wrote:
>>> On Thu, May 22, 2014 at 4:05 PM, Kees Cook  wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started early in
 the process lifetime (e.g., by code that is linked in). While it is
 possible to apply permissive programs prior to process start up, it is
 difficult to further restrict the kernel ABI to those threads after that
 point.

 This change adds a new seccomp extension action for synchronizing thread
 group seccomp filters and a prctl() for accessing that functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
 will attempt to synchronize all threads in current's threadgroup to its
 seccomp filter program. This is possible iff all threads are using a filter
 that is an ancestor to the filter current is attempting to synchronize to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set on 
 the
 calling thread, no_new_privs will be set for all synchronized threads too.
 On success, 0 is returned. On failure, the pid of one of the failing 
 threads
 will be returned, with as many filters installed as possible.
>>>
>>> Is there a use case for adding a filter and synchronizing filters
>>> being separate operations?  If not, I think this would be easier to
>>> understand and to use if there was just a single operation.
>>
>> Yes: if the other thread's lifetime is not well controlled, it's good
>> to be able to have a distinct interface to retry the thread sync that
>> doesn't require adding "no-op" filters.
>
> Wouldn't this still be solved by:
>
> seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);
>
> the idea would be that, if seccomp_add_filter fails, then you give up
> and, if it succeeds, then you're done.  It shouldn't fail unless out
> of memory or you've nested too deeply.

I wanted to keep the case of being able to to wait for non-ancestor
threads to finish. For example, 2 threads start and set separate
filters. 1 does work and exits, 2 starts another thread (3) which adds
filters, does work, and then waits for 1 to finish by calling TSYNC.
Once 1 dies, TSYNC succeeds. In the case of not having direct control
over thread lifetime (say, when using third-party libraries), I'd like
to retain the flexibility of being able to do TSYNC without needing a
filter being attached to it.

>>> If you did that, you'd have to decide whether to continue requiring
>>> that all the other threads have a filter that's an ancestor of the
>>> current thread's filter.
>>
>> This is required no matter what to make sure there is no way to
>> replace a filter tree with a different one (allowing accidental
>> bypasses, misbehavior, etc).
>
> What I mean is:  should the add-new-filter-to-all-threads operation
> add the new filter to all threads, regardless of what their current
> state is, or should it fail if any thread has a filter that isn't an
> ancestor of the current thread's filter?  Either version should be
> safe.

It should fail -- we don't want to run the risk of effectively
replacing a filter out from under a thread. Adding additional
restrictions is safe as long as we retain the nnp from the caller .

-Kees

-- 
Kees Cook
Chrome OS Security
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-27 Thread Kees Cook
On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski l...@amacapital.net wrote:
 On Fri, May 23, 2014 at 10:05 AM, Kees Cook keesc...@chromium.org wrote:
 On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski l...@amacapital.net wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook keesc...@chromium.org wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started early in
 the process lifetime (e.g., by code that is linked in). While it is
 possible to apply permissive programs prior to process start up, it is
 difficult to further restrict the kernel ABI to those threads after that
 point.

 This change adds a new seccomp extension action for synchronizing thread
 group seccomp filters and a prctl() for accessing that functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
 will attempt to synchronize all threads in current's threadgroup to its
 seccomp filter program. This is possible iff all threads are using a filter
 that is an ancestor to the filter current is attempting to synchronize to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set on 
 the
 calling thread, no_new_privs will be set for all synchronized threads too.
 On success, 0 is returned. On failure, the pid of one of the failing 
 threads
 will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing filters
 being separate operations?  If not, I think this would be easier to
 understand and to use if there was just a single operation.

 Yes: if the other thread's lifetime is not well controlled, it's good
 to be able to have a distinct interface to retry the thread sync that
 doesn't require adding no-op filters.

 Wouldn't this still be solved by:

 seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

 the idea would be that, if seccomp_add_filter fails, then you give up
 and, if it succeeds, then you're done.  It shouldn't fail unless out
 of memory or you've nested too deeply.

I wanted to keep the case of being able to to wait for non-ancestor
threads to finish. For example, 2 threads start and set separate
filters. 1 does work and exits, 2 starts another thread (3) which adds
filters, does work, and then waits for 1 to finish by calling TSYNC.
Once 1 dies, TSYNC succeeds. In the case of not having direct control
over thread lifetime (say, when using third-party libraries), I'd like
to retain the flexibility of being able to do TSYNC without needing a
filter being attached to it.

 If you did that, you'd have to decide whether to continue requiring
 that all the other threads have a filter that's an ancestor of the
 current thread's filter.

 This is required no matter what to make sure there is no way to
 replace a filter tree with a different one (allowing accidental
 bypasses, misbehavior, etc).

 What I mean is:  should the add-new-filter-to-all-threads operation
 add the new filter to all threads, regardless of what their current
 state is, or should it fail if any thread has a filter that isn't an
 ancestor of the current thread's filter?  Either version should be
 safe.

It should fail -- we don't want to run the risk of effectively
replacing a filter out from under a thread. Adding additional
restrictions is safe as long as we retain the nnp from the caller .

-Kees

-- 
Kees Cook
Chrome OS Security
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-27 Thread Andy Lutomirski
On Tue, May 27, 2014 at 11:24 AM, Kees Cook keesc...@chromium.org wrote:
 On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski l...@amacapital.net wrote:
 On Fri, May 23, 2014 at 10:05 AM, Kees Cook keesc...@chromium.org wrote:
 On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook keesc...@chromium.org wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started early in
 the process lifetime (e.g., by code that is linked in). While it is
 possible to apply permissive programs prior to process start up, it is
 difficult to further restrict the kernel ABI to those threads after that
 point.

 This change adds a new seccomp extension action for synchronizing thread
 group seccomp filters and a prctl() for accessing that functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
 SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
 will attempt to synchronize all threads in current's threadgroup to its
 seccomp filter program. This is possible iff all threads are using a 
 filter
 that is an ancestor to the filter current is attempting to synchronize to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set on 
 the
 calling thread, no_new_privs will be set for all synchronized threads too.
 On success, 0 is returned. On failure, the pid of one of the failing 
 threads
 will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing filters
 being separate operations?  If not, I think this would be easier to
 understand and to use if there was just a single operation.

 Yes: if the other thread's lifetime is not well controlled, it's good
 to be able to have a distinct interface to retry the thread sync that
 doesn't require adding no-op filters.

 Wouldn't this still be solved by:

 seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

 the idea would be that, if seccomp_add_filter fails, then you give up
 and, if it succeeds, then you're done.  It shouldn't fail unless out
 of memory or you've nested too deeply.

 I wanted to keep the case of being able to to wait for non-ancestor
 threads to finish. For example, 2 threads start and set separate
 filters. 1 does work and exits, 2 starts another thread (3) which adds
 filters, does work, and then waits for 1 to finish by calling TSYNC.
 Once 1 dies, TSYNC succeeds. In the case of not having direct control
 over thread lifetime (say, when using third-party libraries), I'd like
 to retain the flexibility of being able to do TSYNC without needing a
 filter being attached to it.

I must admit this strikes me as odd.  What's the point of having a
thread set a filter if it intends to be a short-lived thread?

In any cast, I must have missed the ability for TSYNC to block.  Hmm.
That seems complicated, albeit potentially useful.


 If you did that, you'd have to decide whether to continue requiring
 that all the other threads have a filter that's an ancestor of the
 current thread's filter.

 This is required no matter what to make sure there is no way to
 replace a filter tree with a different one (allowing accidental
 bypasses, misbehavior, etc).

 What I mean is:  should the add-new-filter-to-all-threads operation
 add the new filter to all threads, regardless of what their current
 state is, or should it fail if any thread has a filter that isn't an
 ancestor of the current thread's filter?  Either version should be
 safe.

 It should fail -- we don't want to run the risk of effectively
 replacing a filter out from under a thread. Adding additional
 restrictions is safe as long as we retain the nnp from the caller .

The other option would be to add the new filter.  The threads wouldn't
end up being ancestors of each other, but that could still be okay.

In any case, I don't have a strong feeling about this particular issue.

--Andy
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-27 Thread Kees Cook
On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski l...@amacapital.net wrote:
 On Tue, May 27, 2014 at 11:24 AM, Kees Cook keesc...@chromium.org wrote:
 On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Fri, May 23, 2014 at 10:05 AM, Kees Cook keesc...@chromium.org wrote:
 On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook keesc...@chromium.org wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started early in
 the process lifetime (e.g., by code that is linked in). While it is
 possible to apply permissive programs prior to process start up, it is
 difficult to further restrict the kernel ABI to those threads after that
 point.

 This change adds a new seccomp extension action for synchronizing thread
 group seccomp filters and a prctl() for accessing that functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
 SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when 
 calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
 will attempt to synchronize all threads in current's threadgroup to its
 seccomp filter program. This is possible iff all threads are using a 
 filter
 that is an ancestor to the filter current is attempting to synchronize 
 to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set on 
 the
 calling thread, no_new_privs will be set for all synchronized threads 
 too.
 On success, 0 is returned. On failure, the pid of one of the failing 
 threads
 will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing filters
 being separate operations?  If not, I think this would be easier to
 understand and to use if there was just a single operation.

 Yes: if the other thread's lifetime is not well controlled, it's good
 to be able to have a distinct interface to retry the thread sync that
 doesn't require adding no-op filters.

 Wouldn't this still be solved by:

 seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

 the idea would be that, if seccomp_add_filter fails, then you give up
 and, if it succeeds, then you're done.  It shouldn't fail unless out
 of memory or you've nested too deeply.

 I wanted to keep the case of being able to to wait for non-ancestor
 threads to finish. For example, 2 threads start and set separate
 filters. 1 does work and exits, 2 starts another thread (3) which adds
 filters, does work, and then waits for 1 to finish by calling TSYNC.
 Once 1 dies, TSYNC succeeds. In the case of not having direct control
 over thread lifetime (say, when using third-party libraries), I'd like
 to retain the flexibility of being able to do TSYNC without needing a
 filter being attached to it.

 I must admit this strikes me as odd.  What's the point of having a
 thread set a filter if it intends to be a short-lived thread?

I was illustrating the potential insanity of third-party libraries.
There isn't much sense in that behavior, but if it exists, working
around it is harder without the separate TSYNC-only call.

 In any case, I must have missed the ability for TSYNC to block.  Hmm.
 That seems complicated, albeit potentially useful.

Oh, no, I didn't mean to imply TSYNC should block. I meant that thread
3 could do:

while (TSYNC-fails)
   wait-on-or-kill-unexpected-thread

-Kees

-- 
Kees Cook
Chrome OS Security
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-27 Thread Andy Lutomirski
On Tue, May 27, 2014 at 11:45 AM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski l...@amacapital.net wrote:
 On Tue, May 27, 2014 at 11:24 AM, Kees Cook keesc...@chromium.org wrote:
 On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Fri, May 23, 2014 at 10:05 AM, Kees Cook keesc...@chromium.org wrote:
 On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook keesc...@chromium.org wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started early in
 the process lifetime (e.g., by code that is linked in). While it is
 possible to apply permissive programs prior to process start up, it is
 difficult to further restrict the kernel ABI to those threads after that
 point.

 This change adds a new seccomp extension action for synchronizing thread
 group seccomp filters and a prctl() for accessing that functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
 SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when 
 calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
 will attempt to synchronize all threads in current's threadgroup to its
 seccomp filter program. This is possible iff all threads are using a 
 filter
 that is an ancestor to the filter current is attempting to synchronize 
 to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set 
 on the
 calling thread, no_new_privs will be set for all synchronized threads 
 too.
 On success, 0 is returned. On failure, the pid of one of the failing 
 threads
 will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing filters
 being separate operations?  If not, I think this would be easier to
 understand and to use if there was just a single operation.

 Yes: if the other thread's lifetime is not well controlled, it's good
 to be able to have a distinct interface to retry the thread sync that
 doesn't require adding no-op filters.

 Wouldn't this still be solved by:

 seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

 the idea would be that, if seccomp_add_filter fails, then you give up
 and, if it succeeds, then you're done.  It shouldn't fail unless out
 of memory or you've nested too deeply.

 I wanted to keep the case of being able to to wait for non-ancestor
 threads to finish. For example, 2 threads start and set separate
 filters. 1 does work and exits, 2 starts another thread (3) which adds
 filters, does work, and then waits for 1 to finish by calling TSYNC.
 Once 1 dies, TSYNC succeeds. In the case of not having direct control
 over thread lifetime (say, when using third-party libraries), I'd like
 to retain the flexibility of being able to do TSYNC without needing a
 filter being attached to it.

 I must admit this strikes me as odd.  What's the point of having a
 thread set a filter if it intends to be a short-lived thread?

 I was illustrating the potential insanity of third-party libraries.
 There isn't much sense in that behavior, but if it exists, working
 around it is harder without the separate TSYNC-only call.

 In any case, I must have missed the ability for TSYNC to block.  Hmm.
 That seems complicated, albeit potentially useful.

 Oh, no, I didn't mean to imply TSYNC should block. I meant that thread
 3 could do:

 while (TSYNC-fails)
wait-on-or-kill-unexpected-thread


Ok.

I'm still not seeing the need for a separate TSYNC option, though --
just add-a-filter-across-all-threads would work if it failed
harmlessly on error.  FWIW, TSYNC is probably equivalent to adding an
always-accept filter across all threads, although no one should really
do the latter for efficiency reasons.

--Andy

 -Kees

 --
 Kees Cook
 Chrome OS Security



-- 
Andy Lutomirski
AMA Capital Management, LLC
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-27 Thread Kees Cook
On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski l...@amacapital.net wrote:
 On Tue, May 27, 2014 at 11:45 AM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 11:24 AM, Kees Cook keesc...@chromium.org wrote:
 On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Fri, May 23, 2014 at 10:05 AM, Kees Cook keesc...@chromium.org wrote:
 On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook keesc...@chromium.org 
 wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started early in
 the process lifetime (e.g., by code that is linked in). While it is
 possible to apply permissive programs prior to process start up, it is
 difficult to further restrict the kernel ABI to those threads after 
 that
 point.

 This change adds a new seccomp extension action for synchronizing 
 thread
 group seccomp filters and a prctl() for accessing that functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
 SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when 
 calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
 will attempt to synchronize all threads in current's threadgroup to its
 seccomp filter program. This is possible iff all threads are using a 
 filter
 that is an ancestor to the filter current is attempting to synchronize 
 to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set 
 on the
 calling thread, no_new_privs will be set for all synchronized threads 
 too.
 On success, 0 is returned. On failure, the pid of one of the failing 
 threads
 will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing filters
 being separate operations?  If not, I think this would be easier to
 understand and to use if there was just a single operation.

 Yes: if the other thread's lifetime is not well controlled, it's good
 to be able to have a distinct interface to retry the thread sync that
 doesn't require adding no-op filters.

 Wouldn't this still be solved by:

 seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

 the idea would be that, if seccomp_add_filter fails, then you give up
 and, if it succeeds, then you're done.  It shouldn't fail unless out
 of memory or you've nested too deeply.

 I wanted to keep the case of being able to to wait for non-ancestor
 threads to finish. For example, 2 threads start and set separate
 filters. 1 does work and exits, 2 starts another thread (3) which adds
 filters, does work, and then waits for 1 to finish by calling TSYNC.
 Once 1 dies, TSYNC succeeds. In the case of not having direct control
 over thread lifetime (say, when using third-party libraries), I'd like
 to retain the flexibility of being able to do TSYNC without needing a
 filter being attached to it.

 I must admit this strikes me as odd.  What's the point of having a
 thread set a filter if it intends to be a short-lived thread?

 I was illustrating the potential insanity of third-party libraries.
 There isn't much sense in that behavior, but if it exists, working
 around it is harder without the separate TSYNC-only call.

 In any case, I must have missed the ability for TSYNC to block.  Hmm.
 That seems complicated, albeit potentially useful.

 Oh, no, I didn't mean to imply TSYNC should block. I meant that thread
 3 could do:

 while (TSYNC-fails)
wait-on-or-kill-unexpected-thread


 Ok.

 I'm still not seeing the need for a separate TSYNC option, though --
 just add-a-filter-across-all-threads would work if it failed
 harmlessly on error.  FWIW, TSYNC is probably equivalent to adding an
 always-accept filter across all threads, although no one should really
 do the latter for efficiency reasons.

Given the complexity of the locking, fail means I applied the
change to all threads except for at least this one: *error code*,
which means looping with the add-a-filter method means all the other
threads keep getting filters added until there is full success. I
don't want that overhead, so this keeps TSYNC distinctly separate.

Because of the filter addition, when using add_filter-TSYNC, it's not
sensible to continue after a failure. However, using just-TSYNC allows
sensible re-trying. Since the environments where TSYNC intend to be
used in can be very weird, I really want to retain the retry ability.

-Kees

-- 
Kees Cook
Chrome OS Security
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-27 Thread Andy Lutomirski
On Tue, May 27, 2014 at 12:23 PM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski l...@amacapital.net wrote:
 On Tue, May 27, 2014 at 11:45 AM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 11:24 AM, Kees Cook keesc...@chromium.org wrote:
 On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Fri, May 23, 2014 at 10:05 AM, Kees Cook keesc...@chromium.org 
 wrote:
 On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook keesc...@chromium.org 
 wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started early 
 in
 the process lifetime (e.g., by code that is linked in). While it is
 possible to apply permissive programs prior to process start up, it is
 difficult to further restrict the kernel ABI to those threads after 
 that
 point.

 This change adds a new seccomp extension action for synchronizing 
 thread
 group seccomp filters and a prctl() for accessing that functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
 SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when 
 calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), 
 it
 will attempt to synchronize all threads in current's threadgroup to 
 its
 seccomp filter program. This is possible iff all threads are using a 
 filter
 that is an ancestor to the filter current is attempting to 
 synchronize to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set 
 on the
 calling thread, no_new_privs will be set for all synchronized threads 
 too.
 On success, 0 is returned. On failure, the pid of one of the failing 
 threads
 will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing filters
 being separate operations?  If not, I think this would be easier to
 understand and to use if there was just a single operation.

 Yes: if the other thread's lifetime is not well controlled, it's good
 to be able to have a distinct interface to retry the thread sync that
 doesn't require adding no-op filters.

 Wouldn't this still be solved by:

 seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

 the idea would be that, if seccomp_add_filter fails, then you give up
 and, if it succeeds, then you're done.  It shouldn't fail unless out
 of memory or you've nested too deeply.

 I wanted to keep the case of being able to to wait for non-ancestor
 threads to finish. For example, 2 threads start and set separate
 filters. 1 does work and exits, 2 starts another thread (3) which adds
 filters, does work, and then waits for 1 to finish by calling TSYNC.
 Once 1 dies, TSYNC succeeds. In the case of not having direct control
 over thread lifetime (say, when using third-party libraries), I'd like
 to retain the flexibility of being able to do TSYNC without needing a
 filter being attached to it.

 I must admit this strikes me as odd.  What's the point of having a
 thread set a filter if it intends to be a short-lived thread?

 I was illustrating the potential insanity of third-party libraries.
 There isn't much sense in that behavior, but if it exists, working
 around it is harder without the separate TSYNC-only call.

 In any case, I must have missed the ability for TSYNC to block.  Hmm.
 That seems complicated, albeit potentially useful.

 Oh, no, I didn't mean to imply TSYNC should block. I meant that thread
 3 could do:

 while (TSYNC-fails)
wait-on-or-kill-unexpected-thread


 Ok.

 I'm still not seeing the need for a separate TSYNC option, though --
 just add-a-filter-across-all-threads would work if it failed
 harmlessly on error.  FWIW, TSYNC is probably equivalent to adding an
 always-accept filter across all threads, although no one should really
 do the latter for efficiency reasons.

 Given the complexity of the locking, fail means I applied the
 change to all threads except for at least this one: *error code*,
 which means looping with the add-a-filter method means all the other
 threads keep getting filters added until there is full success. I
 don't want that overhead, so this keeps TSYNC distinctly separate.

Ugh, right.


 Because of the filter addition, when using add_filter-TSYNC, it's not
 sensible to continue after a failure. However, using just-TSYNC allows
 sensible re-trying. Since the environments where TSYNC intend to be
 used in can be very weird, I really want to retain the retry ability.

OK.  So what's wrong with the other approach in which the

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-27 Thread Kees Cook
On Tue, May 27, 2014 at 12:27 PM, Andy Lutomirski l...@amacapital.net wrote:
 On Tue, May 27, 2014 at 12:23 PM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 12:10 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 11:45 AM, Kees Cook keesc...@chromium.org wrote:
 On Tue, May 27, 2014 at 11:40 AM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Tue, May 27, 2014 at 11:24 AM, Kees Cook keesc...@chromium.org wrote:
 On Mon, May 26, 2014 at 12:27 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Fri, May 23, 2014 at 10:05 AM, Kees Cook keesc...@chromium.org 
 wrote:
 On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski l...@amacapital.net 
 wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook keesc...@chromium.org 
 wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started early 
 in
 the process lifetime (e.g., by code that is linked in). While it is
 possible to apply permissive programs prior to process start up, it 
 is
 difficult to further restrict the kernel ABI to those threads after 
 that
 point.

 This change adds a new seccomp extension action for synchronizing 
 thread
 group seccomp filters and a prctl() for accessing that functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at 
 filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
 SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when 
 calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), 
 it
 will attempt to synchronize all threads in current's threadgroup to 
 its
 seccomp filter program. This is possible iff all threads are using a 
 filter
 that is an ancestor to the filter current is attempting to 
 synchronize to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) are 
 also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been 
 set on the
 calling thread, no_new_privs will be set for all synchronized 
 threads too.
 On success, 0 is returned. On failure, the pid of one of the failing 
 threads
 will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing filters
 being separate operations?  If not, I think this would be easier to
 understand and to use if there was just a single operation.

 Yes: if the other thread's lifetime is not well controlled, it's good
 to be able to have a distinct interface to retry the thread sync that
 doesn't require adding no-op filters.

 Wouldn't this still be solved by:

 seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

 the idea would be that, if seccomp_add_filter fails, then you give up
 and, if it succeeds, then you're done.  It shouldn't fail unless out
 of memory or you've nested too deeply.

 I wanted to keep the case of being able to to wait for non-ancestor
 threads to finish. For example, 2 threads start and set separate
 filters. 1 does work and exits, 2 starts another thread (3) which adds
 filters, does work, and then waits for 1 to finish by calling TSYNC.
 Once 1 dies, TSYNC succeeds. In the case of not having direct control
 over thread lifetime (say, when using third-party libraries), I'd like
 to retain the flexibility of being able to do TSYNC without needing a
 filter being attached to it.

 I must admit this strikes me as odd.  What's the point of having a
 thread set a filter if it intends to be a short-lived thread?

 I was illustrating the potential insanity of third-party libraries.
 There isn't much sense in that behavior, but if it exists, working
 around it is harder without the separate TSYNC-only call.

 In any case, I must have missed the ability for TSYNC to block.  Hmm.
 That seems complicated, albeit potentially useful.

 Oh, no, I didn't mean to imply TSYNC should block. I meant that thread
 3 could do:

 while (TSYNC-fails)
wait-on-or-kill-unexpected-thread


 Ok.

 I'm still not seeing the need for a separate TSYNC option, though --
 just add-a-filter-across-all-threads would work if it failed
 harmlessly on error.  FWIW, TSYNC is probably equivalent to adding an
 always-accept filter across all threads, although no one should really
 do the latter for efficiency reasons.

 Given the complexity of the locking, fail means I applied the
 change to all threads except for at least this one: *error code*,
 which means looping with the add-a-filter method means all the other
 threads keep getting filters added until there is full success. I
 don't want that overhead, so this keeps TSYNC distinctly separate.

 Ugh, right.


 Because of the filter addition, when using add_filter-TSYNC, it's not
 sensible to continue after a failure. However, using just-TSYNC allows
 sensible re-trying. Since the environments where TSYNC intend to be
 used in can be very weird, I really want to 

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-26 Thread Andy Lutomirski
On Fri, May 23, 2014 at 10:05 AM, Kees Cook  wrote:
> On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski  wrote:
>> On Thu, May 22, 2014 at 4:05 PM, Kees Cook  wrote:
>>> Applying restrictive seccomp filter programs to large or diverse
>>> codebases often requires handling threads which may be started early in
>>> the process lifetime (e.g., by code that is linked in). While it is
>>> possible to apply permissive programs prior to process start up, it is
>>> difficult to further restrict the kernel ABI to those threads after that
>>> point.
>>>
>>> This change adds a new seccomp extension action for synchronizing thread
>>> group seccomp filters and a prctl() for accessing that functionality,
>>> as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
>>> installation time.
>>>
>>> When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_FILTER,
>>> flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when calling
>>> prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
>>> will attempt to synchronize all threads in current's threadgroup to its
>>> seccomp filter program. This is possible iff all threads are using a filter
>>> that is an ancestor to the filter current is attempting to synchronize to.
>>> NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
>>> treated as ancestors allowing threads to be transitioned into
>>> SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set on the
>>> calling thread, no_new_privs will be set for all synchronized threads too.
>>> On success, 0 is returned. On failure, the pid of one of the failing threads
>>> will be returned, with as many filters installed as possible.
>>
>> Is there a use case for adding a filter and synchronizing filters
>> being separate operations?  If not, I think this would be easier to
>> understand and to use if there was just a single operation.
>
> Yes: if the other thread's lifetime is not well controlled, it's good
> to be able to have a distinct interface to retry the thread sync that
> doesn't require adding "no-op" filters.

Wouldn't this still be solved by:

seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

the idea would be that, if seccomp_add_filter fails, then you give up
and, if it succeeds, then you're done.  It shouldn't fail unless out
of memory or you've nested too deeply.

>
>> If you did that, you'd have to decide whether to continue requiring
>> that all the other threads have a filter that's an ancestor of the
>> current thread's filter.
>
> This is required no matter what to make sure there is no way to
> replace a filter tree with a different one (allowing accidental
> bypasses, misbehavior, etc).

What I mean is:  should the add-new-filter-to-all-threads operation
add the new filter to all threads, regardless of what their current
state is, or should it fail if any thread has a filter that isn't an
ancestor of the current thread's filter?  Either version should be
safe.

--Andy
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-26 Thread Andy Lutomirski
On Fri, May 23, 2014 at 10:05 AM, Kees Cook keesc...@chromium.org wrote:
 On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski l...@amacapital.net wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook keesc...@chromium.org wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started early in
 the process lifetime (e.g., by code that is linked in). While it is
 possible to apply permissive programs prior to process start up, it is
 difficult to further restrict the kernel ABI to those threads after that
 point.

 This change adds a new seccomp extension action for synchronizing thread
 group seccomp filters and a prctl() for accessing that functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
 will attempt to synchronize all threads in current's threadgroup to its
 seccomp filter program. This is possible iff all threads are using a filter
 that is an ancestor to the filter current is attempting to synchronize to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set on the
 calling thread, no_new_privs will be set for all synchronized threads too.
 On success, 0 is returned. On failure, the pid of one of the failing threads
 will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing filters
 being separate operations?  If not, I think this would be easier to
 understand and to use if there was just a single operation.

 Yes: if the other thread's lifetime is not well controlled, it's good
 to be able to have a distinct interface to retry the thread sync that
 doesn't require adding no-op filters.

Wouldn't this still be solved by:

seccomp_add_filter(final_filter, SECCOMP_FILTER_ALL_THREADS);

the idea would be that, if seccomp_add_filter fails, then you give up
and, if it succeeds, then you're done.  It shouldn't fail unless out
of memory or you've nested too deeply.


 If you did that, you'd have to decide whether to continue requiring
 that all the other threads have a filter that's an ancestor of the
 current thread's filter.

 This is required no matter what to make sure there is no way to
 replace a filter tree with a different one (allowing accidental
 bypasses, misbehavior, etc).

What I mean is:  should the add-new-filter-to-all-threads operation
add the new filter to all threads, regardless of what their current
state is, or should it fail if any thread has a filter that isn't an
ancestor of the current thread's filter?  Either version should be
safe.

--Andy
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-23 Thread Kees Cook
On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski  wrote:
> On Thu, May 22, 2014 at 4:05 PM, Kees Cook  wrote:
>> Applying restrictive seccomp filter programs to large or diverse
>> codebases often requires handling threads which may be started early in
>> the process lifetime (e.g., by code that is linked in). While it is
>> possible to apply permissive programs prior to process start up, it is
>> difficult to further restrict the kernel ABI to those threads after that
>> point.
>>
>> This change adds a new seccomp extension action for synchronizing thread
>> group seccomp filters and a prctl() for accessing that functionality,
>> as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
>> installation time.
>>
>> When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_FILTER,
>> flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when calling
>> prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
>> will attempt to synchronize all threads in current's threadgroup to its
>> seccomp filter program. This is possible iff all threads are using a filter
>> that is an ancestor to the filter current is attempting to synchronize to.
>> NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
>> treated as ancestors allowing threads to be transitioned into
>> SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set on the
>> calling thread, no_new_privs will be set for all synchronized threads too.
>> On success, 0 is returned. On failure, the pid of one of the failing threads
>> will be returned, with as many filters installed as possible.
>
> Is there a use case for adding a filter and synchronizing filters
> being separate operations?  If not, I think this would be easier to
> understand and to use if there was just a single operation.

Yes: if the other thread's lifetime is not well controlled, it's good
to be able to have a distinct interface to retry the thread sync that
doesn't require adding "no-op" filters.

> If you did that, you'd have to decide whether to continue requiring
> that all the other threads have a filter that's an ancestor of the
> current thread's filter.

This is required no matter what to make sure there is no way to
replace a filter tree with a different one (allowing accidental
bypasses, misbehavior, etc).

-Kees

-- 
Kees Cook
Chrome OS Security
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-23 Thread Kees Cook
On Thu, May 22, 2014 at 4:11 PM, Andy Lutomirski l...@amacapital.net wrote:
 On Thu, May 22, 2014 at 4:05 PM, Kees Cook keesc...@chromium.org wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started early in
 the process lifetime (e.g., by code that is linked in). While it is
 possible to apply permissive programs prior to process start up, it is
 difficult to further restrict the kernel ABI to those threads after that
 point.

 This change adds a new seccomp extension action for synchronizing thread
 group seccomp filters and a prctl() for accessing that functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
 will attempt to synchronize all threads in current's threadgroup to its
 seccomp filter program. This is possible iff all threads are using a filter
 that is an ancestor to the filter current is attempting to synchronize to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set on the
 calling thread, no_new_privs will be set for all synchronized threads too.
 On success, 0 is returned. On failure, the pid of one of the failing threads
 will be returned, with as many filters installed as possible.

 Is there a use case for adding a filter and synchronizing filters
 being separate operations?  If not, I think this would be easier to
 understand and to use if there was just a single operation.

Yes: if the other thread's lifetime is not well controlled, it's good
to be able to have a distinct interface to retry the thread sync that
doesn't require adding no-op filters.

 If you did that, you'd have to decide whether to continue requiring
 that all the other threads have a filter that's an ancestor of the
 current thread's filter.

This is required no matter what to make sure there is no way to
replace a filter tree with a different one (allowing accidental
bypasses, misbehavior, etc).

-Kees

-- 
Kees Cook
Chrome OS Security
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-22 Thread Kees Cook
Applying restrictive seccomp filter programs to large or diverse
codebases often requires handling threads which may be started early in
the process lifetime (e.g., by code that is linked in). While it is
possible to apply permissive programs prior to process start up, it is
difficult to further restrict the kernel ABI to those threads after that
point.

This change adds a new seccomp extension action for synchronizing thread
group seccomp filters and a prctl() for accessing that functionality,
as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
installation time.

When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_FILTER,
flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when calling
prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
will attempt to synchronize all threads in current's threadgroup to its
seccomp filter program. This is possible iff all threads are using a filter
that is an ancestor to the filter current is attempting to synchronize to.
NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
treated as ancestors allowing threads to be transitioned into
SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set on the
calling thread, no_new_privs will be set for all synchronized threads too.
On success, 0 is returned. On failure, the pid of one of the failing threads
will be returned, with as many filters installed as possible.

The race conditions are against another thread calling TSYNC, another
thread performing a clone, and another thread changing its filter. The
seccomp write lock is sufficient for these cases, though the clone
case is assisted by the tasklist_lock so that new threads must have a
duplicate of its parent seccomp state when it appears on the tasklist.

Based on patches by Will Drewry.

Suggested-by: Julien Tinnes 
Signed-off-by: Kees Cook 
---
 Documentation/prctl/seccomp_filter.txt |   22 ++-
 include/uapi/linux/seccomp.h   |4 ++
 kernel/seccomp.c   |  106 ++--
 3 files changed, 126 insertions(+), 6 deletions(-)

diff --git a/Documentation/prctl/seccomp_filter.txt 
b/Documentation/prctl/seccomp_filter.txt
index a5e47753b32d..2924a3450870 100644
--- a/Documentation/prctl/seccomp_filter.txt
+++ b/Documentation/prctl/seccomp_filter.txt
@@ -235,5 +235,23 @@ prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
SECCOMP_EXT_ACT_FILTER, flags, prog):
Attach filter, with flags.
 
This is the same as prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prog)
-   except with the addition of optional "flags" argument. No flags
-   are currently recognized.
+   except with the addition of optional "flags" argument:
+
+   SECCOMP_FILTER_TSYNC:
+   After installing filter, perform threadgroup sync, as
+   described below for SECCOMP_EXT_ACT_TSYNC.
+
+prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0):
+   Thread synchronization.
+
+   The current thread requests to synchronize all threads in current's
+   threadgroup to its seccomp filter program. This is possible iff all
+   threads are using a filter that is an ancestor to the filter current
+   is attempting to synchronize to, or the thread has not yet entered
+   seccomp. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set on the
+   calling thread, no_new_privs will be set for all synchronized threads
+   too.
+
+   On success, 0 is returned. On failure, all synchronizable threads
+   will have been synchronized, and the pid of one of the failing
+   threads will be returned.
diff --git a/include/uapi/linux/seccomp.h b/include/uapi/linux/seccomp.h
index d7ad626c684d..7f4431b90fd4 100644
--- a/include/uapi/linux/seccomp.h
+++ b/include/uapi/linux/seccomp.h
@@ -15,6 +15,10 @@
 
 /* Valid extension actions as arg3 to prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT) */
 #define SECCOMP_EXT_ACT_FILTER 1 /* apply seccomp-bpf filter with flags */
+#define SECCOMP_EXT_ACT_TSYNC  2 /* synchronize threadgroup filters */
+
+/* Flags for prctl arg4 when calling SECCOMP_EXT_ACT_FILTER */
+#define SECCOMP_FILTER_TSYNC   1 /* synchronize threadgroup to filter */
 
 /*
  * All BPF programs must return a 32-bit value.
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 088244b2c765..d39c0dad9655 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -25,6 +25,7 @@
 #ifdef CONFIG_SECCOMP_FILTER
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -198,6 +199,93 @@ static u32 seccomp_run_filters(int syscall)
return ret;
 }
 
+/* Returns 1 if the candidate is an ancestor. */
+static int is_ancestor(struct seccomp_filter *candidate,
+  struct seccomp_filter *child)
+{
+   /* NULL is the root ancestor. */
+   if (candidate == NULL)
+   return 1;
+   for (; child; child = child->prev)
+   if (child == candidate)
+ 

Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-22 Thread Andy Lutomirski
On Thu, May 22, 2014 at 4:05 PM, Kees Cook  wrote:
> Applying restrictive seccomp filter programs to large or diverse
> codebases often requires handling threads which may be started early in
> the process lifetime (e.g., by code that is linked in). While it is
> possible to apply permissive programs prior to process start up, it is
> difficult to further restrict the kernel ABI to those threads after that
> point.
>
> This change adds a new seccomp extension action for synchronizing thread
> group seccomp filters and a prctl() for accessing that functionality,
> as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
> installation time.
>
> When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_FILTER,
> flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when calling
> prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
> will attempt to synchronize all threads in current's threadgroup to its
> seccomp filter program. This is possible iff all threads are using a filter
> that is an ancestor to the filter current is attempting to synchronize to.
> NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
> treated as ancestors allowing threads to be transitioned into
> SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set on the
> calling thread, no_new_privs will be set for all synchronized threads too.
> On success, 0 is returned. On failure, the pid of one of the failing threads
> will be returned, with as many filters installed as possible.

Is there a use case for adding a filter and synchronizing filters
being separate operations?  If not, I think this would be easier to
understand and to use if there was just a single operation.

If you did that, you'd have to decide whether to continue requiring
that all the other threads have a filter that's an ancestor of the
current thread's filter.

--Andy
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-22 Thread Andy Lutomirski
On Thu, May 22, 2014 at 4:05 PM, Kees Cook keesc...@chromium.org wrote:
 Applying restrictive seccomp filter programs to large or diverse
 codebases often requires handling threads which may be started early in
 the process lifetime (e.g., by code that is linked in). While it is
 possible to apply permissive programs prior to process start up, it is
 difficult to further restrict the kernel ABI to those threads after that
 point.

 This change adds a new seccomp extension action for synchronizing thread
 group seccomp filters and a prctl() for accessing that functionality,
 as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
 installation time.

 When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_FILTER,
 flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when calling
 prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
 will attempt to synchronize all threads in current's threadgroup to its
 seccomp filter program. This is possible iff all threads are using a filter
 that is an ancestor to the filter current is attempting to synchronize to.
 NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
 treated as ancestors allowing threads to be transitioned into
 SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set on the
 calling thread, no_new_privs will be set for all synchronized threads too.
 On success, 0 is returned. On failure, the pid of one of the failing threads
 will be returned, with as many filters installed as possible.

Is there a use case for adding a filter and synchronizing filters
being separate operations?  If not, I think this would be easier to
understand and to use if there was just a single operation.

If you did that, you'd have to decide whether to continue requiring
that all the other threads have a filter that's an ancestor of the
current thread's filter.

--Andy
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC

2014-05-22 Thread Kees Cook
Applying restrictive seccomp filter programs to large or diverse
codebases often requires handling threads which may be started early in
the process lifetime (e.g., by code that is linked in). While it is
possible to apply permissive programs prior to process start up, it is
difficult to further restrict the kernel ABI to those threads after that
point.

This change adds a new seccomp extension action for synchronizing thread
group seccomp filters and a prctl() for accessing that functionality,
as well as a flag for SECCOMP_EXT_ACT_FILTER to perform sync at filter
installation time.

When calling prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_FILTER,
flags, filter) with flags containing SECCOMP_FILTER_TSYNC, or when calling
prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0), it
will attempt to synchronize all threads in current's threadgroup to its
seccomp filter program. This is possible iff all threads are using a filter
that is an ancestor to the filter current is attempting to synchronize to.
NULL filters (where the task is running as SECCOMP_MODE_NONE) are also
treated as ancestors allowing threads to be transitioned into
SECCOMP_MODE_FILTER. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set on the
calling thread, no_new_privs will be set for all synchronized threads too.
On success, 0 is returned. On failure, the pid of one of the failing threads
will be returned, with as many filters installed as possible.

The race conditions are against another thread calling TSYNC, another
thread performing a clone, and another thread changing its filter. The
seccomp write lock is sufficient for these cases, though the clone
case is assisted by the tasklist_lock so that new threads must have a
duplicate of its parent seccomp state when it appears on the tasklist.

Based on patches by Will Drewry.

Suggested-by: Julien Tinnes j...@chromium.org
Signed-off-by: Kees Cook keesc...@chromium.org
---
 Documentation/prctl/seccomp_filter.txt |   22 ++-
 include/uapi/linux/seccomp.h   |4 ++
 kernel/seccomp.c   |  106 ++--
 3 files changed, 126 insertions(+), 6 deletions(-)

diff --git a/Documentation/prctl/seccomp_filter.txt 
b/Documentation/prctl/seccomp_filter.txt
index a5e47753b32d..2924a3450870 100644
--- a/Documentation/prctl/seccomp_filter.txt
+++ b/Documentation/prctl/seccomp_filter.txt
@@ -235,5 +235,23 @@ prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, 
SECCOMP_EXT_ACT_FILTER, flags, prog):
Attach filter, with flags.
 
This is the same as prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prog)
-   except with the addition of optional flags argument. No flags
-   are currently recognized.
+   except with the addition of optional flags argument:
+
+   SECCOMP_FILTER_TSYNC:
+   After installing filter, perform threadgroup sync, as
+   described below for SECCOMP_EXT_ACT_TSYNC.
+
+prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT, SECCOMP_EXT_ACT_TSYNC, 0, 0):
+   Thread synchronization.
+
+   The current thread requests to synchronize all threads in current's
+   threadgroup to its seccomp filter program. This is possible iff all
+   threads are using a filter that is an ancestor to the filter current
+   is attempting to synchronize to, or the thread has not yet entered
+   seccomp. If prctrl(PR_SET_NO_NEW_PRIVS, ...) has been set on the
+   calling thread, no_new_privs will be set for all synchronized threads
+   too.
+
+   On success, 0 is returned. On failure, all synchronizable threads
+   will have been synchronized, and the pid of one of the failing
+   threads will be returned.
diff --git a/include/uapi/linux/seccomp.h b/include/uapi/linux/seccomp.h
index d7ad626c684d..7f4431b90fd4 100644
--- a/include/uapi/linux/seccomp.h
+++ b/include/uapi/linux/seccomp.h
@@ -15,6 +15,10 @@
 
 /* Valid extension actions as arg3 to prctl(PR_SECCOMP_EXT, SECCOMP_EXT_ACT) */
 #define SECCOMP_EXT_ACT_FILTER 1 /* apply seccomp-bpf filter with flags */
+#define SECCOMP_EXT_ACT_TSYNC  2 /* synchronize threadgroup filters */
+
+/* Flags for prctl arg4 when calling SECCOMP_EXT_ACT_FILTER */
+#define SECCOMP_FILTER_TSYNC   1 /* synchronize threadgroup to filter */
 
 /*
  * All BPF programs must return a 32-bit value.
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 088244b2c765..d39c0dad9655 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -25,6 +25,7 @@
 #ifdef CONFIG_SECCOMP_FILTER
 #include asm/syscall.h
 #include linux/filter.h
+#include linux/pid.h
 #include linux/ptrace.h
 #include linux/security.h
 #include linux/tracehook.h
@@ -198,6 +199,93 @@ static u32 seccomp_run_filters(int syscall)
return ret;
 }
 
+/* Returns 1 if the candidate is an ancestor. */
+static int is_ancestor(struct seccomp_filter *candidate,
+  struct seccomp_filter *child)
+{
+   /* NULL is the root ancestor. */
+   if (candidate == NULL)
+