af_unix: Fix up unix_edge.successor for embryo socket.
To garbage collect inflight AF_UNIX sockets, we must define the
cyclic reference appropriately. This is a bit tricky if the loop
consists of embryo sockets.
Suppose that the fd of AF_UNIX socket A is passed to D and the fd B
to C and that C and D are embryo sockets of A and B, respectively.
It may appear that there are two separate graphs, A (-> D) and
B (-> C), but this is not correct.
A --. .-- B
X
C <-' `-> D
Now, D holds A's refcount, and C has B's refcount, so unix_release()
will never be called for A and B when we close() them. However, no
one can call close() for D and C to free skbs holding refcounts of A
and B because C/D is in A/B's receive queue, which should have been
purged by unix_release() for A and B.
So, here's another type of cyclic reference. When a fd of an AF_UNIX
socket is passed to an embryo socket, the reference is indirectly held
by its parent listening socket.
.-> A .-> B
| `- sk_receive_queue | `- sk_receive_queue
| `- skb | `- skb
| `- sk == C | `- sk == D
| `- sk_receive_queue | `- sk_receive_queue
| `- skb +---------' `- skb +-.
| |
`---------------------------------------------------------'
Technically, the graph must be denoted as A <-> B instead of A (-> D)
and B (-> C) to find such a cyclic reference without touching each
socket's receive queue.
.-> A --. .-- B <-.
| X | == A <-> B
`-- C <-' `-> D --'
We apply this fixup during GC by fetching the real successor by
unix_edge_successor().
When we call accept(), we clear unix_sock.listener under unix_gc_lock
not to confuse GC.
Signed-off-by:
Kuniyuki Iwashima <kuniyu@amazon.com>
Acked-by:
Paolo Abeni <pabeni@redhat.com>
Link: https://lore.kernel.org/r/20240325202425.60930-9-kuniyu@amazon.com
Signed-off-by:
Jakub Kicinski <kuba@kernel.org>
-
mentioned in commit 40fe3009
-
mentioned in commit f301ca1e
-
mentioned in commit f8deba0c
-
mentioned in commit ac7d72ee
-
mentioned in commit 7c4fc96c
-
mentioned in commit 65cbc847
-
mentioned in commit 3bea431f
-
mentioned in commit 0144017f
-
mentioned in commit 8b974aed
-
mentioned in commit a74600c6
-
mentioned in commit d067485d
-
mentioned in commit 2cab8cd9
-
mentioned in commit a081c457
-
mentioned in commit 4b80874c
-
mentioned in commit 70aebcec
-
mentioned in commit 8855fc9f
-
mentioned in commit b3d7c6f0
-
mentioned in commit d3d077c2
-
mentioned in commit 45f502a3
-
mentioned in commit 3bbc9548
-
mentioned in commit 917a1250
-
mentioned in commit d5129576
-
mentioned in commit 15bd6b9e
-
mentioned in commit 9ad91610
-
mentioned in commit 951e4547
-
mentioned in commit 4b5bf4eb
-
mentioned in commit e0a34441
-
mentioned in commit 36ff5620
-
mentioned in commit cb02def5
-
mentioned in commit a26c5acb
-
mentioned in commit 9c2e963f
-
mentioned in commit c862f03e
-
mentioned in commit cfababf4
-
mentioned in commit d55e7772
-
mentioned in commit f3f8d02e
-
mentioned in commit 0bea7c7b
-
mentioned in commit 86e3b411
-
mentioned in commit 7c01ec9c
-
mentioned in commit 6e8c3043
-
mentioned in commit 206c2f4b
-
mentioned in commit e59128b7
-
mentioned in commit f9a2bd69
-
mentioned in commit 38c8379c
-
mentioned in commit 200b75a7
-
mentioned in commit 561fd8ad
-
mentioned in commit 9d043d7b
-
mentioned in commit 43cbbeb1
-
mentioned in commit 0c40a051
-
mentioned in commit a130d07d