| From e9a172c4c1cde8c1a92bea4d4e256028c155e62c Mon Sep 17 00:00:00 2001 |
| From: Mike Christie <mchristi@redhat.com> |
| Date: Thu, 17 Oct 2019 16:27:34 -0500 |
| Subject: [PATCH] nbd: verify socket is supported during setup |
| |
| commit cf1b2326b734896734c6e167e41766f9cee7686a upstream. |
| |
| nbd requires socket families to support the shutdown method so the nbd |
| recv workqueue can be woken up from its sock_recvmsg call. If the socket |
| does not support the callout we will leave recv works running or get hangs |
| later when the device or module is removed. |
| |
| This adds a check during socket connection/reconnection to make sure the |
| socket being passed in supports the needed callout. |
| |
| Reported-by: syzbot+24c12fa8d218ed26011a@syzkaller.appspotmail.com |
| Fixes: e9e006f5fcf2 ("nbd: fix max number of supported devs") |
| Tested-by: Richard W.M. Jones <rjones@redhat.com> |
| Signed-off-by: Mike Christie <mchristi@redhat.com> |
| Signed-off-by: Jens Axboe <axboe@kernel.dk> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c |
| index fcd853d3e940..a49ecfaec571 100644 |
| --- a/drivers/block/nbd.c |
| +++ b/drivers/block/nbd.c |
| @@ -933,6 +933,25 @@ static blk_status_t nbd_queue_rq(struct blk_mq_hw_ctx *hctx, |
| return ret; |
| } |
| |
| +static struct socket *nbd_get_socket(struct nbd_device *nbd, unsigned long fd, |
| + int *err) |
| +{ |
| + struct socket *sock; |
| + |
| + *err = 0; |
| + sock = sockfd_lookup(fd, err); |
| + if (!sock) |
| + return NULL; |
| + |
| + if (sock->ops->shutdown == sock_no_shutdown) { |
| + dev_err(disk_to_dev(nbd->disk), "Unsupported socket: shutdown callout must be supported.\n"); |
| + *err = -EINVAL; |
| + return NULL; |
| + } |
| + |
| + return sock; |
| +} |
| + |
| static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, |
| bool netlink) |
| { |
| @@ -942,7 +961,7 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, |
| struct nbd_sock *nsock; |
| int err; |
| |
| - sock = sockfd_lookup(arg, &err); |
| + sock = nbd_get_socket(nbd, arg, &err); |
| if (!sock) |
| return err; |
| |
| @@ -994,7 +1013,7 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg) |
| int i; |
| int err; |
| |
| - sock = sockfd_lookup(arg, &err); |
| + sock = nbd_get_socket(nbd, arg, &err); |
| if (!sock) |
| return err; |
| |
| -- |
| 2.7.4 |
| |