Re: [PATCH 3/3] seccomp: introduce read protection for struct seccomp

2018-09-28 Thread Tycho Andersen
On Fri, Sep 28, 2018 at 11:54:22PM +0200, Jann Horn wrote:
> On Fri, Sep 28, 2018 at 11:36 PM Tycho Andersen  wrote:
> > On Fri, Sep 28, 2018 at 11:10:48PM +0200, Jann Horn wrote:
> > > On Fri, Sep 28, 2018 at 10:56 PM Tycho Andersen  wrote:
> > > >
> > > > On Fri, Sep 28, 2018 at 10:33:34PM +0200, Jann Horn wrote:
> > > > > On Fri, Sep 28, 2018 at 5:47 PM Tycho Andersen  wrote:
> > > > > > As Jann pointed out, there is a race between 
> > > > > > SECCOMP_FILTER_FLAG_TSYNC and
> > > > > > the ptrace code that can inspect a filter of another process. Let's
> > > > > > introduce read locking into the two ptrace accesses so that we 
> > > > > > don't race.
> > > > >
> > > > > Hmm. Is that true? The ptrace code uses get_nth_filter(), which holds
> > > > > the siglock while grabbing the seccomp filter and bumping its
> > > > > refcount. And TSYNC happens from seccomp_set_mode_filter(), which
> > > > > takes the siglock. So this looks okay to me?
> > > >
> > > > Oh, yes, you're right. So I guess we should just change the comment to
> > > > say we're using siglock to represent the read lock.
> > >
> > > Hmm... actually, looking at this closer, I think you only need the
> > > siglock for writing. As far as I can tell, any read (no matter if
> > > current or non-current) can just use READ_ONCE(), because once a
> > > seccomp filter is in a task's seccomp filter chain, it can't be freed
> > > until the task reaches free_task() and calls put_seccomp_filter() from
> > > there. And if the task whose seccomp filter you're trying to read can
> > > reach free_task(), you have bigger problems.
> >
> > Ok; looks like get_nth_filter() took the siglock anyway. Since we get
> > the filters in these two functions in get_nth_filter(), I think it's
> > enough just to just,
> >
> > diff --git a/kernel/seccomp.c b/kernel/seccomp.c
> > index f65d47650ac1..79d833ed4c34 100644
> > --- a/kernel/seccomp.c
> > +++ b/kernel/seccomp.c
> > @@ -1001,7 +1001,7 @@ static struct seccomp_filter *get_nth_filter(struct 
> > task_struct *task,
> > return ERR_PTR(-EINVAL);
> > }
> >
> > -   orig = task->seccomp.filter;
> > +   orig = READ_ONCE(task->seccomp.filter);
> > __get_seccomp_filter(orig);
> > spin_unlock_irq(>sighand->siglock);
> 
> Huh? Now you're holding the siglock *and* you're using READ_ONCE()?
> I'm not sure what you're trying to accomplish here.

Yes, let's just drop this patch all together.

Tycho


Re: [PATCH 3/3] seccomp: introduce read protection for struct seccomp

2018-09-28 Thread Tycho Andersen
On Fri, Sep 28, 2018 at 11:54:22PM +0200, Jann Horn wrote:
> On Fri, Sep 28, 2018 at 11:36 PM Tycho Andersen  wrote:
> > On Fri, Sep 28, 2018 at 11:10:48PM +0200, Jann Horn wrote:
> > > On Fri, Sep 28, 2018 at 10:56 PM Tycho Andersen  wrote:
> > > >
> > > > On Fri, Sep 28, 2018 at 10:33:34PM +0200, Jann Horn wrote:
> > > > > On Fri, Sep 28, 2018 at 5:47 PM Tycho Andersen  wrote:
> > > > > > As Jann pointed out, there is a race between 
> > > > > > SECCOMP_FILTER_FLAG_TSYNC and
> > > > > > the ptrace code that can inspect a filter of another process. Let's
> > > > > > introduce read locking into the two ptrace accesses so that we 
> > > > > > don't race.
> > > > >
> > > > > Hmm. Is that true? The ptrace code uses get_nth_filter(), which holds
> > > > > the siglock while grabbing the seccomp filter and bumping its
> > > > > refcount. And TSYNC happens from seccomp_set_mode_filter(), which
> > > > > takes the siglock. So this looks okay to me?
> > > >
> > > > Oh, yes, you're right. So I guess we should just change the comment to
> > > > say we're using siglock to represent the read lock.
> > >
> > > Hmm... actually, looking at this closer, I think you only need the
> > > siglock for writing. As far as I can tell, any read (no matter if
> > > current or non-current) can just use READ_ONCE(), because once a
> > > seccomp filter is in a task's seccomp filter chain, it can't be freed
> > > until the task reaches free_task() and calls put_seccomp_filter() from
> > > there. And if the task whose seccomp filter you're trying to read can
> > > reach free_task(), you have bigger problems.
> >
> > Ok; looks like get_nth_filter() took the siglock anyway. Since we get
> > the filters in these two functions in get_nth_filter(), I think it's
> > enough just to just,
> >
> > diff --git a/kernel/seccomp.c b/kernel/seccomp.c
> > index f65d47650ac1..79d833ed4c34 100644
> > --- a/kernel/seccomp.c
> > +++ b/kernel/seccomp.c
> > @@ -1001,7 +1001,7 @@ static struct seccomp_filter *get_nth_filter(struct 
> > task_struct *task,
> > return ERR_PTR(-EINVAL);
> > }
> >
> > -   orig = task->seccomp.filter;
> > +   orig = READ_ONCE(task->seccomp.filter);
> > __get_seccomp_filter(orig);
> > spin_unlock_irq(>sighand->siglock);
> 
> Huh? Now you're holding the siglock *and* you're using READ_ONCE()?
> I'm not sure what you're trying to accomplish here.

Yes, let's just drop this patch all together.

Tycho


Re: [PATCH 3/3] seccomp: introduce read protection for struct seccomp

2018-09-28 Thread Jann Horn
On Fri, Sep 28, 2018 at 11:36 PM Tycho Andersen  wrote:
> On Fri, Sep 28, 2018 at 11:10:48PM +0200, Jann Horn wrote:
> > On Fri, Sep 28, 2018 at 10:56 PM Tycho Andersen  wrote:
> > >
> > > On Fri, Sep 28, 2018 at 10:33:34PM +0200, Jann Horn wrote:
> > > > On Fri, Sep 28, 2018 at 5:47 PM Tycho Andersen  wrote:
> > > > > As Jann pointed out, there is a race between 
> > > > > SECCOMP_FILTER_FLAG_TSYNC and
> > > > > the ptrace code that can inspect a filter of another process. Let's
> > > > > introduce read locking into the two ptrace accesses so that we don't 
> > > > > race.
> > > >
> > > > Hmm. Is that true? The ptrace code uses get_nth_filter(), which holds
> > > > the siglock while grabbing the seccomp filter and bumping its
> > > > refcount. And TSYNC happens from seccomp_set_mode_filter(), which
> > > > takes the siglock. So this looks okay to me?
> > >
> > > Oh, yes, you're right. So I guess we should just change the comment to
> > > say we're using siglock to represent the read lock.
> >
> > Hmm... actually, looking at this closer, I think you only need the
> > siglock for writing. As far as I can tell, any read (no matter if
> > current or non-current) can just use READ_ONCE(), because once a
> > seccomp filter is in a task's seccomp filter chain, it can't be freed
> > until the task reaches free_task() and calls put_seccomp_filter() from
> > there. And if the task whose seccomp filter you're trying to read can
> > reach free_task(), you have bigger problems.
>
> Ok; looks like get_nth_filter() took the siglock anyway. Since we get
> the filters in these two functions in get_nth_filter(), I think it's
> enough just to just,
>
> diff --git a/kernel/seccomp.c b/kernel/seccomp.c
> index f65d47650ac1..79d833ed4c34 100644
> --- a/kernel/seccomp.c
> +++ b/kernel/seccomp.c
> @@ -1001,7 +1001,7 @@ static struct seccomp_filter *get_nth_filter(struct 
> task_struct *task,
> return ERR_PTR(-EINVAL);
> }
>
> -   orig = task->seccomp.filter;
> +   orig = READ_ONCE(task->seccomp.filter);
> __get_seccomp_filter(orig);
> spin_unlock_irq(>sighand->siglock);

Huh? Now you're holding the siglock *and* you're using READ_ONCE()?
I'm not sure what you're trying to accomplish here.

> since once it's returned from get_nth_filter() we don't need to worry
> about multiple accesses?
>
> Tycho


Re: [PATCH 3/3] seccomp: introduce read protection for struct seccomp

2018-09-28 Thread Jann Horn
On Fri, Sep 28, 2018 at 11:36 PM Tycho Andersen  wrote:
> On Fri, Sep 28, 2018 at 11:10:48PM +0200, Jann Horn wrote:
> > On Fri, Sep 28, 2018 at 10:56 PM Tycho Andersen  wrote:
> > >
> > > On Fri, Sep 28, 2018 at 10:33:34PM +0200, Jann Horn wrote:
> > > > On Fri, Sep 28, 2018 at 5:47 PM Tycho Andersen  wrote:
> > > > > As Jann pointed out, there is a race between 
> > > > > SECCOMP_FILTER_FLAG_TSYNC and
> > > > > the ptrace code that can inspect a filter of another process. Let's
> > > > > introduce read locking into the two ptrace accesses so that we don't 
> > > > > race.
> > > >
> > > > Hmm. Is that true? The ptrace code uses get_nth_filter(), which holds
> > > > the siglock while grabbing the seccomp filter and bumping its
> > > > refcount. And TSYNC happens from seccomp_set_mode_filter(), which
> > > > takes the siglock. So this looks okay to me?
> > >
> > > Oh, yes, you're right. So I guess we should just change the comment to
> > > say we're using siglock to represent the read lock.
> >
> > Hmm... actually, looking at this closer, I think you only need the
> > siglock for writing. As far as I can tell, any read (no matter if
> > current or non-current) can just use READ_ONCE(), because once a
> > seccomp filter is in a task's seccomp filter chain, it can't be freed
> > until the task reaches free_task() and calls put_seccomp_filter() from
> > there. And if the task whose seccomp filter you're trying to read can
> > reach free_task(), you have bigger problems.
>
> Ok; looks like get_nth_filter() took the siglock anyway. Since we get
> the filters in these two functions in get_nth_filter(), I think it's
> enough just to just,
>
> diff --git a/kernel/seccomp.c b/kernel/seccomp.c
> index f65d47650ac1..79d833ed4c34 100644
> --- a/kernel/seccomp.c
> +++ b/kernel/seccomp.c
> @@ -1001,7 +1001,7 @@ static struct seccomp_filter *get_nth_filter(struct 
> task_struct *task,
> return ERR_PTR(-EINVAL);
> }
>
> -   orig = task->seccomp.filter;
> +   orig = READ_ONCE(task->seccomp.filter);
> __get_seccomp_filter(orig);
> spin_unlock_irq(>sighand->siglock);

Huh? Now you're holding the siglock *and* you're using READ_ONCE()?
I'm not sure what you're trying to accomplish here.

> since once it's returned from get_nth_filter() we don't need to worry
> about multiple accesses?
>
> Tycho


Re: [PATCH 3/3] seccomp: introduce read protection for struct seccomp

2018-09-28 Thread Tycho Andersen
On Fri, Sep 28, 2018 at 11:10:48PM +0200, Jann Horn wrote:
> On Fri, Sep 28, 2018 at 10:56 PM Tycho Andersen  wrote:
> >
> > On Fri, Sep 28, 2018 at 10:33:34PM +0200, Jann Horn wrote:
> > > On Fri, Sep 28, 2018 at 5:47 PM Tycho Andersen  wrote:
> > > > As Jann pointed out, there is a race between SECCOMP_FILTER_FLAG_TSYNC 
> > > > and
> > > > the ptrace code that can inspect a filter of another process. Let's
> > > > introduce read locking into the two ptrace accesses so that we don't 
> > > > race.
> > >
> > > Hmm. Is that true? The ptrace code uses get_nth_filter(), which holds
> > > the siglock while grabbing the seccomp filter and bumping its
> > > refcount. And TSYNC happens from seccomp_set_mode_filter(), which
> > > takes the siglock. So this looks okay to me?
> >
> > Oh, yes, you're right. So I guess we should just change the comment to
> > say we're using siglock to represent the read lock.
> 
> Hmm... actually, looking at this closer, I think you only need the
> siglock for writing. As far as I can tell, any read (no matter if
> current or non-current) can just use READ_ONCE(), because once a
> seccomp filter is in a task's seccomp filter chain, it can't be freed
> until the task reaches free_task() and calls put_seccomp_filter() from
> there. And if the task whose seccomp filter you're trying to read can
> reach free_task(), you have bigger problems.

Ok; looks like get_nth_filter() took the siglock anyway. Since we get
the filters in these two functions in get_nth_filter(), I think it's
enough just to just,

diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index f65d47650ac1..79d833ed4c34 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -1001,7 +1001,7 @@ static struct seccomp_filter *get_nth_filter(struct 
task_struct *task,
return ERR_PTR(-EINVAL);
}
 
-   orig = task->seccomp.filter;
+   orig = READ_ONCE(task->seccomp.filter);
__get_seccomp_filter(orig);
spin_unlock_irq(>sighand->siglock);
 

since once it's returned from get_nth_filter() we don't need to worry
about multiple accesses?

Tycho


Re: [PATCH 3/3] seccomp: introduce read protection for struct seccomp

2018-09-28 Thread Tycho Andersen
On Fri, Sep 28, 2018 at 11:10:48PM +0200, Jann Horn wrote:
> On Fri, Sep 28, 2018 at 10:56 PM Tycho Andersen  wrote:
> >
> > On Fri, Sep 28, 2018 at 10:33:34PM +0200, Jann Horn wrote:
> > > On Fri, Sep 28, 2018 at 5:47 PM Tycho Andersen  wrote:
> > > > As Jann pointed out, there is a race between SECCOMP_FILTER_FLAG_TSYNC 
> > > > and
> > > > the ptrace code that can inspect a filter of another process. Let's
> > > > introduce read locking into the two ptrace accesses so that we don't 
> > > > race.
> > >
> > > Hmm. Is that true? The ptrace code uses get_nth_filter(), which holds
> > > the siglock while grabbing the seccomp filter and bumping its
> > > refcount. And TSYNC happens from seccomp_set_mode_filter(), which
> > > takes the siglock. So this looks okay to me?
> >
> > Oh, yes, you're right. So I guess we should just change the comment to
> > say we're using siglock to represent the read lock.
> 
> Hmm... actually, looking at this closer, I think you only need the
> siglock for writing. As far as I can tell, any read (no matter if
> current or non-current) can just use READ_ONCE(), because once a
> seccomp filter is in a task's seccomp filter chain, it can't be freed
> until the task reaches free_task() and calls put_seccomp_filter() from
> there. And if the task whose seccomp filter you're trying to read can
> reach free_task(), you have bigger problems.

Ok; looks like get_nth_filter() took the siglock anyway. Since we get
the filters in these two functions in get_nth_filter(), I think it's
enough just to just,

diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index f65d47650ac1..79d833ed4c34 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -1001,7 +1001,7 @@ static struct seccomp_filter *get_nth_filter(struct 
task_struct *task,
return ERR_PTR(-EINVAL);
}
 
-   orig = task->seccomp.filter;
+   orig = READ_ONCE(task->seccomp.filter);
__get_seccomp_filter(orig);
spin_unlock_irq(>sighand->siglock);
 

since once it's returned from get_nth_filter() we don't need to worry
about multiple accesses?

Tycho


Re: [PATCH 3/3] seccomp: introduce read protection for struct seccomp

2018-09-28 Thread Jann Horn
On Fri, Sep 28, 2018 at 10:56 PM Tycho Andersen  wrote:
>
> On Fri, Sep 28, 2018 at 10:33:34PM +0200, Jann Horn wrote:
> > On Fri, Sep 28, 2018 at 5:47 PM Tycho Andersen  wrote:
> > > As Jann pointed out, there is a race between SECCOMP_FILTER_FLAG_TSYNC and
> > > the ptrace code that can inspect a filter of another process. Let's
> > > introduce read locking into the two ptrace accesses so that we don't race.
> >
> > Hmm. Is that true? The ptrace code uses get_nth_filter(), which holds
> > the siglock while grabbing the seccomp filter and bumping its
> > refcount. And TSYNC happens from seccomp_set_mode_filter(), which
> > takes the siglock. So this looks okay to me?
>
> Oh, yes, you're right. So I guess we should just change the comment to
> say we're using siglock to represent the read lock.

Hmm... actually, looking at this closer, I think you only need the
siglock for writing. As far as I can tell, any read (no matter if
current or non-current) can just use READ_ONCE(), because once a
seccomp filter is in a task's seccomp filter chain, it can't be freed
until the task reaches free_task() and calls put_seccomp_filter() from
there. And if the task whose seccomp filter you're trying to read can
reach free_task(), you have bigger problems.


Re: [PATCH 3/3] seccomp: introduce read protection for struct seccomp

2018-09-28 Thread Jann Horn
On Fri, Sep 28, 2018 at 10:56 PM Tycho Andersen  wrote:
>
> On Fri, Sep 28, 2018 at 10:33:34PM +0200, Jann Horn wrote:
> > On Fri, Sep 28, 2018 at 5:47 PM Tycho Andersen  wrote:
> > > As Jann pointed out, there is a race between SECCOMP_FILTER_FLAG_TSYNC and
> > > the ptrace code that can inspect a filter of another process. Let's
> > > introduce read locking into the two ptrace accesses so that we don't race.
> >
> > Hmm. Is that true? The ptrace code uses get_nth_filter(), which holds
> > the siglock while grabbing the seccomp filter and bumping its
> > refcount. And TSYNC happens from seccomp_set_mode_filter(), which
> > takes the siglock. So this looks okay to me?
>
> Oh, yes, you're right. So I guess we should just change the comment to
> say we're using siglock to represent the read lock.

Hmm... actually, looking at this closer, I think you only need the
siglock for writing. As far as I can tell, any read (no matter if
current or non-current) can just use READ_ONCE(), because once a
seccomp filter is in a task's seccomp filter chain, it can't be freed
until the task reaches free_task() and calls put_seccomp_filter() from
there. And if the task whose seccomp filter you're trying to read can
reach free_task(), you have bigger problems.


Re: [PATCH 3/3] seccomp: introduce read protection for struct seccomp

2018-09-28 Thread Tycho Andersen
On Fri, Sep 28, 2018 at 10:33:34PM +0200, Jann Horn wrote:
> On Fri, Sep 28, 2018 at 5:47 PM Tycho Andersen  wrote:
> > As Jann pointed out, there is a race between SECCOMP_FILTER_FLAG_TSYNC and
> > the ptrace code that can inspect a filter of another process. Let's
> > introduce read locking into the two ptrace accesses so that we don't race.
> 
> Hmm. Is that true? The ptrace code uses get_nth_filter(), which holds
> the siglock while grabbing the seccomp filter and bumping its
> refcount. And TSYNC happens from seccomp_set_mode_filter(), which
> takes the siglock. So this looks okay to me?

Oh, yes, you're right. So I guess we should just change the comment to
say we're using siglock to represent the read lock.

Tycho


Re: [PATCH 3/3] seccomp: introduce read protection for struct seccomp

2018-09-28 Thread Tycho Andersen
On Fri, Sep 28, 2018 at 10:33:34PM +0200, Jann Horn wrote:
> On Fri, Sep 28, 2018 at 5:47 PM Tycho Andersen  wrote:
> > As Jann pointed out, there is a race between SECCOMP_FILTER_FLAG_TSYNC and
> > the ptrace code that can inspect a filter of another process. Let's
> > introduce read locking into the two ptrace accesses so that we don't race.
> 
> Hmm. Is that true? The ptrace code uses get_nth_filter(), which holds
> the siglock while grabbing the seccomp filter and bumping its
> refcount. And TSYNC happens from seccomp_set_mode_filter(), which
> takes the siglock. So this looks okay to me?

Oh, yes, you're right. So I guess we should just change the comment to
say we're using siglock to represent the read lock.

Tycho


Re: [PATCH 3/3] seccomp: introduce read protection for struct seccomp

2018-09-28 Thread Jann Horn
On Fri, Sep 28, 2018 at 5:47 PM Tycho Andersen  wrote:
> As Jann pointed out, there is a race between SECCOMP_FILTER_FLAG_TSYNC and
> the ptrace code that can inspect a filter of another process. Let's
> introduce read locking into the two ptrace accesses so that we don't race.

Hmm. Is that true? The ptrace code uses get_nth_filter(), which holds
the siglock while grabbing the seccomp filter and bumping its
refcount. And TSYNC happens from seccomp_set_mode_filter(), which
takes the siglock. So this looks okay to me?

> Signed-off-by: Tycho Andersen 
> Reported-by: Jann Horn 
> CC: Kees Cook 
> CC: Andy Lutomirski 
> ---
>  include/linux/seccomp.h |  4 ++--
>  kernel/seccomp.c| 10 ++
>  2 files changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
> index 8429bdda947a..30b27e898162 100644
> --- a/include/linux/seccomp.h
> +++ b/include/linux/seccomp.h
> @@ -22,8 +22,8 @@ struct seccomp_filter;
>   * @filter: must always point to a valid seccomp-filter or NULL as it is
>   *  accessed without locking during system call entry.
>   *
> - *  @filter must only be accessed from the context of current as 
> there
> - *  is no read locking.
> + *  @filter is read-protected by task->signal->cred_guard_mutex when
> + *  outside of current context.
>   */
>  struct seccomp {
> int mode;
> diff --git a/kernel/seccomp.c b/kernel/seccomp.c
> index ef80dd19f268..f65d47650ac1 100644
> --- a/kernel/seccomp.c
> +++ b/kernel/seccomp.c
> @@ -1042,7 +1042,12 @@ int seccomp_get_filter(struct task_struct *task, 
> unsigned long filter_off,
> return -EACCES;
> }
>
> +   ret = mutex_lock_killable(>signal->cred_guard_mutex);
> +   if (ret < 0)
> +   return ret;
> +
> filter = get_nth_filter(task, filter_off);
> +   mutex_unlock(>signal->cred_guard_mutex);
> if (IS_ERR(filter))
> return PTR_ERR(filter);
>
> @@ -1088,7 +1093,12 @@ int seccomp_get_metadata(struct task_struct *task,
> if (copy_from_user(_off, data, sizeof(kmd.filter_off)))
> return -EFAULT;
>
> +   ret = mutex_lock_killable(>signal->cred_guard_mutex);
> +   if (ret < 0)
> +   return ret;
> +
> filter = get_nth_filter(task, kmd.filter_off);
> +   mutex_unlock(>signal->cred_guard_mutex);
> if (IS_ERR(filter))
> return PTR_ERR(filter);
>
> --
> 2.17.1
>


Re: [PATCH 3/3] seccomp: introduce read protection for struct seccomp

2018-09-28 Thread Jann Horn
On Fri, Sep 28, 2018 at 5:47 PM Tycho Andersen  wrote:
> As Jann pointed out, there is a race between SECCOMP_FILTER_FLAG_TSYNC and
> the ptrace code that can inspect a filter of another process. Let's
> introduce read locking into the two ptrace accesses so that we don't race.

Hmm. Is that true? The ptrace code uses get_nth_filter(), which holds
the siglock while grabbing the seccomp filter and bumping its
refcount. And TSYNC happens from seccomp_set_mode_filter(), which
takes the siglock. So this looks okay to me?

> Signed-off-by: Tycho Andersen 
> Reported-by: Jann Horn 
> CC: Kees Cook 
> CC: Andy Lutomirski 
> ---
>  include/linux/seccomp.h |  4 ++--
>  kernel/seccomp.c| 10 ++
>  2 files changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
> index 8429bdda947a..30b27e898162 100644
> --- a/include/linux/seccomp.h
> +++ b/include/linux/seccomp.h
> @@ -22,8 +22,8 @@ struct seccomp_filter;
>   * @filter: must always point to a valid seccomp-filter or NULL as it is
>   *  accessed without locking during system call entry.
>   *
> - *  @filter must only be accessed from the context of current as 
> there
> - *  is no read locking.
> + *  @filter is read-protected by task->signal->cred_guard_mutex when
> + *  outside of current context.
>   */
>  struct seccomp {
> int mode;
> diff --git a/kernel/seccomp.c b/kernel/seccomp.c
> index ef80dd19f268..f65d47650ac1 100644
> --- a/kernel/seccomp.c
> +++ b/kernel/seccomp.c
> @@ -1042,7 +1042,12 @@ int seccomp_get_filter(struct task_struct *task, 
> unsigned long filter_off,
> return -EACCES;
> }
>
> +   ret = mutex_lock_killable(>signal->cred_guard_mutex);
> +   if (ret < 0)
> +   return ret;
> +
> filter = get_nth_filter(task, filter_off);
> +   mutex_unlock(>signal->cred_guard_mutex);
> if (IS_ERR(filter))
> return PTR_ERR(filter);
>
> @@ -1088,7 +1093,12 @@ int seccomp_get_metadata(struct task_struct *task,
> if (copy_from_user(_off, data, sizeof(kmd.filter_off)))
> return -EFAULT;
>
> +   ret = mutex_lock_killable(>signal->cred_guard_mutex);
> +   if (ret < 0)
> +   return ret;
> +
> filter = get_nth_filter(task, kmd.filter_off);
> +   mutex_unlock(>signal->cred_guard_mutex);
> if (IS_ERR(filter))
> return PTR_ERR(filter);
>
> --
> 2.17.1
>


[PATCH 3/3] seccomp: introduce read protection for struct seccomp

2018-09-28 Thread Tycho Andersen
As Jann pointed out, there is a race between SECCOMP_FILTER_FLAG_TSYNC and
the ptrace code that can inspect a filter of another process. Let's
introduce read locking into the two ptrace accesses so that we don't race.

Signed-off-by: Tycho Andersen 
Reported-by: Jann Horn 
CC: Kees Cook 
CC: Andy Lutomirski 
---
 include/linux/seccomp.h |  4 ++--
 kernel/seccomp.c| 10 ++
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index 8429bdda947a..30b27e898162 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -22,8 +22,8 @@ struct seccomp_filter;
  * @filter: must always point to a valid seccomp-filter or NULL as it is
  *  accessed without locking during system call entry.
  *
- *  @filter must only be accessed from the context of current as there
- *  is no read locking.
+ *  @filter is read-protected by task->signal->cred_guard_mutex when
+ *  outside of current context.
  */
 struct seccomp {
int mode;
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index ef80dd19f268..f65d47650ac1 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -1042,7 +1042,12 @@ int seccomp_get_filter(struct task_struct *task, 
unsigned long filter_off,
return -EACCES;
}
 
+   ret = mutex_lock_killable(>signal->cred_guard_mutex);
+   if (ret < 0)
+   return ret;
+
filter = get_nth_filter(task, filter_off);
+   mutex_unlock(>signal->cred_guard_mutex);
if (IS_ERR(filter))
return PTR_ERR(filter);
 
@@ -1088,7 +1093,12 @@ int seccomp_get_metadata(struct task_struct *task,
if (copy_from_user(_off, data, sizeof(kmd.filter_off)))
return -EFAULT;
 
+   ret = mutex_lock_killable(>signal->cred_guard_mutex);
+   if (ret < 0)
+   return ret;
+
filter = get_nth_filter(task, kmd.filter_off);
+   mutex_unlock(>signal->cred_guard_mutex);
if (IS_ERR(filter))
return PTR_ERR(filter);
 
-- 
2.17.1



[PATCH 3/3] seccomp: introduce read protection for struct seccomp

2018-09-28 Thread Tycho Andersen
As Jann pointed out, there is a race between SECCOMP_FILTER_FLAG_TSYNC and
the ptrace code that can inspect a filter of another process. Let's
introduce read locking into the two ptrace accesses so that we don't race.

Signed-off-by: Tycho Andersen 
Reported-by: Jann Horn 
CC: Kees Cook 
CC: Andy Lutomirski 
---
 include/linux/seccomp.h |  4 ++--
 kernel/seccomp.c| 10 ++
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index 8429bdda947a..30b27e898162 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -22,8 +22,8 @@ struct seccomp_filter;
  * @filter: must always point to a valid seccomp-filter or NULL as it is
  *  accessed without locking during system call entry.
  *
- *  @filter must only be accessed from the context of current as there
- *  is no read locking.
+ *  @filter is read-protected by task->signal->cred_guard_mutex when
+ *  outside of current context.
  */
 struct seccomp {
int mode;
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index ef80dd19f268..f65d47650ac1 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -1042,7 +1042,12 @@ int seccomp_get_filter(struct task_struct *task, 
unsigned long filter_off,
return -EACCES;
}
 
+   ret = mutex_lock_killable(>signal->cred_guard_mutex);
+   if (ret < 0)
+   return ret;
+
filter = get_nth_filter(task, filter_off);
+   mutex_unlock(>signal->cred_guard_mutex);
if (IS_ERR(filter))
return PTR_ERR(filter);
 
@@ -1088,7 +1093,12 @@ int seccomp_get_metadata(struct task_struct *task,
if (copy_from_user(_off, data, sizeof(kmd.filter_off)))
return -EFAULT;
 
+   ret = mutex_lock_killable(>signal->cred_guard_mutex);
+   if (ret < 0)
+   return ret;
+
filter = get_nth_filter(task, kmd.filter_off);
+   mutex_unlock(>signal->cred_guard_mutex);
if (IS_ERR(filter))
return PTR_ERR(filter);
 
-- 
2.17.1