Received: by 2002:a05:6358:11c7:b0:104:8066:f915 with SMTP id i7csp6479663rwl; Wed, 22 Mar 2023 11:08:27 -0700 (PDT) X-Google-Smtp-Source: AK7set9bU0vZrsESuZseXMMV54/TfDuY7vtOl3M2JkLxMM2JC/FU8IdmNk3t+GDjuJ2hQsIrqOiH X-Received: by 2002:a17:906:c348:b0:878:7189:a457 with SMTP id ci8-20020a170906c34800b008787189a457mr7586134ejb.51.1679508506975; Wed, 22 Mar 2023 11:08:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1679508506; cv=none; d=google.com; s=arc-20160816; b=Z/HryagIjsVTLw8mocnQqBh95gJ6ZHCsSB3wgECxPqBdvAZeCO6BWtjROCshqPfsLw RtUpCh5aKXfQPy1catOq2WPK08B1mZ/tQsSO2TcJt445iD2dKC44/m09vmFnTVwWplAV WqiEdMJ9rpfTv/JJfMh1YCxeFl/Dcg0oUypbo3pk/O2jskzOWEgxevOqny4QwbbQW7Dg Rx9HqTUTT1suxl3vPoRQGq+Apb4yRYSaZCQYy/3e+H2pj/IsNKnfz9DZCMzd9vFqu20p wa6dkXm6XRPeZSwZcUOH48WBHIXdNZ29G0tM//+zvUT4fdiULZbpW7wm3av114VXnC2P zr+g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:message-id:date:references :in-reply-to:subject:cc:to:dkim-signature:dkim-signature:from; bh=qkkIbegMxWZUqfbus+RiogTOJuGNyr4tDo4M11krH3E=; b=banToKn//oQX1yE6WEn3gjxJaaggenNH5+98+xYDmEyNIuDvmOgnNyEloQCoJsHu9O HemQ3jFvqCIaULC6vCIuSd8d74Tc9U5OnJJ3HJhXzmdxWboVUlr9pPmoETlRWC6eFYDy 0EmDhVEBdKN1z3AKSEXTIMruDIkLUNz7+zlmcpZ4isQJd/bMM0KYXxSvZ8dAvKCtZpHm L5G/7XBe6DHWkDbowIeN4YdqBLKr2W0fVGVS69pGflWLkkvQemN8ZrI1SokBhIO9JpCI OEKfKycCXU4QYg2ryKcysdu9U+f93jvqVVIsRRTxBF5L8qx+/BoxBgxa1tzXEXuFxQCc xWDw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=RveF1TyO; dkim=neutral (no key) header.i=@linutronix.de; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id s21-20020a17090699d500b00933356c0d7asi12024235ejn.532.2023.03.22.11.08.02; Wed, 22 Mar 2023 11:08:26 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=RveF1TyO; dkim=neutral (no key) header.i=@linutronix.de; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229936AbjCVSFq (ORCPT + 99 others); Wed, 22 Mar 2023 14:05:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44992 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229484AbjCVSFp (ORCPT ); Wed, 22 Mar 2023 14:05:45 -0400 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DE8BD392A9 for ; Wed, 22 Mar 2023 11:05:43 -0700 (PDT) From: Thomas Gleixner DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1679508342; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=qkkIbegMxWZUqfbus+RiogTOJuGNyr4tDo4M11krH3E=; b=RveF1TyOZ7r0Lg/RCtXOOHu0b1IrF/ZlDGJ1o+0q+va/wzNjefS5nJ6onlFkxdE/Rp2ysV tsRO2khSx17Wu/aKIIGgI3ivXQuQt19aeG/SP/sv4IZb+1ko/TSI1gy0jgA4V7RhPlev48 CbOQM+VoYN1ZFbWRVcqqkGtfFwGx41zZxfgsqELe/PtlHK47D/Fz0Ww/CJdSLqIFItEe9g PS2tB7HMgh6jW98YglVVCWV0jBi8cUlCARIsDiIwA8m/kiI1R7cluqxejSG/vn3dzpwHHj sf1YdDBFRPEmo7hHt1yFM9EM9AVhXUMCcw11+uRE3hEvfxdFWeYXzWzjFd+ULA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1679508342; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=qkkIbegMxWZUqfbus+RiogTOJuGNyr4tDo4M11krH3E=; b=VkcPgENxDemQBBlZKrzXljMMc+lFOkhBluqwYJit6GhkgtWUhmqUhJjjak/2BCYKHIkTR7 ovxuJKyauFj2VGDQ== To: Schspa Shi Cc: longman@redhat.com, swboyd@chromium.org, linux@roeck-us.net, wuchi.zero@gmail.com, linux-kernel@vger.kernel.org, syzbot+5093ba19745994288b53@syzkaller.appspotmail.com Subject: Re: [PATCH 1/2] debugobject: fix concurrency issues with is_static_object In-Reply-To: <87sfdw8yru.ffs@tglx> References: <20230303161906.831686-1-schspa@gmail.com> <87bkl9jt3a.ffs@tglx> <87sfdw8yru.ffs@tglx> Date: Wed, 22 Mar 2023 19:05:41 +0100 Message-ID: <87pm908xvu.ffs@tglx> MIME-Version: 1.0 Content-Type: text/plain X-Spam-Status: No, score=-2.5 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, Mar 22 2023 at 18:46, Thomas Gleixner wrote: > On Wed, Mar 22 2023 at 23:40, Schspa Shi wrote: >> I think we should introduce lookup_object_or_alloc and is_static at the >> same time. > > What for? The below has the NONE/INIT issue addressed and plugs that race completely, so no further action required. Thanks, tglx --- --- a/lib/debugobjects.c +++ b/lib/debugobjects.c @@ -216,10 +216,6 @@ static struct debug_obj *__alloc_object( return obj; } -/* - * Allocate a new object. If the pool is empty, switch off the debugger. - * Must be called with interrupts disabled. - */ static struct debug_obj * alloc_object(void *addr, struct debug_bucket *b, const struct debug_obj_descr *descr) { @@ -552,11 +548,49 @@ static void debug_object_is_on_stack(voi WARN_ON(1); } +static struct debug_obj *lookup_object_or_alloc(void *addr, struct debug_bucket *b, + const struct debug_obj_descr *descr, + bool onstack, bool alloc_ifstatic) +{ + struct debug_obj *obj = lookup_object(addr, b); + enum debug_obj_state state = ODEBUG_STATE_NONE; + + if (likely(obj)) + return obj; + + /* + * debug_object_init() unconditionally allocates untracked + * objects. It does not matter whether it is a static object or + * not. + * + * debug_object_assert_init() and debug_object_activate() allow + * allocation only if the descriptor callback confirms that the + * object is static and considered initialized. For non-static + * objects the allocation needs to be done from the fixup callback. + */ + if (unlikely(alloc_ifstatic)) { + if (!descr->is_static_object || !descr->is_static_object(addr)) + return ERR_PTR(-ENOENT); + /* Statically allocated objects are considered initialized */ + state = ODEBUG_STATE_INIT; + } + + obj = alloc_object(addr, b, descr); + if (likely(obj)) { + obj->state = state; + debug_object_is_on_stack(addr, onstack); + return obj; + } + + /* Out of memory. Do the cleanup outside of the locked region */ + debug_objects_enabled = 0; + return NULL; +} + static void __debug_object_init(void *addr, const struct debug_obj_descr *descr, int onstack) { enum debug_obj_state state; - bool check_stack = false; struct debug_bucket *db; struct debug_obj *obj; unsigned long flags; @@ -572,16 +606,11 @@ static void raw_spin_lock_irqsave(&db->lock, flags); - obj = lookup_object(addr, db); - if (!obj) { - obj = alloc_object(addr, db, descr); - if (!obj) { - debug_objects_enabled = 0; - raw_spin_unlock_irqrestore(&db->lock, flags); - debug_objects_oom(); - return; - } - check_stack = true; + obj = lookup_object_or_alloc(addr, db, descr, onstack, false); + if (unlikely(!obj)) { + raw_spin_unlock_irqrestore(&db->lock, flags); + debug_objects_oom(); + return; } switch (obj->state) { @@ -607,8 +636,6 @@ static void } raw_spin_unlock_irqrestore(&db->lock, flags); - if (check_stack) - debug_object_is_on_stack(addr, onstack); } /** @@ -648,14 +675,12 @@ EXPORT_SYMBOL_GPL(debug_object_init_on_s */ int debug_object_activate(void *addr, const struct debug_obj_descr *descr) { + struct debug_obj o = { .object = addr, .state = ODEBUG_STATE_NOTAVAILABLE, .descr = descr }; enum debug_obj_state state; struct debug_bucket *db; struct debug_obj *obj; unsigned long flags; int ret; - struct debug_obj o = { .object = addr, - .state = ODEBUG_STATE_NOTAVAILABLE, - .descr = descr }; if (!debug_objects_enabled) return 0; @@ -664,8 +689,8 @@ int debug_object_activate(void *addr, co raw_spin_lock_irqsave(&db->lock, flags); - obj = lookup_object(addr, db); - if (obj) { + obj = lookup_object_or_alloc(addr, db, descr, false, true); + if (likely(!IS_ERR_OR_NULL(obj))) { bool print_object = false; switch (obj->state) { @@ -698,24 +723,16 @@ int debug_object_activate(void *addr, co raw_spin_unlock_irqrestore(&db->lock, flags); - /* - * We are here when a static object is activated. We - * let the type specific code confirm whether this is - * true or not. if true, we just make sure that the - * static object is tracked in the object tracker. If - * not, this must be a bug, so we try to fix it up. - */ - if (descr->is_static_object && descr->is_static_object(addr)) { - /* track this static object */ - debug_object_init(addr, descr); - debug_object_activate(addr, descr); - } else { - debug_print_object(&o, "activate"); - ret = debug_object_fixup(descr->fixup_activate, addr, - ODEBUG_STATE_NOTAVAILABLE); - return ret ? 0 : -EINVAL; + /* If NULL the allocaction has hit OOM */ + if (!obj) { + debug_objects_oom(); + return 0; } - return 0; + + /* Object is neither static nor tracked. It's not initialized */ + debug_print_object(&o, "activate"); + ret = debug_object_fixup(descr->fixup_activate, addr, ODEBUG_STATE_NOTAVAILABLE); + return ret ? 0 : -EINVAL; } EXPORT_SYMBOL_GPL(debug_object_activate); @@ -869,6 +886,7 @@ EXPORT_SYMBOL_GPL(debug_object_free); */ void debug_object_assert_init(void *addr, const struct debug_obj_descr *descr) { + struct debug_obj o = { .object = addr, .state = ODEBUG_STATE_NOTAVAILABLE, .descr = descr }; struct debug_bucket *db; struct debug_obj *obj; unsigned long flags; @@ -879,31 +897,20 @@ void debug_object_assert_init(void *addr db = get_bucket((unsigned long) addr); raw_spin_lock_irqsave(&db->lock, flags); + obj = lookup_object_or_alloc(addr, db, descr, false, true); + raw_spin_unlock_irqrestore(&db->lock, flags); + if (likely(!IS_ERR_OR_NULL(obj))) + return; - obj = lookup_object(addr, db); + /* If NULL the allocaction has hit OOM */ if (!obj) { - struct debug_obj o = { .object = addr, - .state = ODEBUG_STATE_NOTAVAILABLE, - .descr = descr }; - - raw_spin_unlock_irqrestore(&db->lock, flags); - /* - * Maybe the object is static, and we let the type specific - * code confirm. Track this static object if true, else invoke - * fixup. - */ - if (descr->is_static_object && descr->is_static_object(addr)) { - /* Track this static object */ - debug_object_init(addr, descr); - } else { - debug_print_object(&o, "assert_init"); - debug_object_fixup(descr->fixup_assert_init, addr, - ODEBUG_STATE_NOTAVAILABLE); - } + debug_objects_oom(); return; } - raw_spin_unlock_irqrestore(&db->lock, flags); + /* Object is neither tracked nor static. It's not initialized. */ + debug_print_object(&o, "assert_init"); + debug_object_fixup(descr->fixup_assert_init, addr, ODEBUG_STATE_NOTAVAILABLE); } EXPORT_SYMBOL_GPL(debug_object_assert_init);