* [PATCH net,v4] netlink: fix potential sleeping issue in mqueue_flush_file
@ 2024-01-22 1:18 Zhengchao Shao
2024-01-22 8:56 ` Pablo Neira Ayuso
2024-01-23 11:00 ` patchwork-bot+netdevbpf
0 siblings, 2 replies; 5+ messages in thread
From: Zhengchao Shao @ 2024-01-22 1:18 UTC (permalink / raw)
To: netdev, davem, edumazet, kuba, pabeni
Cc: horms, anjali.k.kulkarni, kuniyu, fw, pablo, weiyongjun1,
yuehaibing, shaozhengchao
I analyze the potential sleeping issue of the following processes:
Thread A Thread B
... netlink_create //ref = 1
do_mq_notify ...
sock = netlink_getsockbyfilp ... //ref = 2
info->notify_sock = sock; ...
... netlink_sendmsg
... skb = netlink_alloc_large_skb //skb->head is vmalloced
... netlink_unicast
... sk = netlink_getsockbyportid //ref = 3
... netlink_sendskb
... __netlink_sendskb
... skb_queue_tail //put skb to sk_receive_queue
... sock_put //ref = 2
... ...
... netlink_release
... deferred_put_nlk_sk //ref = 1
mqueue_flush_file
spin_lock
remove_notification
netlink_sendskb
sock_put //ref = 0
sk_free
...
__sk_destruct
netlink_sock_destruct
skb_queue_purge //get skb from sk_receive_queue
...
__skb_queue_purge_reason
kfree_skb_reason
__kfree_skb
...
skb_release_all
skb_release_head_state
netlink_skb_destructor
vfree(skb->head) //sleeping while holding spinlock
In netlink_sendmsg, if the memory pointed to by skb->head is allocated by
vmalloc, and is put to sk_receive_queue queue, also the skb is not freed.
When the mqueue executes flush, the sleeping bug will occur. Use
vfree_atomic instead of vfree in netlink_skb_destructor to solve the issue.
Fixes: c05cdb1b864f ("netlink: allow large data transfers from user-space")
Signed-off-by: Zhengchao Shao <shaozhengchao@huawei.com>
---
v4: Use vfree_atomic to release skb->head
v3: Put sock after releasing the spinlock.
v2: CCed some networking maintainer & netdev list
---
net/netlink/af_netlink.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 4ed8ffd58ff3..9c962347cf85 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -374,7 +374,7 @@ static void netlink_skb_destructor(struct sk_buff *skb)
if (is_vmalloc_addr(skb->head)) {
if (!skb->cloned ||
!atomic_dec_return(&(skb_shinfo(skb)->dataref)))
- vfree(skb->head);
+ vfree_atomic(skb->head);
skb->head = NULL;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH net,v4] netlink: fix potential sleeping issue in mqueue_flush_file
2024-01-22 1:18 [PATCH net,v4] netlink: fix potential sleeping issue in mqueue_flush_file Zhengchao Shao
@ 2024-01-22 8:56 ` Pablo Neira Ayuso
2024-01-22 11:10 ` shaozhengchao
2024-01-23 11:00 ` patchwork-bot+netdevbpf
1 sibling, 1 reply; 5+ messages in thread
From: Pablo Neira Ayuso @ 2024-01-22 8:56 UTC (permalink / raw)
To: Zhengchao Shao
Cc: netdev, davem, edumazet, kuba, pabeni, horms, anjali.k.kulkarni,
kuniyu, fw, weiyongjun1, yuehaibing
On Mon, Jan 22, 2024 at 09:18:07AM +0800, Zhengchao Shao wrote:
> I analyze the potential sleeping issue of the following processes:
> Thread A Thread B
> ... netlink_create //ref = 1
> do_mq_notify ...
> sock = netlink_getsockbyfilp ... //ref = 2
> info->notify_sock = sock; ...
> ... netlink_sendmsg
> ... skb = netlink_alloc_large_skb //skb->head is vmalloced
> ... netlink_unicast
> ... sk = netlink_getsockbyportid //ref = 3
> ... netlink_sendskb
> ... __netlink_sendskb
> ... skb_queue_tail //put skb to sk_receive_queue
> ... sock_put //ref = 2
> ... ...
> ... netlink_release
> ... deferred_put_nlk_sk //ref = 1
> mqueue_flush_file
> spin_lock
> remove_notification
> netlink_sendskb
> sock_put //ref = 0
> sk_free
> ...
> __sk_destruct
> netlink_sock_destruct
> skb_queue_purge //get skb from sk_receive_queue
> ...
> __skb_queue_purge_reason
> kfree_skb_reason
> __kfree_skb
> ...
> skb_release_all
> skb_release_head_state
> netlink_skb_destructor
> vfree(skb->head) //sleeping while holding spinlock
>
> In netlink_sendmsg, if the memory pointed to by skb->head is allocated by
> vmalloc, and is put to sk_receive_queue queue, also the skb is not freed.
> When the mqueue executes flush, the sleeping bug will occur. Use
> vfree_atomic instead of vfree in netlink_skb_destructor to solve the issue.
mqueue notification is of NOTIFY_COOKIE_LEN size:
static int do_mq_notify(mqd_t mqdes, const struct sigevent *notification)
{
[...]
if (notification->sigev_notify == SIGEV_THREAD) {
long timeo;
/* create the notify skb */
nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL);
if (!nc)
return -ENOMEM;
Do you have a reproducer?
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net,v4] netlink: fix potential sleeping issue in mqueue_flush_file
2024-01-22 8:56 ` Pablo Neira Ayuso
@ 2024-01-22 11:10 ` shaozhengchao
2024-01-23 10:48 ` Paolo Abeni
0 siblings, 1 reply; 5+ messages in thread
From: shaozhengchao @ 2024-01-22 11:10 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: netdev, davem, edumazet, kuba, pabeni, horms, anjali.k.kulkarni,
kuniyu, fw, weiyongjun1, yuehaibing
On 2024/1/22 16:56, Pablo Neira Ayuso wrote:
> On Mon, Jan 22, 2024 at 09:18:07AM +0800, Zhengchao Shao wrote:
>> I analyze the potential sleeping issue of the following processes:
>> Thread A Thread B
>> ... netlink_create //ref = 1
>> do_mq_notify ...
>> sock = netlink_getsockbyfilp ... //ref = 2
>> info->notify_sock = sock; ...
>> ... netlink_sendmsg
>> ... skb = netlink_alloc_large_skb //skb->head is vmalloced
>> ... netlink_unicast
>> ... sk = netlink_getsockbyportid //ref = 3
>> ... netlink_sendskb
>> ... __netlink_sendskb
>> ... skb_queue_tail //put skb to sk_receive_queue
>> ... sock_put //ref = 2
>> ... ...
>> ... netlink_release
>> ... deferred_put_nlk_sk //ref = 1
>> mqueue_flush_file
>> spin_lock
>> remove_notification
>> netlink_sendskb
>> sock_put //ref = 0
>> sk_free
>> ...
>> __sk_destruct
>> netlink_sock_destruct
>> skb_queue_purge //get skb from sk_receive_queue
>> ...
>> __skb_queue_purge_reason
>> kfree_skb_reason
>> __kfree_skb
>> ...
>> skb_release_all
>> skb_release_head_state
>> netlink_skb_destructor
>> vfree(skb->head) //sleeping while holding spinlock
>>
>> In netlink_sendmsg, if the memory pointed to by skb->head is allocated by
>> vmalloc, and is put to sk_receive_queue queue, also the skb is not freed.
>> When the mqueue executes flush, the sleeping bug will occur. Use
>> vfree_atomic instead of vfree in netlink_skb_destructor to solve the issue.
>
> mqueue notification is of NOTIFY_COOKIE_LEN size:
>
> static int do_mq_notify(mqd_t mqdes, const struct sigevent *notification)
> {
> [...]
> if (notification->sigev_notify == SIGEV_THREAD) {
> long timeo;
>
> /* create the notify skb */
> nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL);
> if (!nc)
> return -ENOMEM;
>
> Do you have a reproducer?
Hi Pablo:
I donot have reproducer. I found the issue when running syz on
the 5.10 stable branch, but it only happened once. Then I analyzed the
mainline code and found the same issue.
The sock can be obtained from the value of sigev_signo
transferred by the user in do_mq_notify. And the sock may be of type
netlink, and it is possible to allocate the head area using vmalloc.
Not only release the skb allocated in do_mq_notify, but also release
the skb allocated in netlink_sendmsg when put sock mqueue_flush_file.
What I missed?
Thank you.
Zhengchao Shao
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net,v4] netlink: fix potential sleeping issue in mqueue_flush_file
2024-01-22 11:10 ` shaozhengchao
@ 2024-01-23 10:48 ` Paolo Abeni
0 siblings, 0 replies; 5+ messages in thread
From: Paolo Abeni @ 2024-01-23 10:48 UTC (permalink / raw)
To: shaozhengchao, Pablo Neira Ayuso
Cc: netdev, davem, edumazet, kuba, horms, anjali.k.kulkarni, kuniyu,
fw, weiyongjun1, yuehaibing
Hi,
On Mon, 2024-01-22 at 19:10 +0800, shaozhengchao wrote:
> On 2024/1/22 16:56, Pablo Neira Ayuso wrote:
> > On Mon, Jan 22, 2024 at 09:18:07AM +0800, Zhengchao Shao wrote:
> > > I analyze the potential sleeping issue of the following processes:
> > > Thread A Thread B
> > > ... netlink_create //ref = 1
> > > do_mq_notify ...
> > > sock = netlink_getsockbyfilp ... //ref = 2
> > > info->notify_sock = sock; ...
> > > ... netlink_sendmsg
> > > ... skb = netlink_alloc_large_skb //skb->head is vmalloced
> > > ... netlink_unicast
> > > ... sk = netlink_getsockbyportid //ref = 3
> > > ... netlink_sendskb
> > > ... __netlink_sendskb
> > > ... skb_queue_tail //put skb to sk_receive_queue
> > > ... sock_put //ref = 2
> > > ... ...
> > > ... netlink_release
> > > ... deferred_put_nlk_sk //ref = 1
> > > mqueue_flush_file
> > > spin_lock
> > > remove_notification
> > > netlink_sendskb
> > > sock_put //ref = 0
> > > sk_free
> > > ...
> > > __sk_destruct
> > > netlink_sock_destruct
> > > skb_queue_purge //get skb from sk_receive_queue
> > > ...
> > > __skb_queue_purge_reason
> > > kfree_skb_reason
> > > __kfree_skb
> > > ...
> > > skb_release_all
> > > skb_release_head_state
> > > netlink_skb_destructor
> > > vfree(skb->head) //sleeping while holding spinlock
> > >
> > > In netlink_sendmsg, if the memory pointed to by skb->head is allocated by
> > > vmalloc, and is put to sk_receive_queue queue, also the skb is not freed.
> > > When the mqueue executes flush, the sleeping bug will occur. Use
> > > vfree_atomic instead of vfree in netlink_skb_destructor to solve the issue.
> >
> > mqueue notification is of NOTIFY_COOKIE_LEN size:
> >
> > static int do_mq_notify(mqd_t mqdes, const struct sigevent *notification)
> > {
> > [...]
> > if (notification->sigev_notify == SIGEV_THREAD) {
> > long timeo;
> >
> > /* create the notify skb */
> > nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL);
> > if (!nc)
> > return -ENOMEM;
> >
> > Do you have a reproducer?
> Hi Pablo:
> I donot have reproducer. I found the issue when running syz on
> the 5.10 stable branch, but it only happened once. Then I analyzed the
> mainline code and found the same issue.
> The sock can be obtained from the value of sigev_signo
> transferred by the user in do_mq_notify. And the sock may be of type
> netlink, and it is possible to allocate the head area using vmalloc.
> Not only release the skb allocated in do_mq_notify, but also release
> the skb allocated in netlink_sendmsg when put sock mqueue_flush_file.
> What I missed?
I believe your explanation is solid and the patch looks safe, I'm
applying it.
Thank you!
Paolo
p.s. for once I'm answering in place of Pablo, which is sort of funny
given that our names are confused a significant number of times on the
ML...)
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net,v4] netlink: fix potential sleeping issue in mqueue_flush_file
2024-01-22 1:18 [PATCH net,v4] netlink: fix potential sleeping issue in mqueue_flush_file Zhengchao Shao
2024-01-22 8:56 ` Pablo Neira Ayuso
@ 2024-01-23 11:00 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 5+ messages in thread
From: patchwork-bot+netdevbpf @ 2024-01-23 11:00 UTC (permalink / raw)
To: shaozhengchao
Cc: netdev, davem, edumazet, kuba, pabeni, horms, anjali.k.kulkarni,
kuniyu, fw, pablo, weiyongjun1, yuehaibing
Hello:
This patch was applied to netdev/net.git (main)
by Paolo Abeni <pabeni@redhat.com>:
On Mon, 22 Jan 2024 09:18:07 +0800 you wrote:
> I analyze the potential sleeping issue of the following processes:
> Thread A Thread B
> ... netlink_create //ref = 1
> do_mq_notify ...
> sock = netlink_getsockbyfilp ... //ref = 2
> info->notify_sock = sock; ...
> ... netlink_sendmsg
> ... skb = netlink_alloc_large_skb //skb->head is vmalloced
> ... netlink_unicast
> ... sk = netlink_getsockbyportid //ref = 3
> ... netlink_sendskb
> ... __netlink_sendskb
> ... skb_queue_tail //put skb to sk_receive_queue
> ... sock_put //ref = 2
> ... ...
> ... netlink_release
> ... deferred_put_nlk_sk //ref = 1
> mqueue_flush_file
> spin_lock
> remove_notification
> netlink_sendskb
> sock_put //ref = 0
> sk_free
> ...
> __sk_destruct
> netlink_sock_destruct
> skb_queue_purge //get skb from sk_receive_queue
> ...
> __skb_queue_purge_reason
> kfree_skb_reason
> __kfree_skb
> ...
> skb_release_all
> skb_release_head_state
> netlink_skb_destructor
> vfree(skb->head) //sleeping while holding spinlock
>
> [...]
Here is the summary with links:
- [net,v4] netlink: fix potential sleeping issue in mqueue_flush_file
https://git.kernel.org/netdev/net/c/234ec0b6034b
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-01-23 11:00 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-01-22 1:18 [PATCH net,v4] netlink: fix potential sleeping issue in mqueue_flush_file Zhengchao Shao
2024-01-22 8:56 ` Pablo Neira Ayuso
2024-01-22 11:10 ` shaozhengchao
2024-01-23 10:48 ` Paolo Abeni
2024-01-23 11:00 ` patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).