<feed xmlns='http://www.w3.org/2005/Atom'>
<title>kernel.git/net/unix, branch linux-6.10.y</title>
<subtitle>Hosts the 0x221E linux distro kernel.
</subtitle>
<id>https://git.0xinfinity.dev/distro/kernel.git/atom?h=linux-6.10.y</id>
<link rel='self' href='https://git.0xinfinity.dev/distro/kernel.git/atom?h=linux-6.10.y'/>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/'/>
<updated>2024-09-12T09:12:50Z</updated>
<entry>
<title>af_unix: Remove put_pid()/put_cred() in copy_peercred().</title>
<updated>2024-09-12T09:12:50Z</updated>
<author>
<name>Kuniyuki Iwashima</name>
</author>
<published>2024-06-20T20:56:22Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=c8cb076f865fc780bdfbdde4fd6802bf07e6923c'/>
<id>urn:sha1:c8cb076f865fc780bdfbdde4fd6802bf07e6923c</id>
<content type='text'>
[ Upstream commit e4bd881d987121dbf1a288641491955a53d9f8f7 ]

When (AF_UNIX, SOCK_STREAM) socket connect()s to a listening socket,
the listener's sk_peer_pid/sk_peer_cred are copied to the client in
copy_peercred().

Then, the client's sk_peer_pid and sk_peer_cred are always NULL, so
we need not call put_pid() and put_cred() there.

Signed-off-by: Kuniyuki Iwashima &lt;kuniyu@amazon.com&gt;
Signed-off-by: Paolo Abeni &lt;pabeni@redhat.com&gt;
Signed-off-by: Sasha Levin &lt;sashal@kernel.org&gt;
</content>
</entry>
<entry>
<title>af_unix: Don't retry after unix_state_lock_nested() in unix_stream_connect().</title>
<updated>2024-08-14T13:34:09Z</updated>
<author>
<name>Kuniyuki Iwashima</name>
</author>
<published>2024-06-20T20:56:15Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=67e8a89ffcd37878fd3f7aa76990accbb19fdbf8'/>
<id>urn:sha1:67e8a89ffcd37878fd3f7aa76990accbb19fdbf8</id>
<content type='text'>
[ Upstream commit 1ca27e0c8c13ac50a4acf9cdf77069e2d94a547d ]

When a SOCK_(STREAM|SEQPACKET) socket connect()s to another one, we need
to lock the two sockets to check their states in unix_stream_connect().

We use unix_state_lock() for the server and unix_state_lock_nested() for
client with tricky sk-&gt;sk_state check to avoid deadlock.

The possible deadlock scenario are the following:

  1) Self connect()
  2) Simultaneous connect()

The former is simple, attempt to grab the same lock, and the latter is
AB-BA deadlock.

After the server's unix_state_lock(), we check the server socket's state,
and if it's not TCP_LISTEN, connect() fails with -EINVAL.

Then, we avoid the former deadlock by checking the client's state before
unix_state_lock_nested().  If its state is not TCP_LISTEN, we can make
sure that the client and the server are not identical based on the state.

Also, the latter deadlock can be avoided in the same way.  Due to the
server sk-&gt;sk_state requirement, AB-BA deadlock could happen only with
TCP_LISTEN sockets.  So, if the client's state is TCP_LISTEN, we can
give up the second lock to avoid the deadlock.

  CPU 1                 CPU 2                  CPU 3
  connect(A -&gt; B)       connect(B -&gt; A)        listen(A)
  ---                   ---                    ---
  unix_state_lock(B)
  B-&gt;sk_state == TCP_LISTEN
  READ_ONCE(A-&gt;sk_state) == TCP_CLOSE
                            ^^^^^^^^^
                            ok, will lock A    unix_state_lock(A)
             .--------------'                  WRITE_ONCE(A-&gt;sk_state, TCP_LISTEN)
             |                                 unix_state_unlock(A)
             |
             |          unix_state_lock(A)
             |          A-&gt;sk_sk_state == TCP_LISTEN
             |          READ_ONCE(B-&gt;sk_state) == TCP_LISTEN
             v                                    ^^^^^^^^^^
  unix_state_lock_nested(A)                       Don't lock B !!

Currently, while checking the client's state, we also check if it's
TCP_ESTABLISHED, but this is unlikely and can be checked after we know
the state is not TCP_CLOSE.

Moreover, if it happens after the second lock, we now jump to the restart
label, but it's unlikely that the server is not found during the retry,
so the jump is mostly to revist the client state check.

Let's remove the retry logic and check the state against TCP_CLOSE first.

Signed-off-by: Kuniyuki Iwashima &lt;kuniyu@amazon.com&gt;
Signed-off-by: Paolo Abeni &lt;pabeni@redhat.com&gt;
Signed-off-by: Sasha Levin &lt;sashal@kernel.org&gt;
</content>
</entry>
<entry>
<title>af_unix: Disable MSG_OOB handling for sockets in sockmap/sockhash</title>
<updated>2024-08-03T07:01:01Z</updated>
<author>
<name>Michal Luczaj</name>
</author>
<published>2024-07-13T19:41:38Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=1c939f94571b90c485fec66cc1c9464e89ed9663'/>
<id>urn:sha1:1c939f94571b90c485fec66cc1c9464e89ed9663</id>
<content type='text'>
[ Upstream commit 638f32604385fd23059985da8de918e9c18f0b98 ]

AF_UNIX socket tracks the most recent OOB packet (in its receive queue)
with an `oob_skb` pointer. BPF redirecting does not account for that: when
an OOB packet is moved between sockets, `oob_skb` is left outdated. This
results in a single skb that may be accessed from two different sockets.

Take the easy way out: silently drop MSG_OOB data targeting any socket that
is in a sockmap or a sockhash. Note that such silent drop is akin to the
fate of redirected skb's scm_fp_list (SCM_RIGHTS, SCM_CREDENTIALS).

For symmetry, forbid MSG_OOB in unix_bpf_recvmsg().

Fixes: 314001f0bf92 ("af_unix: Add OOB support")
Suggested-by: Kuniyuki Iwashima &lt;kuniyu@amazon.com&gt;
Signed-off-by: Michal Luczaj &lt;mhal@rbox.co&gt;
Signed-off-by: Daniel Borkmann &lt;daniel@iogearbox.net&gt;
Tested-by: Jakub Sitnicki &lt;jakub@cloudflare.com&gt;
Reviewed-by: Kuniyuki Iwashima &lt;kuniyu@amazon.com&gt;
Reviewed-by: Jakub Sitnicki &lt;jakub@cloudflare.com&gt;
Link: https://lore.kernel.org/bpf/20240713200218.2140950-2-mhal@rbox.co
Signed-off-by: Sasha Levin &lt;sashal@kernel.org&gt;
</content>
</entry>
<entry>
<title>af_unix: Fix uninit-value in __unix_walk_scc()</title>
<updated>2024-07-04T02:36:22Z</updated>
<author>
<name>Shigeru Yoshida</name>
</author>
<published>2024-07-02T16:04:27Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=927fa5b3e4f52e0967bfc859afc98ad1c523d2d5'/>
<id>urn:sha1:927fa5b3e4f52e0967bfc859afc98ad1c523d2d5</id>
<content type='text'>
KMSAN reported uninit-value access in __unix_walk_scc() [1].

In the list_for_each_entry_reverse() loop, when the vertex's index
equals it's scc_index, the loop uses the variable vertex as a
temporary variable that points to a vertex in scc. And when the loop
is finished, the variable vertex points to the list head, in this case
scc, which is a local variable on the stack (more precisely, it's not
even scc and might underflow the call stack of __unix_walk_scc():
container_of(&amp;scc, struct unix_vertex, scc_entry)).

However, the variable vertex is used under the label prev_vertex. So
if the edge_stack is not empty and the function jumps to the
prev_vertex label, the function will access invalid data on the
stack. This causes the uninit-value access issue.

Fix this by introducing a new temporary variable for the loop.

[1]
BUG: KMSAN: uninit-value in __unix_walk_scc net/unix/garbage.c:478 [inline]
BUG: KMSAN: uninit-value in unix_walk_scc net/unix/garbage.c:526 [inline]
BUG: KMSAN: uninit-value in __unix_gc+0x2589/0x3c20 net/unix/garbage.c:584
 __unix_walk_scc net/unix/garbage.c:478 [inline]
 unix_walk_scc net/unix/garbage.c:526 [inline]
 __unix_gc+0x2589/0x3c20 net/unix/garbage.c:584
 process_one_work kernel/workqueue.c:3231 [inline]
 process_scheduled_works+0xade/0x1bf0 kernel/workqueue.c:3312
 worker_thread+0xeb6/0x15b0 kernel/workqueue.c:3393
 kthread+0x3c4/0x530 kernel/kthread.c:389
 ret_from_fork+0x6e/0x90 arch/x86/kernel/process.c:147
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244

Uninit was stored to memory at:
 unix_walk_scc net/unix/garbage.c:526 [inline]
 __unix_gc+0x2adf/0x3c20 net/unix/garbage.c:584
 process_one_work kernel/workqueue.c:3231 [inline]
 process_scheduled_works+0xade/0x1bf0 kernel/workqueue.c:3312
 worker_thread+0xeb6/0x15b0 kernel/workqueue.c:3393
 kthread+0x3c4/0x530 kernel/kthread.c:389
 ret_from_fork+0x6e/0x90 arch/x86/kernel/process.c:147
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244

Local variable entries created at:
 ref_tracker_free+0x48/0xf30 lib/ref_tracker.c:222
 netdev_tracker_free include/linux/netdevice.h:4058 [inline]
 netdev_put include/linux/netdevice.h:4075 [inline]
 dev_put include/linux/netdevice.h:4101 [inline]
 update_gid_event_work_handler+0xaa/0x1b0 drivers/infiniband/core/roce_gid_mgmt.c:813

CPU: 1 PID: 12763 Comm: kworker/u8:31 Not tainted 6.10.0-rc4-00217-g35bb670d65fc #32
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-2.fc40 04/01/2014
Workqueue: events_unbound __unix_gc

Fixes: 3484f063172d ("af_unix: Detect Strongly Connected Components.")
Reported-by: syzkaller &lt;syzkaller@googlegroups.com&gt;
Signed-off-by: Shigeru Yoshida &lt;syoshida@redhat.com&gt;
Reviewed-by: Kuniyuki Iwashima &lt;kuniyu@amazon.com&gt;
Link: https://patch.msgid.link/20240702160428.10153-1-syoshida@redhat.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>af_unix: Fix wrong ioctl(SIOCATMARK) when consumed OOB skb is at the head.</title>
<updated>2024-06-27T10:05:01Z</updated>
<author>
<name>Kuniyuki Iwashima</name>
</author>
<published>2024-06-25T01:36:44Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=e400cfa38bb0419cf1313e5494ea2b7d114e86d7'/>
<id>urn:sha1:e400cfa38bb0419cf1313e5494ea2b7d114e86d7</id>
<content type='text'>
Even if OOB data is recv()ed, ioctl(SIOCATMARK) must return 1 when the
OOB skb is at the head of the receive queue and no new OOB data is queued.

Without fix:

  #  RUN           msg_oob.no_peek.oob ...
  # msg_oob.c:305:oob:Expected answ[0] (0) == oob_head (1)
  # oob: Test terminated by assertion
  #          FAIL  msg_oob.no_peek.oob
  not ok 2 msg_oob.no_peek.oob

With fix:

  #  RUN           msg_oob.no_peek.oob ...
  #            OK  msg_oob.no_peek.oob
  ok 2 msg_oob.no_peek.oob

Fixes: 314001f0bf92 ("af_unix: Add OOB support")
Signed-off-by: Kuniyuki Iwashima &lt;kuniyu@amazon.com&gt;
Signed-off-by: Paolo Abeni &lt;pabeni@redhat.com&gt;

</content>
</entry>
<entry>
<title>af_unix: Don't stop recv() at consumed ex-OOB skb.</title>
<updated>2024-06-27T10:05:01Z</updated>
<author>
<name>Kuniyuki Iwashima</name>
</author>
<published>2024-06-25T01:36:40Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=36893ef0b661671ee64eb37bf5f345f33d2cabb7'/>
<id>urn:sha1:36893ef0b661671ee64eb37bf5f345f33d2cabb7</id>
<content type='text'>
Currently, recv() is stopped at a consumed OOB skb even if a new
OOB skb is queued and we can ignore the old OOB skb.

  &gt;&gt;&gt; from socket import *
  &gt;&gt;&gt; c1, c2 = socket(AF_UNIX, SOCK_STREAM)
  &gt;&gt;&gt; c1.send(b'hellowor', MSG_OOB)
  8
  &gt;&gt;&gt; c2.recv(1, MSG_OOB)  # consume OOB data stays at middle of recvq.
  b'r'
  &gt;&gt;&gt; c1.send(b'ld', MSG_OOB)
  2
  &gt;&gt;&gt; c2.recv(10)          # recv() stops at the old consumed OOB
  b'hellowo'               # should be 'hellowol'

manage_oob() should not stop recv() at the old consumed OOB skb if
there is a new OOB data queued.

Note that TCP behaviour is apparently wrong in this test case because
we can recv() the same OOB data twice.

Without fix:

  #  RUN           msg_oob.no_peek.ex_oob_ahead_break ...
  # msg_oob.c:138:ex_oob_ahead_break:AF_UNIX :hellowo
  # msg_oob.c:139:ex_oob_ahead_break:Expected:hellowol
  # msg_oob.c:141:ex_oob_ahead_break:Expected ret[0] (7) == expected_len (8)
  # ex_oob_ahead_break: Test terminated by assertion
  #          FAIL  msg_oob.no_peek.ex_oob_ahead_break
  not ok 11 msg_oob.no_peek.ex_oob_ahead_break

With fix:

  #  RUN           msg_oob.no_peek.ex_oob_ahead_break ...
  # msg_oob.c:146:ex_oob_ahead_break:AF_UNIX :hellowol
  # msg_oob.c:147:ex_oob_ahead_break:TCP     :helloworl
  #            OK  msg_oob.no_peek.ex_oob_ahead_break
  ok 11 msg_oob.no_peek.ex_oob_ahead_break

Fixes: 314001f0bf92 ("af_unix: Add OOB support")
Signed-off-by: Kuniyuki Iwashima &lt;kuniyu@amazon.com&gt;
Signed-off-by: Paolo Abeni &lt;pabeni@redhat.com&gt;

</content>
</entry>
<entry>
<title>af_unix: Don't stop recv(MSG_DONTWAIT) if consumed OOB skb is at the head.</title>
<updated>2024-06-27T10:05:01Z</updated>
<author>
<name>Kuniyuki Iwashima</name>
</author>
<published>2024-06-25T01:36:38Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=93c99f21db360957d49853e5666b5c147f593bda'/>
<id>urn:sha1:93c99f21db360957d49853e5666b5c147f593bda</id>
<content type='text'>
Let's say a socket send()s "hello" with MSG_OOB and "world" without flags,

  &gt;&gt;&gt; from socket import *
  &gt;&gt;&gt; c1, c2 = socketpair(AF_UNIX)
  &gt;&gt;&gt; c1.send(b'hello', MSG_OOB)
  5
  &gt;&gt;&gt; c1.send(b'world')
  5

and its peer recv()s "hell" and "o".

  &gt;&gt;&gt; c2.recv(10)
  b'hell'
  &gt;&gt;&gt; c2.recv(1, MSG_OOB)
  b'o'

Now the consumed OOB skb stays at the head of recvq to return a correct
value for ioctl(SIOCATMARK), which is broken now and fixed by a later
patch.

Then, if peer issues recv() with MSG_DONTWAIT, manage_oob() returns NULL,
so recv() ends up with -EAGAIN.

  &gt;&gt;&gt; c2.setblocking(False)  # This causes -EAGAIN even with available data
  &gt;&gt;&gt; c2.recv(5)
  Traceback (most recent call last):
    File "&lt;stdin&gt;", line 1, in &lt;module&gt;
  BlockingIOError: [Errno 11] Resource temporarily unavailable

However, next recv() will return the following available data, "world".

  &gt;&gt;&gt; c2.recv(5)
  b'world'

When the consumed OOB skb is at the head of the queue, we need to fetch
the next skb to fix the weird behaviour.

Note that the issue does not happen without MSG_DONTWAIT because we can
retry after manage_oob().

This patch also adds a test case that covers the issue.

Without fix:

  #  RUN           msg_oob.no_peek.ex_oob_break ...
  # msg_oob.c:134:ex_oob_break:AF_UNIX :Resource temporarily unavailable
  # msg_oob.c:135:ex_oob_break:Expected:ld
  # msg_oob.c:137:ex_oob_break:Expected ret[0] (-1) == expected_len (2)
  # ex_oob_break: Test terminated by assertion
  #          FAIL  msg_oob.no_peek.ex_oob_break
  not ok 8 msg_oob.no_peek.ex_oob_break

With fix:

  #  RUN           msg_oob.no_peek.ex_oob_break ...
  #            OK  msg_oob.no_peek.ex_oob_break
  ok 8 msg_oob.no_peek.ex_oob_break

Fixes: 314001f0bf92 ("af_unix: Add OOB support")
Signed-off-by: Kuniyuki Iwashima &lt;kuniyu@amazon.com&gt;
Signed-off-by: Paolo Abeni &lt;pabeni@redhat.com&gt;

</content>
</entry>
<entry>
<title>af_unix: Stop recv(MSG_PEEK) at consumed OOB skb.</title>
<updated>2024-06-27T10:05:00Z</updated>
<author>
<name>Kuniyuki Iwashima</name>
</author>
<published>2024-06-25T01:36:37Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=b94038d841a91d0e3f59cfe4d073e210910366ee'/>
<id>urn:sha1:b94038d841a91d0e3f59cfe4d073e210910366ee</id>
<content type='text'>
After consuming OOB data, recv() reading the preceding data must break at
the OOB skb regardless of MSG_PEEK.

Currently, MSG_PEEK does not stop recv() for AF_UNIX, and the behaviour is
not compliant with TCP.

  &gt;&gt;&gt; from socket import *
  &gt;&gt;&gt; c1, c2 = socketpair(AF_UNIX)
  &gt;&gt;&gt; c1.send(b'hello', MSG_OOB)
  5
  &gt;&gt;&gt; c1.send(b'world')
  5
  &gt;&gt;&gt; c2.recv(1, MSG_OOB)
  b'o'
  &gt;&gt;&gt; c2.recv(9, MSG_PEEK)  # This should return b'hell'
  b'hellworld'              # even with enough buffer.

Let's fix it by returning NULL for consumed skb and unlinking it only if
MSG_PEEK is not specified.

This patch also adds test cases that add recv(MSG_PEEK) before each recv().

Without fix:

  #  RUN           msg_oob.peek.oob_ahead_break ...
  # msg_oob.c:134:oob_ahead_break:AF_UNIX :hellworld
  # msg_oob.c:135:oob_ahead_break:Expected:hell
  # msg_oob.c:137:oob_ahead_break:Expected ret[0] (9) == expected_len (4)
  # oob_ahead_break: Test terminated by assertion
  #          FAIL  msg_oob.peek.oob_ahead_break
  not ok 13 msg_oob.peek.oob_ahead_break

With fix:

  #  RUN           msg_oob.peek.oob_ahead_break ...
  #            OK  msg_oob.peek.oob_ahead_break
  ok 13 msg_oob.peek.oob_ahead_break

Fixes: 314001f0bf92 ("af_unix: Add OOB support")
Signed-off-by: Kuniyuki Iwashima &lt;kuniyu@amazon.com&gt;
Signed-off-by: Paolo Abeni &lt;pabeni@redhat.com&gt;

</content>
</entry>
<entry>
<title>af_unix: Read with MSG_PEEK loops if the first unread byte is OOB</title>
<updated>2024-06-13T15:03:55Z</updated>
<author>
<name>Rao Shoaib</name>
</author>
<published>2024-06-11T08:46:39Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=a6736a0addd60fccc3a3508461d72314cc609772'/>
<id>urn:sha1:a6736a0addd60fccc3a3508461d72314cc609772</id>
<content type='text'>
Read with MSG_PEEK flag loops if the first byte to read is an OOB byte.
commit 22dd70eb2c3d ("af_unix: Don't peek OOB data without MSG_OOB.")
addresses the loop issue but does not address the issue that no data
beyond OOB byte can be read.

&gt;&gt;&gt; from socket import *
&gt;&gt;&gt; c1, c2 = socketpair(AF_UNIX, SOCK_STREAM)
&gt;&gt;&gt; c1.send(b'a', MSG_OOB)
1
&gt;&gt;&gt; c1.send(b'b')
1
&gt;&gt;&gt; c2.recv(1, MSG_PEEK | MSG_DONTWAIT)
b'b'

&gt;&gt;&gt; from socket import *
&gt;&gt;&gt; c1, c2 = socketpair(AF_UNIX, SOCK_STREAM)
&gt;&gt;&gt; c2.setsockopt(SOL_SOCKET, SO_OOBINLINE, 1)
&gt;&gt;&gt; c1.send(b'a', MSG_OOB)
1
&gt;&gt;&gt; c1.send(b'b')
1
&gt;&gt;&gt; c2.recv(1, MSG_PEEK | MSG_DONTWAIT)
b'a'
&gt;&gt;&gt; c2.recv(1, MSG_PEEK | MSG_DONTWAIT)
b'a'
&gt;&gt;&gt; c2.recv(1, MSG_DONTWAIT)
b'a'
&gt;&gt;&gt; c2.recv(1, MSG_PEEK | MSG_DONTWAIT)
b'b'
&gt;&gt;&gt;

Fixes: 314001f0bf92 ("af_unix: Add OOB support")
Signed-off-by: Rao Shoaib &lt;Rao.Shoaib@oracle.com&gt;
Reviewed-by: Kuniyuki Iwashima &lt;kuniyu@amazon.com&gt;
Link: https://lore.kernel.org/r/20240611084639.2248934-1-Rao.Shoaib@oracle.com
Signed-off-by: Jakub Kicinski &lt;kuba@kernel.org&gt;
</content>
</entry>
<entry>
<title>af_unix: Annotate data-race of sk-&gt;sk_shutdown in sk_diag_fill().</title>
<updated>2024-06-06T10:57:15Z</updated>
<author>
<name>Kuniyuki Iwashima</name>
</author>
<published>2024-06-04T16:52:41Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=efaf24e30ec39ebbea9112227485805a48b0ceb1'/>
<id>urn:sha1:efaf24e30ec39ebbea9112227485805a48b0ceb1</id>
<content type='text'>
While dumping sockets via UNIX_DIAG, we do not hold unix_state_lock().

Let's use READ_ONCE() to read sk-&gt;sk_shutdown.

Fixes: e4e541a84863 ("sock-diag: Report shutdown for inet and unix sockets (v2)")
Signed-off-by: Kuniyuki Iwashima &lt;kuniyu@amazon.com&gt;
Signed-off-by: Paolo Abeni &lt;pabeni@redhat.com&gt;

</content>
</entry>
</feed>
