diff options
author | Paolo Abeni <[email protected]> | 2024-05-21 13:42:16 +0200 |
---|---|---|
committer | Paolo Abeni <[email protected]> | 2024-05-21 13:42:17 +0200 |
commit | 580acf6cd807921bc0e9657c5aa02d2360bb5b63 (patch) | |
tree | f7b5b83578580ada5b06ed49f0645d2e6f4a29db | |
parent | 3ebc46ca8675de6378e3f8f40768e180bb8afa66 (diff) | |
parent | e060e433e51246d970c5a8aa1c5ccd9ecc7ba4bf (diff) |
Merge branch 'af_unix-fix-gc-and-improve-selftest'
Michal Luczaj says:
====================
af_unix: Fix GC and improve selftest
Series deals with AF_UNIX garbage collector mishandling some in-flight
graph cycles. Embryos carrying OOB packets with SCM_RIGHTS cause issues.
Patch 1/2 fixes the memory leak.
Patch 2/2 tweaks the selftest for a better OOB coverage.
v3:
- Patch 1/2: correct the commit message (Kuniyuki)
v2: https://lore.kernel.org/netdev/[email protected]/
- Patch 1/2: remove WARN_ON_ONCE() (Kuniyuki)
- Combine both patches into a series (Kuniyuki)
v1: https://lore.kernel.org/netdev/[email protected]/
====================
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Paolo Abeni <[email protected]>
-rw-r--r-- | net/unix/garbage.c | 23 | ||||
-rw-r--r-- | tools/testing/selftests/net/af_unix/scm_rights.c | 4 |
2 files changed, 16 insertions, 11 deletions
diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 1f8b8cdfcdc8..dfe94a90ece4 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -342,6 +342,18 @@ enum unix_recv_queue_lock_class { U_RECVQ_LOCK_EMBRYO, }; +static void unix_collect_queue(struct unix_sock *u, struct sk_buff_head *hitlist) +{ + skb_queue_splice_init(&u->sk.sk_receive_queue, hitlist); + +#if IS_ENABLED(CONFIG_AF_UNIX_OOB) + if (u->oob_skb) { + WARN_ON_ONCE(skb_unref(u->oob_skb)); + u->oob_skb = NULL; + } +#endif +} + static void unix_collect_skb(struct list_head *scc, struct sk_buff_head *hitlist) { struct unix_vertex *vertex; @@ -365,18 +377,11 @@ static void unix_collect_skb(struct list_head *scc, struct sk_buff_head *hitlist /* listener -> embryo order, the inversion never happens. */ spin_lock_nested(&embryo_queue->lock, U_RECVQ_LOCK_EMBRYO); - skb_queue_splice_init(embryo_queue, hitlist); + unix_collect_queue(unix_sk(skb->sk), hitlist); spin_unlock(&embryo_queue->lock); } } else { - skb_queue_splice_init(queue, hitlist); - -#if IS_ENABLED(CONFIG_AF_UNIX_OOB) - if (u->oob_skb) { - kfree_skb(u->oob_skb); - u->oob_skb = NULL; - } -#endif + unix_collect_queue(u, hitlist); } spin_unlock(&queue->lock); diff --git a/tools/testing/selftests/net/af_unix/scm_rights.c b/tools/testing/selftests/net/af_unix/scm_rights.c index bab606c9f1eb..2bfed46e0b19 100644 --- a/tools/testing/selftests/net/af_unix/scm_rights.c +++ b/tools/testing/selftests/net/af_unix/scm_rights.c @@ -197,8 +197,8 @@ void __send_fd(struct __test_metadata *_metadata, const FIXTURE_VARIANT(scm_rights) *variant, int inflight, int receiver) { -#define MSG "nop" -#define MSGLEN 3 +#define MSG "x" +#define MSGLEN 1 struct { struct cmsghdr cmsghdr; int fd[2]; |