All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kuniyuki Iwashima <kuniyu@amazon.com>
To: <keescook@chromium.org>
Cc: <ayudutta@amazon.com>, <brauner@kernel.org>, <kuni1840@gmail.com>,
	<kuniyu@amazon.com>, <linux-kernel@vger.kernel.org>,
	<luto@amacapital.net>,
	<syzbot+ab17848fe269b573eb71@syzkaller.appspotmail.com>,
	<wad@chromium.org>
Subject: Re: [PATCH v1] seccomp: Release filter when copy_process() fails.
Date: Mon, 22 Aug 2022 17:00:35 -0700	[thread overview]
Message-ID: <20220823000035.35716-1-kuniyu@amazon.com> (raw)
In-Reply-To: <202208221636.1DE3D674@keescook>

From:   Kees Cook <keescook@chromium.org>
Date:   Mon, 22 Aug 2022 16:38:07 -0700
> On Mon, Aug 22, 2022 at 02:49:35PM -0700, Kuniyuki Iwashima wrote:
> > From:   Kees Cook <keescook@chromium.org>
> > Date:   Mon, 22 Aug 2022 14:16:03 -0700
> > > On Mon, Aug 22, 2022 at 01:44:36PM -0700, Kuniyuki Iwashima wrote:
> > > > Our syzbot instance reported memory leaks in do_seccomp() [0], similar
> > > > to the report [1].  It shows that we miss freeing struct seccomp_filter
> > > > and some objects included in it.
> > > > 
> > > > We can reproduce the issue with the program below [2] which calls one
> > > > seccomp() and two clone() syscalls.
> > > > 
> > > > The first clone()d child exits earlier than its parent and sends a
> > > > signal to kill it during the second clone(), more precisely before the
> > > > fatal_signal_pending() test in copy_process().  When the parent receives
> > > > the signal, it has to destroy the embryonic process and return -EINTR to
> > > > user space.  In the failure path, we have to call seccomp_filter_release()
> > > > to decrement the filter's ref count.
> > > > 
> > > > Initially, we called it in free_task() called from the failure path, but
> > > > the commit 3a15fb6ed92c ("seccomp: release filter after task is fully
> > > > dead") moved it to release_task() to notify user space as early as possible
> > > > that the filter is no longer used.
> > > > 
> > > > To keep the change, let's call seccomp_filter_release() in copy_process()
> > > > and add a WARN_ON_ONCE() in free_task() for future debugging.
> > > 
> > > Thanks for tracking this down! I think I'd prefer to avoid changing the
> > > semantics around the existing seccomp refcount lifetime, so what about
> > > just moving copy_seccomp() below the last possible error path?
> > 
> > Actually, I also thought of it but avoid it because it means we move the
> > signal check relatively earlier than before, so would-be-killed processes
> > could consume more resouces.
> > 
> > What do you think about this?
> 
> There's no allocation happening in copy_seccomp(), just reference
> counts being added. Given the lock that is held, the ordering here
> doesn't matter as far as I can tell, except for the fact that
> copy_seccomp() expects to go through full thread death if something goes
> wrong. So, simply moving it later should do the trick here.

Ok, I'm fine with that change.
I'll test it again and post v2 with WARN_ON_ONCE().
Thank you!


> 
> -Kees
> 
> > 
> > > 
> > > 
> > > diff --git a/kernel/fork.c b/kernel/fork.c
> > > index 90c85b17bf69..e7f4e7f1e01e 100644
> > > --- a/kernel/fork.c
> > > +++ b/kernel/fork.c
> > > @@ -2409,12 +2409,6 @@ static __latent_entropy struct task_struct *copy_process(
> > >  
> > >  	spin_lock(&current->sighand->siglock);
> > >  
> > > -	/*
> > > -	 * Copy seccomp details explicitly here, in case they were changed
> > > -	 * before holding sighand lock.
> > > -	 */
> > > -	copy_seccomp(p);
> > > -
> > >  	rv_task_fork(p);
> > >  
> > >  	rseq_fork(p, clone_flags);
> > > @@ -2431,6 +2425,14 @@ static __latent_entropy struct task_struct *copy_process(
> > >  		goto bad_fork_cancel_cgroup;
> > >  	}
> > >  
> > > +	/* No more failures paths after this point. */
> > > +
> > > +	/*
> > > +	 * Copy seccomp details explicitly here, in case they were changed
> > > +	 * before holding sighand lock.
> > > +	 */
> > > +	copy_seccomp(p);
> > > +
> > >  	init_task_pid_links(p);
> > >  	if (likely(p->pid)) {
> > >  		ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);
> > > 
> > > 
> > > Totally untested, but I think it would fix this?
> > > 
> > > -Kees
> > > 
> > > -- 
> > > Kees Cook
> 
> -- 
> Kees Cook

  reply	other threads:[~2022-08-23  0:01 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-22 20:44 [PATCH v1] seccomp: Release filter when copy_process() fails Kuniyuki Iwashima
2022-08-22 21:16 ` Kees Cook
2022-08-22 21:49   ` Kuniyuki Iwashima
2022-08-22 23:38     ` Kees Cook
2022-08-23  0:00       ` Kuniyuki Iwashima [this message]
2022-09-02  3:16 ` kernel test robot
2022-09-02  3:16 ` kernel test robot

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=20220823000035.35716-1-kuniyu@amazon.com \
    --to=kuniyu@amazon.com \
    --cc=ayudutta@amazon.com \
    --cc=brauner@kernel.org \
    --cc=keescook@chromium.org \
    --cc=kuni1840@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=syzbot+ab17848fe269b573eb71@syzkaller.appspotmail.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.