Skip to content

Commit 6f99ac0

Browse files
author
Christoph Hellwig
committed
nvme: consult the CSE log page for unprivileged passthrough
Commands like Write Zeros can change the contents of a namespaces without actually transferring data. To protect against this, check the Commands Supported and Effects log is supported by the controller for any unprivileg command passthrough and refuse unprivileged passthrough if the command has any effects that can change data or metadata. Note: While the Commands Support and Effects log page has only been mandatory since NVMe 2.0, it is widely supported because Windows requires it for any command passthrough from userspace. Fixes: e4fbcf3 ("nvme: identify-namespace without CAP_SYS_ADMIN") Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Keith Busch <[email protected]> Reviewed-by: Sagi Grimberg <[email protected]> Reviewed-by: Kanchan Joshi <[email protected]>
1 parent 831ed60 commit 6f99ac0

File tree

2 files changed

+25
-4
lines changed

2 files changed

+25
-4
lines changed

drivers/nvme/host/ioctl.c

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
static bool nvme_cmd_allowed(struct nvme_ns *ns, struct nvme_command *c,
1212
fmode_t mode)
1313
{
14+
u32 effects;
15+
1416
if (capable(CAP_SYS_ADMIN))
1517
return true;
1618

@@ -43,11 +45,29 @@ static bool nvme_cmd_allowed(struct nvme_ns *ns, struct nvme_command *c,
4345
}
4446

4547
/*
46-
* Only allow I/O commands that transfer data to the controller if the
47-
* special file is open for writing, but always allow I/O commands that
48-
* transfer data from the controller.
48+
* Check if the controller provides a Commands Supported and Effects log
49+
* and marks this command as supported. If not reject unprivileged
50+
* passthrough.
51+
*/
52+
effects = nvme_command_effects(ns->ctrl, ns, c->common.opcode);
53+
if (!(effects & NVME_CMD_EFFECTS_CSUPP))
54+
return false;
55+
56+
/*
57+
* Don't allow passthrough for command that have intrusive (or unknown)
58+
* effects.
59+
*/
60+
if (effects & ~(NVME_CMD_EFFECTS_CSUPP | NVME_CMD_EFFECTS_LBCC |
61+
NVME_CMD_EFFECTS_UUID_SEL |
62+
NVME_CMD_EFFECTS_SCOPE_MASK))
63+
return false;
64+
65+
/*
66+
* Only allow I/O commands that transfer data to the controller or that
67+
* change the logical block contents if the file descriptor is open for
68+
* writing.
4969
*/
50-
if (nvme_is_write(c))
70+
if (nvme_is_write(c) || (effects & NVME_CMD_EFFECTS_LBCC))
5171
return mode & FMODE_WRITE;
5272
return true;
5373
}

include/linux/nvme.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,7 @@ enum {
642642
NVME_CMD_EFFECTS_CCC = 1 << 4,
643643
NVME_CMD_EFFECTS_CSE_MASK = GENMASK(18, 16),
644644
NVME_CMD_EFFECTS_UUID_SEL = 1 << 19,
645+
NVME_CMD_EFFECTS_SCOPE_MASK = GENMASK(31, 20),
645646
};
646647

647648
struct nvme_effects_log {

0 commit comments

Comments
 (0)