lkml.org 
[lkml]   [2021]   [Jul]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.13 595/800] writeback: fix obtain a reference to a freeing memcg css
    Date
    From: Muchun Song <songmuchun@bytedance.com>

    [ Upstream commit 8b0ed8443ae6458786580d36b7d5f8125535c5d4 ]

    The caller of wb_get_create() should pin the memcg, because
    wb_get_create() relies on this guarantee. The rcu read lock
    only can guarantee that the memcg css returned by css_from_id()
    cannot be released, but the reference of the memcg can be zero.

    rcu_read_lock()
    memcg_css = css_from_id()
    wb_get_create(memcg_css)
    cgwb_create(memcg_css)
    // css_get can change the ref counter from 0 back to 1
    css_get(memcg_css)
    rcu_read_unlock()

    Fix it by holding a reference to the css before calling
    wb_get_create(). This is not a problem I encountered in the
    real world. Just the result of a code review.

    Fixes: 682aa8e1a6a1 ("writeback: implement unlocked_inode_to_wb transaction and use it for stat updates")
    Link: https://lore.kernel.org/r/20210402091145.80635-1-songmuchun@bytedance.com
    Signed-off-by: Muchun Song <songmuchun@bytedance.com>
    Acked-by: Michal Hocko <mhocko@suse.com>
    Acked-by: Tejun Heo <tj@kernel.org>
    Signed-off-by: Jan Kara <jack@suse.cz>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/fs-writeback.c | 9 +++++++--
    1 file changed, 7 insertions(+), 2 deletions(-)

    diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
    index d684f541af48..8d4130b01423 100644
    --- a/fs/fs-writeback.c
    +++ b/fs/fs-writeback.c
    @@ -510,9 +510,14 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
    /* find and pin the new wb */
    rcu_read_lock();
    memcg_css = css_from_id(new_wb_id, &memory_cgrp_subsys);
    - if (memcg_css)
    - isw->new_wb = wb_get_create(bdi, memcg_css, GFP_ATOMIC);
    + if (memcg_css && !css_tryget(memcg_css))
    + memcg_css = NULL;
    rcu_read_unlock();
    + if (!memcg_css)
    + goto out_free;
    +
    + isw->new_wb = wb_get_create(bdi, memcg_css, GFP_ATOMIC);
    + css_put(memcg_css);
    if (!isw->new_wb)
    goto out_free;

    --
    2.30.2


    \
     
     \ /
      Last update: 2021-07-12 11:10    [W:2.216 / U:1.392 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site