diff mbox

[net] net_sched: fix struct tc_u_hnode layout in u32

Message ID 1425945820-9582-1-git-send-email-xiyou.wangcong@gmail.com
State Accepted, archived
Delegated to: David Miller
Headers show

Commit Message

Cong Wang March 10, 2015, 12:03 a.m. UTC
We dynamically allocate divisor+1 entries for ->ht[] in tc_u_hnode:

  ht = kzalloc(sizeof(*ht) + divisor*sizeof(void *), GFP_KERNEL);

So ->ht is supposed to be the last field of this struct, however
this is broken, since an rcu head is appended after it.

Fixes: 1ce87720d456 ("net: sched: make cls_u32 lockless")
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
 net/sched/cls_u32.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

Comments

Eric Dumazet March 10, 2015, 12:13 a.m. UTC | #1
On Mon, 2015-03-09 at 17:03 -0700, Cong Wang wrote:
> We dynamically allocate divisor+1 entries for ->ht[] in tc_u_hnode:
> 
>   ht = kzalloc(sizeof(*ht) + divisor*sizeof(void *), GFP_KERNEL);
> 
> So ->ht is supposed to be the last field of this struct, however
> this is broken, since an rcu head is appended after it.
> 
> Fixes: 1ce87720d456 ("net: sched: make cls_u32 lockless")
> Cc: Jamal Hadi Salim <jhs@mojatatu.com>
> Cc: John Fastabend <john.fastabend@gmail.com>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
> ---
>  net/sched/cls_u32.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
> index 09487af..95fdf4e 100644
> --- a/net/sched/cls_u32.c
> +++ b/net/sched/cls_u32.c
> @@ -78,8 +78,11 @@ struct tc_u_hnode {
>  	struct tc_u_common	*tp_c;
>  	int			refcnt;
>  	unsigned int		divisor;
> -	struct tc_u_knode __rcu	*ht[1];
>  	struct rcu_head		rcu;
> +	/* The 'ht' field MUST be the last field in structure to allow for
> +	 * more entries allocated at end of structure.
> +	 */
> +	struct tc_u_knode __rcu	*ht[1];
>  };

Good catch.

Definitely a call to make this a flexible array in net-next (ht[]), so
that compiler would have catch the bug.

Acked-by: Eric Dumazet <edumazet@google.com>




--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Miller March 10, 2015, 3:45 a.m. UTC | #2
From: Cong Wang <xiyou.wangcong@gmail.com>
Date: Mon,  9 Mar 2015 17:03:40 -0700

> We dynamically allocate divisor+1 entries for ->ht[] in tc_u_hnode:
> 
>   ht = kzalloc(sizeof(*ht) + divisor*sizeof(void *), GFP_KERNEL);
> 
> So ->ht is supposed to be the last field of this struct, however
> this is broken, since an rcu head is appended after it.
> 
> Fixes: 1ce87720d456 ("net: sched: make cls_u32 lockless")
> Cc: Jamal Hadi Salim <jhs@mojatatu.com>
> Cc: John Fastabend <john.fastabend@gmail.com>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>

Applied and queued up for -stable, thanks.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 09487af..95fdf4e 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -78,8 +78,11 @@  struct tc_u_hnode {
 	struct tc_u_common	*tp_c;
 	int			refcnt;
 	unsigned int		divisor;
-	struct tc_u_knode __rcu	*ht[1];
 	struct rcu_head		rcu;
+	/* The 'ht' field MUST be the last field in structure to allow for
+	 * more entries allocated at end of structure.
+	 */
+	struct tc_u_knode __rcu	*ht[1];
 };
 
 struct tc_u_common {