All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kees Cook <kees@kernel.org>
To: Andrei Vagin <avagin@google.com>
Cc: Andy Lutomirski <luto@amacapital.net>,
	Will Drewry <wad@chromium.org>, Oleg Nesterov <oleg@redhat.com>,
	Christian Brauner <brauner@kernel.org>,
	linux-kernel@vger.kernel.org,
	Tycho Andersen <tandersen@netflix.com>,
	Jens Axboe <axboe@kernel.dk>
Subject: Re: [PATCH 2/3] seccomp: release task filters when the task exits
Date: Wed, 26 Jun 2024 11:57:40 -0700	[thread overview]
Message-ID: <202406261154.50DCF7B7@keescook> (raw)
In-Reply-To: <20240523014540.372255-3-avagin@google.com>

On Thu, May 23, 2024 at 01:45:39AM +0000, Andrei Vagin wrote:
> Previously, seccomp filters were released in release_task(), which
> required the process to exit and its zombie to be collected. However,
> exited threads/processes can't trigger any seccomp events, making it
> more logical to release filters upon task exits.
> 
> This adjustment simplifies scenarios where a parent is tracing its child
> process. The parent process can now handle all events from a seccomp
> listening descriptor and then call wait to collect a child zombie.
> 
> seccomp_filter_release takes the siglock to avoid races with
> seccomp_sync_threads. There was an idea to bypass taking the lock by
> checking PF_EXITING, but it can be set without holding siglock if
> threads have SIGNAL_GROUP_EXIT. This means it can happen concurently
> with seccomp_filter_release.
> 
> Signed-off-by: Andrei Vagin <avagin@google.com>
> ---
>  kernel/exit.c    |  3 ++-
>  kernel/seccomp.c | 22 ++++++++++++++++------
>  2 files changed, 18 insertions(+), 7 deletions(-)
> 
> diff --git a/kernel/exit.c b/kernel/exit.c
> index 41a12630cbbc..23439c021d8d 100644
> --- a/kernel/exit.c
> +++ b/kernel/exit.c
> @@ -278,7 +278,6 @@ void release_task(struct task_struct *p)
>  	}
>  
>  	write_unlock_irq(&tasklist_lock);
> -	seccomp_filter_release(p);
>  	proc_flush_pid(thread_pid);
>  	put_pid(thread_pid);
>  	release_thread(p);
> @@ -836,6 +835,8 @@ void __noreturn do_exit(long code)
>  	io_uring_files_cancel();
>  	exit_signals(tsk);  /* sets PF_EXITING */
>  
> +	seccomp_filter_release(tsk);
> +
>  	acct_update_integrals(tsk);
>  	group_dead = atomic_dec_and_test(&tsk->signal->live);
>  	if (group_dead) {
> diff --git a/kernel/seccomp.c b/kernel/seccomp.c
> index 35435e8f1035..67305e776dd3 100644
> --- a/kernel/seccomp.c
> +++ b/kernel/seccomp.c
> @@ -502,6 +502,9 @@ static inline pid_t seccomp_can_sync_threads(void)
>  		/* Skip current, since it is initiating the sync. */
>  		if (thread == caller)
>  			continue;
> +		/* Skip exited threads. */
> +		if (thread->flags & PF_EXITING)
> +			continue;
>  
>  		if (thread->seccomp.mode == SECCOMP_MODE_DISABLED ||
>  		    (thread->seccomp.mode == SECCOMP_MODE_FILTER &&
> @@ -563,18 +566,18 @@ static void __seccomp_filter_release(struct seccomp_filter *orig)
>   * @tsk: task the filter should be released from.
>   *
>   * This function should only be called when the task is exiting as
> - * it detaches it from its filter tree. As such, READ_ONCE() and
> - * barriers are not needed here, as would normally be needed.
> + * it detaches it from its filter tree. PF_EXITING has to be set
> + * for the task.

Let's capture this requirement with a WARN_ON() (like was done for the
sighand case before). So before the spinlock, check for PF_EXITING and
fail safe (don't release):

	if (WARN_ON((tsk->flags & PF_EXITING) == 0))
		return;

>   */
>  void seccomp_filter_release(struct task_struct *tsk)
>  {
> -	struct seccomp_filter *orig = tsk->seccomp.filter;
> -
> -	/* We are effectively holding the siglock by not having any sighand. */
> -	WARN_ON(tsk->sighand != NULL);
> +	struct seccomp_filter *orig;
>  
> +	spin_lock_irq(&current->sighand->siglock);

Shouldn't this be "tsk" not "current"?

> +	orig = tsk->seccomp.filter;
>  	/* Detach task from its filter tree. */
>  	tsk->seccomp.filter = NULL;
> +	spin_unlock_irq(&current->sighand->siglock);

Same.

>  	__seccomp_filter_release(orig);
>  }
>  
> @@ -602,6 +605,13 @@ static inline void seccomp_sync_threads(unsigned long flags)
>  		if (thread == caller)
>  			continue;
>  
> +		/*
> +		 * Skip exited threads. seccomp_filter_release could have
> +		 * been already called for this task.
> +		 */
> +		if (thread->flags & PF_EXITING)
> +			continue;
> +
>  		/* Get a task reference for the new leaf node. */
>  		get_seccomp_filter(caller);
>  
> -- 
> 2.45.1.288.g0e0cd299f1-goog
> 

Otherwise, looks good!

-- 
Kees Cook

  parent reply	other threads:[~2024-06-26 18:57 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-23  1:45 [PATCH 0/3 v2] seccomp: improve handling of SECCOMP_IOCTL_NOTIF_RECV Andrei Vagin
2024-05-23  1:45 ` [PATCH 1/3] seccomp: interrupt SECCOMP_IOCTL_NOTIF_RECV when all users have exited Andrei Vagin
2024-05-23  8:59   ` Oleg Nesterov
2024-05-24 17:47     ` Andrei Vagin
2024-05-23  1:45 ` [PATCH 2/3] seccomp: release task filters when the task exits Andrei Vagin
2024-05-23  9:00   ` Oleg Nesterov
2024-06-26 18:57   ` Kees Cook [this message]
2024-05-23  1:45 ` [PATCH 3/3] selftests/seccomp: add test for NOTIF_RECV and unused filters Andrei Vagin
2024-05-23  9:33 ` [PATCH 0/3 v2] seccomp: improve handling of SECCOMP_IOCTL_NOTIF_RECV Oleg Nesterov
2024-06-25  0:19   ` Andrei Vagin
2024-06-25  0:17 ` Andrei Vagin
2024-06-26 19:00   ` Kees Cook
     [not found] <20240514175551.297237-1-avagin@google.com>
     [not found] ` <20240514175551.297237-3-avagin@google.com>
     [not found]   ` <20240515125113.GC6821@redhat.com>
     [not found]     ` <CAEWA0a5dBvRwGAnztL56i=JV-WGGiaTd-GdJYdOxZmq1c+bdpg@mail.gmail.com>
2024-05-16  9:34       ` [PATCH 2/3] seccomp: release task filters when the task exits Oleg Nesterov
2024-05-16 13:09         ` Oleg Nesterov
2024-05-22  6:49           ` Andrei Vagin
2024-05-22  7:06             ` Andrei Vagin
2024-05-22 10:35               ` Oleg Nesterov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=202406261154.50DCF7B7@keescook \
    --to=kees@kernel.org \
    --cc=avagin@google.com \
    --cc=axboe@kernel.dk \
    --cc=brauner@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=oleg@redhat.com \
    --cc=tandersen@netflix.com \
    --cc=wad@chromium.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.