Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932412AbcJPP5X (ORCPT ); Sun, 16 Oct 2016 11:57:23 -0400 Received: from aserp1040.oracle.com ([141.146.126.69]:46616 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757263AbcJPP42 (ORCPT ); Sun, 16 Oct 2016 11:56:28 -0400 From: Vegard Nossum To: Akinobu Mita Cc: linux-kernel@vger.kernel.org, Vegard Nossum , Hillf Danton Subject: [PATCH 04/10] fault injection: prevent recursive fault injection Date: Sun, 16 Oct 2016 17:56:06 +0200 Message-Id: <20161016155612.4784-4-vegard.nossum@oracle.com> X-Mailer: git-send-email 2.10.0.479.g221bd91 In-Reply-To: <20161016155612.4784-1-vegard.nossum@oracle.com> References: <20161016155612.4784-1-vegard.nossum@oracle.com> X-Source-IP: aserv0022.oracle.com [141.146.126.234] Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1754 Lines: 67 If something we call in the fail_dump() code path tries to acquire a resource that might fail (due to fault injection), then we should not try to recurse back into the fault injection code. I've seen this happen with the console semaphore in the upcoming semaphore trylock fault injection code. Cc: Hillf Danton Signed-off-by: Vegard Nossum --- lib/fault-inject.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/lib/fault-inject.c b/lib/fault-inject.c index 6a823a5..adba7c9 100644 --- a/lib/fault-inject.c +++ b/lib/fault-inject.c @@ -100,6 +100,33 @@ static inline bool fail_stacktrace(struct fault_attr *attr) #endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */ +static DEFINE_PER_CPU(int, fault_active); + +static bool __fail(struct fault_attr *attr) +{ + bool ret = false; + + /* + * Prevent recursive fault injection (this could happen if for + * example printing the fault would itself run some code that + * could fail) + */ + preempt_disable(); + if (unlikely(__this_cpu_inc_return(fault_active) != 1)) + goto out; + + ret = true; + fail_dump(attr); + + if (atomic_read(&attr->times) != -1) + atomic_dec_not_zero(&attr->times); + +out: + __this_cpu_dec(fault_active); + preempt_enable(); + return ret; +} + /* * This code is stolen from failmalloc-1.0 * http://www.nongnu.org/failmalloc/ @@ -134,12 +161,7 @@ bool should_fail(struct fault_attr *attr, ssize_t size) if (!fail_stacktrace(attr)) return false; - fail_dump(attr); - - if (atomic_read(&attr->times) != -1) - atomic_dec_not_zero(&attr->times); - - return true; + return __fail(attr); } EXPORT_SYMBOL_GPL(should_fail); -- 2.10.0.479.g221bd91