Received: by 10.223.185.116 with SMTP id b49csp471836wrg; Wed, 21 Feb 2018 01:20:34 -0800 (PST) X-Google-Smtp-Source: AH8x2270bxlYtnvm1hwtgpSmeYWtz261/wBpVRt/LqmEhcZ98WiHnzykGCBOkWPOZtQqZxvzWI/E X-Received: by 10.98.39.197 with SMTP id n188mr2678736pfn.58.1519204834063; Wed, 21 Feb 2018 01:20:34 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519204834; cv=none; d=google.com; s=arc-20160816; b=CtH3NcyA6j3CrsgdFYD/3dQJ5p5AjIKlHec8ql6e9qY1p0Tg12NnL0gnZ/TeFGD8ys mgqhVyVCxBqdpJ0f1/7BgVSQOUJb8OtpXMs3aolIk4Mix2tEHJrls4HVuDlCfIvwRxG8 qFrZvGCTIHm9dIwHlEIVKNZnis5yWh7B2Xm74M3KhZO946KdY/DBrpnyDScBOLAD2Sur KZsJwmIzG7DKk2cl+sRbMeMtAy6gtd21rLMdLYc7hl3KGBtzdTwsVv9pje1Ji0zC7m7+ 5jNAHrOi4EbwIrKodjcJ1VS0TxNwZDL28GSI478P49qoSKvNJemJh9jP5MQAmgXiioOM m8Aw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:dkim-signature:arc-authentication-results; bh=VQpgG7ASSAlymaDYObKPZI4qeZOeKJxkF+SNgyF5m7w=; b=sbInPw2AkRA6Tt/ZCtgK+1BmD/yjq89mD1U2yLMH+lMvQegQq9lgrXTw427crtM7Lc R0Tw4TdyuNIW31UaqdLinnxG+BOgKmxuey+GLciDK0jOb9BafBr9PORYc5hTAYYERWts s6+ywEdlvK4TxxWAcOYll+323PHMzylCfYIh+mimyb+hzSmPzaILggGb+8Jgoez4HNJk PGSESmxdUn+KA3yqZNFgXM831Pi4mHzLjJb2lBc8O0ev1IlwuoBVK75CXHAAMJMpk22O rrLGgGhWd0M7gKz35rZor1u17HdDVrpzWtFhV1z0pg0OhpR94wAarXS6thWNHplTkIkw L1Mg== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@infradead.org header.s=bombadil.20170209 header.b=HA0dtqEa; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y6si601271pfg.385.2018.02.21.01.20.19; Wed, 21 Feb 2018 01:20:34 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=fail header.i=@infradead.org header.s=bombadil.20170209 header.b=HA0dtqEa; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753171AbeBUJPq (ORCPT + 99 others); Wed, 21 Feb 2018 04:15:46 -0500 Received: from bombadil.infradead.org ([198.137.202.133]:57156 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752923AbeBUJPP (ORCPT ); Wed, 21 Feb 2018 04:15:15 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20170209; h=In-Reply-To:Content-Type:MIME-Version :References:Message-ID:Subject:Cc:To:From:Date:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=VQpgG7ASSAlymaDYObKPZI4qeZOeKJxkF+SNgyF5m7w=; b=HA0dtqEaoIypFcbGXBiWXqp5A g3a8q/U0HqfjKgI3ogVGfyPsp3PqAMAdn+WsAxqtdqIeNHPLJAa4hj/XerON43BwJAlX34eh+K7RD w7civLGe+Fp8r6TpOVB2LYlJsgvEdfy6JqgQ+2qcm6IFl+s/mpACJUGxv5HcXnowke/9iESNuThi8 Mn+elE81B5rm+dkFbl+oZqAXXgTVpgYC093LQHJV/gIYBP0QGzOKEfFc/edpo84BQkkFuwdFTTBLX SehwcnUshf8ZwHqkV8W5/w98qX6JpgshrC9sDEc+kW+b9CrIVSSuES5F7Pfi/yCB/NhVDnB0neGCc zLkVYrqVQ==; Received: from j217100.upc-j.chello.nl ([24.132.217.100] helo=hirez.programming.kicks-ass.net) by bombadil.infradead.org with esmtpsa (Exim 4.89 #1 (Red Hat Linux)) id 1eoQUT-0001ZL-V1; Wed, 21 Feb 2018 09:15:06 +0000 Received: by hirez.programming.kicks-ass.net (Postfix, from userid 1000) id 0A5CF20274D67; Wed, 21 Feb 2018 10:15:04 +0100 (CET) Date: Wed, 21 Feb 2018 10:15:04 +0100 From: Peter Zijlstra To: Ingo Molnar Cc: Paul Moore , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, stable@vger.kernel.org, Dmitry Vyukov , linux-audit@redhat.com, Thomas Gleixner , rgb@redhat.com Subject: Re: [PATCH 4.10 070/111] audit: fix auditd/kernel connection state tracking Message-ID: <20180221091503.GK25181@hirez.programming.kicks-ass.net> References: <20170328122915.640228468@linuxfoundation.org> <20170328122918.597715642@linuxfoundation.org> <20180220123757.GE25314@hirez.programming.kicks-ass.net> <20180220140640.GE25201@hirez.programming.kicks-ass.net> <20180220151849.GG25201@hirez.programming.kicks-ass.net> <20180221084601.scnvgiiv32s2pgye@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20180221084601.scnvgiiv32s2pgye@gmail.com> User-Agent: Mutt/1.9.2 (2017-12-15) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, Feb 21, 2018 at 09:46:02AM +0100, Ingo Molnar wrote: > AFAICS the primary problem appears to be this code path: > > audit_receive() -> audit_receive_msg() -> AUDIT_TTY_SET -> audit_log_common_recv_msg() -> audit_log_start() > > where we can arrive already holding the lock. > > I.e. recursive mutex, kinda. I _think_ something like the below ought to work, but I've no idea how to even begin testing audit. --- kernel/audit.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 227db99b0f19..24175754f79d 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -184,6 +184,9 @@ static char *audit_feature_names[2] = { /* Serialize requests from userspace. */ DEFINE_MUTEX(audit_cmd_mutex); +static struct audit_buffer *__audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, + int type, bool recursive); + /* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting * audit records. Since printk uses a 1024 byte buffer, this buffer * should be at least that large. */ @@ -357,7 +360,7 @@ static int audit_log_config_change(char *function_name, u32 new, u32 old, struct audit_buffer *ab; int rc = 0; - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); + ab = __audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, true); if (unlikely(!ab)) return rc; audit_log_format(ab, "%s=%u old=%u", function_name, new, old); @@ -1024,7 +1027,7 @@ static void audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) return; } - *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); + *ab = __audit_log_start(NULL, GFP_KERNEL, msg_type, true); if (unlikely(!*ab)) return; audit_log_format(*ab, "pid=%d uid=%u", pid, uid); @@ -1057,7 +1060,7 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature if (audit_enabled == AUDIT_OFF) return; - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_FEATURE_CHANGE); + ab = __audit_log_start(NULL, GFP_KERNEL, AUDIT_FEATURE_CHANGE, true); audit_log_task_info(ab, current); audit_log_format(ab, " feature=%s old=%u new=%u old_lock=%u new_lock=%u res=%d", audit_feature_names[which], !!old_feature, !!new_feature, @@ -1578,6 +1581,12 @@ static int __init audit_enable(char *str) if (audit_default == AUDIT_OFF) audit_initialized = AUDIT_DISABLED; + /* + * Normally audit_set_enabled() would need to be called under + * @audit_cmd_mutex, however since audit_do_config_change() will not in + * fact call audit_log_config_change() when 'audit_enabled == + * AUDIT_OFF', we can use it here without issue. + */ if (audit_set_enabled(audit_default)) panic("audit: error setting audit state (%d)\n", audit_default); @@ -1690,8 +1699,8 @@ static inline void audit_get_stamp(struct audit_context *ctx, * will be written at syscall exit. If there is no associated task, then * task context (ctx) should be NULL. */ -struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, - int type) +static struct audit_buffer *__audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, + int type, bool recursive) { struct audit_buffer *ab; struct timespec64 t; @@ -1703,6 +1712,9 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, if (unlikely(!audit_filter(type, AUDIT_FILTER_TYPE))) return NULL; + if (recursive) + lockdep_assert_held(&audit_cmd_mutex); + /* NOTE: don't ever fail/sleep on these two conditions: * 1. auditd generated record - since we need auditd to drain the * queue; also, when we are checking for auditd, compare PIDs using @@ -1710,8 +1722,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, * using a PID anchored in the caller's namespace * 2. generator holding the audit_cmd_mutex - we don't want to block * while holding the mutex */ - if (!(auditd_test_task(current) || - (current == __mutex_owner(&audit_cmd_mutex)))) { + if (!(auditd_test_task(current) || recursive)) { long stime = audit_backlog_wait_time; while (audit_backlog_limit && @@ -1753,6 +1764,12 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, return ab; } +struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, + int type) +{ + return __audit_log_start(ctx, gfp_mask, type, false); +} + /** * audit_expand - expand skb in the audit buffer * @ab: audit_buffer