Received: by 2002:a05:6a10:16a7:0:0:0:0 with SMTP id gp39csp828610pxb; Tue, 3 Nov 2020 13:43:41 -0800 (PST) X-Google-Smtp-Source: ABdhPJyBZEkIGJlghL1ebiKYWh0SqjbK6ZtdsC0fffOZz4lcoCDM7UgSxMIQ97XMS4Adb51j7Hn4 X-Received: by 2002:a17:906:170f:: with SMTP id c15mr22912793eje.347.1604439821283; Tue, 03 Nov 2020 13:43:41 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1604439821; cv=none; d=google.com; s=arc-20160816; b=GPLQJVarE1W/WCNv82V0c9m8C2kibV1ED3Gy5JvmcwUzONRQyS5UFcCNzseN97Rgfi 9MHIrD9kCfOEnEsnEdjfyMQGnG6GHTAkKHeNB16T03nGhMHrtoORIDV809MPSW0t3hVS Gg4m1iPTfu/pbNCTaynhDxLMzjDYAwrqjaqP71fuUhrfaJXDG+160AC1PhzFlPjR8j/D ALk9PV2h/akI7/V0d1Fpa0FnmKoVL15ARoXYKYaevN5bmBNpcW3vZQDwCsCPClQVv1O8 NamSqP+gCkloz91n4AR0NBFQeBnJwFkme7LqsazrEYumnFozkT2vhW2j/TV5LuN1rndm 8ruw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=QV8YfegSdDCIr7m/fkOXR4km7DqRhaNcpXBQURVHmKA=; b=XyQW0odBMAjInJgFFiJhuACsdxow6iT8l5mHC+WJ6F/dx1HebiApbnBh5KZyu2hlei nTQpsqjx/TVeO6RE9Bf2piqtWV3b0i6q2gr4g86cFl1hcybZznc9AKiFEi4yMevVtF6K mjhR/Jg9J5fLph+L1A89DSrCUpKT7KmuWjFpAWZKosyZWCwE3WHeQ/1w0vvKdwDyWsjX HiMTy5b6z7DhzjrLNATamqAT8XYSxD904ZbEw/zKXT06+1TE9yCeu5NxCGtYIWACqqN8 kk82Ma958nitUejsASQi4m5d0cTYpupNi/oKnEUX7rcM9yGjjGXxS6IpcJbADqv4djdX 85aA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=yQfBuRWH; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id re2si77924ejb.378.2020.11.03.13.43.18; Tue, 03 Nov 2020 13:43:41 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=yQfBuRWH; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732738AbgKCU4e (ORCPT + 99 others); Tue, 3 Nov 2020 15:56:34 -0500 Received: from mail.kernel.org ([198.145.29.99]:58368 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732732AbgKCU4c (ORCPT ); Tue, 3 Nov 2020 15:56:32 -0500 Received: from localhost (83-86-74-64.cable.dynamic.v4.ziggo.nl [83.86.74.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 2D2182053B; Tue, 3 Nov 2020 20:56:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604436991; bh=te4H7KDbiguDBzWhtYno9Wfee3FJDvyCwukbvBPGZIo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=yQfBuRWHLlsUbn3yiM/emJgdeYAB45Bq8dLtEdGdb4GN1Da8M3RWCS1KDsD61t5IY RMQMzPL4R+OJ7FxV6cjcd2IgDTFfpAwlbWEsOhTRFwgl53v499x281Pgd0QoEpYyP5 w0XTTD0Qwr490kIZAemZoTPeqWYoU2QJg6JsOtpQ= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Tycho Andersen , Jann Horn , Kees Cook Subject: [PATCH 5.4 099/214] seccomp: Make duplicate listener detection non-racy Date: Tue, 3 Nov 2020 21:35:47 +0100 Message-Id: <20201103203259.806931684@linuxfoundation.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201103203249.448706377@linuxfoundation.org> References: <20201103203249.448706377@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Jann Horn commit dfe719fef03d752f1682fa8aeddf30ba501c8555 upstream. Currently, init_listener() tries to prevent adding a filter with SECCOMP_FILTER_FLAG_NEW_LISTENER if one of the existing filters already has a listener. However, this check happens without holding any lock that would prevent another thread from concurrently installing a new filter (potentially with a listener) on top of the ones we already have. Theoretically, this is also a data race: The plain load from current->seccomp.filter can race with concurrent writes to the same location. Fix it by moving the check into the region that holds the siglock to guard against concurrent TSYNC. (The "Fixes" tag points to the commit that introduced the theoretical data race; concurrent installation of another filter with TSYNC only became possible later, in commit 51891498f2da ("seccomp: allow TSYNC and USER_NOTIF together").) Fixes: 6a21cc50f0c7 ("seccomp: add a return code to trap to userspace") Reviewed-by: Tycho Andersen Signed-off-by: Jann Horn Signed-off-by: Kees Cook Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20201005014401.490175-1-jannh@google.com Signed-off-by: Greg Kroah-Hartman --- kernel/seccomp.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -1219,13 +1219,7 @@ static const struct file_operations secc static struct file *init_listener(struct seccomp_filter *filter) { - struct file *ret = ERR_PTR(-EBUSY); - struct seccomp_filter *cur; - - for (cur = current->seccomp.filter; cur; cur = cur->prev) { - if (cur->notif) - goto out; - } + struct file *ret; ret = ERR_PTR(-ENOMEM); filter->notif = kzalloc(sizeof(*(filter->notif)), GFP_KERNEL); @@ -1252,6 +1246,31 @@ out: return ret; } +/* + * Does @new_child have a listener while an ancestor also has a listener? + * If so, we'll want to reject this filter. + * This only has to be tested for the current process, even in the TSYNC case, + * because TSYNC installs @child with the same parent on all threads. + * Note that @new_child is not hooked up to its parent at this point yet, so + * we use current->seccomp.filter. + */ +static bool has_duplicate_listener(struct seccomp_filter *new_child) +{ + struct seccomp_filter *cur; + + /* must be protected against concurrent TSYNC */ + lockdep_assert_held(¤t->sighand->siglock); + + if (!new_child->notif) + return false; + for (cur = current->seccomp.filter; cur; cur = cur->prev) { + if (cur->notif) + return true; + } + + return false; +} + /** * seccomp_set_mode_filter: internal function for setting seccomp filter * @flags: flags to change filter behavior @@ -1321,6 +1340,11 @@ static long seccomp_set_mode_filter(unsi if (!seccomp_may_assign_mode(seccomp_mode)) goto out; + if (has_duplicate_listener(prepared)) { + ret = -EBUSY; + goto out; + } + ret = seccomp_attach_filter(flags, prepared); if (ret) goto out;