[PATCH] nvmet: don't allow referral to match parent traddr+trsvcid
Sagi Grimberg
sagi at grimberg.me
Tue Feb 6 01:46:34 PST 2018
No way this can work and most likely cause endless recursion
for hosts that trying to discover referrals as well.
Signed-off-by: Sagi Grimberg <sagi at grimberg.me>
---
drivers/nvme/target/configfs.c | 13 ++++++++-----
drivers/nvme/target/discovery.c | 14 +++++++++++++-
drivers/nvme/target/nvmet.h | 2 +-
3 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index 615a89c7cbc0..0edd37683f88 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -842,17 +842,20 @@ static ssize_t nvmet_referral_enable_store(struct config_item *item,
struct nvmet_port *port = to_nvmet_port(item);
bool enable;
- if (strtobool(page, &enable))
+ if (strtobool(page, &enable)) {
+ pr_err("Invalid value '%s' for enable\n", page);
goto inval;
+ }
- if (enable)
- nvmet_referral_enable(parent, port);
- else
+ if (enable) {
+ if (nvmet_referral_enable(parent, port))
+ goto inval;
+ } else {
nvmet_referral_disable(port);
+ }
return count;
inval:
- pr_err("Invalid value '%s' for enable\n", page);
return -EINVAL;
}
diff --git a/drivers/nvme/target/discovery.c b/drivers/nvme/target/discovery.c
index a72425d8bce0..85feb05de7e1 100644
--- a/drivers/nvme/target/discovery.c
+++ b/drivers/nvme/target/discovery.c
@@ -20,15 +20,27 @@ struct nvmet_subsys *nvmet_disc_subsys;
u64 nvmet_genctr;
-void nvmet_referral_enable(struct nvmet_port *parent, struct nvmet_port *port)
+int nvmet_referral_enable(struct nvmet_port *parent, struct nvmet_port *port)
{
+ int ret = 0;
down_write(&nvmet_config_sem);
if (list_empty(&port->entry)) {
+ if (!memcmp(parent->disc_addr.traddr, port->disc_addr.traddr,
+ NVMF_TRADDR_SIZE) &&
+ !memcmp(parent->disc_addr.trsvcid, port->disc_addr.trsvcid,
+ NVMF_TRSVCID_SIZE)) {
+ pr_err("referral with the same traddr (%s) and trsvcid (%s)\n",
+ parent->disc_addr.traddr, parent->disc_addr.trsvcid);
+ ret = -EINVAL;
+ goto out;
+ }
list_add_tail(&port->entry, &parent->referrals);
port->enabled = true;
nvmet_genctr++;
}
+out:
up_write(&nvmet_config_sem);
+ return ret;
}
void nvmet_referral_disable(struct nvmet_port *port)
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index a6e191ff34ba..51a5ab99b85d 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -315,7 +315,7 @@ void nvmet_unregister_transport(struct nvmet_fabrics_ops *ops);
int nvmet_enable_port(struct nvmet_port *port);
void nvmet_disable_port(struct nvmet_port *port);
-void nvmet_referral_enable(struct nvmet_port *parent, struct nvmet_port *port);
+int nvmet_referral_enable(struct nvmet_port *parent, struct nvmet_port *port);
void nvmet_referral_disable(struct nvmet_port *port);
u16 nvmet_copy_to_sgl(struct nvmet_req *req, off_t off, const void *buf,
--
2.14.1
More information about the Linux-nvme
mailing list