summaryrefslogtreecommitdiff
path: root/net/unix
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2024-05-13 12:39:49 +0300
committerTakashi Iwai <tiwai@suse.de>2024-05-13 12:39:49 +0300
commit3a07362fab1653d3aca31a9155c8cc776138fd02 (patch)
tree91ecdfabfce8f12bffa2fb64a595a821b67d3422 /net/unix
parent762e6af39883a816290286d5d46a20bbd0f3a135 (diff)
parentc3c5ac4bd7d7019f2e3ad1720572d53226fe656e (diff)
downloadlinux-3a07362fab1653d3aca31a9155c8cc776138fd02.tar.xz
Merge tag 'asoc-v6.10' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v6.10 This is a very big update, in large part due to extensive work the Intel people have been doing in their drivers though it's also been busy elsewhere. There's also a big overhaul of the DAPM documentation from Luca Ceresoli arising from the work he did putting together his recent ELC talk, and he also contributed a new tool for visualising the DAPM state. - A new tool dapm-graph for visualising the DAPM state. - Substantial fixes and clarifications for the DAPM documentation. - Very large updates throughout the Intel audio drivers. - Cleanups of accessors for driver data, module labelling, and for constification. - Modernsation and cleanup work in the Mediatek drivers. - Several fixes and features for the DaVinci I2S driver. - New drivers for several AMD and Intel platforms, Nuvoton NAU8325, Rockchip RK3308 and Texas Instruments PCM6240.
Diffstat (limited to 'net/unix')
-rw-r--r--net/unix/af_unix.c16
-rw-r--r--net/unix/garbage.c18
2 files changed, 26 insertions, 8 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 5b41e2321209..9a6ad5974dff 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2663,9 +2663,13 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
WRITE_ONCE(u->oob_skb, NULL);
consume_skb(skb);
}
- } else if (!(flags & MSG_PEEK)) {
+ } else if (flags & MSG_PEEK) {
+ skb = NULL;
+ } else {
skb_unlink(skb, &sk->sk_receive_queue);
- consume_skb(skb);
+ WRITE_ONCE(u->oob_skb, NULL);
+ if (!WARN_ON_ONCE(skb_unref(skb)))
+ kfree_skb(skb);
skb = skb_peek(&sk->sk_receive_queue);
}
}
@@ -2739,18 +2743,16 @@ redo:
last = skb = skb_peek(&sk->sk_receive_queue);
last_len = last ? last->len : 0;
+again:
#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
if (skb) {
skb = manage_oob(skb, sk, flags, copied);
- if (!skb) {
+ if (!skb && copied) {
unix_state_unlock(sk);
- if (copied)
- break;
- goto redo;
+ break;
}
}
#endif
-again:
if (skb == NULL) {
if (copied >= target)
goto unlock;
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index fa39b6265238..0104be9d4704 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -274,11 +274,22 @@ static void __unix_gc(struct work_struct *work)
* receive queues. Other, non candidate sockets _can_ be
* added to queue, so we must make sure only to touch
* candidates.
+ *
+ * Embryos, though never candidates themselves, affect which
+ * candidates are reachable by the garbage collector. Before
+ * being added to a listener's queue, an embryo may already
+ * receive data carrying SCM_RIGHTS, potentially making the
+ * passed socket a candidate that is not yet reachable by the
+ * collector. It becomes reachable once the embryo is
+ * enqueued. Therefore, we must ensure that no SCM-laden
+ * embryo appears in a (candidate) listener's queue between
+ * consecutive scan_children() calls.
*/
list_for_each_entry_safe(u, next, &gc_inflight_list, link) {
+ struct sock *sk = &u->sk;
long total_refs;
- total_refs = file_count(u->sk.sk_socket->file);
+ total_refs = file_count(sk->sk_socket->file);
WARN_ON_ONCE(!u->inflight);
WARN_ON_ONCE(total_refs < u->inflight);
@@ -286,6 +297,11 @@ static void __unix_gc(struct work_struct *work)
list_move_tail(&u->link, &gc_candidates);
__set_bit(UNIX_GC_CANDIDATE, &u->gc_flags);
__set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
+
+ if (sk->sk_state == TCP_LISTEN) {
+ unix_state_lock_nested(sk, U_LOCK_GC_LISTENER);
+ unix_state_unlock(sk);
+ }
}
}