lkml.org 
[lkml]   [2019]   [Sep]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.2 03/94] net: sched: act_sample: fix psample group handling on overwrite
    Date
    From: Vlad Buslov <vladbu@mellanox.com>

    [ Upstream commit dbf47a2a094edf58983265e323ca4bdcdb58b5ee ]

    Action sample doesn't properly handle psample_group pointer in overwrite
    case. Following issues need to be fixed:

    - In tcf_sample_init() function RCU_INIT_POINTER() is used to set
    s->psample_group, even though we neither setting the pointer to NULL, nor
    preventing concurrent readers from accessing the pointer in some way.
    Use rcu_swap_protected() instead to safely reset the pointer.

    - Old value of s->psample_group is not released or deallocated in any way,
    which results resource leak. Use psample_group_put() on non-NULL value
    obtained with rcu_swap_protected().

    - The function psample_group_put() that released reference to struct
    psample_group pointed by rcu-pointer s->psample_group doesn't respect rcu
    grace period when deallocating it. Extend struct psample_group with rcu
    head and use kfree_rcu when freeing it.

    Fixes: 5c5670fae430 ("net/sched: Introduce sample tc action")
    Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    include/net/psample.h | 1 +
    net/psample/psample.c | 2 +-
    net/sched/act_sample.c | 6 +++++-
    3 files changed, 7 insertions(+), 2 deletions(-)

    --- a/include/net/psample.h
    +++ b/include/net/psample.h
    @@ -11,6 +11,7 @@ struct psample_group {
    u32 group_num;
    u32 refcount;
    u32 seq;
    + struct rcu_head rcu;
    };

    struct psample_group *psample_group_get(struct net *net, u32 group_num);
    --- a/net/psample/psample.c
    +++ b/net/psample/psample.c
    @@ -154,7 +154,7 @@ static void psample_group_destroy(struct
    {
    psample_group_notify(group, PSAMPLE_CMD_DEL_GROUP);
    list_del(&group->list);
    - kfree(group);
    + kfree_rcu(group, rcu);
    }

    static struct psample_group *
    --- a/net/sched/act_sample.c
    +++ b/net/sched/act_sample.c
    @@ -102,13 +102,17 @@ static int tcf_sample_init(struct net *n
    goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
    s->rate = rate;
    s->psample_group_num = psample_group_num;
    - RCU_INIT_POINTER(s->psample_group, psample_group);
    + rcu_swap_protected(s->psample_group, psample_group,
    + lockdep_is_held(&s->tcf_lock));

    if (tb[TCA_SAMPLE_TRUNC_SIZE]) {
    s->truncate = true;
    s->trunc_size = nla_get_u32(tb[TCA_SAMPLE_TRUNC_SIZE]);
    }
    spin_unlock_bh(&s->tcf_lock);
    +
    + if (psample_group)
    + psample_group_put(psample_group);
    if (goto_ch)
    tcf_chain_put_by_act(goto_ch);


    \
     
     \ /
      Last update: 2019-09-08 14:57    [W:2.600 / U:0.356 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site