drivers/hv/connection.c | 4 ++++ 1 file changed, 4 insertions(+)
relid2channel() assumes vmbus channel array to be allocated when called.
However, in cases such as kdump/kexec, not all relids will be reset by the host.
When the second kernel boots and if the guest receives a vmbus interrupt during
vmbus driver initialization before vmbus_connect() is called, before it finishes,
or if it fails, the vmbus interrupt service routine is called which in turn calls
relid2channel() and can cause a null pointer dereference.
So Make relid2channel() check if vmbus channels is allocated first, and if not
print a warning and return NULL to the caller.
Fixes: 8b6a877c060e ("Drivers: hv: vmbus: Replace the per-CPU channel lists with a global array of channels")
Signed-off-by: Mohammed Gamal <mgamal@redhat.com>
---
Changes from v1:
* Corrected and detailed description in commit message
* Added detailed warning message
---
drivers/hv/connection.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index 9dc27e5d367a..82876e84f719 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -409,6 +409,10 @@ void vmbus_disconnect(void)
*/
struct vmbus_channel *relid2channel(u32 relid)
{
+ if (vmbus_connection.channels == NULL) {
+ WARN(1, "Requested relid=%u, but channel mapping not allocated!\n", relid);
+ return NULL;
+ }
if (WARN_ON(relid >= MAX_CHANNEL_RELIDS))
return NULL;
return READ_ONCE(vmbus_connection.channels[relid]);
--
2.38.1
> From: Mohammed Gamal <mgamal@redhat.com> > Sent: Tuesday, February 14, 2023 3:28 AM > ... > So Make relid2channel() check if vmbus channels is allocated first, and if not > print a warning and return NULL to the caller. Can we change the above to: Print a warning and error out in relid2channel() for a channel id that's invalid in the second kernel. > --- a/drivers/hv/connection.c > +++ b/drivers/hv/connection.c > @@ -409,6 +409,10 @@ void vmbus_disconnect(void) > */ > struct vmbus_channel *relid2channel(u32 relid) > { > + if (vmbus_connection.channels == NULL) { > + WARN(1, "Requested relid=%u, but channel mapping not > allocated!\n", relid); WARN() may be too noisy. I suggest we use pr_warn() instead. Can we make the line a little shorter: pr_warn("relid2channel: invalid channel id %u\n", relid);
Dexuan Cui <decui@microsoft.com> writes: >> From: Mohammed Gamal <mgamal@redhat.com> >> Sent: Tuesday, February 14, 2023 3:28 AM >> ... >> So Make relid2channel() check if vmbus channels is allocated first, and if not >> print a warning and return NULL to the caller. > Can we change the above to: > > Print a warning and error out in relid2channel() for a channel id that's invalid > in the second kernel. > >> --- a/drivers/hv/connection.c >> +++ b/drivers/hv/connection.c >> @@ -409,6 +409,10 @@ void vmbus_disconnect(void) >> */ >> struct vmbus_channel *relid2channel(u32 relid) >> { >> + if (vmbus_connection.channels == NULL) { >> + WARN(1, "Requested relid=%u, but channel mapping not >> allocated!\n", relid); > > WARN() may be too noisy. I suggest we use pr_warn() instead. > > Can we make the line a little shorter: > pr_warn("relid2channel: invalid channel id %u\n", relid); > I'd even suggest to make it pr_warn_once() to be safe. In theory, vmbus_chan_sched() call site looks like it can create a lot of noise. -- Vitaly
> From: Vitaly Kuznetsov <vkuznets@redhat.com> > Sent: Friday, February 17, 2023 1:52 AM > > I'd even suggest to make it pr_warn_once() to be > safe. In theory, vmbus_chan_sched() call site looks like it can create a > lot of noise. Good point.
On Fri, Feb 17, 2023 at 8:25 AM Dexuan Cui <decui@microsoft.com> wrote: > > > From: Mohammed Gamal <mgamal@redhat.com> > > Sent: Tuesday, February 14, 2023 3:28 AM > > ... > > So Make relid2channel() check if vmbus channels is allocated first, and if not > > print a warning and return NULL to the caller. > Can we change the above to: > > Print a warning and error out in relid2channel() for a channel id that's invalid > in the second kernel. Will do! > > > --- a/drivers/hv/connection.c > > +++ b/drivers/hv/connection.c > > @@ -409,6 +409,10 @@ void vmbus_disconnect(void) > > */ > > struct vmbus_channel *relid2channel(u32 relid) > > { > > + if (vmbus_connection.channels == NULL) { > > + WARN(1, "Requested relid=%u, but channel mapping not > > allocated!\n", relid); > > WARN() may be too noisy. I suggest we use pr_warn() instead. > Makes sense. Will use pr_warn() instead. > Can we make the line a little shorter: > pr_warn("relid2channel: invalid channel id %u\n", relid); > I think this message could be a bit misleading. The problem here is not that the relid is invalid, but that the relid-to-channel mapping hasn't been allocated by the second kernel yet. An invalid relid could simply be the case where relid >= MAX_CHANNEL_RELIDS. May be something like: pr_warn("relid2channel: No channels mapped for relid %d\n, relid"); would be clearer?
> From: Mohammed Gamal <mgamal@redhat.com> > Sent: Friday, February 17, 2023 1:43 AM > > > @@ -409,6 +409,10 @@ void vmbus_disconnect(void) > > > */ > > > struct vmbus_channel *relid2channel(u32 relid) > > > { > > > + if (vmbus_connection.channels == NULL) { > > > + WARN(1, "Requested relid=%u, but channel mapping not > > > allocated!\n", relid); > > > > WARN() may be too noisy. I suggest we use pr_warn() instead. > > > Makes sense. Will use pr_warn() instead. As Vitaly suggested, pr_warn_once() looks better. > > Can we make the line a little shorter: > > pr_warn("relid2channel: invalid channel id %u\n", relid); > > > I think this message could be a bit misleading. The problem here is > not that the relid > is invalid, but that the relid-to-channel mapping hasn't been > allocated by the second > kernel yet. An invalid relid could simply be the case where relid >= > MAX_CHANNEL_RELIDS. > > May be something like: > pr_warn("relid2channel: No channels mapped for relid %d\n, relid"); > would be clearer? IMO the 'relid' is invalid in the second kernel because the second kernel has not called vmbus_request_offers() yet, but your new message is ok to me. I just wanted to avoid a too long line of >80 characters :-)
© 2016 - 2025 Red Hat, Inc.