From mboxrd@z Thu Jan 1 00:00:00 1970 From: Willem de Bruijn Subject: [PATCH net] packet: avoid out of bounds read in round robin fanout Date: Tue, 16 Jun 2015 17:07:59 -0400 Message-ID: <1434488879-10663-1-git-send-email-willemb@google.com> Cc: davem@davemloft.net, edumazet@google.com, Willem de Bruijn To: netdev@vger.kernel.org Return-path: Received: from mail-yk0-f171.google.com ([209.85.160.171]:32863 "EHLO mail-yk0-f171.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753814AbbFPVI2 (ORCPT ); Tue, 16 Jun 2015 17:08:28 -0400 Received: by ykfr66 with SMTP id r66so24284147ykf.0 for ; Tue, 16 Jun 2015 14:08:28 -0700 (PDT) Sender: netdev-owner@vger.kernel.org List-ID: From: Willem de Bruijn PACKET_FANOUT_LB computes f->rr_cur such that it is modulo f->num_members. It returns the old value unconditionally, but f->num_members may have changed since the last store. This can be fixed with - return cur + return cur < num ? : 0; When modifying the logic, simplify it further by replacing the loop with an unconditional atomic increment. Fixes: dc99f600698d ("packet: Add fanout support.") Suggested-by: Eric Dumazet Signed-off-by: Willem de Bruijn --- net/packet/af_packet.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index b5989c6..efd35e8 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1272,16 +1272,6 @@ static void packet_sock_destruct(struct sock *sk) sk_refcnt_debug_dec(sk); } -static int fanout_rr_next(struct packet_fanout *f, unsigned int num) -{ - int x = atomic_read(&f->rr_cur) + 1; - - if (x >= num) - x = 0; - - return x; -} - static unsigned int fanout_demux_hash(struct packet_fanout *f, struct sk_buff *skb, unsigned int num) @@ -1293,13 +1283,8 @@ static unsigned int fanout_demux_lb(struct packet_fanout *f, struct sk_buff *skb, unsigned int num) { - int cur, old; - - cur = atomic_read(&f->rr_cur); - while ((old = atomic_cmpxchg(&f->rr_cur, cur, - fanout_rr_next(f, num))) != cur) - cur = old; - return cur; + unsigned int val = atomic_inc_return(&f->rr_cur); + return val % num; } static unsigned int fanout_demux_cpu(struct packet_fanout *f, -- 2.2.0.rc0.207.ga3a616c