Re: [PATCH v5 6/6] seccomp: add SECCOMP_EXT_ACT_TSYNC and SECCOMP_FILTER_TSYNC
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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) +