Received: by 2002:a05:6a10:413:0:0:0:0 with SMTP id 19csp2406772pxp; Mon, 21 Mar 2022 19:24:48 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxV0cKtLBG+/79olB+qysjlfPbT3HdNc013WkL7zNuYy8/QSvMkodTNFsmJu8NNuCHqdCkH X-Received: by 2002:a05:6a00:cc2:b0:4fa:7b92:ba06 with SMTP id b2-20020a056a000cc200b004fa7b92ba06mr17114488pfv.59.1647915888547; Mon, 21 Mar 2022 19:24:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1647915888; cv=none; d=google.com; s=arc-20160816; b=N97xwu06uwdznBoyQNpzG3SWQBZEhPqbVSntVNMjgnpfQJ1A6TtAsJrXlBty/j1XD4 sB8I55Rd6qUhHQPqsi8Ba1F2qQn2lcwTCYi9oNCR7rvGz8zZ3/cD2PNywFJazT94k210 cSx+NbG381ajsMThxZz5EJcilFFTFl+pyJejmihvoQLFHy0SQFgkMvKDkGhhsQuPFMHC eQ2iAEvbkbegwQJXzXwjeh8kwSChPeKrA+D95POfDAAD5jwLlAz37bu4QXVcGe6dIY6t 3D/LII1wt4J7xKS2obOnbzYVZ+/tHS3MtEg8SNYeO1h0h/8ND7OoNGAlSlDbpKt/CKdx aG2w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version:dkim-signature; bh=eu82S/LN4yJm+Zr0EcUu+NKIR8yR7yewIFipExmLnts=; b=qSNVBHSlPP+Oc2cwCm2GVU+ZsTLUHi2MoTbiXdnM7f9hm7lOosHy/xkbLEY3I5l5H/ vfQioM1CTmd8gZps3PoeO1wtvAAt+aiSAg6J/Pm+Gn9ha0gLw3cW0PBTVGPYknPVddB/ qFmPxUlXbrLUTYaOgNlr1/rqJhU7gDU6FvEgpXkE2lHI4giOZRUdzdtDpjFP6It6TULk Ru/RV2y1L9LFle0o6ZemlaCYwwb+innhyyJvAw9z01NcQFl9Q2JOItcTdDJmpZnQ0YWL 0EUgDq4njYEAbnx+lonQFK5hGR+W4HG7/G6zfjbUW/jrveztigQlkAuEL9TMFQmDwE+3 q7BA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=tmn+mtJM; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [23.128.96.19]) by mx.google.com with ESMTPS id o6-20020a63f146000000b003816043ef58si14311362pgk.333.2022.03.21.19.24.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Mar 2022 19:24:48 -0700 (PDT) Received-SPF: softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) client-ip=23.128.96.19; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20210112 header.b=tmn+mtJM; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 56CE23DDFE; Mon, 21 Mar 2022 18:57:31 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235264AbiCVB6w (ORCPT + 99 others); Mon, 21 Mar 2022 21:58:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37678 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235253AbiCVB6v (ORCPT ); Mon, 21 Mar 2022 21:58:51 -0400 Received: from mail-ed1-x534.google.com (mail-ed1-x534.google.com [IPv6:2a00:1450:4864:20::534]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C0A2B44761 for ; Mon, 21 Mar 2022 18:57:24 -0700 (PDT) Received: by mail-ed1-x534.google.com with SMTP id w25so19958236edi.11 for ; Mon, 21 Mar 2022 18:57:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=eu82S/LN4yJm+Zr0EcUu+NKIR8yR7yewIFipExmLnts=; b=tmn+mtJMulOY4ofwfJbO4qp0DVMbyuIKSSmBHV1gWJExoLcc7Iwt7juvCR29p6Zn+E /pa85Rd+BUJTwgk/hmZonCLc8mygujG71WvK48iP4C0PgmkPKXK+fLBS/JpdVMP333Cd mu8g594S706CMxBVum1OZLOHnNLHZkV0Qh6UbjvxSUPRhRngWM5Of3D3WbTcCTr6M2Ds KKUkHEsUT5nLtsK2wxFlcjsGD1UNtWVakR2lB7fBVSMN8yrNTyXLjz+SOlox1wxh6lJf nX6JL3+TScbK0E3r0BHM1N/uqnqbrJejp8WCzUxtGQZN30pdXoDSW/pI43IFJSYToSxg eD+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=eu82S/LN4yJm+Zr0EcUu+NKIR8yR7yewIFipExmLnts=; b=VuOArDtHnICh3+EAC3OEQHyS5+PBbAb8tafoc1p0HCO+0gdEoMqha7Ul6fisjToDUa njMtvatm4s1J9eD2yFKvdfn0n4Qx2OjNz8WClPYcmJyZzMgoRhUu6HO8svHRhJyM6lmB MlNTR8iotdsysLGjJW9hE27z8DdHA+bBJp5XD7pTMEDpzdUB9myIEx9ZUrc0FrPV2Ciw 19fDGnPA6ghsoeaLDLf6PXAtnhsBXIC/MV65cvBYIdQTK09A+P1PcbOrQ5V8WfYWhfWn wjMRmxhC6MeEvGHMqK3V2xg6aWgNgHfNwFjIkGkysJfHZJme0Zp8qPgA1bSZLoN4bfwL qkqA== X-Gm-Message-State: AOAM530jDBC8W3NzdATTR0KleP1hMsRWLqc1xQ0i9N2yeXCIKUstMvyo 7ZIDt+e2zRXViOJT+oo0dpzINzUSISWtIy2HdI+LTFSk8auPgQ== X-Received: by 2002:a50:c307:0:b0:418:ec3b:2242 with SMTP id a7-20020a50c307000000b00418ec3b2242mr25864060edb.229.1647914243135; Mon, 21 Mar 2022 18:57:23 -0700 (PDT) MIME-Version: 1.0 References: <20220319055600.3471875-1-davidgow@google.com> In-Reply-To: <20220319055600.3471875-1-davidgow@google.com> From: Daniel Latypov Date: Mon, 21 Mar 2022 20:57:12 -0500 Message-ID: Subject: Re: [PATCH] kunit: Rework kunit_resource allocation policy To: David Gow Cc: Brendan Higgins , Shuah Khan , kunit-dev@googlegroups.com, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-9.5 required=5.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE, USER_IN_DEF_DKIM_WL autolearn=no 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 Sat, Mar 19, 2022 at 12:56 AM David Gow wrote: > > KUnit's test-managed resources can be created in two ways: > - Using the kunit_add_resource() family of functions, which accept a > struct kunit_resource pointer, typically allocated statically or on > the stack during the test. > - Using the kunit_alloc_resource() family of functions, which allocate a > struct kunit_resource using kzalloc() behind the scenes. > > Both of these families of functions accept a 'free' function to be > called when the resource is finally disposed of. > > At present, KUnit will kfree() the resource if this 'free' function is > specified, and will not if it is NULL. However, this can lead > kunit_alloc_resource() to leak memory (if no 'free' function is passed > in), or kunit_add_resource() to incorrectly kfree() memory which was > allocated by some other means (on the stack, as part of a larger > allocation, etc), if a 'free' function is provided. Trying it with this: static void noop_free_resource(struct kunit_resource *) {} struct kunit_resource global_res; static void example_simple_test(struct kunit *test) { kunit_add_resource(test, NULL, noop_free_resource, &global_res, test); } Running then with $ run_kunit --kunitconfig=lib/kunit --arch=x86_64 --build_dir=kunit_x86/ --kconfig_add=CONFIG_KASAN=y Before: BUG: KASAN: double-free or invalid-free in kunit_cleanup+0x51/0xb0 After: Passes > > Instead, always kfree() if the resource was allocated with > kunit_alloc_resource(), and never kfree() if it was passed into > kunit_add_resource() by the user. (If the user of kunit_add_resource() > wishes the resource be kfree()ed, they can call kfree() on the resource > from within the 'free' function. > > This is implemented by adding a 'should_free' member to nit: would `should_kfree` be a bit better? `should_free` almost sounds like "should we invoke res->free" (as nonsensical as that might be) > struct kunit_resource and setting it appropriately. To facilitate this, > the various resource add/alloc functions have been refactored somewhat, > making them all call a __kunit_add_resource() helper after setting the > 'should_free' member appropriately. In the process, all other functions > have been made static inline functions. > > Signed-off-by: David Gow Tested-by: Daniel Latypov > --- > include/kunit/test.h | 135 +++++++++++++++++++++++++++++++++++-------- > lib/kunit/test.c | 65 +++------------------ > 2 files changed, 120 insertions(+), 80 deletions(-) > > diff --git a/include/kunit/test.h b/include/kunit/test.h > index 00b9ff7783ab..5a3aacbadda2 100644 > --- a/include/kunit/test.h > +++ b/include/kunit/test.h > @@ -36,11 +36,14 @@ typedef void (*kunit_resource_free_t)(struct kunit_resource *); > * struct kunit_resource - represents a *test managed resource* > * @data: for the user to store arbitrary data. > * @name: optional name > - * @free: a user supplied function to free the resource. Populated by > - * kunit_resource_alloc(). > + * @free: a user supplied function to free the resource. > * > * Represents a *test managed resource*, a resource which will automatically be > - * cleaned up at the end of a test case. > + * cleaned up at the end of a test case. This cleanup is performed by the 'free' > + * function. The resource itself is allocated with kmalloc() and freed with > + * kfree() if created with kunit_alloc_{,and_get_}resource(), otherwise it must > + * be freed by the user, typically with the 'free' function, or automatically if > + * it's allocated on the stack. I'm not a fan of this complexity, but I'm not sure if we have a way around it, esp. w/ stack-allocated data. Perhaps this would be a bit easier to read if we tweaked it a bit like: "freed with kfree() if allocated by KUnit (via kunit_alloc..." Maybe we can drop the "or automatically, if it's allocated on the stack" as well. A bigger way to simplify: perhaps we should get rid of kunit_alloc_and_get_resource() first? It's only used in KUnit's tests for itself. They could instead use kunit_alloc_resource() + kunit_find_resource(test, kunit_resource_instance_match, data). We could even define the helper with the same name in kunit-test.c (the only place it's used). Alternatively, we could make it an internal helper and define kunit_alloc_resource() as void *kunit_alloc_resource(...) { struct kunit_resource *res = _kunit_alloc_and_get_resource(...) if (res) return res->data; return NULL; } ?