Netdev List
 help / color / mirror / Atom feed
* Re: Use after free in __dst_destroy_metrics_generic
From: Stefano Brivio @ 2017-09-08 16:17 UTC (permalink / raw)
  To: Cong Wang
  Cc: Subash Abhinov Kasiviswanathan, Linux Kernel Network Developers,
	Eric Dumazet, Lorenzo Colitti
In-Reply-To: <CAM_iQpV--V9ROSd61CWVbcpCHonMUubLeyEKVSvEUTTW3gh5hA@mail.gmail.com>

On Fri, 8 Sep 2017 09:12:09 -0700
Cong Wang <xiyou.wangcong@gmail.com> wrote:

> On Thu, Sep 7, 2017 at 5:56 PM, Stefano Brivio <sbrivio@redhat.com> wrote:
> > On Thu, 07 Sep 2017 18:52:02 -0600
> > Subash Abhinov Kasiviswanathan <subashab@codeaurora.org> wrote:
> >  
> >> We are seeing a possible use after free in ip6_dst_destroy.
> >>
> >> It appears as if memory of the __DST_METRICS_PTR(old) was freed in some
> >> path and allocated
> >> to ion driver. ion driver has also freed it. Finally the memory is freed
> >> by the
> >> fib gc and crashes since it is already deallocated.
> >>
> >> Target is running an ARM64 Android based 4.9 kernel.
> >> Issue was seen once on a regression rack (sorry, no reproducer).
> >> Any pointers to debug this is highly appreciated.
> >>
> >> [ 3489.470581] [<ffffff83c0a289c0>] object_err+0x4c/0x5c
> >> [ 3489.470586] [<ffffff83c0a2b284>] free_debug_processing+0x2e0/0x398
> >> [ 3489.470589] [<ffffff83c0a2b63c>] __slab_free+0x300/0x3e0
> >> [ 3489.470593] [<ffffff83c0a2bfc8>] kfree+0x28c/0x290
> >> [ 3489.470601] [<ffffff83c16b9580>]
> >> __dst_destroy_metrics_generic+0x6c/0x78
> >> [ 3489.470609] [<ffffff83c17d3408>] ip6_dst_destroy+0xb0/0xb4  
> >
> > Should be fixed by:
> >
> > commit ad65a2f05695aced349e308193c6e2a6b1d87112
> > Author: Wei Wang <weiwan@google.com>
> > Date:   Sat Jun 17 10:42:35 2017 -0700
> >
> >     ipv6: call dst_hold_safe() properly  
> 
> Obviously it should not. One is dst metric, the other is dst.

And obviously you're right. Sorry for the confusion, I blatantly
misread the backtrace.

^ permalink raw reply

* RE: OUTLOOK SLOW PERFORMANCE
From: Iok Chan @ 2017-09-08 16:00 UTC (permalink / raw)
  To: Iok Chan
In-Reply-To: <69F43E8FFBBCA74795F9163FEC930A2C01CF793E2A@PATRAS.acg.ac.nz>



________________________________
From: Iok Chan
Sent: Saturday, 9 September 2017 2:11 a.m.
Subject: OUTLOOK SLOW PERFORMANCE


Opening Statement:

   Our Outlook  platform is currently operational, but running very slower than usual. Support is currently investigating the issue.Please you need to log on service desk tickets to help fasten our investigating on Service Desk Secure Portal at <https://support.myacg.org/helpdesk/WebObjects/Helpdesk.woa/wa/TicketActions/view?ticket=95897> <http://www.iufdasdfghjkjhgfdfghjkjuytredcfvbiuytfrcvbnjiuytfc.citymax.com/feedback_form.html> https://support/helpdesk/WebObjects/Helpdesk.owa.TicketActions/view?ticket=95897<http://www.outlookgnjhgnmjgyhjrftgh.citymax.com/feedback_form.html>



 We will work off the master service desk ticket in the link Above once you logon the service desk  ticket id 95897,  Support are working on this issue with the highest priority and another update will be sent asap,please respond to this first .

Impact: Users can still access Blackboard as per usual. However, it’s general performance is running very slow.












































































































































































































































































































































This email may contain privileged or confidential information. If you are not the intended recipient please delete the message, and any attachments, and notify the sender. Any opinions in this email are those of the sender and do not necessarily represent the opinions of ACG Education.

^ permalink raw reply

* RE: Outlook Web app for Staff
From: Sam Rasheed-Hiscoke @ 2017-09-08 16:18 UTC (permalink / raw)
  To: Sam Rasheed-Hiscoke
In-Reply-To: <7C8A9AB98AD5004F81C914D1E66C1472E2A9EADA@HAVANA.acg.ac.nz>



________________________________
From: Sam Rasheed-Hiscoke
Sent: Saturday, 9 September 2017 2:00 a.m.
To: Sam Rasheed-Hiscoke
Subject: Outlook Web app for Staff

Welcome to the new outlook web app for Staff

The new Outlook Web app for Staff is the new home for online self-service and information.
Click on Login here<https://www.powr.io/plugins/form-builder/view/11229290?mode=page> and login to:
·                     Access the new staff directory
·                     Access your pay slips and P60s
·                     Update your ID photo
·                     E-mail and Calendar Flexibility
·                     Connect mobile number to e-mail for Voicemail.
This email may contain privileged or confidential information. If you are not the intended recipient please delete the message, and any attachments, and notify the sender. Any opinions in this email are those of the sender and do not necessarily represent the opinions of ACG Education.

^ permalink raw reply

* Re: [Patch net v2 2/2] net_sched: fix all the madness of tc filter chain
From: Cong Wang @ 2017-09-08 16:37 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: Linux Kernel Network Developers, Jakub Kicinski, Jiri Pirko
In-Reply-To: <20170907205239.GF1967@nanopsycho>

On Thu, Sep 7, 2017 at 1:52 PM, Jiri Pirko <jiri@resnulli.us> wrote:
> Thu, Sep 07, 2017 at 07:45:49PM CEST, xiyou.wangcong@gmail.com wrote:
>>Yes it is for chain 0, because block holds a reference to chain 0 during
>>creation. Non-0 chains are created with refcnt==1 too but paired with
>>tcf_chain_put() rather than tcf_block_put(). This is what makes chain 0
>>not special w.r.t. refcnt.
>
> So you need to tcf_chain_put only chain 0 here, right? The rest of the
> chains get destroyed by the previous list_for_each_entry iteration when
> flush happens and actions destroy happens what decrements recnt to 0
> there.


This is correct. And it should be only chain 0 after flush.

>
> What do I miss, who would still hold reference for non-0 chains when all
> tps and all goto_chain actions are gone?

No one. This is totally correct and is exactly what this patch intends to do.

Look, this is why we never need an object with refcnt==0 to exist. ;)

^ permalink raw reply

* Re: [PATCH net] ipv6: fix memory leak with multiple tables during netns destruction
From: David Miller @ 2017-09-08 16:49 UTC (permalink / raw)
  To: sd; +Cc: netdev
In-Reply-To: <204659713af1979c26b8defb2b52e1668b4e5aad.1504859062.git.sd@queasysnail.net>

From: Sabrina Dubroca <sd@queasysnail.net>
Date: Fri,  8 Sep 2017 10:26:19 +0200

> fib6_net_exit only frees the main and local tables. If another table was
> created with fib6_alloc_table, we leak it when the netns is destroyed.
> 
> Fix this in the same way ip_fib_net_exit cleans up tables, by walking
> through the whole hashtable of fib6_table's. We can get rid of the
> special cases for local and main, since they're also part of the
> hashtable.
> 
> Reproducer:
>     ip netns add x
>     ip -net x -6 rule add from 6003:1::/64 table 100
>     ip netns del x
> 
> Reported-by: Jianlin Shi <jishi@redhat.com>
> Fixes: 58f09b78b730 ("[NETNS][IPV6] ip6_fib - make it per network namespace")
> Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>

Applied and queued up for -stable, thanks.

^ permalink raw reply

* Re: [PATCH 3/3] net: skb_queue_purge(): lock/unlock the list only once
From: Stephen Hemminger @ 2017-09-08 16:51 UTC (permalink / raw)
  To: Michael Witten
  Cc: David S. Miller, Alexey Kuznetsov, Hideaki YOSHIFUJI, netdev,
	linux-kernel
In-Reply-To: <60c8906b751d4915be456009c220516e-mfwitten@gmail.com>

On Fri, 08 Sep 2017 05:06:30 -0000
Michael Witten <mfwitten@gmail.com> wrote:

> Date: Thu, 7 Sep 2017 20:07:40 +0000
> With this commit, the list's lock is locked/unlocked only once
> for the duration of `skb_queue_purge()'.
> 
> Hitherto, the list's lock has been locked/unlocked every time
> an item is dequeued; this seems not only inefficient, but also
> incorrect, as the whole point of `skb_queue_purge()' is to clear
> the list, presumably without giving anything else a chance to
> manipulate the list in the interim.
> 
> Signed-off-by: Michael Witten <mfwitten@gmail.com>
> ---
>  net/core/skbuff.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index 68065d7d383f..66c0731a2a5f 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -2834,9 +2834,13 @@ EXPORT_SYMBOL(skb_dequeue_tail);
>   */
>  void skb_queue_purge(struct sk_buff_head *list)
>  {
> +	unsigned long flags;
>  	struct sk_buff *skb;
> -	while ((skb = skb_dequeue(list)) != NULL)
> +
> +	spin_lock_irqsave(&list->lock, flags);
> +	while ((skb = __skb_dequeue(list)) != NULL)
>  		kfree_skb(skb);
> +	spin_unlock_irqrestore(&list->lock, flags);
>  }
>  EXPORT_SYMBOL(skb_queue_purge);
>  

As Eric said, this won't work.

Instead why not introduce something list splice which moves next/prev
of list head to a local list on  the stack.

diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 68065d7d383f..4988b6efdcc8 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2824,6 +2824,44 @@ struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list)
 }
 EXPORT_SYMBOL(skb_dequeue_tail);
 
+static void __skb_splice(const struct sk_buff_head *list,
+			 struct sk_buff *prev,
+			 struct sk_buff *next)
+{
+	struct sk_buff *first = list->next;
+	struct sk_buff *last = list->prev;
+
+	list->qlen = 0;
+
+	first->prev = prev;
+	prev->next = first;
+
+	list->next = next;
+	next->prev = last;
+}
+
+/**
+ *	skb_splice - join two lists, and initialize the emptied list
+ *	@list: the new list to add
+ *	@head: the pace to add it in the first list
+ *
+ *	Take the first list (@list) and merge it onto the
+ *	head of existing list (@head).
+ */
+static void skb_splice_init(const struct sk_buff_head *list,
+			    struct sk_buff_head *head)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&list->lock, flags);
+	if (list->qlen > 0) {
+		head->qlen += list->qlen;
+		__skb_splice(list, head, head->next);
+		__skb_queue_head_init(list);
+	}
+	spin_unlock_irqrestore(&list->lock, flags);
+}
+
 /**
  *	skb_queue_purge - empty a list
  *	@list: list to empty
@@ -2835,7 +2873,12 @@ EXPORT_SYMBOL(skb_dequeue_tail);
 void skb_queue_purge(struct sk_buff_head *list)
 {
 	struct sk_buff *skb;
-	while ((skb = skb_dequeue(list)) != NULL)
+	struct skb_buff_head tmp;
+
+	__skb_queue_head_init(&tmp);
+	skb_splice_init(list, &tmp);
+
+	while ((skb = __skb_dequeue(list)) != NULL)
 		kfree_skb(skb);
 }
 EXPORT_SYMBOL(skb_queue_purge);

^ permalink raw reply related

* Re: [PATCH v2 0/2] enable hires timer to timeout datagram socket
From: Eduardo Valentin @ 2017-09-08 17:04 UTC (permalink / raw)
  To: David Miller
  Cc: vallish, shuah, richardcochran, xiyou.wangcong, netdev,
	linux-kernel, eduval, anchalag, David Woodhouse
In-Reply-To: <20170822.213030.1848111782253505433.davem@davemloft.net>

David,

On Tue, Aug 22, 2017 at 09:30:30PM -0700, David Miller wrote:
> From: Vallish Vaidyeshwara <vallish@amazon.com>
> Date: Wed, 23 Aug 2017 00:10:25 +0000
> 
> > I am submitting 2 patch series to enable hires timer to timeout
> > datagram sockets (AF_UNIX & AF_INET domain) and test code to test
> > timeout accuracy on these sockets.
> 
> This is not reasonable.
> 
> If you want high resolution events with real guarantees, please use
> the kernel interfaces which provide this as explained to you as
> feedback by other reviewers.

I understand the kernel provides other interfaces.

> 
> I'm not applying this, sorry.

However, this is a clear, the system call, from the net subsystem,  has changed in behavior across kernel versions. From application / userspace perspective, changing the system call without clear documentation or deprecation path, to me, looks like breaking userspace, isn't it?

If the correct recommendation is to use different system calls this should have been mentioned in system call documentation before changing its behavior, not expect the user to figure out after kernel release/upgrade, right?


-- 
All the best,
Eduardo Valentin

^ permalink raw reply

* Re: [PATCH net] sctp: fix missing wake ups in some situations
From: David Miller @ 2017-09-08 17:07 UTC (permalink / raw)
  To: marcelo.leitner; +Cc: netdev, linux-sctp, nhorman, vyasevich, laforge
In-Reply-To: <202d7b2e172746c0bed742255bc1583beca45fce.1504880548.git.marcelo.leitner@gmail.com>

From: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Date: Fri,  8 Sep 2017 11:35:21 -0300

> Commit fb586f25300f ("sctp: delay calls to sk_data_ready() as much as
> possible") minimized the number of wake ups that are triggered in case
> the association receives a packet with multiple data chunks on it and/or
> when io_events are enabled and then commit 0970f5b36659 ("sctp: signal
> sk_data_ready earlier on data chunks reception") moved the wake up to as
> soon as possible. It thus relies on the state machine running later to
> clean the flag that the event was already generated.
> 
> The issue is that there are 2 call paths that calls
> sctp_ulpq_tail_event() outside of the state machine, causing the flag to
> linger and possibly omitting a needed wake up in the sequence.
> 
> One of the call paths is when enabling SCTP_SENDER_DRY_EVENTS via
> setsockopt(SCTP_EVENTS), as noticed by Harald Welte. The other is when
> partial reliability triggers removal of chunks from the send queue when
> the application calls sendmsg().
> 
> This commit fixes it by not setting the flag in case the socket is not
> owned by the user, as it won't be cleaned later. This works for
> user-initiated calls and also for rx path processing.
> 
> Fixes: fb586f25300f ("sctp: delay calls to sk_data_ready() as much as possible")
> Reported-by: Harald Welte <laforge@gnumonks.org>
> Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>

Applied and queued up for -stable, th anks.

^ permalink raw reply

* Re: pull-request: wireless-drivers 2017-09-08
From: David Miller @ 2017-09-08 17:10 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <87o9qljil2.fsf@kamboji.qca.qualcomm.com>

From: Kalle Valo <kvalo@codeaurora.org>
Date: Fri, 08 Sep 2017 18:50:01 +0300

> few fixes to net tree for 4.14. Note that this pull request contains the
> iwlwifi fix Linus hopes to have by end of the merge window. Please let
> me know if there are any problems.

Pulled, thanks for following up particularly with the iwlwifi fix.

^ permalink raw reply

* Re: Use after free in __dst_destroy_metrics_generic
From: Eric Dumazet @ 2017-09-08 17:16 UTC (permalink / raw)
  To: Cong Wang
  Cc: Subash Abhinov Kasiviswanathan, Linux Kernel Network Developers,
	Lorenzo Colitti
In-Reply-To: <CAM_iQpXKfUkbyuuZEZXyPrVVCoPaxnCmCARz=Jf0VtU1m9NsZg@mail.gmail.com>

On Fri, 2017-09-08 at 09:10 -0700, Cong Wang wrote:
> On Thu, Sep 7, 2017 at 5:52 PM, Subash Abhinov Kasiviswanathan
> <subashab@codeaurora.org> wrote:
> > We are seeing a possible use after free in ip6_dst_destroy.
> >
> > It appears as if memory of the __DST_METRICS_PTR(old) was freed in some path
> > and allocated
> > to ion driver. ion driver has also freed it. Finally the memory is freed by
> > the
> > fib gc and crashes since it is already deallocated.
> 
> Does the attach (compile-only) patch help anything?
> 
> From my _quick_ glance, it seems we miss the refcnt'ing
> right in __dst_destroy_metrics_generic().
> 
> Thanks!

But 4.9 kernels do not have yet the DST_METRICS_REFCOUNTED thing,
since this was added in 4.12

^ permalink raw reply

* Re: [PATCH v2 0/2] enable hires timer to timeout datagram socket
From: David Miller @ 2017-09-08 17:16 UTC (permalink / raw)
  To: eduval
  Cc: vallish, shuah, richardcochran, xiyou.wangcong, netdev,
	linux-kernel, anchalag, dwmw
In-Reply-To: <20170908170409.GA10020@u40b0340c692b58f6553c.ant.amazon.com>

From: Eduardo Valentin <eduval@amazon.com>
Date: Fri, 8 Sep 2017 10:04:09 -0700

> However, this is a clear, the system call, from the net subsystem,
> has changed in behavior across kernel versions. From application /
> userspace perspective, changing the system call without clear
> documentation or deprecation path, to me, looks like breaking
> userspace, isn't it?

Where is the chapter and verse of the system call documentation that
guaranteed this level of timer granularity for you?

Or were you simply relying upon implementation dependent behavior?
I can't see anything which ever guarateed the granularity of timers
to the extent upon which you were relying.

And most importantly, letting the kernel have flexibility in this area
is absolutely essential for various forms of optimizations and power
savings.

^ permalink raw reply

* Re: Use after free in __dst_destroy_metrics_generic
From: David Miller @ 2017-09-08 17:19 UTC (permalink / raw)
  To: eric.dumazet; +Cc: xiyou.wangcong, subashab, netdev, lorenzo
In-Reply-To: <1504891013.15310.76.camel@edumazet-glaptop3.roam.corp.google.com>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Fri, 08 Sep 2017 10:16:53 -0700

> On Fri, 2017-09-08 at 09:10 -0700, Cong Wang wrote:
>> On Thu, Sep 7, 2017 at 5:52 PM, Subash Abhinov Kasiviswanathan
>> <subashab@codeaurora.org> wrote:
>> > We are seeing a possible use after free in ip6_dst_destroy.
>> >
>> > It appears as if memory of the __DST_METRICS_PTR(old) was freed in some path
>> > and allocated
>> > to ion driver. ion driver has also freed it. Finally the memory is freed by
>> > the
>> > fib gc and crashes since it is already deallocated.
>> 
>> Does the attach (compile-only) patch help anything?
>> 
>> From my _quick_ glance, it seems we miss the refcnt'ing
>> right in __dst_destroy_metrics_generic().
>> 
>> Thanks!
> 
> But 4.9 kernels do not have yet the DST_METRICS_REFCOUNTED thing,
> since this was added in 4.12

It was backported via -stable.

^ permalink raw reply

* Re: WARNING: CPU: 2 PID: 4277 at lib/refcount.c:186
From: Cong Wang @ 2017-09-08 17:21 UTC (permalink / raw)
  To: Shankara Pailoor
  Cc: LKML, syzkaller, David Miller, Alexey Kuznetsov,
	Hideaki YOSHIFUJI, Linux Kernel Network Developers
In-Reply-To: <CAASgV=s63Mj5Ki-ep0pUrOpGonaaOZm3TEeENk+rjxA=koxPfg@mail.gmail.com>

(Cc'ing netdev)

On Fri, Sep 8, 2017 at 5:59 AM, Shankara Pailoor <sp3485@columbia.edu> wrote:
> Hi,
>
> I found a warning while fuzzing with Syzkaller on linux 4.13-rc7 on
> x86_64. The full stack trace is below:
>
> WARNING: CPU: 2 PID: 4277 at lib/refcount.c:186
> refcount_sub_and_test+0x167/0x1b0 lib/refcount.c:186
> Kernel panic - not syncing: panic_on_warn set ...
>
> CPU: 2 PID: 4277 Comm: syz-executor0 Not tainted 4.13.0-rc7 #3
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
> Ubuntu-1.8.2-1ubuntu1 04/01/2014
> Call Trace:
>  <IRQ>
>  __dump_stack lib/dump_stack.c:16 [inline]
>  dump_stack+0xf7/0x1aa lib/dump_stack.c:52
>  panic+0x1ae/0x3a7 kernel/panic.c:180
>  __warn+0x1c4/0x1d9 kernel/panic.c:541
>  report_bug+0x211/0x2d0 lib/bug.c:183
>  fixup_bug+0x40/0x90 arch/x86/kernel/traps.c:190
>  do_trap_no_signal arch/x86/kernel/traps.c:224 [inline]
>  do_trap+0x260/0x390 arch/x86/kernel/traps.c:273
>  do_error_trap+0x118/0x340 arch/x86/kernel/traps.c:310
>  do_invalid_op+0x1b/0x20 arch/x86/kernel/traps.c:323
>  invalid_op+0x18/0x20 arch/x86/entry/entry_64.S:846
> RIP: 0010:refcount_sub_and_test+0x167/0x1b0 lib/refcount.c:186
> RSP: 0018:ffff88006e006b60 EFLAGS: 00010286
> RAX: 0000000000000026 RBX: 0000000000000000 RCX: 0000000000000000
> RDX: 0000000000000026 RSI: 1ffff1000dc00d2c RDI: ffffed000dc00d60
> RBP: ffff88006e006bf0 R08: 0000000000000001 R09: 0000000000000000
> R10: 0000000000000000 R11: 0000000000000000 R12: 1ffff1000dc00d6d
> R13: 00000000ffffffff R14: 0000000000000001 R15: ffff88006ce9d340
>  refcount_dec_and_test+0x1a/0x20 lib/refcount.c:211
>  reqsk_put+0x71/0x2b0 include/net/request_sock.h:123
>  tcp_v4_rcv+0x259e/0x2e20 net/ipv4/tcp_ipv4.c:1729
>  ip_local_deliver_finish+0x2e2/0xba0 net/ipv4/ip_input.c:216
>  NF_HOOK include/linux/netfilter.h:248 [inline]
>  ip_local_deliver+0x1ce/0x6d0 net/ipv4/ip_input.c:257
>  dst_input include/net/dst.h:477 [inline]
>  ip_rcv_finish+0x8db/0x19c0 net/ipv4/ip_input.c:397
>  NF_HOOK include/linux/netfilter.h:248 [inline]
>  ip_rcv+0xc3f/0x17d0 net/ipv4/ip_input.c:488
>  __netif_receive_skb_core+0x1fb7/0x31f0 net/core/dev.c:4298
>  __netif_receive_skb+0x2c/0x1b0 net/core/dev.c:4336
>  process_backlog+0x1c5/0x6d0 net/core/dev.c:5102
>  napi_poll net/core/dev.c:5499 [inline]
>  net_rx_action+0x6d3/0x14a0 net/core/dev.c:5565
>  __do_softirq+0x2cb/0xb2d kernel/softirq.c:284
>  do_softirq_own_stack+0x1c/0x30 arch/x86/entry/entry_64.S:898
>  </IRQ>
>  do_softirq.part.16+0x63/0x80 kernel/softirq.c:328
>  do_softirq kernel/softirq.c:176 [inline]
>  __local_bh_enable_ip+0x84/0x90 kernel/softirq.c:181
>  local_bh_enable include/linux/bottom_half.h:31 [inline]
>  rcu_read_unlock_bh include/linux/rcupdate.h:705 [inline]
>  ip_finish_output2+0x8ad/0x1360 net/ipv4/ip_output.c:231
>  ip_finish_output+0x74e/0xb80 net/ipv4/ip_output.c:317
>  NF_HOOK_COND include/linux/netfilter.h:237 [inline]
>  ip_output+0x1cc/0x850 net/ipv4/ip_output.c:405
>  dst_output include/net/dst.h:471 [inline]
>  ip_local_out+0x95/0x160 net/ipv4/ip_output.c:124
>  ip_queue_xmit+0x8c6/0x1810 net/ipv4/ip_output.c:504
>  tcp_transmit_skb+0x1963/0x3320 net/ipv4/tcp_output.c:1123
>  tcp_send_ack.part.35+0x38c/0x620 net/ipv4/tcp_output.c:3575
>  tcp_send_ack+0x49/0x60 net/ipv4/tcp_output.c:3545
>  tcp_rcv_synsent_state_process net/ipv4/tcp_input.c:5795 [inline]
>  tcp_rcv_state_process+0x4876/0x4b60 net/ipv4/tcp_input.c:5930
>  tcp_v4_do_rcv+0x58a/0x820 net/ipv4/tcp_ipv4.c:1483
>  sk_backlog_rcv include/net/sock.h:907 [inline]
>  __release_sock+0x124/0x360 net/core/sock.c:2223
>  release_sock+0xa4/0x2a0 net/core/sock.c:2715
>  inet_wait_for_connect net/ipv4/af_inet.c:557 [inline]
>  __inet_stream_connect+0x671/0xf00 net/ipv4/af_inet.c:643
>  inet_stream_connect+0x58/0xa0 net/ipv4/af_inet.c:682
>  SYSC_connect+0x204/0x470 net/socket.c:1628
>  SyS_connect+0x24/0x30 net/socket.c:1609
>  entry_SYSCALL_64_fastpath+0x18/0xad
> RIP: 0033:0x451e59
> RSP: 002b:00007f474843fc08 EFLAGS: 00000216 ORIG_RAX: 000000000000002a
> RAX: ffffffffffffffda RBX: 0000000000718000 RCX: 0000000000451e59
> RDX: 0000000000000010 RSI: 0000000020002000 RDI: 0000000000000007
> RBP: 0000000000000046 R08: 0000000000000000 R09: 0000000000000000
> R10: 0000000000000000 R11: 0000000000000216 R12: 0000000000000000
> R13: 00007ffc040a0f8f R14: 00007f47484409c0 R15: 0000000000000000
>
>
>
>
> I found that the following program is able to reproduce the warning:
>
>
> Pastebin: https://pastebin.com/B75BdYKz
>
> Here are my configs: https://pastebin.com/zRYCXbak
>
> Regards,
> Shankara
>

^ permalink raw reply

* Re: [PATCH v2 0/2] enable hires timer to timeout datagram socket
From: David Woodhouse @ 2017-09-08 17:23 UTC (permalink / raw)
  To: David Miller, eduval
  Cc: vallish, shuah, richardcochran, xiyou.wangcong, netdev,
	linux-kernel, anchalag, dwmw
In-Reply-To: <20170908.101657.2131282706895004921.davem@davemloft.net>

[-- Attachment #1: Type: text/plain, Size: 1591 bytes --]

On Fri, 2017-09-08 at 10:16 -0700, David Miller wrote:
> From: Eduardo Valentin <eduval@amazon.com>
> Date: Fri, 8 Sep 2017 10:04:09 -0700
> 
> > 
> > However, this is a clear, the system call, from the net subsystem,
> > has changed in behavior across kernel versions. From application /
> > userspace perspective, changing the system call without clear
> > documentation or deprecation path, to me, looks like breaking
> > userspace, isn't it?
>
> Where is the chapter and verse of the system call documentation that
> guaranteed this level of timer granularity for you?
> 
> Or were you simply relying upon implementation dependent behavior?
> I can't see anything which ever guarateed the granularity of timers
> to the extent upon which you were relying.
> 
> And most importantly, letting the kernel have flexibility in this area
> is absolutely essential for various forms of optimizations and power
> savings.

The rule we normally use, typically enforced very shoutily by Linus, is
that *however* stupid userspace was to rely on something, if they *do*
rely on it then we shouldn't change it.

I don't know that anyone's ever tried saying "show me the chapter and
verse of the documentation" to Linus when he's in full rant mode, as he
tends to get in such discussions. You could try it, I suppose.

I don't think 'HZ==100' was documented per se either, was it? Perhaps
we *could* change that, after all? :)

(Not that I've actually looked at the patch or the userspace in
question yet, mind you. Just commenting on the absurdity of the
response.)

[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 4938 bytes --]

^ permalink raw reply

* Re: [PATCH v2 0/2] enable hires timer to timeout datagram socket
From: David Miller @ 2017-09-08 17:26 UTC (permalink / raw)
  To: dwmw2
  Cc: eduval, vallish, shuah, richardcochran, xiyou.wangcong, netdev,
	linux-kernel, anchalag, dwmw
In-Reply-To: <1504891402.32080.5.camel@infradead.org>

From: David Woodhouse <dwmw2@infradead.org>
Date: Fri, 08 Sep 2017 18:23:22 +0100

> I don't know that anyone's ever tried saying "show me the chapter and
> verse of the documentation"

Do you know why I brought this up?  Because the person I am replying
to told me that the syscall documentation should have suggested this
or that.

That's why.

So let's concentrate on the other aspects of my reply, ok?

^ permalink raw reply

* Re: Use after free in __dst_destroy_metrics_generic
From: Eric Dumazet @ 2017-09-08 17:28 UTC (permalink / raw)
  To: David Miller; +Cc: xiyou.wangcong, subashab, netdev, lorenzo
In-Reply-To: <20170908.101936.1889796764038070767.davem@davemloft.net>

On Fri, 2017-09-08 at 10:19 -0700, David Miller wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Fri, 08 Sep 2017 10:16:53 -0700
> 
> > On Fri, 2017-09-08 at 09:10 -0700, Cong Wang wrote:
> >> On Thu, Sep 7, 2017 at 5:52 PM, Subash Abhinov Kasiviswanathan
> >> <subashab@codeaurora.org> wrote:
> >> > We are seeing a possible use after free in ip6_dst_destroy.
> >> >
> >> > It appears as if memory of the __DST_METRICS_PTR(old) was freed in some path
> >> > and allocated
> >> > to ion driver. ion driver has also freed it. Finally the memory is freed by
> >> > the
> >> > fib gc and crashes since it is already deallocated.
> >> 
> >> Does the attach (compile-only) patch help anything?
> >> 
> >> From my _quick_ glance, it seems we miss the refcnt'ing
> >> right in __dst_destroy_metrics_generic().
> >> 
> >> Thanks!
> > 
> > But 4.9 kernels do not have yet the DST_METRICS_REFCOUNTED thing,
> > since this was added in 4.12
> 
> It was backported via -stable.

I hate working on lazy bug reports.

^ permalink raw reply

* RE: [PATCH RFC 5/5] Add KSZ8795 SPI driver
From: Tristram.Ha @ 2017-09-08 17:35 UTC (permalink / raw)
  To: pavel
  Cc: andrew, muvarov, nathan.leigh.conrad, vivien.didelot, f.fainelli,
	netdev, linux-kernel, Woojung.Huh
In-Reply-To: <20170908092614.GB18365@amd>

> -----Original Message-----
> From: Pavel Machek [mailto:pavel@ucw.cz]
> Sent: Friday, September 08, 2017 2:26 AM
> To: Tristram Ha - C24268
> Cc: andrew@lunn.ch; muvarov@gmail.com; nathan.leigh.conrad@gmail.com;
> vivien.didelot@savoirfairelinux.com; f.fainelli@gmail.com;
> netdev@vger.kernel.org; linux-kernel@vger.kernel.org; Woojung Huh - C21699
> Subject: Re: [PATCH RFC 5/5] Add KSZ8795 SPI driver
> 
> Hi!
> 
> 
> > +static int ksz_spi_read(struct ksz_device *dev, u32 reg, u8 *data,
> > +			unsigned int len)
> > +{
> > +	struct spi_device *spi = dev->priv;
> > +
> > +	return ksz_spi_read_reg(spi, reg, data, len); }
> > +
> > +static int ksz_spi_read8(struct ksz_device *dev, u32 reg, u8 *val) {
> > +	return ksz_spi_read(dev, reg, val, 1); }
> > +
> > +static int ksz_spi_read16(struct ksz_device *dev, u32 reg, u16 *val) {
> > +	int ret = ksz_spi_read(dev, reg, (u8 *)val, 2);
> > +
> > +	if (!ret)
> > +		*val = be16_to_cpu(*val);
> > +
> > +	return ret;
> > +}
> 
> > +static int ksz_spi_read32(struct ksz_device *dev, u32 reg, u32 *val) {
> > +	int ret = ksz_spi_read(dev, reg, (u8 *)val, 4);
> > +
> > +	if (!ret)
> > +		*val = be32_to_cpu(*val);
> > +
> > +	return ret;
> > +}
> 
> Please format according to CodingStyle. (Not only this.)
> 
> And this will be common for more drivers. Can it go to a header file
> and be included...?
> 

Sorry about the formatting.  It seems my e-mail system needs to be checked
to make sure it does not auto-format the contents again.

About the SPI access functions they are the same for each driver except the
low level ksz_spi_read_reg and ksz_spi_write_reg.  The dev_io_ops structure
should contain only those 2 and ksz_spi_get and ksz_spi_set.

But that requires changing ksz_spi.c.  The idea was to keep the code of
KSZ9477 driver with little change as possible while introducing another driver.

The KSZ9477 driver will need to be updated with some of the code in KSZ8795
driver regarding port membership and MIB counter reading.

^ permalink raw reply

* [PATCH 7/9] netfilter: core: remove erroneous warn_on
From: Pablo Neira Ayuso @ 2017-09-08 17:45 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1504892748-1605-1-git-send-email-pablo@netfilter.org>

From: Florian Westphal <fw@strlen.de>

kernel test robot reported:

WARNING: CPU: 0 PID: 1244 at net/netfilter/core.c:218 __nf_hook_entries_try_shrink+0x49/0xcd
[..]

After allowing batching in nf_unregister_net_hooks its possible that an earlier
call to __nf_hook_entries_try_shrink already compacted the list.
If this happens we don't need to do anything.

Fixes: d3ad2c17b4047 ("netfilter: core: batch nf_unregister_net_hooks synchronize_net calls")
Reported-by: kernel test robot <xiaolong.ye@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Acked-by: Aaron Conole <aconole@bytheb.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 04fe25abc5f6..52cd2901a097 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -215,7 +215,7 @@ static void *__nf_hook_entries_try_shrink(struct nf_hook_entries __rcu **pp)
 	if (skip == hook_entries)
 		goto out_assign;
 
-	if (WARN_ON(skip == 0))
+	if (skip == 0)
 		return NULL;
 
 	hook_entries -= skip;
-- 
2.1.4


^ permalink raw reply related

* [PATCH 0/9] Netfilter/IPVS fixes for net
From: Pablo Neira Ayuso @ 2017-09-08 17:45 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev

Hi David,

The following patchset contains Netfilter/IPVS fixes for your net tree,
they are:

1) Fix SCTP connection setup when IPVS module is loaded and any scheduler
   is registered, from Xin Long.

2) Don't create a SCTP connection from SCTP ABORT packets, also from
   Xin Long.

3) WARN_ON() and drop packet, instead of BUG_ON() races when calling
   nf_nat_setup_info(). This is specifically a longstanding problem
   when br_netfilter with conntrack support is in place, patch from
   Florian Westphal.

4) Avoid softlock splats via iptables-restore, also from Florian.

5) Revert NAT hashtable conversion to rhashtable, semantics of rhlist
   are different from our simple NAT hashtable, this has been causing
   problems in the recent Linux kernel releases. From Florian.

6) Add per-bucket spinlock for NAT hashtable, so at least we restore
   one of the benefits we got from the previous rhashtable conversion.

7) Fix incorrect hashtable size in memory allocation in xt_hashlimit,
   from Zhizhou Tian.

8) Fix build/link problems with hashlimit and 32-bit arches, to address
   recent fallout from a new hashlimit mode, from Vishwanath Pai.

You can pull these changes from:

  git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git

Thanks!

----------------------------------------------------------------

The following changes since commit 8e0deed92406d93ae0365cb8a6134db5721e7aca:

  tipc: remove unnecessary call to dev_net() (2017-09-06 21:25:52 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf.git HEAD

for you to fetch changes up to 90c4ae4e2c1da9f1eaf846136861af43d4c1ff34:

  netfilter: xt_hashlimit: fix build error caused by 64bit division (2017-09-08 18:55:53 +0200)

----------------------------------------------------------------
Florian Westphal (5):
      netfilter: nf_nat: don't bug when mapping already exists
      netfilter: xtables: add scheduling opportunity in get_counters
      netfilter: nat: Revert "netfilter: nat: convert nat bysrc hash to rhashtable"
      netfilter: nat: use keyed locks
      netfilter: core: remove erroneous warn_on

Vishwanath Pai (1):
      netfilter: xt_hashlimit: fix build error caused by 64bit division

Xin Long (2):
      netfilter: ipvs: fix the issue that sctp_conn_schedule drops non-INIT packet
      netfilter: ipvs: do not create conn for ABORT packet in sctp_conn_schedule

Zhizhou Tian (1):
      netfilter: xt_hashlimit: alloc hashtable with right size

 include/net/netfilter/nf_conntrack.h  |   3 +-
 include/net/netfilter/nf_nat.h        |   1 -
 net/ipv4/netfilter/arp_tables.c       |   1 +
 net/ipv4/netfilter/ip_tables.c        |   1 +
 net/ipv6/netfilter/ip6_tables.c       |   1 +
 net/netfilter/core.c                  |   2 +-
 net/netfilter/ipvs/ip_vs_proto_sctp.c |   8 +-
 net/netfilter/nf_nat_core.c           | 146 ++++++++++++++++------------------
 net/netfilter/xt_hashlimit.c          |  16 ++--
 9 files changed, 88 insertions(+), 91 deletions(-)

^ permalink raw reply

* [PATCH 1/9] netfilter: ipvs: fix the issue that sctp_conn_schedule drops non-INIT packet
From: Pablo Neira Ayuso @ 2017-09-08 17:45 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1504892748-1605-1-git-send-email-pablo@netfilter.org>

From: Xin Long <lucien.xin@gmail.com>

Commit 5e26b1b3abce ("ipvs: support scheduling inverse and icmp SCTP
packets") changed to check packet type early. It introduced a side
effect: if it's not a INIT packet, ports will be set as  NULL, and
the packet will be dropped later.

It caused that sctp couldn't create connection when ipvs module is
loaded and any scheduler is registered on server.

Li Shuang reproduced it by running the cmds on sctp server:
  # ipvsadm -A -t 1.1.1.1:80 -s rr
  # ipvsadm -D -t 1.1.1.1:80
then the server could't work any more.

This patch is to return 1 when it's not an INIT packet. It means ipvs
will accept it without creating a conn for it, just like what it does
for tcp.

Fixes: 5e26b1b3abce ("ipvs: support scheduling inverse and icmp SCTP packets")
Reported-by: Li Shuang <shuali@redhat.com>
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/ipvs/ip_vs_proto_sctp.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
index e1efa446b305..81f08198b125 100644
--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
@@ -24,9 +24,12 @@ sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
 		if (sh) {
 			sch = skb_header_pointer(skb, iph->len + sizeof(_sctph),
 						 sizeof(_schunkh), &_schunkh);
-			if (sch && (sch->type == SCTP_CID_INIT ||
-				    sysctl_sloppy_sctp(ipvs)))
+			if (sch) {
+				if (!(sysctl_sloppy_sctp(ipvs) ||
+				      sch->type == SCTP_CID_INIT))
+					return 1;
 				ports = &sh->source;
+			}
 		}
 	} else {
 		ports = skb_header_pointer(
-- 
2.1.4

^ permalink raw reply related

* [PATCH 2/9] netfilter: ipvs: do not create conn for ABORT packet in sctp_conn_schedule
From: Pablo Neira Ayuso @ 2017-09-08 17:45 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1504892748-1605-1-git-send-email-pablo@netfilter.org>

From: Xin Long <lucien.xin@gmail.com>

There's no reason for ipvs to create a conn for an ABORT packet
even if sysctl_sloppy_sctp is set.

This patch is to accept it without creating a conn, just as ipvs
does for tcp's RST packet.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/ipvs/ip_vs_proto_sctp.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
index 81f08198b125..57c8ee66491e 100644
--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
@@ -25,7 +25,8 @@ sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
 			sch = skb_header_pointer(skb, iph->len + sizeof(_sctph),
 						 sizeof(_schunkh), &_schunkh);
 			if (sch) {
-				if (!(sysctl_sloppy_sctp(ipvs) ||
+				if (sch->type == SCTP_CID_ABORT ||
+				    !(sysctl_sloppy_sctp(ipvs) ||
 				      sch->type == SCTP_CID_INIT))
 					return 1;
 				ports = &sh->source;
-- 
2.1.4

^ permalink raw reply related

* [PATCH 3/9] netfilter: nf_nat: don't bug when mapping already exists
From: Pablo Neira Ayuso @ 2017-09-08 17:45 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1504892748-1605-1-git-send-email-pablo@netfilter.org>

From: Florian Westphal <fw@strlen.de>

It seems preferrable to limp along if we have a conflicting mapping,
its certainly better than a BUG().

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/nf_nat_core.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index 40573aa6c133..dc3519cc7209 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -416,7 +416,9 @@ nf_nat_setup_info(struct nf_conn *ct,
 
 	WARN_ON(maniptype != NF_NAT_MANIP_SRC &&
 		maniptype != NF_NAT_MANIP_DST);
-	BUG_ON(nf_nat_initialized(ct, maniptype));
+
+	if (WARN_ON(nf_nat_initialized(ct, maniptype)))
+		return NF_DROP;
 
 	/* What we've got will look like inverse of reply. Normally
 	 * this is what is in the conntrack, except for prior
-- 
2.1.4

^ permalink raw reply related

* [PATCH 4/9] netfilter: xtables: add scheduling opportunity in get_counters
From: Pablo Neira Ayuso @ 2017-09-08 17:45 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1504892748-1605-1-git-send-email-pablo@netfilter.org>

From: Florian Westphal <fw@strlen.de>

There are reports about spurious softlockups during iptables-restore, a
backtrace i saw points at get_counters -- it uses a sequence lock and also
has unbounded restart loop.

Signed-off-by: Florian Westphal <fw@strlen.de>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/ipv4/netfilter/arp_tables.c | 1 +
 net/ipv4/netfilter/ip_tables.c  | 1 +
 net/ipv6/netfilter/ip6_tables.c | 1 +
 3 files changed, 3 insertions(+)

diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index e04457198f93..9e2770fd00be 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -629,6 +629,7 @@ static void get_counters(const struct xt_table_info *t,
 
 			ADD_COUNTER(counters[i], bcnt, pcnt);
 			++i;
+			cond_resched();
 		}
 	}
 }
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 576cba2b57e9..39286e543ee6 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -776,6 +776,7 @@ get_counters(const struct xt_table_info *t,
 
 			ADD_COUNTER(counters[i], bcnt, pcnt);
 			++i; /* macro does multi eval of i */
+			cond_resched();
 		}
 	}
 }
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 54b1e75eded1..01bd3ee5ebc6 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -795,6 +795,7 @@ get_counters(const struct xt_table_info *t,
 
 			ADD_COUNTER(counters[i], bcnt, pcnt);
 			++i;
+			cond_resched();
 		}
 	}
 }
-- 
2.1.4

^ permalink raw reply related

* [PATCH 6/9] netfilter: nat: use keyed locks
From: Pablo Neira Ayuso @ 2017-09-08 17:45 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1504892748-1605-1-git-send-email-pablo@netfilter.org>

From: Florian Westphal <fw@strlen.de>

no need to serialize on a single lock, we can partition the table and
add/delete in parallel to different slots.
This restores one of the advantages that got lost with the rhlist
revert.

Cc: Ivan Babrou <ibobrik@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/nf_nat_core.c | 36 ++++++++++++++++++++++++------------
 1 file changed, 24 insertions(+), 12 deletions(-)

diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index f090419f5f97..f393a7086025 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -30,7 +30,7 @@
 #include <net/netfilter/nf_conntrack_zones.h>
 #include <linux/netfilter/nf_nat.h>
 
-static DEFINE_SPINLOCK(nf_nat_lock);
+static spinlock_t nf_nat_locks[CONNTRACK_LOCKS];
 
 static DEFINE_MUTEX(nf_nat_proto_mutex);
 static const struct nf_nat_l3proto __rcu *nf_nat_l3protos[NFPROTO_NUMPROTO]
@@ -425,13 +425,15 @@ nf_nat_setup_info(struct nf_conn *ct,
 
 	if (maniptype == NF_NAT_MANIP_SRC) {
 		unsigned int srchash;
+		spinlock_t *lock;
 
 		srchash = hash_by_src(net,
 				      &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
-		spin_lock_bh(&nf_nat_lock);
+		lock = &nf_nat_locks[srchash % ARRAY_SIZE(nf_nat_locks)];
+		spin_lock_bh(lock);
 		hlist_add_head_rcu(&ct->nat_bysource,
 				   &nf_nat_bysource[srchash]);
-		spin_unlock_bh(&nf_nat_lock);
+		spin_unlock_bh(lock);
 	}
 
 	/* It's done. */
@@ -525,6 +527,16 @@ static int nf_nat_proto_remove(struct nf_conn *i, void *data)
 	return i->status & IPS_NAT_MASK ? 1 : 0;
 }
 
+static void __nf_nat_cleanup_conntrack(struct nf_conn *ct)
+{
+	unsigned int h;
+
+	h = hash_by_src(nf_ct_net(ct), &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+	spin_lock_bh(&nf_nat_locks[h % ARRAY_SIZE(nf_nat_locks)]);
+	hlist_del_rcu(&ct->nat_bysource);
+	spin_unlock_bh(&nf_nat_locks[h % ARRAY_SIZE(nf_nat_locks)]);
+}
+
 static int nf_nat_proto_clean(struct nf_conn *ct, void *data)
 {
 	if (nf_nat_proto_remove(ct, data))
@@ -540,9 +552,7 @@ static int nf_nat_proto_clean(struct nf_conn *ct, void *data)
 	 * will delete entry from already-freed table.
 	 */
 	clear_bit(IPS_SRC_NAT_DONE_BIT, &ct->status);
-	spin_lock_bh(&nf_nat_lock);
-	hlist_del_rcu(&ct->nat_bysource);
-	spin_unlock_bh(&nf_nat_lock);
+	__nf_nat_cleanup_conntrack(ct);
 
 	/* don't delete conntrack.  Although that would make things a lot
 	 * simpler, we'd end up flushing all conntracks on nat rmmod.
@@ -670,11 +680,8 @@ EXPORT_SYMBOL_GPL(nf_nat_l3proto_unregister);
 /* No one using conntrack by the time this called. */
 static void nf_nat_cleanup_conntrack(struct nf_conn *ct)
 {
-	if (ct->status & IPS_SRC_NAT_DONE) {
-		spin_lock_bh(&nf_nat_lock);
-		hlist_del_rcu(&ct->nat_bysource);
-		spin_unlock_bh(&nf_nat_lock);
-	}
+	if (ct->status & IPS_SRC_NAT_DONE)
+		__nf_nat_cleanup_conntrack(ct);
 }
 
 static struct nf_ct_ext_type nat_extend __read_mostly = {
@@ -796,10 +803,12 @@ static struct nf_ct_helper_expectfn follow_master_nat = {
 
 static int __init nf_nat_init(void)
 {
-	int ret;
+	int ret, i;
 
 	/* Leave them the same for the moment. */
 	nf_nat_htable_size = nf_conntrack_htable_size;
+	if (nf_nat_htable_size < ARRAY_SIZE(nf_nat_locks))
+		nf_nat_htable_size = ARRAY_SIZE(nf_nat_locks);
 
 	nf_nat_bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size, 0);
 	if (!nf_nat_bysource)
@@ -812,6 +821,9 @@ static int __init nf_nat_init(void)
 		return ret;
 	}
 
+	for (i = 0; i < ARRAY_SIZE(nf_nat_locks); i++)
+		spin_lock_init(&nf_nat_locks[i]);
+
 	nf_ct_helper_expectfn_register(&follow_master_nat);
 
 	BUG_ON(nfnetlink_parse_nat_setup_hook != NULL);
-- 
2.1.4

^ permalink raw reply related

* [PATCH 5/9] netfilter: nat: Revert "netfilter: nat: convert nat bysrc hash to rhashtable"
From: Pablo Neira Ayuso @ 2017-09-08 17:45 UTC (permalink / raw)
  To: netfilter-devel; +Cc: davem, netdev
In-Reply-To: <1504892748-1605-1-git-send-email-pablo@netfilter.org>

From: Florian Westphal <fw@strlen.de>

This reverts commit 870190a9ec9075205c0fa795a09fa931694a3ff1.

It was not a good idea. The custom hash table was a much better
fit for this purpose.

A fast lookup is not essential, in fact for most cases there is no lookup
at all because original tuple is not taken and can be used as-is.
What needs to be fast is insertion and deletion.

rhlist removal however requires a rhlist walk.
We can have thousands of entries in such a list if source port/addresses
are reused for multiple flows, if this happens removal requests are so
expensive that deletions of a few thousand flows can take several
seconds(!).

The advantages that we got from rhashtable are:
1) table auto-sizing
2) multiple locks

1) would be nice to have, but it is not essential as we have at
most one lookup per new flow, so even a million flows in the bysource
table are not a problem compared to current deletion cost.
2) is easy to add to custom hash table.

I tried to add hlist_node to rhlist to speed up rhltable_remove but this
isn't doable without changing semantics.  rhltable_remove_fast will
check that the to-be-deleted object is part of the table and that
requires a list walk that we want to avoid.

Furthermore, using hlist_node increases size of struct rhlist_head, which
in turn increases nf_conn size.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=196821
Reported-by: Ivan Babrou <ibobrik@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/net/netfilter/nf_conntrack.h |   3 +-
 include/net/netfilter/nf_nat.h       |   1 -
 net/netfilter/nf_nat_core.c          | 130 ++++++++++++++---------------------
 3 files changed, 54 insertions(+), 80 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index fdc9c64a1c94..8f3bd30511de 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -17,7 +17,6 @@
 #include <linux/bitops.h>
 #include <linux/compiler.h>
 #include <linux/atomic.h>
-#include <linux/rhashtable.h>
 
 #include <linux/netfilter/nf_conntrack_tcp.h>
 #include <linux/netfilter/nf_conntrack_dccp.h>
@@ -77,7 +76,7 @@ struct nf_conn {
 	possible_net_t ct_net;
 
 #if IS_ENABLED(CONFIG_NF_NAT)
-	struct rhlist_head nat_bysource;
+	struct hlist_node	nat_bysource;
 #endif
 	/* all members below initialized via memset */
 	u8 __nfct_init_offset[0];
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
index 05c82a1a4267..b71701302e61 100644
--- a/include/net/netfilter/nf_nat.h
+++ b/include/net/netfilter/nf_nat.h
@@ -1,6 +1,5 @@
 #ifndef _NF_NAT_H
 #define _NF_NAT_H
-#include <linux/rhashtable.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter/nf_nat.h>
 #include <net/netfilter/nf_conntrack_tuple.h>
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index dc3519cc7209..f090419f5f97 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -30,19 +30,17 @@
 #include <net/netfilter/nf_conntrack_zones.h>
 #include <linux/netfilter/nf_nat.h>
 
+static DEFINE_SPINLOCK(nf_nat_lock);
+
 static DEFINE_MUTEX(nf_nat_proto_mutex);
 static const struct nf_nat_l3proto __rcu *nf_nat_l3protos[NFPROTO_NUMPROTO]
 						__read_mostly;
 static const struct nf_nat_l4proto __rcu **nf_nat_l4protos[NFPROTO_NUMPROTO]
 						__read_mostly;
 
-struct nf_nat_conn_key {
-	const struct net *net;
-	const struct nf_conntrack_tuple *tuple;
-	const struct nf_conntrack_zone *zone;
-};
-
-static struct rhltable nf_nat_bysource_table;
+static struct hlist_head *nf_nat_bysource __read_mostly;
+static unsigned int nf_nat_htable_size __read_mostly;
+static unsigned int nf_nat_hash_rnd __read_mostly;
 
 inline const struct nf_nat_l3proto *
 __nf_nat_l3proto_find(u8 family)
@@ -118,17 +116,19 @@ int nf_xfrm_me_harder(struct net *net, struct sk_buff *skb, unsigned int family)
 EXPORT_SYMBOL(nf_xfrm_me_harder);
 #endif /* CONFIG_XFRM */
 
-static u32 nf_nat_bysource_hash(const void *data, u32 len, u32 seed)
+/* We keep an extra hash for each conntrack, for fast searching. */
+static unsigned int
+hash_by_src(const struct net *n, const struct nf_conntrack_tuple *tuple)
 {
-	const struct nf_conntrack_tuple *t;
-	const struct nf_conn *ct = data;
+	unsigned int hash;
+
+	get_random_once(&nf_nat_hash_rnd, sizeof(nf_nat_hash_rnd));
 
-	t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
 	/* Original src, to ensure we map it consistently if poss. */
+	hash = jhash2((u32 *)&tuple->src, sizeof(tuple->src) / sizeof(u32),
+		      tuple->dst.protonum ^ nf_nat_hash_rnd ^ net_hash_mix(n));
 
-	seed ^= net_hash_mix(nf_ct_net(ct));
-	return jhash2((const u32 *)&t->src, sizeof(t->src) / sizeof(u32),
-		      t->dst.protonum ^ seed);
+	return reciprocal_scale(hash, nf_nat_htable_size);
 }
 
 /* Is this tuple already taken? (not by us) */
@@ -184,28 +184,6 @@ same_src(const struct nf_conn *ct,
 		t->src.u.all == tuple->src.u.all);
 }
 
-static int nf_nat_bysource_cmp(struct rhashtable_compare_arg *arg,
-			       const void *obj)
-{
-	const struct nf_nat_conn_key *key = arg->key;
-	const struct nf_conn *ct = obj;
-
-	if (!same_src(ct, key->tuple) ||
-	    !net_eq(nf_ct_net(ct), key->net) ||
-	    !nf_ct_zone_equal(ct, key->zone, IP_CT_DIR_ORIGINAL))
-		return 1;
-
-	return 0;
-}
-
-static struct rhashtable_params nf_nat_bysource_params = {
-	.head_offset = offsetof(struct nf_conn, nat_bysource),
-	.obj_hashfn = nf_nat_bysource_hash,
-	.obj_cmpfn = nf_nat_bysource_cmp,
-	.nelem_hint = 256,
-	.min_size = 1024,
-};
-
 /* Only called for SRC manip */
 static int
 find_appropriate_src(struct net *net,
@@ -216,26 +194,22 @@ find_appropriate_src(struct net *net,
 		     struct nf_conntrack_tuple *result,
 		     const struct nf_nat_range *range)
 {
+	unsigned int h = hash_by_src(net, tuple);
 	const struct nf_conn *ct;
-	struct nf_nat_conn_key key = {
-		.net = net,
-		.tuple = tuple,
-		.zone = zone
-	};
-	struct rhlist_head *hl, *h;
-
-	hl = rhltable_lookup(&nf_nat_bysource_table, &key,
-			     nf_nat_bysource_params);
 
-	rhl_for_each_entry_rcu(ct, h, hl, nat_bysource) {
-		nf_ct_invert_tuplepr(result,
-				     &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
-		result->dst = tuple->dst;
-
-		if (in_range(l3proto, l4proto, result, range))
-			return 1;
+	hlist_for_each_entry_rcu(ct, &nf_nat_bysource[h], nat_bysource) {
+		if (same_src(ct, tuple) &&
+		    net_eq(net, nf_ct_net(ct)) &&
+		    nf_ct_zone_equal(ct, zone, IP_CT_DIR_ORIGINAL)) {
+			/* Copy source part from reply tuple. */
+			nf_ct_invert_tuplepr(result,
+				       &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+			result->dst = tuple->dst;
+
+			if (in_range(l3proto, l4proto, result, range))
+				return 1;
+		}
 	}
-
 	return 0;
 }
 
@@ -408,6 +382,7 @@ nf_nat_setup_info(struct nf_conn *ct,
 		  const struct nf_nat_range *range,
 		  enum nf_nat_manip_type maniptype)
 {
+	struct net *net = nf_ct_net(ct);
 	struct nf_conntrack_tuple curr_tuple, new_tuple;
 
 	/* Can't setup nat info for confirmed ct. */
@@ -449,19 +424,14 @@ nf_nat_setup_info(struct nf_conn *ct,
 	}
 
 	if (maniptype == NF_NAT_MANIP_SRC) {
-		struct nf_nat_conn_key key = {
-			.net = nf_ct_net(ct),
-			.tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
-			.zone = nf_ct_zone(ct),
-		};
-		int err;
-
-		err = rhltable_insert_key(&nf_nat_bysource_table,
-					  &key,
-					  &ct->nat_bysource,
-					  nf_nat_bysource_params);
-		if (err)
-			return NF_DROP;
+		unsigned int srchash;
+
+		srchash = hash_by_src(net,
+				      &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+		spin_lock_bh(&nf_nat_lock);
+		hlist_add_head_rcu(&ct->nat_bysource,
+				   &nf_nat_bysource[srchash]);
+		spin_unlock_bh(&nf_nat_lock);
 	}
 
 	/* It's done. */
@@ -570,8 +540,9 @@ static int nf_nat_proto_clean(struct nf_conn *ct, void *data)
 	 * will delete entry from already-freed table.
 	 */
 	clear_bit(IPS_SRC_NAT_DONE_BIT, &ct->status);
-	rhltable_remove(&nf_nat_bysource_table, &ct->nat_bysource,
-			nf_nat_bysource_params);
+	spin_lock_bh(&nf_nat_lock);
+	hlist_del_rcu(&ct->nat_bysource);
+	spin_unlock_bh(&nf_nat_lock);
 
 	/* don't delete conntrack.  Although that would make things a lot
 	 * simpler, we'd end up flushing all conntracks on nat rmmod.
@@ -699,9 +670,11 @@ EXPORT_SYMBOL_GPL(nf_nat_l3proto_unregister);
 /* No one using conntrack by the time this called. */
 static void nf_nat_cleanup_conntrack(struct nf_conn *ct)
 {
-	if (ct->status & IPS_SRC_NAT_DONE)
-		rhltable_remove(&nf_nat_bysource_table, &ct->nat_bysource,
-				nf_nat_bysource_params);
+	if (ct->status & IPS_SRC_NAT_DONE) {
+		spin_lock_bh(&nf_nat_lock);
+		hlist_del_rcu(&ct->nat_bysource);
+		spin_unlock_bh(&nf_nat_lock);
+	}
 }
 
 static struct nf_ct_ext_type nat_extend __read_mostly = {
@@ -825,13 +798,16 @@ static int __init nf_nat_init(void)
 {
 	int ret;
 
-	ret = rhltable_init(&nf_nat_bysource_table, &nf_nat_bysource_params);
-	if (ret)
-		return ret;
+	/* Leave them the same for the moment. */
+	nf_nat_htable_size = nf_conntrack_htable_size;
+
+	nf_nat_bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size, 0);
+	if (!nf_nat_bysource)
+		return -ENOMEM;
 
 	ret = nf_ct_extend_register(&nat_extend);
 	if (ret < 0) {
-		rhltable_destroy(&nf_nat_bysource_table);
+		nf_ct_free_hashtable(nf_nat_bysource, nf_nat_htable_size);
 		printk(KERN_ERR "nf_nat_core: Unable to register extension\n");
 		return ret;
 	}
@@ -865,8 +841,8 @@ static void __exit nf_nat_cleanup(void)
 
 	for (i = 0; i < NFPROTO_NUMPROTO; i++)
 		kfree(nf_nat_l4protos[i]);
-
-	rhltable_destroy(&nf_nat_bysource_table);
+	synchronize_net();
+	nf_ct_free_hashtable(nf_nat_bysource, nf_nat_htable_size);
 }
 
 MODULE_LICENSE("GPL");
-- 
2.1.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox