Commit 580acf6c authored by Paolo Abeni's avatar Paolo Abeni
Browse files

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/20240516145457.1206847-1-mhal@rbox.co/
  - Patch 1/2: remove WARN_ON_ONCE() (Kuniyuki)
  - Combine both patches into a series (Kuniyuki)

v1: https://lore.kernel.org/netdev/20240516103049.1132040-1-mhal@rbox.co/
====================

Link: https://lore.kernel.org/r/20240517093138.1436323-1-mhal@rbox.co


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 3ebc46ca e060e433
Loading
Loading
Loading
Loading
+14 −9
Original line number Diff line number Diff line
@@ -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);
+2 −2
Original line number Diff line number Diff line
@@ -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];