2023-02-14 11:28:50

by Mohammed Gamal

[permalink] [raw]
Subject: [PATCH v2] Drivers: vmbus: Check for channel allocation before looking up relids

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 <[email protected]>
---
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



2023-02-17 06:25:36

by Dexuan Cui

[permalink] [raw]
Subject: RE: [PATCH v2] Drivers: vmbus: Check for channel allocation before looking up relids

> From: Mohammed Gamal <[email protected]>
> 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);

2023-02-17 09:43:57

by Mohammed Gamal

[permalink] [raw]
Subject: Re: [PATCH v2] Drivers: vmbus: Check for channel allocation before looking up relids

On Fri, Feb 17, 2023 at 8:25 AM Dexuan Cui <[email protected]> wrote:
>
> > From: Mohammed Gamal <[email protected]>
> > 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?


2023-02-17 09:52:30

by Vitaly Kuznetsov

[permalink] [raw]
Subject: RE: [PATCH v2] Drivers: vmbus: Check for channel allocation before looking up relids

Dexuan Cui <[email protected]> writes:

>> From: Mohammed Gamal <[email protected]>
>> 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


2023-02-17 19:00:00

by Dexuan Cui

[permalink] [raw]
Subject: RE: [PATCH v2] Drivers: vmbus: Check for channel allocation before looking up relids

> From: Mohammed Gamal <[email protected]>
> 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 :-)

2023-02-17 19:00:23

by Dexuan Cui

[permalink] [raw]
Subject: RE: [PATCH v2] Drivers: vmbus: Check for channel allocation before looking up relids

> From: Vitaly Kuznetsov <[email protected]>
> 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.