forked from Minki/linux
2a63866c8b
syzbot is reporting hung task at nbd_ioctl() [1], for there are two problems regarding TIPC's connectionless socket's shutdown() operation. ---------- #include <fcntl.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <linux/nbd.h> #include <unistd.h> int main(int argc, char *argv[]) { const int fd = open("/dev/nbd0", 3); alarm(5); ioctl(fd, NBD_SET_SOCK, socket(PF_TIPC, SOCK_DGRAM, 0)); ioctl(fd, NBD_DO_IT, 0); /* To be interrupted by SIGALRM. */ return 0; } ---------- One problem is that wait_for_completion() from flush_workqueue() from nbd_start_device_ioctl() from nbd_ioctl() cannot be completed when nbd_start_device_ioctl() received a signal at wait_event_interruptible(), for tipc_shutdown() from kernel_sock_shutdown(SHUT_RDWR) from nbd_mark_nsock_dead() from sock_shutdown() from nbd_start_device_ioctl() is failing to wake up a WQ thread sleeping at wait_woken() from tipc_wait_for_rcvmsg() from sock_recvmsg() from sock_xmit() from nbd_read_stat() from recv_work() scheduled by nbd_start_device() from nbd_start_device_ioctl(). Fix this problem by always invoking sk->sk_state_change() (like inet_shutdown() does) when tipc_shutdown() is called. The other problem is that tipc_wait_for_rcvmsg() cannot return when tipc_shutdown() is called, for tipc_shutdown() sets sk->sk_shutdown to SEND_SHUTDOWN (despite "how" is SHUT_RDWR) while tipc_wait_for_rcvmsg() needs sk->sk_shutdown set to RCV_SHUTDOWN or SHUTDOWN_MASK. Fix this problem by setting sk->sk_shutdown to SHUTDOWN_MASK (like inet_shutdown() does) when the socket is connectionless. [1] https://syzkaller.appspot.com/bug?id=3fe51d307c1f0a845485cf1798aa059d12bf18b2 Reported-by: syzbot <syzbot+e36f41d207137b5d12f7@syzkaller.appspotmail.com> Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: David S. Miller <davem@davemloft.net> |
||
---|---|---|
.. | ||
addr.c | ||
addr.h | ||
bcast.c | ||
bcast.h | ||
bearer.c | ||
bearer.h | ||
core.c | ||
core.h | ||
crypto.c | ||
crypto.h | ||
diag.c | ||
discover.c | ||
discover.h | ||
eth_media.c | ||
group.c | ||
group.h | ||
ib_media.c | ||
Kconfig | ||
link.c | ||
link.h | ||
Makefile | ||
monitor.c | ||
monitor.h | ||
msg.c | ||
msg.h | ||
name_distr.c | ||
name_distr.h | ||
name_table.c | ||
name_table.h | ||
net.c | ||
net.h | ||
netlink_compat.c | ||
netlink.c | ||
netlink.h | ||
node.c | ||
node.h | ||
socket.c | ||
socket.h | ||
subscr.c | ||
subscr.h | ||
sysctl.c | ||
topsrv.c | ||
topsrv.h | ||
trace.c | ||
trace.h | ||
udp_media.c | ||
udp_media.h |