From: Sonia Sharma <sosha@linux.microsoft.com>
To: linux-kernel@vger.kernel.org
Cc: sosha@microsoft.com
Subject: [PATCH] Drivers: hv: Allow single instance of hv_util devices
Date: Fri, 20 Dec 2024 15:51:24 -0800 [thread overview]
Message-ID: <1734738684-20713-1-git-send-email-sosha@linux.microsoft.com> (raw)
From: Sonia Sharma <sonia.sharma@linux.microsoft.com>
Harden hv_util type device drivers to allow single
instance of the device be configured at given time.
New function vmbus_is_valid_hvutil_offer() is added.
It checks if the new offer is for hv_util device type,
then read the refcount for that device and accept or
reject the offer accordingly.
Signed-off-by: Sonia Sharma <sonia.sharma@linux.microsoft.com>
---
drivers/hv/channel_mgmt.c | 64 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 63 insertions(+), 1 deletion(-)
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 3c6011a48dab..1a135cfad81f 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -20,6 +20,7 @@
#include <linux/delay.h>
#include <linux/cpu.h>
#include <linux/hyperv.h>
+#include <linux/refcount.h>
#include <asm/mshyperv.h>
#include <linux/sched/isolation.h>
@@ -156,6 +157,8 @@ const struct vmbus_device vmbus_devs[] = {
};
EXPORT_SYMBOL_GPL(vmbus_devs);
+static refcount_t singleton_vmbus_devs[HV_UNKNOWN + 1];
+
static const struct {
guid_t guid;
} vmbus_unsupported_devs[] = {
@@ -198,6 +201,25 @@ static bool is_unsupported_vmbus_devs(const guid_t *guid)
return false;
}
+static bool is_dev_hv_util(u16 dev_type)
+{
+ switch (dev_type) {
+ case HV_SHUTDOWN:
+ fallthrough;
+ case HV_TS:
+ fallthrough;
+ case HV_HB:
+ fallthrough;
+ case HV_KVP:
+ fallthrough;
+ case HV_BACKUP:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
static u16 hv_get_dev_type(const struct vmbus_channel *channel)
{
const guid_t *guid = &channel->offermsg.offer.if_type;
@@ -1004,6 +1026,26 @@ find_primary_channel_by_offer(const struct vmbus_channel_offer_channel *offer)
return channel;
}
+static u16 vmbus_is_valid_hvutil_offer(const struct vmbus_channel_offer_channel *offer)
+{
+ const guid_t *guid = &offer->offer.if_type;
+ u16 i;
+
+ if (is_hvsock_offer(offer))
+ return HV_UNKNOWN;
+
+ for (i = HV_IDE; i < HV_UNKNOWN; i++) {
+ if (guid_equal(guid, &vmbus_devs[i].guid) && is_dev_hv_util(i)) {
+ if (refcount_read(&singleton_vmbus_devs[i]))
+ return HV_UNKNOWN;
+ refcount_set(&singleton_vmbus_devs[i], 1);
+ return i;
+ }
+ }
+
+ return i;
+}
+
static bool vmbus_is_valid_offer(const struct vmbus_channel_offer_channel *offer)
{
const guid_t *guid = &offer->offer.if_type;
@@ -1031,6 +1073,7 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
struct vmbus_channel_offer_channel *offer;
struct vmbus_channel *oldchannel, *newchannel;
size_t offer_sz;
+ u16 dev_type;
offer = (struct vmbus_channel_offer_channel *)hdr;
@@ -1115,11 +1158,29 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
return;
}
+ /*
+ * If vmbus_is_valid_offer() returns -
+ * HV_UNKNOWN - Subsequent offer received for hv_util dev, thus reject offer.
+ * HV_SHUTDOWN|HV_TS|HV_KVP|HV_HB|HV-KVP|HV_BACKUP - Increment refcount
+ * Others - Continue as is without doing anything.
+ *
+ * NOTE - We do not want to increase refcount if we resume from hibernation.
+ */
+ dev_type = vmbus_is_valid_hvutil_offer(offer);
+ if (dev_type == HV_UNKNOWN) {
+ pr_err_ratelimited("Invalid hv_util offer %d from the host supporting "
+ "isolation\n", offer->child_relid);
+ atomic_dec(&vmbus_connection.offer_in_progress);
+ return;
+ }
+
/* Allocate the channel object and save this offer. */
newchannel = alloc_channel();
if (!newchannel) {
vmbus_release_relid(offer->child_relid);
atomic_dec(&vmbus_connection.offer_in_progress);
+ if (is_dev_hv_util(dev_type))
+ refcount_dec(&singleton_vmbus_devs[dev_type]);
pr_err("Unable to allocate channel object\n");
return;
}
@@ -1235,7 +1296,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
/*
* At this point, the rescind handling can proceed safely.
*/
-
if (channel->device_obj) {
if (channel->chn_rescind_callback) {
channel->chn_rescind_callback(channel);
@@ -1251,6 +1311,8 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
*/
dev = get_device(&channel->device_obj->device);
if (dev) {
+ if (is_dev_hv_util(hv_get_dev_type(channel)))
+ refcount_dec(&singleton_vmbus_devs[hv_get_dev_type(channel)]);
vmbus_device_unregister(channel->device_obj);
put_device(dev);
}
--
2.34.1
next reply other threads:[~2024-12-20 23:51 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-20 23:51 Sonia Sharma [this message]
-- strict thread matches above, loose matches on Subject: below --
2024-12-20 23:55 [PATCH] Drivers: hv: Allow single instance of hv_util devices Sonia Sharma
2024-12-29 18:02 ` Michael Kelley
2025-01-07 2:00 ` Wei Liu
[not found] ` <CH4PR21MB4613241E591ED702A508C35491112@CH4PR21MB4613.namprd21.prod.outlook.com>
2025-01-09 7:35 ` Sonia Sharma
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1734738684-20713-1-git-send-email-sosha@linux.microsoft.com \
--to=sosha@linux.microsoft.com \
--cc=linux-kernel@vger.kernel.org \
--cc=sosha@microsoft.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox