[2/2] maple_tree: Fix a potential memory leak, OOB access, or other unpredictable bug
Message ID | 20230407040718.99064-2-zhangpeng.00@bytedance.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp41855vqo; Thu, 6 Apr 2023 21:36:22 -0700 (PDT) X-Google-Smtp-Source: AKy350acVxA14ZSbalKnHEYz5UecyDk3Pxr4jJYmr9G0OwgP0Gnq7I2a6xdia1D0XuLNd7s1+g7N X-Received: by 2002:aa7:d701:0:b0:4fe:1b62:4741 with SMTP id t1-20020aa7d701000000b004fe1b624741mr1322321edq.28.1680842182733; Thu, 06 Apr 2023 21:36:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1680842182; cv=none; d=google.com; s=arc-20160816; b=sxcX+kopp8PnDInuZNhPwLhfg+PPlEsL186F/PaY/Bft4Lu2sUZC16aY661I2TDKQF CSnTUJopxqkcwUjxPQjPi4XcHyQuPQqb4I3rRW2sj2ulGL+55Vq9LYYeCQn14+cgWos0 omUycR5GS/J6z1/MMrI29jXep9DMJ9qYYQcdSBewazbS3jlxntLp4AjYTbTv0BjcFPdy Gm37QRGy1lVYdD+zoTRr+T0tjbUrwDVh1IPmOq1U06tvM10ejODI9v4N/eIIeTfi5Dnj AynG5ET9/iEUv+7q0xeNyS83V8V+ggDxH0rP28oORKXRj+imHiUy7sd/Pueh4BSx49ct E3og== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=0Aui47sYym6eUyJHeRSbvJzsgj2hZgpPMPWCUjUt8JA=; b=wdyEGACMr8wTME6ID7+luINzq68fBbukHyWDSdP56CGYN6s+3Q3fn5L/pBovQzl3Nw CHZvnW4HZ3Wn7+kZuEYtlY1Y2LweYZVlnlyRfJa5bJQ+J2WleuqnRI9h0USkdrkTBUEp dE4k6cnYSb8Hp1N8t3dtFM/qFt7PSdrwTrGgwMqPhTej1pAshwWzYi2rggRGlQmxjbUQ muI5pU5dW65SuxUUjZseIZ7WP5bPRbefEg+RSzhnu7SDGN8XZw5hq3VpwNf1zKUU/0lR dEuUmU1iAFAlijmaXyFQCB827/xheYxGiBbsxU1YyL8SLUZllZPpFxrLKu5x0y0OsEab jveg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@bytedance.com header.s=google header.b="btjxM/o5"; 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=QUARANTINE sp=QUARANTINE dis=NONE) header.from=bytedance.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id n21-20020a056402515500b005027e754e86si2570774edd.452.2023.04.06.21.35.58; Thu, 06 Apr 2023 21:36:22 -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=@bytedance.com header.s=google header.b="btjxM/o5"; 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=QUARANTINE sp=QUARANTINE dis=NONE) header.from=bytedance.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231404AbjDGEKB (ORCPT <rfc822;a1648639935@gmail.com> + 99 others); Fri, 7 Apr 2023 00:10:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59924 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229455AbjDGEJ7 (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Fri, 7 Apr 2023 00:09:59 -0400 Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 323646A4D for <linux-kernel@vger.kernel.org>; Thu, 6 Apr 2023 21:09:58 -0700 (PDT) Received: by mail-pj1-x102c.google.com with SMTP id b5-20020a17090a6e0500b0023f32869993so539124pjk.1 for <linux-kernel@vger.kernel.org>; Thu, 06 Apr 2023 21:09:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1680840597; x=1683432597; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=0Aui47sYym6eUyJHeRSbvJzsgj2hZgpPMPWCUjUt8JA=; b=btjxM/o5y/IqXBtaNZ/DMdaeS8q7W0fcBp996++PmoaYGUmmjxC5+4oxxfu8uCia4a z/9uPMy8aZ4wrmYFHh2isoSkOuu3PIg3rh383oHcggyXy6bZxTcORAPuWHS5LL/Al5r5 tXN5pQdxmZ5pkQi7wWoAQom/VP4xuGT4xhjUe/dVi62TP9vf4COSlJGWAQTN8BpSyVKW KIKCIGH0wEmaOYsU5v7ipz4jT+4WhkeRS1iUYCLZo5dIJxNNUL7r1dnCoydWF9tqIer9 2NURW97pKYXL+4qBdxTgPc1pPH1xF8JNcAsebHvKj73WL9Q0ZH2c9FKM600UDK0L7Qwj IYIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680840597; x=1683432597; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=0Aui47sYym6eUyJHeRSbvJzsgj2hZgpPMPWCUjUt8JA=; b=tR0pIhBp6QIh1PtXKOlbyQyy6fzzmgMpf3sGqBQhKbDZvSNLlVqtifX5z9FszZRQmb nz/x+I5R+8War3Wppbl0D5/y3BrZjKnFR+adyNyUpXS+yuRmBRvfqbIY6QL/nIofe/D4 9P+s2F6U+2S13CFQRht1SgosBKKQwMazHdAxkOx3TLU8wgiVVIxJ4I2U8ZdG+gBrbcEF 9Or65QTC4D6+ISPgKlSib+jQPglugGWB+wAQtesEU3i6J77zQwTCBSEEw7YYySBqrhSX ENQ459pAqdCtvRXs3l6WX4DJ3rFVCez2hCs6Cvx05AeR0OfANd6OVQbpL+RcOJ6f6LrL FfjQ== X-Gm-Message-State: AAQBX9fdpX1qqe8Uh9NB0jqkgggwW/3qc8iq5Jhf+nnAIzHleRIlADtU sQJPLXOYAH1zK98oVQGifdPSJA== X-Received: by 2002:a05:6a20:38a2:b0:de:5082:c9ec with SMTP id n34-20020a056a2038a200b000de5082c9ecmr756627pzf.2.1680840597673; Thu, 06 Apr 2023 21:09:57 -0700 (PDT) Received: from GL4FX4PXWL.bytedance.net ([139.177.225.248]) by smtp.gmail.com with ESMTPSA id b8-20020aa78108000000b0062d7c0dc4f4sm2058010pfi.80.2023.04.06.21.09.54 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 06 Apr 2023 21:09:57 -0700 (PDT) From: Peng Zhang <zhangpeng.00@bytedance.com> To: Liam.Howlett@oracle.com Cc: akpm@linux-foundation.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, maple-tree@lists.infradead.org, Peng Zhang <zhangpeng.00@bytedance.com>, stable@vger.kernel.org Subject: [PATCH 2/2] maple_tree: Fix a potential memory leak, OOB access, or other unpredictable bug Date: Fri, 7 Apr 2023 12:07:18 +0800 Message-Id: <20230407040718.99064-2-zhangpeng.00@bytedance.com> X-Mailer: git-send-email 2.37.0 (Apple Git-136) In-Reply-To: <20230407040718.99064-1-zhangpeng.00@bytedance.com> References: <20230407040718.99064-1-zhangpeng.00@bytedance.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-0.2 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS 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: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1762490772784612893?= X-GMAIL-MSGID: =?utf-8?q?1762490772784612893?= |
Series |
[1/2] maple_tree: Add a test case to check maple_alloc
|
|
Commit Message
Peng Zhang
April 7, 2023, 4:07 a.m. UTC
In mas_alloc_nodes(), there is such a piece of code:
while (requested) {
...
node->node_count = 0;
...
}
"node->node_count = 0" means to initialize the node_count field of the
new node, but the node may not be a new node. It may be a node that
existed before and node_count has a value, setting it to 0 will cause a
memory leak. At this time, mas->alloc->total will be greater than the
actual number of nodes in the linked list, which may cause many other
errors. For example, out-of-bounds access in mas_pop_node(), and
mas_pop_node() may return addresses that should not be used.
Fix it by initializing node_count only for new nodes.
Fixes: 54a611b60590 ("Maple Tree: add new data structure")
Signed-off-by: Peng Zhang <zhangpeng.00@bytedance.com>
Cc: <stable@vger.kernel.org>
---
lib/maple_tree.c | 16 ++++------------
1 file changed, 4 insertions(+), 12 deletions(-)
Comments
* Peng Zhang <zhangpeng.00@bytedance.com> [230407 00:10]: > In mas_alloc_nodes(), there is such a piece of code: > while (requested) { > ... > node->node_count = 0; > ... > } You don't need to quote code in your commit message since it is available in the change log or in the file itself. > "node->node_count = 0" means to initialize the node_count field of the > new node, but the node may not be a new node. It may be a node that > existed before and node_count has a value, setting it to 0 will cause a > memory leak. At this time, mas->alloc->total will be greater than the > actual number of nodes in the linked list, which may cause many other > errors. For example, out-of-bounds access in mas_pop_node(), and > mas_pop_node() may return addresses that should not be used. > Fix it by initializing node_count only for new nodes. > > Fixes: 54a611b60590 ("Maple Tree: add new data structure") > Signed-off-by: Peng Zhang <zhangpeng.00@bytedance.com> > Cc: <stable@vger.kernel.org> > --- > lib/maple_tree.c | 16 ++++------------ > 1 file changed, 4 insertions(+), 12 deletions(-) > > diff --git a/lib/maple_tree.c b/lib/maple_tree.c > index 65fd861b30e1..9e25b3215803 100644 > --- a/lib/maple_tree.c > +++ b/lib/maple_tree.c > @@ -1249,26 +1249,18 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp) > node = mas->alloc; > node->request_count = 0; > while (requested) { > - max_req = MAPLE_ALLOC_SLOTS; > - if (node->node_count) { > - unsigned int offset = node->node_count; > - > - slots = (void **)&node->slot[offset]; > - max_req -= offset; > - } else { > - slots = (void **)&node->slot; > - } > - > + max_req = MAPLE_ALLOC_SLOTS - node->node_count; > + slots = (void **)&node->slot[node->node_count]; Thanks, this is much cleaner. > max_req = min(requested, max_req); > count = mt_alloc_bulk(gfp, max_req, slots); > if (!count) > goto nomem_bulk; > > + if (node->node_count == 0) > + node->slot[0]->node_count = 0; > node->node_count += count; > allocated += count; > node = node->slot[0]; > - node->node_count = 0; > - node->request_count = 0; Why are we not clearing request_count anymore? > requested -= count; > } > mas->alloc->total = allocated; > -- > 2.20.1 >
在 2023/4/10 20:43, Liam R. Howlett 写道: > * Peng Zhang <zhangpeng.00@bytedance.com> [230407 00:10]: >> In mas_alloc_nodes(), there is such a piece of code: >> while (requested) { >> ... >> node->node_count = 0; >> ... >> } > You don't need to quote code in your commit message since it is > available in the change log or in the file itself. Ok, I will change it in the next version. > >> "node->node_count = 0" means to initialize the node_count field of the >> new node, but the node may not be a new node. It may be a node that >> existed before and node_count has a value, setting it to 0 will cause a >> memory leak. At this time, mas->alloc->total will be greater than the >> actual number of nodes in the linked list, which may cause many other >> errors. For example, out-of-bounds access in mas_pop_node(), and >> mas_pop_node() may return addresses that should not be used. >> Fix it by initializing node_count only for new nodes. >> >> Fixes: 54a611b60590 ("Maple Tree: add new data structure") >> Signed-off-by: Peng Zhang <zhangpeng.00@bytedance.com> >> Cc: <stable@vger.kernel.org> >> --- >> lib/maple_tree.c | 16 ++++------------ >> 1 file changed, 4 insertions(+), 12 deletions(-) >> >> diff --git a/lib/maple_tree.c b/lib/maple_tree.c >> index 65fd861b30e1..9e25b3215803 100644 >> --- a/lib/maple_tree.c >> +++ b/lib/maple_tree.c >> @@ -1249,26 +1249,18 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp) >> node = mas->alloc; >> node->request_count = 0; >> while (requested) { >> - max_req = MAPLE_ALLOC_SLOTS; >> - if (node->node_count) { >> - unsigned int offset = node->node_count; >> - >> - slots = (void **)&node->slot[offset]; >> - max_req -= offset; >> - } else { >> - slots = (void **)&node->slot; >> - } >> - >> + max_req = MAPLE_ALLOC_SLOTS - node->node_count; >> + slots = (void **)&node->slot[node->node_count]; > Thanks, this is much cleaner. > >> max_req = min(requested, max_req); >> count = mt_alloc_bulk(gfp, max_req, slots); >> if (!count) >> goto nomem_bulk; >> >> + if (node->node_count == 0) >> + node->slot[0]->node_count = 0; >> node->node_count += count; >> allocated += count; >> node = node->slot[0]; >> - node->node_count = 0; >> - node->request_count = 0; > Why are we not clearing request_count anymore? Because the node pointed to by the variable "node" must not be the head node of the linked list at this time, we only need to maintain the information of the head node. > >> requested -= count; >> } >> mas->alloc->total = allocated; >> -- >> 2.20.1 >>
* Peng Zhang <perlyzhang@gmail.com> [230410 08:58]: > > 在 2023/4/10 20:43, Liam R. Howlett 写道: > > * Peng Zhang <zhangpeng.00@bytedance.com> [230407 00:10]: > > > In mas_alloc_nodes(), there is such a piece of code: > > > while (requested) { > > > ... > > > node->node_count = 0; > > > ... > > > } > > You don't need to quote code in your commit message since it is > > available in the change log or in the file itself. > Ok, I will change it in the next version. > > > > > "node->node_count = 0" means to initialize the node_count field of the > > > new node, but the node may not be a new node. It may be a node that > > > existed before and node_count has a value, setting it to 0 will cause a > > > memory leak. At this time, mas->alloc->total will be greater than the > > > actual number of nodes in the linked list, which may cause many other > > > errors. For example, out-of-bounds access in mas_pop_node(), and > > > mas_pop_node() may return addresses that should not be used. > > > Fix it by initializing node_count only for new nodes. > > > > > > Fixes: 54a611b60590 ("Maple Tree: add new data structure") > > > Signed-off-by: Peng Zhang <zhangpeng.00@bytedance.com> > > > Cc: <stable@vger.kernel.org> > > > --- > > > lib/maple_tree.c | 16 ++++------------ > > > 1 file changed, 4 insertions(+), 12 deletions(-) > > > > > > diff --git a/lib/maple_tree.c b/lib/maple_tree.c > > > index 65fd861b30e1..9e25b3215803 100644 > > > --- a/lib/maple_tree.c > > > +++ b/lib/maple_tree.c > > > @@ -1249,26 +1249,18 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp) > > > node = mas->alloc; > > > node->request_count = 0; > > > while (requested) { > > > - max_req = MAPLE_ALLOC_SLOTS; > > > - if (node->node_count) { > > > - unsigned int offset = node->node_count; > > > - > > > - slots = (void **)&node->slot[offset]; > > > - max_req -= offset; > > > - } else { > > > - slots = (void **)&node->slot; > > > - } > > > - > > > + max_req = MAPLE_ALLOC_SLOTS - node->node_count; > > > + slots = (void **)&node->slot[node->node_count]; > > Thanks, this is much cleaner. > > > > > max_req = min(requested, max_req); > > > count = mt_alloc_bulk(gfp, max_req, slots); > > > if (!count) > > > goto nomem_bulk; > > > + if (node->node_count == 0) > > > + node->slot[0]->node_count = 0; > > > node->node_count += count; > > > allocated += count; > > > node = node->slot[0]; > > > - node->node_count = 0; > > > - node->request_count = 0; > > Why are we not clearing request_count anymore? > Because the node pointed to by the variable "node" > must not be the head node of the linked list at > this time, we only need to maintain the information > of the head node. Right, at this time it is not the head node, but could it become the head node with invalid data? I think it can, because we don't explicitly set it in mas_pop_node()? In any case, be sure to mention that you make a change like this in the change log, like "Drop setting the resquest_count as it is unnecessary because.." in a new paragraph, so that it is not missed. > > > > > requested -= count; > > > } > > > mas->alloc->total = allocated; > > > -- > > > 2.20.1 > > >
在 2023/4/10 21:12, Liam R. Howlett 写道: > * Peng Zhang <perlyzhang@gmail.com> [230410 08:58]: >> 在 2023/4/10 20:43, Liam R. Howlett 写道: >>> * Peng Zhang <zhangpeng.00@bytedance.com> [230407 00:10]: >>>> In mas_alloc_nodes(), there is such a piece of code: >>>> while (requested) { >>>> ... >>>> node->node_count = 0; >>>> ... >>>> } >>> You don't need to quote code in your commit message since it is >>> available in the change log or in the file itself. >> Ok, I will change it in the next version. >>>> "node->node_count = 0" means to initialize the node_count field of the >>>> new node, but the node may not be a new node. It may be a node that >>>> existed before and node_count has a value, setting it to 0 will cause a >>>> memory leak. At this time, mas->alloc->total will be greater than the >>>> actual number of nodes in the linked list, which may cause many other >>>> errors. For example, out-of-bounds access in mas_pop_node(), and >>>> mas_pop_node() may return addresses that should not be used. >>>> Fix it by initializing node_count only for new nodes. >>>> >>>> Fixes: 54a611b60590 ("Maple Tree: add new data structure") >>>> Signed-off-by: Peng Zhang <zhangpeng.00@bytedance.com> >>>> Cc: <stable@vger.kernel.org> >>>> --- >>>> lib/maple_tree.c | 16 ++++------------ >>>> 1 file changed, 4 insertions(+), 12 deletions(-) >>>> >>>> diff --git a/lib/maple_tree.c b/lib/maple_tree.c >>>> index 65fd861b30e1..9e25b3215803 100644 >>>> --- a/lib/maple_tree.c >>>> +++ b/lib/maple_tree.c >>>> @@ -1249,26 +1249,18 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp) >>>> node = mas->alloc; >>>> node->request_count = 0; >>>> while (requested) { >>>> - max_req = MAPLE_ALLOC_SLOTS; >>>> - if (node->node_count) { >>>> - unsigned int offset = node->node_count; >>>> - >>>> - slots = (void **)&node->slot[offset]; >>>> - max_req -= offset; >>>> - } else { >>>> - slots = (void **)&node->slot; >>>> - } >>>> - >>>> + max_req = MAPLE_ALLOC_SLOTS - node->node_count; >>>> + slots = (void **)&node->slot[node->node_count]; >>> Thanks, this is much cleaner. >>> >>>> max_req = min(requested, max_req); >>>> count = mt_alloc_bulk(gfp, max_req, slots); >>>> if (!count) >>>> goto nomem_bulk; >>>> + if (node->node_count == 0) >>>> + node->slot[0]->node_count = 0; >>>> node->node_count += count; >>>> allocated += count; >>>> node = node->slot[0]; >>>> - node->node_count = 0; >>>> - node->request_count = 0; >>> Why are we not clearing request_count anymore? >> Because the node pointed to by the variable "node" >> must not be the head node of the linked list at >> this time, we only need to maintain the information >> of the head node. > Right, at this time it is not the head node, but could it become the > head node with invalid data? I think it can, because we don't > explicitly set it in mas_pop_node()? 1. Actually in mas_pop_node(), when a node becomes the head node, we initialize its total field and request_count field. 2. The total field and request_count field of any non-head node, even if we initialize it, cannot be considered a valid value. Imagine if the request_count of the head node is changed, then we don't actually change the request_count of the non-head nodes, so it is an invalid value anyway. > > In any case, be sure to mention that you make a change like this in the > change log, like "Drop setting the resquest_count as it is unnecessary > because.." in a new paragraph, so that it is not missed. I thought it was a small change that wasn't written in the changelog. In the next version and any future patches, I will write down the details of any changes. Thanks. > > >>>> requested -= count; >>>> } >>>> mas->alloc->total = allocated; >>>> -- >>>> 2.20.1 >>>>
* Peng Zhang <perlyzhang@gmail.com> [230410 09:28]: > > 在 2023/4/10 21:12, Liam R. Howlett 写道: > > * Peng Zhang <perlyzhang@gmail.com> [230410 08:58]: > > > 在 2023/4/10 20:43, Liam R. Howlett 写道: > > > > * Peng Zhang <zhangpeng.00@bytedance.com> [230407 00:10]: > > > > > In mas_alloc_nodes(), there is such a piece of code: > > > > > while (requested) { > > > > > ... > > > > > node->node_count = 0; > > > > > ... > > > > > } > > > > You don't need to quote code in your commit message since it is > > > > available in the change log or in the file itself. > > > Ok, I will change it in the next version. > > > > > "node->node_count = 0" means to initialize the node_count field of the > > > > > new node, but the node may not be a new node. It may be a node that > > > > > existed before and node_count has a value, setting it to 0 will cause a > > > > > memory leak. At this time, mas->alloc->total will be greater than the > > > > > actual number of nodes in the linked list, which may cause many other > > > > > errors. For example, out-of-bounds access in mas_pop_node(), and > > > > > mas_pop_node() may return addresses that should not be used. > > > > > Fix it by initializing node_count only for new nodes. > > > > > > > > > > Fixes: 54a611b60590 ("Maple Tree: add new data structure") > > > > > Signed-off-by: Peng Zhang <zhangpeng.00@bytedance.com> > > > > > Cc: <stable@vger.kernel.org> > > > > > --- > > > > > lib/maple_tree.c | 16 ++++------------ > > > > > 1 file changed, 4 insertions(+), 12 deletions(-) > > > > > > > > > > diff --git a/lib/maple_tree.c b/lib/maple_tree.c > > > > > index 65fd861b30e1..9e25b3215803 100644 > > > > > --- a/lib/maple_tree.c > > > > > +++ b/lib/maple_tree.c > > > > > @@ -1249,26 +1249,18 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp) > > > > > node = mas->alloc; > > > > > node->request_count = 0; > > > > > while (requested) { > > > > > - max_req = MAPLE_ALLOC_SLOTS; > > > > > - if (node->node_count) { > > > > > - unsigned int offset = node->node_count; > > > > > - > > > > > - slots = (void **)&node->slot[offset]; > > > > > - max_req -= offset; > > > > > - } else { > > > > > - slots = (void **)&node->slot; > > > > > - } > > > > > - > > > > > + max_req = MAPLE_ALLOC_SLOTS - node->node_count; > > > > > + slots = (void **)&node->slot[node->node_count]; > > > > Thanks, this is much cleaner. > > > > > > > > > max_req = min(requested, max_req); > > > > > count = mt_alloc_bulk(gfp, max_req, slots); > > > > > if (!count) > > > > > goto nomem_bulk; > > > > > + if (node->node_count == 0) > > > > > + node->slot[0]->node_count = 0; > > > > > node->node_count += count; > > > > > allocated += count; > > > > > node = node->slot[0]; > > > > > - node->node_count = 0; > > > > > - node->request_count = 0; > > > > Why are we not clearing request_count anymore? > > > Because the node pointed to by the variable "node" > > > must not be the head node of the linked list at > > > this time, we only need to maintain the information > > > of the head node. > > Right, at this time it is not the head node, but could it become the > > head node with invalid data? I think it can, because we don't > > explicitly set it in mas_pop_node()? > 1. Actually in mas_pop_node(), when a node becomes the head node, > we initialize its total field and request_count field. Only if there is a request_count to begin with, right? > > 2. The total field and request_count field of any non-head node, > even if we initialize it, cannot be considered a valid value. > Imagine if the request_count of the head node is changed, then > we don't actually change the request_count of the non-head nodes, > so it is an invalid value anyway. When we pop a node, we record the requested value and only initialize it to the recorded value + 1 if it wasn't zero. So if there are no requests, we don't initialize it. This works because of the zeroing of that request_count that you removed here. But it was, as you pointed out, not always using the right node. I think this needs to be moved to your new 'if' statement. > > > > > In any case, be sure to mention that you make a change like this in the > > change log, like "Drop setting the resquest_count as it is unnecessary > > because.." in a new paragraph, so that it is not missed. > I thought it was a small change that wasn't written in the changelog. > In the next version and any future patches, I will write down the > details of any changes. > > Thanks. > > > > > > > > > > requested -= count; > > > > > } > > > > > mas->alloc->total = allocated; > > > > > -- > > > > > 2.20.1 > > > > > >
在 2023/4/10 23:00, Liam R. Howlett 写道: > * Peng Zhang <perlyzhang@gmail.com> [230410 09:28]: >> 在 2023/4/10 21:12, Liam R. Howlett 写道: >>> * Peng Zhang <perlyzhang@gmail.com> [230410 08:58]: >>>> 在 2023/4/10 20:43, Liam R. Howlett 写道: >>>>> * Peng Zhang <zhangpeng.00@bytedance.com> [230407 00:10]: >>>>>> In mas_alloc_nodes(), there is such a piece of code: >>>>>> while (requested) { >>>>>> ... >>>>>> node->node_count = 0; >>>>>> ... >>>>>> } >>>>> You don't need to quote code in your commit message since it is >>>>> available in the change log or in the file itself. >>>> Ok, I will change it in the next version. >>>>>> "node->node_count = 0" means to initialize the node_count field of the >>>>>> new node, but the node may not be a new node. It may be a node that >>>>>> existed before and node_count has a value, setting it to 0 will cause a >>>>>> memory leak. At this time, mas->alloc->total will be greater than the >>>>>> actual number of nodes in the linked list, which may cause many other >>>>>> errors. For example, out-of-bounds access in mas_pop_node(), and >>>>>> mas_pop_node() may return addresses that should not be used. >>>>>> Fix it by initializing node_count only for new nodes. >>>>>> >>>>>> Fixes: 54a611b60590 ("Maple Tree: add new data structure") >>>>>> Signed-off-by: Peng Zhang <zhangpeng.00@bytedance.com> >>>>>> Cc: <stable@vger.kernel.org> >>>>>> --- >>>>>> lib/maple_tree.c | 16 ++++------------ >>>>>> 1 file changed, 4 insertions(+), 12 deletions(-) >>>>>> >>>>>> diff --git a/lib/maple_tree.c b/lib/maple_tree.c >>>>>> index 65fd861b30e1..9e25b3215803 100644 >>>>>> --- a/lib/maple_tree.c >>>>>> +++ b/lib/maple_tree.c >>>>>> @@ -1249,26 +1249,18 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp) >>>>>> node = mas->alloc; >>>>>> node->request_count = 0; >>>>>> while (requested) { >>>>>> - max_req = MAPLE_ALLOC_SLOTS; >>>>>> - if (node->node_count) { >>>>>> - unsigned int offset = node->node_count; >>>>>> - >>>>>> - slots = (void **)&node->slot[offset]; >>>>>> - max_req -= offset; >>>>>> - } else { >>>>>> - slots = (void **)&node->slot; >>>>>> - } >>>>>> - >>>>>> + max_req = MAPLE_ALLOC_SLOTS - node->node_count; >>>>>> + slots = (void **)&node->slot[node->node_count]; >>>>> Thanks, this is much cleaner. >>>>> >>>>>> max_req = min(requested, max_req); >>>>>> count = mt_alloc_bulk(gfp, max_req, slots); >>>>>> if (!count) >>>>>> goto nomem_bulk; >>>>>> + if (node->node_count == 0) >>>>>> + node->slot[0]->node_count = 0; >>>>>> node->node_count += count; >>>>>> allocated += count; >>>>>> node = node->slot[0]; >>>>>> - node->node_count = 0; >>>>>> - node->request_count = 0; >>>>> Why are we not clearing request_count anymore? >>>> Because the node pointed to by the variable "node" >>>> must not be the head node of the linked list at >>>> this time, we only need to maintain the information >>>> of the head node. >>> Right, at this time it is not the head node, but could it become the >>> head node with invalid data? I think it can, because we don't >>> explicitly set it in mas_pop_node()? >> 1. Actually in mas_pop_node(), when a node becomes the head node, >> we initialize its total field and request_count field. > Only if there is a request_count to begin with, right? > >> 2. The total field and request_count field of any non-head node, >> even if we initialize it, cannot be considered a valid value. >> Imagine if the request_count of the head node is changed, then >> we don't actually change the request_count of the non-head nodes, >> so it is an invalid value anyway. > When we pop a node, we record the requested value and only initialize it > to the recorded value + 1 if it wasn't zero. So if there are no > requests, we don't initialize it. Yes, you are right. I neglected that if request_count is equal to 0, the request_count field of the new head node will not be set. There are many implementation details of maple_tree, which is quite error-prone. I will modify it in the next version. Thanks. > > This works because of the zeroing of that request_count that you removed > here. But it was, as you pointed out, not always using the right node. > I think this needs to be moved to your new 'if' statement. > >>> In any case, be sure to mention that you make a change like this in the >>> change log, like "Drop setting the resquest_count as it is unnecessary >>> because.." in a new paragraph, so that it is not missed. >> I thought it was a small change that wasn't written in the changelog. >> In the next version and any future patches, I will write down the >> details of any changes. >> >> Thanks. >> >>> >>>>>> requested -= count; >>>>>> } >>>>>> mas->alloc->total = allocated; >>>>>> -- >>>>>> 2.20.1 >>>>>>
diff --git a/lib/maple_tree.c b/lib/maple_tree.c index 65fd861b30e1..9e25b3215803 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -1249,26 +1249,18 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp) node = mas->alloc; node->request_count = 0; while (requested) { - max_req = MAPLE_ALLOC_SLOTS; - if (node->node_count) { - unsigned int offset = node->node_count; - - slots = (void **)&node->slot[offset]; - max_req -= offset; - } else { - slots = (void **)&node->slot; - } - + max_req = MAPLE_ALLOC_SLOTS - node->node_count; + slots = (void **)&node->slot[node->node_count]; max_req = min(requested, max_req); count = mt_alloc_bulk(gfp, max_req, slots); if (!count) goto nomem_bulk; + if (node->node_count == 0) + node->slot[0]->node_count = 0; node->node_count += count; allocated += count; node = node->slot[0]; - node->node_count = 0; - node->request_count = 0; requested -= count; } mas->alloc->total = allocated;