diff mbox series

[net] af_unix: Fix a data-race in unix_dgram_peer_wake_me().

Message ID 20220605232325.11804-1-kuniyu@amazon.com (mailing list archive)
State Accepted
Commit 662a80946ce13633ae90a55379f1346c10f0c432
Delegated to: Netdev Maintainers
Headers show
Series [net] af_unix: Fix a data-race in unix_dgram_peer_wake_me(). | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for net
netdev/fixes_present success Fixes tag present in non-next series
netdev/subject_prefix success Link
netdev/cover_letter success Single patches do not need cover letters
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 9 this patch: 9
netdev/cc_maintainers fail 1 blamed authors not CCed: jbaron@akamai.com; 2 maintainers not CCed: viro@zeniv.linux.org.uk jbaron@akamai.com
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 9 this patch: 9
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 8 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Kuniyuki Iwashima June 5, 2022, 11:23 p.m. UTC
unix_dgram_poll() calls unix_dgram_peer_wake_me() without `other`'s
lock held and check if its receive queue is full.  Here we need to
use unix_recvq_full_lockless() instead of unix_recvq_full(), otherwise
KCSAN will report a data-race.

Fixes: 7d267278a9ec ("unix: avoid use-after-free in ep_remove_wait_queue")
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
---
As Eric noted in commit 04f08eb44b501, I think rest of unix_recvq_full()
can be turned into the lockless version.  After this merge window, I can
send a follow-up patch if there is no objection.
---
 net/unix/af_unix.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Paolo Abeni June 7, 2022, 10:35 a.m. UTC | #1
On Sun, 2022-06-05 at 16:23 -0700, Kuniyuki Iwashima wrote:
> unix_dgram_poll() calls unix_dgram_peer_wake_me() without `other`'s
> lock held and check if its receive queue is full.  Here we need to
> use unix_recvq_full_lockless() instead of unix_recvq_full(), otherwise
> KCSAN will report a data-race.
> 
> Fixes: 7d267278a9ec ("unix: avoid use-after-free in ep_remove_wait_queue")
> Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
> ---
> As Eric noted in commit 04f08eb44b501, I think rest of unix_recvq_full()
> can be turned into the lockless version.  After this merge window, I can
> send a follow-up patch if there is no objection.

It looks like replacing the remaining instances of unix_recvq_full()
with unix_recvq_full_lockless() should be safe, but I'm wondering if
doing that while retaining the current state lock scope it's worthy?!? 

It may trick later readers of the relevant code to think that such code
may be reached without a lock. Or are you suggesting to additionally
shrink the state lock scope? that latter part looks much more tricky,
IMHO.

Cheers,

Paolo
patchwork-bot+netdevbpf@kernel.org June 7, 2022, 10:40 a.m. UTC | #2
Hello:

This patch was applied to netdev/net.git (master)
by Paolo Abeni <pabeni@redhat.com>:

On Sun, 5 Jun 2022 16:23:25 -0700 you wrote:
> unix_dgram_poll() calls unix_dgram_peer_wake_me() without `other`'s
> lock held and check if its receive queue is full.  Here we need to
> use unix_recvq_full_lockless() instead of unix_recvq_full(), otherwise
> KCSAN will report a data-race.
> 
> Fixes: 7d267278a9ec ("unix: avoid use-after-free in ep_remove_wait_queue")
> Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
> 
> [...]

Here is the summary with links:
  - [net] af_unix: Fix a data-race in unix_dgram_peer_wake_me().
    https://git.kernel.org/netdev/net/c/662a80946ce1

You are awesome, thank you!
Kuniyuki Iwashima June 7, 2022, 2:14 p.m. UTC | #3
From:   Paolo Abeni <pabeni@redhat.com>
Date:   Tue, 07 Jun 2022 12:35:13 +0200
> On Sun, 2022-06-05 at 16:23 -0700, Kuniyuki Iwashima wrote:
>> unix_dgram_poll() calls unix_dgram_peer_wake_me() without `other`'s
>> lock held and check if its receive queue is full.  Here we need to
>> use unix_recvq_full_lockless() instead of unix_recvq_full(), otherwise
>> KCSAN will report a data-race.
>> 
>> Fixes: 7d267278a9ec ("unix: avoid use-after-free in ep_remove_wait_queue")
>> Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
>> ---
>> As Eric noted in commit 04f08eb44b501, I think rest of unix_recvq_full()
>> can be turned into the lockless version.  After this merge window, I can
>> send a follow-up patch if there is no objection.
> 
> It looks like replacing the remaining instances of unix_recvq_full()
> with unix_recvq_full_lockless() should be safe, but I'm wondering if
> doing that while retaining the current state lock scope it's worthy?!? 
> 
> It may trick later readers of the relevant code to think that such code
> may be reached without a lock. Or are you suggesting to additionally
> shrink the state lock scope? that latter part looks much more tricky,
> IMHO.

I thought removing unix_recvq_full() will prevent the same mistakes, but
I agree that it is confusing for later readers.

Thank you!
diff mbox series

Patch

diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 654dcef7cfb3..2206e6f8902d 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -490,7 +490,7 @@  static int unix_dgram_peer_wake_me(struct sock *sk, struct sock *other)
 	 * -ECONNREFUSED. Otherwise, if we haven't queued any skbs
 	 * to other and its full, we will hang waiting for POLLOUT.
 	 */
-	if (unix_recvq_full(other) && !sock_flag(other, SOCK_DEAD))
+	if (unix_recvq_full_lockless(other) && !sock_flag(other, SOCK_DEAD))
 		return 1;
 
 	if (connected)