Skip to content

Commit 313c08c

Browse files
author
Christoph Hellwig
committed
nvme: don't allow unprivileged passthrough on partitions
Passthrough commands can always access the entire device, and thus submitting them on partitions is an privelege escalation. In hindsight we should have never allowed any passthrough commands on partitions, but it's probably too late to change that decision now. Fixes: e4fbcf3 ("nvme: identify-namespace without CAP_SYS_ADMIN") Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Keith Busch <kbusch@kernel.org> Reviewed-by: Kanchan Joshi <joshi.k@samsung.com> Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
1 parent 7b7fdb8 commit 313c08c

File tree

1 file changed

+31
-16
lines changed

1 file changed

+31
-16
lines changed

drivers/nvme/host/ioctl.c

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,24 @@
1010

1111
enum {
1212
NVME_IOCTL_VEC = (1 << 0),
13+
NVME_IOCTL_PARTITION = (1 << 1),
1314
};
1415

1516
static bool nvme_cmd_allowed(struct nvme_ns *ns, struct nvme_command *c,
16-
fmode_t mode)
17+
unsigned int flags, fmode_t mode)
1718
{
1819
u32 effects;
1920

2021
if (capable(CAP_SYS_ADMIN))
2122
return true;
2223

24+
/*
25+
* Do not allow unprivileged passthrough on partitions, as that allows an
26+
* escape from the containment of the partition.
27+
*/
28+
if (flags & NVME_IOCTL_PARTITION)
29+
return false;
30+
2331
/*
2432
* Do not allow unprivileged processes to send vendor specific or fabrics
2533
* commands as we can't be sure about their effects.
@@ -327,7 +335,8 @@ static bool nvme_validate_passthru_nsid(struct nvme_ctrl *ctrl,
327335
}
328336

329337
static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
330-
struct nvme_passthru_cmd __user *ucmd, fmode_t mode)
338+
struct nvme_passthru_cmd __user *ucmd, unsigned int flags,
339+
fmode_t mode)
331340
{
332341
struct nvme_passthru_cmd cmd;
333342
struct nvme_command c;
@@ -355,7 +364,7 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
355364
c.common.cdw14 = cpu_to_le32(cmd.cdw14);
356365
c.common.cdw15 = cpu_to_le32(cmd.cdw15);
357366

358-
if (!nvme_cmd_allowed(ns, &c, mode))
367+
if (!nvme_cmd_allowed(ns, &c, 0, mode))
359368
return -EACCES;
360369

361370
if (cmd.timeout_ms)
@@ -402,7 +411,7 @@ static int nvme_user_cmd64(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
402411
c.common.cdw14 = cpu_to_le32(cmd.cdw14);
403412
c.common.cdw15 = cpu_to_le32(cmd.cdw15);
404413

405-
if (!nvme_cmd_allowed(ns, &c, mode))
414+
if (!nvme_cmd_allowed(ns, &c, flags, mode))
406415
return -EACCES;
407416

408417
if (cmd.timeout_ms)
@@ -571,7 +580,7 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
571580
c.common.cdw14 = cpu_to_le32(READ_ONCE(cmd->cdw14));
572581
c.common.cdw15 = cpu_to_le32(READ_ONCE(cmd->cdw15));
573582

574-
if (!nvme_cmd_allowed(ns, &c, ioucmd->file->f_mode))
583+
if (!nvme_cmd_allowed(ns, &c, 0, ioucmd->file->f_mode))
575584
return -EACCES;
576585

577586
d.metadata = READ_ONCE(cmd->metadata);
@@ -641,7 +650,7 @@ static int nvme_ctrl_ioctl(struct nvme_ctrl *ctrl, unsigned int cmd,
641650
{
642651
switch (cmd) {
643652
case NVME_IOCTL_ADMIN_CMD:
644-
return nvme_user_cmd(ctrl, NULL, argp, mode);
653+
return nvme_user_cmd(ctrl, NULL, argp, 0, mode);
645654
case NVME_IOCTL_ADMIN64_CMD:
646655
return nvme_user_cmd64(ctrl, NULL, argp, 0, mode);
647656
default:
@@ -668,16 +677,14 @@ struct nvme_user_io32 {
668677
#endif /* COMPAT_FOR_U64_ALIGNMENT */
669678

670679
static int nvme_ns_ioctl(struct nvme_ns *ns, unsigned int cmd,
671-
void __user *argp, fmode_t mode)
680+
void __user *argp, unsigned int flags, fmode_t mode)
672681
{
673-
unsigned int flags = 0;
674-
675682
switch (cmd) {
676683
case NVME_IOCTL_ID:
677684
force_successful_syscall_return();
678685
return ns->head->ns_id;
679686
case NVME_IOCTL_IO_CMD:
680-
return nvme_user_cmd(ns->ctrl, ns, argp, mode);
687+
return nvme_user_cmd(ns->ctrl, ns, argp, flags, mode);
681688
/*
682689
* struct nvme_user_io can have different padding on some 32-bit ABIs.
683690
* Just accept the compat version as all fields that are used are the
@@ -703,10 +710,14 @@ int nvme_ioctl(struct block_device *bdev, fmode_t mode,
703710
{
704711
struct nvme_ns *ns = bdev->bd_disk->private_data;
705712
void __user *argp = (void __user *)arg;
713+
unsigned int flags = 0;
714+
715+
if (bdev_is_partition(bdev))
716+
flags |= NVME_IOCTL_PARTITION;
706717

707718
if (is_ctrl_ioctl(cmd))
708719
return nvme_ctrl_ioctl(ns->ctrl, cmd, argp, mode);
709-
return nvme_ns_ioctl(ns, cmd, argp, mode);
720+
return nvme_ns_ioctl(ns, cmd, argp, flags, mode);
710721
}
711722

712723
long nvme_ns_chr_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -717,7 +728,7 @@ long nvme_ns_chr_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
717728

718729
if (is_ctrl_ioctl(cmd))
719730
return nvme_ctrl_ioctl(ns->ctrl, cmd, argp, file->f_mode);
720-
return nvme_ns_ioctl(ns, cmd, argp, file->f_mode);
731+
return nvme_ns_ioctl(ns, cmd, argp, 0, file->f_mode);
721732
}
722733

723734
static int nvme_uring_cmd_checks(unsigned int issue_flags)
@@ -807,6 +818,10 @@ int nvme_ns_head_ioctl(struct block_device *bdev, fmode_t mode,
807818
void __user *argp = (void __user *)arg;
808819
struct nvme_ns *ns;
809820
int srcu_idx, ret = -EWOULDBLOCK;
821+
unsigned int flags = 0;
822+
823+
if (bdev_is_partition(bdev))
824+
flags |= NVME_IOCTL_PARTITION;
810825

811826
srcu_idx = srcu_read_lock(&head->srcu);
812827
ns = nvme_find_path(head);
@@ -822,7 +837,7 @@ int nvme_ns_head_ioctl(struct block_device *bdev, fmode_t mode,
822837
return nvme_ns_head_ctrl_ioctl(ns, cmd, argp, head, srcu_idx,
823838
mode);
824839

825-
ret = nvme_ns_ioctl(ns, cmd, argp, mode);
840+
ret = nvme_ns_ioctl(ns, cmd, argp, flags, mode);
826841
out_unlock:
827842
srcu_read_unlock(&head->srcu, srcu_idx);
828843
return ret;
@@ -847,7 +862,7 @@ long nvme_ns_head_chr_ioctl(struct file *file, unsigned int cmd,
847862
return nvme_ns_head_ctrl_ioctl(ns, cmd, argp, head, srcu_idx,
848863
file->f_mode);
849864

850-
ret = nvme_ns_ioctl(ns, cmd, argp, file->f_mode);
865+
ret = nvme_ns_ioctl(ns, cmd, argp, 0, file->f_mode);
851866
out_unlock:
852867
srcu_read_unlock(&head->srcu, srcu_idx);
853868
return ret;
@@ -946,7 +961,7 @@ static int nvme_dev_user_cmd(struct nvme_ctrl *ctrl, void __user *argp,
946961
kref_get(&ns->kref);
947962
up_read(&ctrl->namespaces_rwsem);
948963

949-
ret = nvme_user_cmd(ctrl, ns, argp, mode);
964+
ret = nvme_user_cmd(ctrl, ns, argp, 0, mode);
950965
nvme_put_ns(ns);
951966
return ret;
952967

@@ -963,7 +978,7 @@ long nvme_dev_ioctl(struct file *file, unsigned int cmd,
963978

964979
switch (cmd) {
965980
case NVME_IOCTL_ADMIN_CMD:
966-
return nvme_user_cmd(ctrl, NULL, argp, file->f_mode);
981+
return nvme_user_cmd(ctrl, NULL, argp, 0, file->f_mode);
967982
case NVME_IOCTL_ADMIN64_CMD:
968983
return nvme_user_cmd64(ctrl, NULL, argp, 0, file->f_mode);
969984
case NVME_IOCTL_IO_CMD:

0 commit comments

Comments
 (0)