From: Kees Cook <keescook@chromium.org>
To: Christian Brauner <christian.brauner@ubuntu.com>
Cc: linux-kernel@vger.kernel.org, Andy Lutomirski <luto@kernel.org>,
Tycho Andersen <tycho@tycho.ws>,
Matt Denton <mpdenton@google.com>,
Sargun Dhillon <sargun@sargun.me>, Jann Horn <jannh@google.com>,
Chris Palmer <palmer@google.com>,
Aleksa Sarai <cyphar@cyphar.com>,
Robert Sesek <rsesek@google.com>,
Jeffrey Vander Stoep <jeffv@google.com>,
Linux Containers <containers@lists.linux-foundation.org>
Subject: Re: [PATCH v2 1/2] seccomp: notify user trap about unused filter
Date: Thu, 28 May 2020 16:11:00 -0700 [thread overview]
Message-ID: <202005281404.276641223F@keescook> (raw)
In-Reply-To: <20200528151412.265444-1-christian.brauner@ubuntu.com>
On Thu, May 28, 2020 at 05:14:11PM +0200, Christian Brauner wrote:
> * @usage: reference count to manage the object lifetime.
> * get/put helpers should be used when accessing an instance
> * outside of a lifetime-guarded section. In general, this
> * is only needed for handling filters shared across tasks.
> [...]
> + * @live: Number of tasks that use this filter directly and number
> + * of dependent filters that have a non-zero @live counter.
> + * Altered during fork(), exit(), and filter installation
> [...]
> refcount_set(&sfilter->usage, 1);
> + refcount_set(&sfilter->live, 1);
I'd like these reference counters to have more descriptive names. "usage"
by what? "live" from what perspective? At the least, I think we need
to be explicit in the comment, and at best we should do that and rename
them to be a bit more clear.
A filter's "usage" is incremented for each directly-attached task
(task::seccomp_data.filter, via fork() or thread_sync), once for the
dependent filter (filter::prev), and once for an open user_notif file
(file::private_data). When it reaches zero, there are (should be) no more
active memory references back to the struct filter and it can be freed.
A filter's "live" is incremented for each directly-attached task
(task::seccomp_data.filter, via fork() or thread_sync), and once for
the dependent filter (filter::prev). When it reaches zero there is no
way for new tasks to get associated with the filter, but there may still
be user_notif file::private_data references pointing at the filter.
But we're tracking "validity lifetime" (live) and "memory reference
safety" (usage).
signal_struct has "sigcnt" and "live". I find "sigcnt" to be an
unhelpful name too. (And why isn't it refcount_t?)
So, perhaps leave "live", but rename "usage" -> "references".
After looking at these other lifetime management examples in the kernel,
I'm convinced that tracking these states separately is correct, but I
remain uncomfortable about task management needing to explicitly make
two calls to let go of the filter.
I wonder if release_task() should also detach the filter from the task
and do a put_seccomp_filter() instead of waiting for task_free(). This
is supported by the other place where seccomp_filter_release() is
called:
> @@ -396,6 +400,7 @@ static inline void seccomp_sync_threads(unsigned long flags)
> * allows a put before the assignment.)
> */
> put_seccomp_filter(thread);
> + seccomp_filter_release(thread);
This would also remove the only put_seccomp_filter() call outside of
seccomp.c, since the free_task() call will be removed now in favor of
the task_release() call.
So, is it safe to detach the filter in release_task()? Has dethreading
happened yet? i.e. can we race TSYNC? -- is there a possible
inc-from-zero? (Actually, all our refcount_inc()s should be
refcount_inc_not_zero() just for robustness.) I *think* we can do it
before the release_thread() call (instead of after cgroup_release()).
With that, then seccomp_filter_release() could assign the filter to NULL
and do the clean up:
void seccomp_filter_release(const struct task_struct *tsk)
{
struct seccomp_filter *orig = READ_ONCE(tsk->seccomp.filter);
smp_store_release(&tsk->seccomp.filter, NULL);
__seccomp_filter_release(orig);
}
All other refcounting is then internal to seccomp.c. Which brings me
back to TSYNC, since we don't want to write NULL to task->seccomp.filter
during TSYNC. TSYNC can use:
void __seccomp_filter_release(struct seccomp_filter *filter)
{
while (filter && refcount_dec_and_test(&filter->live)) {
if (waitqueue_active(&filter->wqh))
wake_up_poll(&filter->wqh, EPOLLHUP);
filter = filter->prev;
}
__put_seccomp_filter(filter);
}
Thoughts?
--
Kees Cook
next prev parent reply other threads:[~2020-05-28 23:11 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-28 15:14 [PATCH v2 1/2] seccomp: notify user trap about unused filter Christian Brauner
2020-05-28 15:14 ` [PATCH v2 2/2] tests: test seccomp filter notifications Christian Brauner
2020-05-29 5:41 ` Kees Cook
2020-05-29 8:00 ` Christian Brauner
2020-05-28 23:11 ` Kees Cook [this message]
2020-05-28 23:32 ` [PATCH v2 1/2] seccomp: notify user trap about unused filter Jann Horn
2020-05-29 5:36 ` Kees Cook
2020-05-29 7:51 ` Christian Brauner
2020-05-29 7:56 ` Kees Cook
2020-05-29 8:00 ` Christian Brauner
2020-05-29 8:50 ` Christian Brauner
2020-05-29 7:47 ` Christian Brauner
2020-05-29 8:02 ` Kees Cook
2020-05-29 7:56 ` Christian Brauner
2020-05-29 8:06 ` Kees Cook
2020-05-29 8:37 ` Christian Brauner
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=202005281404.276641223F@keescook \
--to=keescook@chromium.org \
--cc=christian.brauner@ubuntu.com \
--cc=containers@lists.linux-foundation.org \
--cc=cyphar@cyphar.com \
--cc=jannh@google.com \
--cc=jeffv@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mpdenton@google.com \
--cc=palmer@google.com \
--cc=rsesek@google.com \
--cc=sargun@sargun.me \
--cc=tycho@tycho.ws \
/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.