From patchwork Thu Mar 16 12:24:47 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Rutland X-Patchwork-Id: 95393 Delivered-To: patch@linaro.org Received: by 10.140.89.134 with SMTP id v6csp790976qgd; Thu, 16 Mar 2017 05:25:14 -0700 (PDT) X-Received: by 10.98.19.12 with SMTP id b12mr10134273pfj.150.1489667114731; Thu, 16 Mar 2017 05:25:14 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f2si3670154pfb.187.2017.03.16.05.25.14; Thu, 16 Mar 2017 05:25:14 -0700 (PDT) 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; 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 S1752178AbdCPMZN (ORCPT + 25 others); Thu, 16 Mar 2017 08:25:13 -0400 Received: from foss.arm.com ([217.140.101.70]:33046 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751524AbdCPMZM (ORCPT ); Thu, 16 Mar 2017 08:25:12 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 21AF5687; Thu, 16 Mar 2017 05:25:04 -0700 (PDT) Received: from leverpostej.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 62B113F5C9; Thu, 16 Mar 2017 05:25:03 -0700 (PDT) From: Mark Rutland To: linux-kernel@vger.kernel.org Cc: Mark Rutland , Peter Zijlstra , Ingo Molnar Subject: [PATCHv2] lockdep: avoid signed overflow Date: Thu, 16 Mar 2017 12:24:47 +0000 Message-Id: <1489667087-19550-1-git-send-email-mark.rutland@arm.com> X-Mailer: git-send-email 1.9.1 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The counters in struct lockdep_stats are all (signed) ints. For some counters (e.g. hardirqs_on_events, hardirqs_off_events), it's easy to trigger an overflow in a short period of time, rendering the information exposed under /proc/lockdep_stats erroneous, and causing UBSAN to scream. Since all counters can never validly be negative, we can make them unsigned, which is sufficient to placate UBSAN. However, this merely doubles the time until an overflow silently occurs, rendering the information under /proc/lockdep_stats erroneous. To avoid the undefined behaviour and to avoid erroneous results, this patch upgrades all of the counters to unsigned long long, which cannot overflow in a reasonable time frame. We don't need to change anything else, since the counters are only manipulated via this_cpu inc/dec operations, which are unaffected by the type. The counters are only read when generating /proc/lockdep_stats, where they are summed into unsigned long longs. Common code already uses 64-bit values with this_cpu operations, so this shouldn't be problematic for 32-bit parts. Original UBSAN splats: [137987.143729] ================================================================================ [137987.152266] UBSAN: Undefined behaviour in kernel/locking/lockdep.c:2696:2 [137987.159140] signed integer overflow: [137987.162801] 2147483647 + 1 cannot be represented in type 'int' [137987.168723] CPU: 0 PID: 24149 Comm: qemu-system-aar Not tainted 4.11.0-rc1-00002-g23187dc #12 [137987.177329] Hardware name: AMD Seattle (Rev.B0) Development Board (Overdrive) (DT) [137987.184980] Call trace: [137987.187523] [] dump_backtrace+0x0/0x538 [137987.193010] [] show_stack+0x20/0x30 [137987.198150] [] dump_stack+0x120/0x188 [137987.203463] [] ubsan_epilogue+0x18/0x98 [137987.208948] [] handle_overflow+0x1f0/0x234 [137987.214695] [] __ubsan_handle_add_overflow+0x34/0x44 [137987.221311] [] trace_hardirqs_on_caller+0x728/0x768 [137987.227838] [] trace_hardirqs_on+0x10/0x18 [137987.233585] [] yield_to+0x3c4/0x700 [137987.238725] [] kvm_vcpu_yield_to+0x138/0x2f8 [137987.244646] [] kvm_vcpu_on_spin+0x448/0x718 [137987.250480] [] kvm_handle_wfx+0x80/0x228 [137987.256053] [] handle_exit+0x258/0x5b0 [137987.261453] [] kvm_arch_vcpu_ioctl_run+0x7ac/0x1170 [137987.267980] [] kvm_vcpu_ioctl+0x6bc/0xe30 [137987.273641] [] do_vfs_ioctl+0x194/0x14a0 [137987.279213] [] SyS_ioctl+0xa8/0xb8 [137987.284265] [] el0_svc_naked+0x24/0x28 [137987.289659] ================================================================================ [137987.298322] ================================================================================ [137987.306912] UBSAN: Undefined behaviour in kernel/locking/lockdep.c:2775:3 [137987.313791] signed integer overflow: [137987.317457] 2147483647 + 1 cannot be represented in type 'int' [137987.323384] CPU: 0 PID: 24149 Comm: qemu-system-aar Not tainted 4.11.0-rc1-00002-g23187dc #12 [137987.331997] Hardware name: AMD Seattle (Rev.B0) Development Board (Overdrive) (DT) [137987.339654] Call trace: [137987.342197] [] dump_backtrace+0x0/0x538 [137987.347691] [] show_stack+0x20/0x30 [137987.352836] [] dump_stack+0x120/0x188 [137987.358155] [] ubsan_epilogue+0x18/0x98 [137987.363648] [] handle_overflow+0x1f0/0x234 [137987.369401] [] __ubsan_handle_add_overflow+0x34/0x44 [137987.376023] [] trace_hardirqs_off_caller+0x2b8/0x420 [137987.382645] [] trace_hardirqs_off+0x10/0x18 [137987.388484] [] el1_irq+0x70/0x130 [137987.393457] [] kvm_vcpu_yield_to+0x138/0x2f8 [137987.399384] [] kvm_vcpu_on_spin+0x448/0x718 [137987.405225] [] kvm_handle_wfx+0x80/0x228 [137987.410804] [] handle_exit+0x258/0x5b0 [137987.416211] [] kvm_arch_vcpu_ioctl_run+0x7ac/0x1170 [137987.422746] [] kvm_vcpu_ioctl+0x6bc/0xe30 [137987.428412] [] do_vfs_ioctl+0x194/0x14a0 [137987.433991] [] SyS_ioctl+0xa8/0xb8 [137987.439049] [] el0_svc_naked+0x24/0x28 [137987.444451] ================================================================================ Signed-off-by: Mark Rutland Cc: Peter Zijlstra Cc: Ingo Molnar Cc: linux-kernel@vger.kernel.org --- kernel/locking/lockdep_internals.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) Since v1 [1]: * Use unsigned long long to ensure counters are wide enough on 32-bit parts Mark. [1] https://lkml.kernel.org/r/1489595492-11745-1-git-send-email-mark.rutland@arm.com -- 1.9.1 diff --git a/kernel/locking/lockdep_internals.h b/kernel/locking/lockdep_internals.h index c2b8849..6e019f7 100644 --- a/kernel/locking/lockdep_internals.h +++ b/kernel/locking/lockdep_internals.h @@ -132,23 +132,23 @@ extern void get_usage_chars(struct lock_class *class, * and we want to avoid too much cache bouncing. */ struct lockdep_stats { - int chain_lookup_hits; - int chain_lookup_misses; - int hardirqs_on_events; - int hardirqs_off_events; - int redundant_hardirqs_on; - int redundant_hardirqs_off; - int softirqs_on_events; - int softirqs_off_events; - int redundant_softirqs_on; - int redundant_softirqs_off; - int nr_unused_locks; - int nr_cyclic_checks; - int nr_cyclic_check_recursions; - int nr_find_usage_forwards_checks; - int nr_find_usage_forwards_recursions; - int nr_find_usage_backwards_checks; - int nr_find_usage_backwards_recursions; + unsigned long long chain_lookup_hits; + unsigned long long chain_lookup_misses; + unsigned long long hardirqs_on_events; + unsigned long long hardirqs_off_events; + unsigned long long redundant_hardirqs_on; + unsigned long long redundant_hardirqs_off; + unsigned long long softirqs_on_events; + unsigned long long softirqs_off_events; + unsigned long long redundant_softirqs_on; + unsigned long long redundant_softirqs_off; + unsigned long long nr_unused_locks; + unsigned long long nr_cyclic_checks; + unsigned long long nr_cyclic_check_recursions; + unsigned long long nr_find_usage_forwards_checks; + unsigned long long nr_find_usage_forwards_recursions; + unsigned long long nr_find_usage_backwards_checks; + unsigned long long nr_find_usage_backwards_recursions; }; DECLARE_PER_CPU(struct lockdep_stats, lockdep_stats);