Received: by 2002:a05:7412:d008:b0:f9:6acb:47ec with SMTP id bd8csp187501rdb; Tue, 19 Dec 2023 13:20:34 -0800 (PST) X-Google-Smtp-Source: AGHT+IF7mhPAyqbiAezdTKgh3uUsIdmN2pEQ88LymPVA2goyG5hslq6jQ8XjGzYJednLQ7qY5nRr X-Received: by 2002:a17:90a:f492:b0:28b:b6fa:82ec with SMTP id bx18-20020a17090af49200b0028bb6fa82ecmr1300829pjb.52.1703020834584; Tue, 19 Dec 2023 13:20:34 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1703020834; cv=none; d=google.com; s=arc-20160816; b=GTStLx3tffG5tE/2FqVAl0ElBYXVEwu+n9p7lxIX7gLppkdbsuFa0zjkSpgGzub1Hf JdLb4F7WLN2oNn8776ASZNcTyEmQZVoE3PxJLA4MOTA5moOLo7E/DH5/PAbLuegFhvKL ir2m7c5pLfG965BLcd6CtFPa2F4nnLX2+pJH0F41xDfPbiCqWdAxh3CPddP6fIt66kGc JW7hIKU4H4knuLsKpMzJWpl5PsiRMh2zSLQDd4p5yU5GP0fzArppC5+gWoE+Hj/2GSFA NLP4wR3ieRcOyL/jwgcWigtVRPc0lAr/szNGHbfM05r+EkLWougrjhC8vca84hfu5/wH YImg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=IugD6msAA76PLOkulY8RL+cRtUx1nL2a5VcYM7ZPFvs=; fh=xumGgQ3/A3VHYu1DQDaIWA+Xl29EI5lD+bm6U+z1O60=; b=tHX0BTB3gRND+v280Q6waqY337pzwH4oU9pB1zMfTW0rZMCX05IpESqy9YD9GKxnkC PalQHvazlwQnVawYSbBITJO4INQS/IlUOCz0dq6LKVF29JkgCuWGoFY4ay0GYkNxxrwQ Hn4xzvtrYge7zLxUpUCVd/ZRxIkE4V4kzpxGrT9WTNwsXDibPEx/3mM6gNhfSfX/f/lL rhJZWr5hGKm1jo9N3zg074PAn3e2UnNR6TOsDy2BiaftGR2IJiJyWK8r9/8WDbBLAwbZ UbBtTjAhStpK3GI2WakM2+Lzy1lKIeyh7rrSpPOKFHp/J1fQi2TOuy4zxBOzSMx1GjQf AGfw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linux.dev header.s=key1 header.b=IR+Whe6+; spf=pass (google.com: domain of linux-kernel+bounces-5960-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-5960-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.dev Return-Path: Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [2604:1380:40f1:3f00::1]) by mx.google.com with ESMTPS id z13-20020a17090ad78d00b0028a30507ff6si1828802pju.150.2023.12.19.13.20.34 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Dec 2023 13:20:34 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-5960-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) client-ip=2604:1380:40f1:3f00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@linux.dev header.s=key1 header.b=IR+Whe6+; spf=pass (google.com: domain of linux-kernel+bounces-5960-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-5960-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linux.dev Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id 29C2EB2409E for ; Tue, 19 Dec 2023 21:20:31 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 64ADE3EA75; Tue, 19 Dec 2023 21:20:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="IR+Whe6+" X-Original-To: linux-kernel@vger.kernel.org Received: from out-180.mta1.migadu.com (out-180.mta1.migadu.com [95.215.58.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E3B0B3D0A2 for ; Tue, 19 Dec 2023 21:19:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1703020798; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=IugD6msAA76PLOkulY8RL+cRtUx1nL2a5VcYM7ZPFvs=; b=IR+Whe6+qpxv+At+vArbXY01tYtvfspW3PKw8UAncGDGnEEps0UIMWhP+wPzEx5NxY9M8h m1TDVtQZm9HrpXOj1mV5z/Lc+HwiQjOjMkmc/bfj2auMjP1/9llRH/NH6L89Gq+qP7zEz3 M7vUVsknaJSSv98tDJGKvpfbqCVOHN0= From: andrey.konovalov@linux.dev To: Andrew Morton Cc: Andrey Konovalov , Marco Elver , Alexander Potapenko , Dmitry Vyukov , Vlastimil Babka , kasan-dev@googlegroups.com, Evgenii Stepanov , Tetsuo Handa , linux-mm@kvack.org, linux-kernel@vger.kernel.org, Andrey Konovalov , syzbot+186b55175d8360728234@syzkaller.appspotmail.com Subject: [PATCH v3 mm 2/4] kasan: handle concurrent kasan_record_aux_stack calls Date: Tue, 19 Dec 2023 22:19:51 +0100 Message-Id: <1606b960e2f746862d1f459515972f9695bf448a.1703020707.git.andreyknvl@google.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Migadu-Flow: FLOW_OUT From: Andrey Konovalov kasan_record_aux_stack can be called concurrently on the same object. This might lead to a race condition when rotating the saved aux stack trace handles, which in turns leads to incorrect accounting of stack depot handles and refcount underflows in the stack depot code. Fix by introducing a raw spinlock to protect the aux stack trace handles in kasan_record_aux_stack. Reported-by: Tetsuo Handa Reported-by: syzbot+186b55175d8360728234@syzkaller.appspotmail.com Closes: https://lore.kernel.org/all/000000000000784b1c060b0074a2@google.com/ Fixes: 773688a6cb24 ("kasan: use stack_depot_put for Generic mode") Signed-off-by: Andrey Konovalov --- Changes v2->v3: - Use raw spinlock to avoid lockdep complaints on RT kernels. Changes v1->v2: - Use per-object spinlock instead of a global one. --- mm/kasan/generic.c | 32 +++++++++++++++++++++++++++++--- mm/kasan/kasan.h | 8 ++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c index 54e20b2bc3e1..55e6b5db2cae 100644 --- a/mm/kasan/generic.c +++ b/mm/kasan/generic.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -471,8 +472,18 @@ void kasan_init_object_meta(struct kmem_cache *cache, const void *object) struct kasan_free_meta *free_meta; alloc_meta = kasan_get_alloc_meta(cache, object); - if (alloc_meta) + if (alloc_meta) { __memset(alloc_meta, 0, sizeof(*alloc_meta)); + + /* + * Temporarily disable KASAN bug reporting to allow instrumented + * raw_spin_lock_init to access aux_lock, which resides inside + * of a redzone. + */ + kasan_disable_current(); + raw_spin_lock_init(&alloc_meta->aux_lock); + kasan_enable_current(); + } free_meta = kasan_get_free_meta(cache, object); if (free_meta) __memset(free_meta, 0, sizeof(*free_meta)); @@ -502,6 +513,8 @@ static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags) struct kmem_cache *cache; struct kasan_alloc_meta *alloc_meta; void *object; + depot_stack_handle_t new_handle, old_handle; + unsigned long flags; if (is_kfence_address(addr) || !slab) return; @@ -512,9 +525,22 @@ static void __kasan_record_aux_stack(void *addr, depot_flags_t depot_flags) if (!alloc_meta) return; - stack_depot_put(alloc_meta->aux_stack[1]); + new_handle = kasan_save_stack(0, depot_flags); + + /* + * Temporarily disable KASAN bug reporting to allow instrumented + * spinlock functions to access aux_lock, which resides inside of a + * redzone. + */ + kasan_disable_current(); + raw_spin_lock_irqsave(&alloc_meta->aux_lock, flags); + old_handle = alloc_meta->aux_stack[1]; alloc_meta->aux_stack[1] = alloc_meta->aux_stack[0]; - alloc_meta->aux_stack[0] = kasan_save_stack(0, depot_flags); + alloc_meta->aux_stack[0] = new_handle; + raw_spin_unlock_irqrestore(&alloc_meta->aux_lock, flags); + kasan_enable_current(); + + stack_depot_put(old_handle); } void kasan_record_aux_stack(void *addr) diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h index 5e298e3ac909..69e4f5e58e33 100644 --- a/mm/kasan/kasan.h +++ b/mm/kasan/kasan.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #if defined(CONFIG_KASAN_SW_TAGS) || defined(CONFIG_KASAN_HW_TAGS) @@ -249,6 +250,13 @@ struct kasan_global { struct kasan_alloc_meta { struct kasan_track alloc_track; /* Free track is stored in kasan_free_meta. */ + /* + * aux_lock protects aux_stack from accesses from concurrent + * kasan_record_aux_stack calls. It is a raw spinlock to avoid sleeping + * on RT kernels, as kasan_record_aux_stack_noalloc can be called from + * non-sleepable contexts. + */ + raw_spinlock_t aux_lock; depot_stack_handle_t aux_stack[2]; }; -- 2.25.1