net/iucv: Add lock nesting annotation in iucv_sock_close()

iucv_sock_close() acquires lock_sock(sk) and then, when the socket is in
IUCV_LISTEN state, calls iucv_sock_cleanup_listen() which acquires
lock_sock(child_sk) for each pending child socket. Moreover
iucv_sock_close(child_sk) is called on the pending child sockets.

Avoid lockdep warning by using lock_sock_nested() in iucv_sock_close().
Split off __iucv_sock_close(), so iucv_sock_cleanup_listen() can call it
without nesting.

This is a missing lockdep annotation - not a real deadlock.

Example warning:
[ 6690.906930] ============================================
[ 6690.906935] WARNING: possible recursive locking detected
[ 6690.906942] 7.3.0-rc1net_KCSAN_KASAN-00240-g641d03105cc0 #23 Not tainted
[ 6690.906948] --------------------------------------------
[ 6690.906953] afiucv_test_loc/5183 is trying to acquire lock:
[ 6690.906959] 000601ad13f20a78 (sk_lock-IUCV){+.+.}-{0:0}, at: iucv_accept_dequeue+0xdc/0x340 [af_iucv]
[ 6690.906984]
               but task is already holding lock:
[ 6690.906989] 000601ad1c115278 (sk_lock-IUCV){+.+.}-{0:0}, at: iucv_sock_close+0x82/0x7d0 [af_iucv]
[ 6690.907006]
               other info that might help us debug this:
[ 6690.907010]  Possible unsafe locking scenario:

[ 6690.907014]        CPU0
[ 6690.907018]        ----
[ 6690.907021]   lock(sk_lock-IUCV);
[ 6690.907028]   lock(sk_lock-IUCV);
[ 6690.907034]
                *** DEADLOCK ***

[ 6690.907038]  May be due to missing lock nesting notation

[ 6690.907043] locks held by afiucv_test_loc/5183: 2, last CPU#0:
[ 6690.907085]  #0: 000601ad137a5550 (&sb->s_type->i_mutex_key#12){+.+.}-{3:3}, at: __sock_release+0x7e/0x230
[ 6690.907109]  #1: 000601ad1c115278 (sk_lock-IUCV){+.+.}-{0:0}, at: iucv_sock_close+0x82/0x7d0 [af_iucv]
[ 6690.907127]
               stack backtrace:
[ 6690.907135] CPU: 0 UID: 0 PID: 5183 Comm: afiucv_test_loc Kdump: loaded Not tainted 7.3.0-rc1net_KCSAN_KASAN-00240-g641d03105cc0 #23 PREEMPT
[ 6690.907140] Hardware name: IBM 8561 T01 703 (z/VM 7.4.0)
[ 6690.907142] Call Trace:
[ 6690.907144]  [<00061ab555fd6208>] dump_stack_lvl+0xe8/0x140
[ 6690.907151]  [<00061ab55623a110>] print_deadlock_bug+0x340/0x350
[ 6690.907156]  [<00061ab55623f768>] __lock_acquire+0x11b8/0x15d0
[ 6690.907159]  [<00061ab55623fc9c>] lock_acquire.part.0+0x11c/0x290
[ 6690.907162]  [<00061ab55623fec4>] lock_acquire+0xb4/0x1e0
[ 6690.907164]  [<00061ab5580d6b96>] lock_sock_nested+0x46/0xf0
[ 6690.907167]  [<00061ab4d66e38dc>] iucv_accept_dequeue+0xdc/0x340 [af_iucv]
[ 6690.907171]  [<00061ab4d66e541c>] iucv_sock_close+0xdc/0x7d0 [af_iucv]
[ 6690.907174]  [<00061ab4d66e5b62>] iucv_sock_release+0x52/0x130 [af_iucv]
[ 6690.907177]  [<00061ab5580c5b24>] __sock_release+0xa4/0x230
[ 6690.907180]  [<00061ab5580c5cdc>] sock_close+0x2c/0x40
[ 6690.907183]  [<00061ab556ac7a00>] __fput+0x2f0/0x880
[ 6690.907187]  [<00061ab556ac8cc0>] fput_close_sync+0xd0/0x1c0
[ 6690.907189]  [<00061ab556abbc70>] __s390x_sys_close+0x90/0xf0
[ 6690.907192]  [<00061ab55894df0e>] __do_syscall+0x1be/0x5a0
[ 6690.907196]  [<00061ab558976a7a>] system_call+0x72/0x90
[ 6690.907200] INFO: lockdep is turned off.

Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260910162919.2100124-1-wintera@linux.ibm.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Alexandra Winter authored and Jakub Kicinski committed 2026-09-14 18:52:33 -07:00
1 parent afabe5e67b
commit aa5ec571b9
1 file changed
+14 -6
+14 -6
View File
@@ -90,7 +90,7 @@ do { \
static struct sock *iucv_accept_dequeue(struct sock *parent,
struct socket *newsock);
static void iucv_sock_kill(struct sock *sk);
static void iucv_sock_close(struct sock *sk);
static void __iucv_sock_close(struct sock *sk);
static void afiucv_hs_callback_txnotify(struct sock *sk, enum iucv_tx_notify);
@@ -302,7 +302,9 @@ static void iucv_sock_cleanup_listen(struct sock *parent)
/* Close non-accepted connections */
while ((sk = iucv_accept_dequeue(parent, NULL))) {
iucv_sock_close(sk);
lock_sock(sk);
__iucv_sock_close(sk);
release_sock(sk);
iucv_sock_kill(sk);
}
@@ -394,15 +396,16 @@ static int iucv_send_ctrl(struct sock *sk, u8 flags)
return err;
}
/* Close an IUCV socket */
static void iucv_sock_close(struct sock *sk)
/**
* __iucv_sock_close() - close socket, caller holds lock_sock(sk)
* @sk: network socket
*/
static void __iucv_sock_close(struct sock *sk)
{
struct iucv_sock *iucv = iucv_sk(sk);
unsigned long timeo;
int err = 0;
lock_sock(sk);
switch (sk->sk_state) {
case IUCV_LISTEN:
iucv_sock_cleanup_listen(sk);
@@ -454,7 +457,12 @@ static void iucv_sock_close(struct sock *sk)
/* mark socket for deletion by iucv_sock_kill() */
sock_set_flag(sk, SOCK_ZAPPED);
}
static void iucv_sock_close(struct sock *sk)
{
lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
__iucv_sock_close(sk);
release_sock(sk);
}