Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

vsock: split dwork to avoid reinitializations

syzbot reported that we reinitialize an active delayed
work in vsock_stream_connect():

ODEBUG: init active (active state 0) object type: timer_list hint:
delayed_work_timer_fn+0x0/0x90 kernel/workqueue.c:1414
WARNING: CPU: 1 PID: 11518 at lib/debugobjects.c:329
debug_print_object+0x16a/0x210 lib/debugobjects.c:326

The pattern is apparently wrong, we should only initialize
the dealyed work once and could repeatly schedule it. So we
have to move out the initializations to allocation side.
And to avoid confusion, we can split the shared dwork
into two, instead of re-using the same one.

Fixes: d021c344051a ("VSOCK: Introduce VM Sockets")
Reported-by: <syzbot+8a9b1bd330476a4f3db6@syzkaller.appspotmail.com>
Cc: Andy king <acking@vmware.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Cc: Jorgen Hansen <jhansen@vmware.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Cong Wang and committed by
David S. Miller
455f05ec a94cead7

+11 -11
+2 -2
include/net/af_vsock.h
··· 64 64 struct list_head pending_links; 65 65 struct list_head accept_queue; 66 66 bool rejected; 67 - struct delayed_work dwork; 67 + struct delayed_work connect_work; 68 + struct delayed_work pending_work; 68 69 struct delayed_work close_work; 69 70 bool close_work_scheduled; 70 71 u32 peer_shutdown; ··· 78 77 79 78 s64 vsock_stream_has_data(struct vsock_sock *vsk); 80 79 s64 vsock_stream_has_space(struct vsock_sock *vsk); 81 - void vsock_pending_work(struct work_struct *work); 82 80 struct sock *__vsock_create(struct net *net, 83 81 struct socket *sock, 84 82 struct sock *parent,
+8 -7
net/vmw_vsock/af_vsock.c
··· 451 451 return transport->shutdown(vsock_sk(sk), mode); 452 452 } 453 453 454 - void vsock_pending_work(struct work_struct *work) 454 + static void vsock_pending_work(struct work_struct *work) 455 455 { 456 456 struct sock *sk; 457 457 struct sock *listener; 458 458 struct vsock_sock *vsk; 459 459 bool cleanup; 460 460 461 - vsk = container_of(work, struct vsock_sock, dwork.work); 461 + vsk = container_of(work, struct vsock_sock, pending_work.work); 462 462 sk = sk_vsock(vsk); 463 463 listener = vsk->listener; 464 464 cleanup = true; ··· 498 498 sock_put(sk); 499 499 sock_put(listener); 500 500 } 501 - EXPORT_SYMBOL_GPL(vsock_pending_work); 502 501 503 502 /**** SOCKET OPERATIONS ****/ 504 503 ··· 596 597 return retval; 597 598 } 598 599 600 + static void vsock_connect_timeout(struct work_struct *work); 601 + 599 602 struct sock *__vsock_create(struct net *net, 600 603 struct socket *sock, 601 604 struct sock *parent, ··· 639 638 vsk->sent_request = false; 640 639 vsk->ignore_connecting_rst = false; 641 640 vsk->peer_shutdown = 0; 641 + INIT_DELAYED_WORK(&vsk->connect_work, vsock_connect_timeout); 642 + INIT_DELAYED_WORK(&vsk->pending_work, vsock_pending_work); 642 643 643 644 psk = parent ? vsock_sk(parent) : NULL; 644 645 if (parent) { ··· 1120 1117 struct vsock_sock *vsk; 1121 1118 int cancel = 0; 1122 1119 1123 - vsk = container_of(work, struct vsock_sock, dwork.work); 1120 + vsk = container_of(work, struct vsock_sock, connect_work.work); 1124 1121 sk = sk_vsock(vsk); 1125 1122 1126 1123 lock_sock(sk); ··· 1224 1221 * timeout fires. 1225 1222 */ 1226 1223 sock_hold(sk); 1227 - INIT_DELAYED_WORK(&vsk->dwork, 1228 - vsock_connect_timeout); 1229 - schedule_delayed_work(&vsk->dwork, timeout); 1224 + schedule_delayed_work(&vsk->connect_work, timeout); 1230 1225 1231 1226 /* Skip ahead to preserve error code set above. */ 1232 1227 goto out_wait;
+1 -2
net/vmw_vsock/vmci_transport.c
··· 1094 1094 vpending->listener = sk; 1095 1095 sock_hold(sk); 1096 1096 sock_hold(pending); 1097 - INIT_DELAYED_WORK(&vpending->dwork, vsock_pending_work); 1098 - schedule_delayed_work(&vpending->dwork, HZ); 1097 + schedule_delayed_work(&vpending->pending_work, HZ); 1099 1098 1100 1099 out: 1101 1100 return err;