Thread (39 messages) 39 messages, 8 authors, 2022-05-06

Re: [PATCH v2] net: rds: acquire refcount on TCP sockets

From: Eric Dumazet <edumazet@google.com>
Date: 2022-05-03 13:43:44
Also in: linux-rdma

On Tue, May 3, 2022 at 6:27 AM David Laight [off-list ref] wrote:
From: Paolo Abeni
quoted
Sent: 03 May 2022 10:03

Hello,

On Mon, 2022-05-02 at 10:40 +0900, Tetsuo Handa wrote:
quoted
syzbot is reporting use-after-free read in tcp_retransmit_timer() [1],
for TCP socket used by RDS is accessing sock_net() without acquiring a
refcount on net namespace. Since TCP's retransmission can happen after
a process which created net namespace terminated, we need to explicitly
acquire a refcount.

Link: https://syzkaller.appspot.com/bug?extid=694120e1002c117747ed [1]
Reported-by: syzbot <redacted>
Fixes: 26abe14379f8e2fa ("net: Modify sk_alloc to not reference count the netns of kernel sockets.")
Fixes: 8a68173691f03661 ("net: sk_clone_lock() should only do get_net() if the parent is not a
kernel socket")
quoted
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Tested-by: syzbot <redacted>
---
Changes in v2:
  Add Fixes: tag.
  Move to inside lock_sock() section.

I chose 26abe14379f8e2fa and 8a68173691f03661 which went to 4.2 for Fixes: tag,
for refcount was implicitly taken when 70041088e3b97662 ("RDS: Add TCP transport
to RDS") was added to 2.6.32.

 net/rds/tcp.c | 8 ++++++++
 1 file changed, 8 insertions(+)
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index 5327d130c4b5..2f638f8b7b1e 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -495,6 +495,14 @@ void rds_tcp_tune(struct socket *sock)

    tcp_sock_set_nodelay(sock->sk);
    lock_sock(sk);
+   /* TCP timer functions might access net namespace even after
+    * a process which created this net namespace terminated.
+    */
+   if (!sk->sk_net_refcnt) {
+           sk->sk_net_refcnt = 1;
+           get_net_track(net, &sk->ns_tracker, GFP_KERNEL);
+           sock_inuse_add(net, 1);
+   }
    if (rtn->sndbuf_size > 0) {
            sk->sk_sndbuf = rtn->sndbuf_size;
            sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
This looks equivalent to the fix presented here:

https://lore.kernel.org/all/CANn89i+484ffqb93aQm1N-tjxxvb3WDKX0EbD7318RwRgsatjw@mail.gmail.com/ (local)

but the latter looks a more generic solution. @Tetsuo could you please
test the above in your setup?
Wouldn't a more generic solution be to add a flag to sock_create_kern()
so that it acquires a reference to the namespace?
This could be a bit on one of the existing parameters - like SOCK_NONBLOCK.

I've a driver that uses __sock_create() in order to get that reference.
I'm pretty sure the extra 'security' check will never fail.
This would be silly really.

Definition of a 'kernel socket' is that it does not hold a reference
to the namespace.
(otherwise a netns could not be destroyed by user space)

A kernel layer using kernel sockets needs to properly dismantle them
when a namespace is destroyed.

In the RDS case, the socket was a user socket, or RDS lacked proper
tracking of all the sockets
so that they can be dismantled properly.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help