Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753333AbdI0P0o (ORCPT ); Wed, 27 Sep 2017 11:26:44 -0400 Received: from mail-oi0-f42.google.com ([209.85.218.42]:51167 "EHLO mail-oi0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752630AbdI0P0m (ORCPT ); Wed, 27 Sep 2017 11:26:42 -0400 X-Google-Smtp-Source: AOwi7QBO6XOiGHeuOYKOh17GC41bfQsXxOnFaNh2H0bDKnYvhGkWKtvpcC39AhR4SHSxeVJT3a0TNQ== From: Tycho Andersen To: Kees Cook Cc: linux-kernel@vger.kernel.org, Andy Lutomirski , Will Drewry , security@kernel.org, Chris Salls , Oleg Nesterov , stable@vger.kernel.org, Tycho Andersen Subject: [PATCH v2] seccomp: fix the usage of get/put_seccomp_filter() in seccomp_get_filter() Date: Wed, 27 Sep 2017 09:25:30 -0600 Message-Id: <20170927152530.26520-1-tycho@docker.com> X-Mailer: git-send-email 2.11.0 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2738 Lines: 86 From: Oleg Nesterov As Chris explains, get_seccomp_filter() and put_seccomp_filter() can use the different filters, once we drop ->siglock task->seccomp.filter can be replaced by SECCOMP_FILTER_FLAG_TSYNC. v2: add __get_seccomp_filter vs. open coding refcount_inc() Fixes: f8e529ed941b ("seccomp, ptrace: add support for dumping seccomp filters") Reported-by: Chris Salls Cc: stable@vger.kernel.org Signed-off-by: Oleg Nesterov Signed-off-by: Tycho Andersen --- kernel/seccomp.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/kernel/seccomp.c b/kernel/seccomp.c index c24579dfa7a1..bb3a38005b9c 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -473,14 +473,19 @@ static long seccomp_attach_filter(unsigned int flags, return 0; } +void __get_seccomp_filter(struct seccomp_filter *filter) +{ + /* Reference count is bounded by the number of total processes. */ + refcount_inc(&filter->usage); +} + /* get_seccomp_filter - increments the reference count of the filter on @tsk */ void get_seccomp_filter(struct task_struct *tsk) { struct seccomp_filter *orig = tsk->seccomp.filter; if (!orig) return; - /* Reference count is bounded by the number of total processes. */ - refcount_inc(&orig->usage); + __get_seccomp_filter(orig); } static inline void seccomp_filter_free(struct seccomp_filter *filter) @@ -491,10 +496,8 @@ static inline void seccomp_filter_free(struct seccomp_filter *filter) } } -/* put_seccomp_filter - decrements the ref count of tsk->seccomp.filter */ -void put_seccomp_filter(struct task_struct *tsk) +static void __put_seccomp_filter(struct seccomp_filter *orig) { - struct seccomp_filter *orig = tsk->seccomp.filter; /* Clean up single-reference branches iteratively. */ while (orig && refcount_dec_and_test(&orig->usage)) { struct seccomp_filter *freeme = orig; @@ -503,6 +506,12 @@ void put_seccomp_filter(struct task_struct *tsk) } } +/* put_seccomp_filter - decrements the ref count of tsk->seccomp.filter */ +void put_seccomp_filter(struct task_struct *tsk) +{ + __put_seccomp_filter(tsk->seccomp.filter); +} + static void seccomp_init_siginfo(siginfo_t *info, int syscall, int reason) { memset(info, 0, sizeof(*info)); @@ -1025,13 +1034,13 @@ long seccomp_get_filter(struct task_struct *task, unsigned long filter_off, if (!data) goto out; - get_seccomp_filter(task); + __get_seccomp_filter(filter); spin_unlock_irq(&task->sighand->siglock); if (copy_to_user(data, fprog->filter, bpf_classic_proglen(fprog))) ret = -EFAULT; - put_seccomp_filter(task); + __put_seccomp_filter(filter); return ret; out: -- 2.11.0