All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] Granular CAP_SYS_ADMIN
       [not found] <CGME20221020071338epcas5p16d72f5d4d868b889e3a98688bc454a98@epcas5p1.samsung.com>
@ 2022-10-20  7:02 ` Kanchan Joshi
       [not found]   ` <CGME20221020071343epcas5p3722073ab4822d39d6ca91606869f0379@epcas5p3.samsung.com>
                     ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Kanchan Joshi @ 2022-10-20  7:02 UTC (permalink / raw)
  To: hch, kbusch, sagi, axboe; +Cc: linux-nvme, gost.dev, Kanchan Joshi

Hi,

Patch 1 is for io-commands. It implements the shift to file-mode based
policy.
Patch 2 is to allow identify-namespace command. This is based on the feedback
received during ALPSS.

@Sagi: Since patch 1 is changed a bit (changelog below), I did not
apply the reviewed-by tag. Please take a look again.

Changes since v2:
- Add patch 2 that allows identify-ns
- Patch 1: Move nvme_cmd_allowed check further down, so that we can use CNS
  values for decision making in patch 2
- Patch 1: invert if condition (Sagi)

Changes since v1:
- Move nvme_cmd_allowed check at a place that allows using nvme_is_write
  helper (hch)
- Keep everything into single patch (chaitanya, hch)
- Comments cleanup (hch, chaitanya)
- Part of cover-letter moved to commit-description

Examples (after patches):
***************************

#1: Two NS, one with 666 another with 600
$: ls -l /dev/ng*
crw-rw-rw- 1 root root 242, 0 Oct 20 12:04 /dev/ng0n1
crw------- 1 root root 242, 1 Oct 20 12:04 /dev/ng0n2

#2: this should fail
$: nvme id-ns /dev/ng0n2
/dev/ng0n2: Permission denied
Usage: nvme id-ns <device> [OPTIONS]

Send an Identify Namespace command to the given device, returns properties of
the specified namespace in either human-readable or binary format. Can also
return binary vendor-specific namespace attributes.

Options:
  [  --namespace-id=<NUM>, -n <NUM> ]   --- identifier of desired namespace
  [  --force ]                          --- Return this namespace, even if
                                            not attaced (1.2 devices only)
  [  --vendor-specific, -v ]            --- dump binary vendor fields
  [  --raw-binary, -b ]                 --- show identify in binary format
  [  --output-format=<FMT>, -o <FMT> ]  --- Output format: normal|json|binary
  [  --human-readable, -H ]             --- show identify in readable format

#3: this should travel
$: nvme id-ns /dev/ng0n1
NVME Identify Namespace 1:
nsze    : 0x300000
ncap    : 0x300000
nuse    : 0x300000
nsfeat  : 0
nlbaf   : 7
flbas   : 0x4
mc      : 0
dpc     : 0
dps     : 0
nmic    : 0
rescap  : 0
fpi     : 0
dlfeat  : 9
nawun   : 0
nawupf  : 0
nacwu   : 0
nabsn   : 0
nabo    : 0
nabspf  : 0
noiob   : 0
nvmcap  : 0
mssrl   : 256
mcl     : 256
msrc    : 127
nulbaf  : 0
anagrpid: 0
nsattr  : 0
nvmsetid: 0
endgid  : 0
nguid   : 00000000000000000000000000000000
eui64   : 0000000000000000
lbaf  0 : ms:0   lbads:9  rp:0
lbaf  1 : ms:8   lbads:9  rp:0
lbaf  2 : ms:16  lbads:9  rp:0
lbaf  3 : ms:64  lbads:9  rp:0
lbaf  4 : ms:0   lbads:12 rp:0 (in use)
lbaf  5 : ms:8   lbads:12 rp:0
lbaf  6 : ms:16  lbads:12 rp:0
lbaf  7 : ms:64  lbads:12 rp:0

#4: this should not travel
$: nvme id-ctrl /dev/ng0n1
identify controller: Permission denied

#5: uring-passthru read on ng0n1 (should work)
$: ./fio -iodepth=1 -rw=randread -ioengine=io_uring_cmd -cmd_type=nvme -bs=4k -numjobs=1 -size=4k -filename=/dev/ng0n1 -name=pt
pt: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=io_uring_cmd, iodepth=1
fio-3.32-58-gb19c-dirty
Starting 1 process

pt: (groupid=0, jobs=1): err= 0: pid=56582: Thu Oct 20 12:12:50 2022
  read: IOPS=500, BW=2000KiB/s (2048kB/s)(4096B/2msec)
    slat (nsec): min=461505, max=461505, avg=461505.00, stdev= 0.00
    clat (nsec): min=544742, max=544742, avg=544742.00, stdev= 0.00
     lat (nsec): min=1006.2k, max=1006.2k, avg=1006247.00, stdev= 0.00
    clat percentiles (usec):
     |  1.00th=[  545],  5.00th=[  545], 10.00th=[  545], 20.00th=[  545],
     | 30.00th=[  545], 40.00th=[  545], 50.00th=[  545], 60.00th=[  545],
     | 70.00th=[  545], 80.00th=[  545], 90.00th=[  545], 95.00th=[  545],
     | 99.00th=[  545], 99.50th=[  545], 99.90th=[  545], 99.95th=[  545],
     | 99.99th=[  545]
  lat (usec)   : 750=100.00%
  cpu          : usr=0.00%, sys=200.00%, ctx=1, majf=0, minf=6
  IO depths    : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     issued rwts: total=1,0,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=1

Run status group 0 (all jobs):
   READ: bw=2000KiB/s (2048kB/s), 2000KiB/s-2000KiB/s (2048kB/s-2048kB/s), io=4096B (4096B), run=2-2msec

#6: uring-passthru read on ng0n2 (should fail)
$: ./fio -iodepth=1 -rw=randread -ioengine=io_uring_cmd -cmd_type=nvme -bs=4k -numjobs=1 -size=4k -filename=/dev/ng0n2 -name=pt
pt: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=io_uring_cmd, iodepth=1
fio-3.32-58-gb19c-dirty
Starting 1 process



Run status group 0 (all jobs):


Kanchan Joshi (2):
  nvme: fine-granular CAP_SYS_ADMIN for nvme io commands
  nvme: identify-namespace without CAP_SYS_ADMIN

 drivers/nvme/host/ioctl.c | 107 ++++++++++++++++++++++++++------------
 include/linux/nvme.h      |   1 +
 2 files changed, 75 insertions(+), 33 deletions(-)

-- 
2.25.1



^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/2] nvme: fine-granular CAP_SYS_ADMIN for nvme io commands
       [not found]   ` <CGME20221020071343epcas5p3722073ab4822d39d6ca91606869f0379@epcas5p3.samsung.com>
@ 2022-10-20  7:02     ` Kanchan Joshi
  0 siblings, 0 replies; 8+ messages in thread
From: Kanchan Joshi @ 2022-10-20  7:02 UTC (permalink / raw)
  To: hch, kbusch, sagi, axboe; +Cc: linux-nvme, gost.dev, Kanchan Joshi

Currently both io and admin commands are kept under a
coarse-granular CAP_SYS_ADMIN check, disregarding file mode completely.

$ ls -l /dev/ng*
crw-rw-rw- 1 root root 242, 0 Sep  9 19:20 /dev/ng0n1
crw------- 1 root root 242, 1 Sep  9 19:20 /dev/ng0n2

In the example above, ng0n1 appears as if it may allow unprivileged
read/write operation but it does not and behaves same as ng0n2.

This patch implements a shift from CAP_SYS_ADMIN to more fine-granular
control for io-commands.
If CAP_SYS_ADMIN is present, nothing else is checked as before.
Otherwise, following rules are in place
- any admin-cmd is not allowed
- vendor-specific and fabric commmand are not allowed
- io-commands that can write are allowed if matching FMODE_WRITE
permission is present
- io-commands that read are allowed

Add a helper nvme_cmd_allowed that implements above policy.
Change all the callers of CAP_SYS_ADMIN to go through nvme_cmd_allowed
for any decision making.
Since file open mode is counted for any approval/denial, change at
various places to keep file-mode information handy.

Signed-off-by: Kanchan Joshi <joshi.k@samsung.com>
---
 drivers/nvme/host/ioctl.c | 97 ++++++++++++++++++++++++++-------------
 include/linux/nvme.h      |  1 +
 2 files changed, 65 insertions(+), 33 deletions(-)

diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
index 81f5550b670d..9c581b1a8956 100644
--- a/drivers/nvme/host/ioctl.c
+++ b/drivers/nvme/host/ioctl.c
@@ -8,6 +8,29 @@
 #include <linux/io_uring.h>
 #include "nvme.h"
 
+bool nvme_cmd_allowed(struct nvme_ns *ns, struct nvme_command *c, fmode_t mode)
+{
+	u8 opcode = c->common.opcode;
+
+	if (capable(CAP_SYS_ADMIN))
+		return true;
+
+	/* admin commands are not allowed */
+	if (!ns)
+		return false;
+
+	/* exclude vendor-specific io and fabrics commands */
+	if (opcode >= nvme_cmd_vendor_start || opcode == nvme_fabrics_command)
+		return false;
+
+	/* allow write cmds only if matching FMODE is present */
+	if (nvme_is_write(c))
+		return mode & FMODE_WRITE;
+
+	/* allow read cmds as the device permission allows access */
+	return true;
+}
+
 /*
  * Convert integer values from ioctl structures to user pointers, silently
  * ignoring the upper bits in the compat case to match behaviour of 32-bit
@@ -261,7 +284,7 @@ static bool nvme_validate_passthru_nsid(struct nvme_ctrl *ctrl,
 }
 
 static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
-			struct nvme_passthru_cmd __user *ucmd)
+			struct nvme_passthru_cmd __user *ucmd, fmode_t mode)
 {
 	struct nvme_passthru_cmd cmd;
 	struct nvme_command c;
@@ -269,8 +292,6 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
 	u64 result;
 	int status;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
 	if (copy_from_user(&cmd, ucmd, sizeof(cmd)))
 		return -EFAULT;
 	if (cmd.flags)
@@ -291,6 +312,9 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
 	c.common.cdw14 = cpu_to_le32(cmd.cdw14);
 	c.common.cdw15 = cpu_to_le32(cmd.cdw15);
 
+	if (!nvme_cmd_allowed(ns, &c, mode))
+		return -EACCES;
+
 	if (cmd.timeout_ms)
 		timeout = msecs_to_jiffies(cmd.timeout_ms);
 
@@ -308,15 +332,14 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
 }
 
 static int nvme_user_cmd64(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
-			struct nvme_passthru_cmd64 __user *ucmd, bool vec)
+			struct nvme_passthru_cmd64 __user *ucmd, bool vec,
+			fmode_t mode)
 {
 	struct nvme_passthru_cmd64 cmd;
 	struct nvme_command c;
 	unsigned timeout = 0;
 	int status;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
 	if (copy_from_user(&cmd, ucmd, sizeof(cmd)))
 		return -EFAULT;
 	if (cmd.flags)
@@ -337,6 +360,9 @@ static int nvme_user_cmd64(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
 	c.common.cdw14 = cpu_to_le32(cmd.cdw14);
 	c.common.cdw15 = cpu_to_le32(cmd.cdw15);
 
+	if (!nvme_cmd_allowed(ns, &c, mode))
+		return -EACCES;
+
 	if (cmd.timeout_ms)
 		timeout = msecs_to_jiffies(cmd.timeout_ms);
 
@@ -483,9 +509,6 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
 	void *meta = NULL;
 	int ret;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
-
 	c.common.opcode = READ_ONCE(cmd->opcode);
 	c.common.flags = READ_ONCE(cmd->flags);
 	if (c.common.flags)
@@ -507,6 +530,9 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
 	c.common.cdw14 = cpu_to_le32(READ_ONCE(cmd->cdw14));
 	c.common.cdw15 = cpu_to_le32(READ_ONCE(cmd->cdw15));
 
+	if (!nvme_cmd_allowed(ns, &c, ioucmd->file->f_mode))
+		return -EACCES;
+
 	d.metadata = READ_ONCE(cmd->metadata);
 	d.addr = READ_ONCE(cmd->addr);
 	d.data_len = READ_ONCE(cmd->data_len);
@@ -570,13 +596,13 @@ static bool is_ctrl_ioctl(unsigned int cmd)
 }
 
 static int nvme_ctrl_ioctl(struct nvme_ctrl *ctrl, unsigned int cmd,
-		void __user *argp)
+		void __user *argp, fmode_t mode)
 {
 	switch (cmd) {
 	case NVME_IOCTL_ADMIN_CMD:
-		return nvme_user_cmd(ctrl, NULL, argp);
+		return nvme_user_cmd(ctrl, NULL, argp, mode);
 	case NVME_IOCTL_ADMIN64_CMD:
-		return nvme_user_cmd64(ctrl, NULL, argp, false);
+		return nvme_user_cmd64(ctrl, NULL, argp, false, mode);
 	default:
 		return sed_ioctl(ctrl->opal_dev, cmd, argp);
 	}
@@ -601,14 +627,14 @@ struct nvme_user_io32 {
 #endif /* COMPAT_FOR_U64_ALIGNMENT */
 
 static int nvme_ns_ioctl(struct nvme_ns *ns, unsigned int cmd,
-		void __user *argp)
+		void __user *argp, fmode_t mode)
 {
 	switch (cmd) {
 	case NVME_IOCTL_ID:
 		force_successful_syscall_return();
 		return ns->head->ns_id;
 	case NVME_IOCTL_IO_CMD:
-		return nvme_user_cmd(ns->ctrl, ns, argp);
+		return nvme_user_cmd(ns->ctrl, ns, argp, mode);
 	/*
 	 * struct nvme_user_io can have different padding on some 32-bit ABIs.
 	 * Just accept the compat version as all fields that are used are the
@@ -620,19 +646,20 @@ static int nvme_ns_ioctl(struct nvme_ns *ns, unsigned int cmd,
 	case NVME_IOCTL_SUBMIT_IO:
 		return nvme_submit_io(ns, argp);
 	case NVME_IOCTL_IO64_CMD:
-		return nvme_user_cmd64(ns->ctrl, ns, argp, false);
+		return nvme_user_cmd64(ns->ctrl, ns, argp, false, mode);
 	case NVME_IOCTL_IO64_CMD_VEC:
-		return nvme_user_cmd64(ns->ctrl, ns, argp, true);
+		return nvme_user_cmd64(ns->ctrl, ns, argp, true, mode);
 	default:
 		return -ENOTTY;
 	}
 }
 
-static int __nvme_ioctl(struct nvme_ns *ns, unsigned int cmd, void __user *arg)
+static int __nvme_ioctl(struct nvme_ns *ns, unsigned int cmd, void __user *arg,
+			fmode_t mode)
 {
-       if (is_ctrl_ioctl(cmd))
-               return nvme_ctrl_ioctl(ns->ctrl, cmd, arg);
-       return nvme_ns_ioctl(ns, cmd, arg);
+	if (is_ctrl_ioctl(cmd))
+		return nvme_ctrl_ioctl(ns->ctrl, cmd, arg, mode);
+	return nvme_ns_ioctl(ns, cmd, arg, mode);
 }
 
 int nvme_ioctl(struct block_device *bdev, fmode_t mode,
@@ -640,7 +667,7 @@ int nvme_ioctl(struct block_device *bdev, fmode_t mode,
 {
 	struct nvme_ns *ns = bdev->bd_disk->private_data;
 
-	return __nvme_ioctl(ns, cmd, (void __user *)arg);
+	return __nvme_ioctl(ns, cmd, (void __user *)arg, mode);
 }
 
 long nvme_ns_chr_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -648,7 +675,7 @@ long nvme_ns_chr_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	struct nvme_ns *ns =
 		container_of(file_inode(file)->i_cdev, struct nvme_ns, cdev);
 
-	return __nvme_ioctl(ns, cmd, (void __user *)arg);
+	return __nvme_ioctl(ns, cmd, (void __user *)arg, file->f_mode);
 }
 
 static int nvme_uring_cmd_checks(unsigned int issue_flags)
@@ -716,7 +743,8 @@ int nvme_ns_chr_uring_cmd_iopoll(struct io_uring_cmd *ioucmd,
 }
 #ifdef CONFIG_NVME_MULTIPATH
 static int nvme_ns_head_ctrl_ioctl(struct nvme_ns *ns, unsigned int cmd,
-		void __user *argp, struct nvme_ns_head *head, int srcu_idx)
+		void __user *argp, struct nvme_ns_head *head, int srcu_idx,
+		fmode_t mode)
 	__releases(&head->srcu)
 {
 	struct nvme_ctrl *ctrl = ns->ctrl;
@@ -724,7 +752,7 @@ static int nvme_ns_head_ctrl_ioctl(struct nvme_ns *ns, unsigned int cmd,
 
 	nvme_get_ctrl(ns->ctrl);
 	srcu_read_unlock(&head->srcu, srcu_idx);
-	ret = nvme_ctrl_ioctl(ns->ctrl, cmd, argp);
+	ret = nvme_ctrl_ioctl(ns->ctrl, cmd, argp, mode);
 
 	nvme_put_ctrl(ctrl);
 	return ret;
@@ -749,9 +777,10 @@ int nvme_ns_head_ioctl(struct block_device *bdev, fmode_t mode,
 	 * deadlock when deleting namespaces using the passthrough interface.
 	 */
 	if (is_ctrl_ioctl(cmd))
-		return nvme_ns_head_ctrl_ioctl(ns, cmd, argp, head, srcu_idx);
+		return nvme_ns_head_ctrl_ioctl(ns, cmd, argp, head, srcu_idx,
+					mode);
 
-	ret = nvme_ns_ioctl(ns, cmd, argp);
+	ret = nvme_ns_ioctl(ns, cmd, argp, mode);
 out_unlock:
 	srcu_read_unlock(&head->srcu, srcu_idx);
 	return ret;
@@ -773,9 +802,10 @@ long nvme_ns_head_chr_ioctl(struct file *file, unsigned int cmd,
 		goto out_unlock;
 
 	if (is_ctrl_ioctl(cmd))
-		return nvme_ns_head_ctrl_ioctl(ns, cmd, argp, head, srcu_idx);
+		return nvme_ns_head_ctrl_ioctl(ns, cmd, argp, head, srcu_idx,
+				file->f_mode);
 
-	ret = nvme_ns_ioctl(ns, cmd, argp);
+	ret = nvme_ns_ioctl(ns, cmd, argp, file->f_mode);
 out_unlock:
 	srcu_read_unlock(&head->srcu, srcu_idx);
 	return ret;
@@ -849,7 +879,8 @@ int nvme_dev_uring_cmd(struct io_uring_cmd *ioucmd, unsigned int issue_flags)
 	return ret;
 }
 
-static int nvme_dev_user_cmd(struct nvme_ctrl *ctrl, void __user *argp)
+static int nvme_dev_user_cmd(struct nvme_ctrl *ctrl, void __user *argp,
+		fmode_t mode)
 {
 	struct nvme_ns *ns;
 	int ret;
@@ -873,7 +904,7 @@ static int nvme_dev_user_cmd(struct nvme_ctrl *ctrl, void __user *argp)
 	kref_get(&ns->kref);
 	up_read(&ctrl->namespaces_rwsem);
 
-	ret = nvme_user_cmd(ctrl, ns, argp);
+	ret = nvme_user_cmd(ctrl, ns, argp, mode);
 	nvme_put_ns(ns);
 	return ret;
 
@@ -890,11 +921,11 @@ long nvme_dev_ioctl(struct file *file, unsigned int cmd,
 
 	switch (cmd) {
 	case NVME_IOCTL_ADMIN_CMD:
-		return nvme_user_cmd(ctrl, NULL, argp);
+		return nvme_user_cmd(ctrl, NULL, argp, file->f_mode);
 	case NVME_IOCTL_ADMIN64_CMD:
-		return nvme_user_cmd64(ctrl, NULL, argp, false);
+		return nvme_user_cmd64(ctrl, NULL, argp, false, file->f_mode);
 	case NVME_IOCTL_IO_CMD:
-		return nvme_dev_user_cmd(ctrl, argp);
+		return nvme_dev_user_cmd(ctrl, argp, file->f_mode);
 	case NVME_IOCTL_RESET:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EACCES;
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index 050d7d0cd81b..1d102b662e88 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -797,6 +797,7 @@ enum nvme_opcode {
 	nvme_cmd_zone_mgmt_send	= 0x79,
 	nvme_cmd_zone_mgmt_recv	= 0x7a,
 	nvme_cmd_zone_append	= 0x7d,
+	nvme_cmd_vendor_start	= 0x80,
 };
 
 #define nvme_opcode_name(opcode)	{ opcode, #opcode }
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/2] nvme: identify-namespace without CAP_SYS_ADMIN
       [not found]   ` <CGME20221020071346epcas5p4c3b8da5e60f94947ad570cbd151eb38d@epcas5p4.samsung.com>
@ 2022-10-20  7:02     ` Kanchan Joshi
  2022-10-31  6:55       ` Chaitanya Kulkarni
  0 siblings, 1 reply; 8+ messages in thread
From: Kanchan Joshi @ 2022-10-20  7:02 UTC (permalink / raw)
  To: hch, kbusch, sagi, axboe; +Cc: linux-nvme, gost.dev, Kanchan Joshi

Allow all identify-namespace variants (CNS 00h, 05h and 08h) without
requiring CAP_SYS_ADMIN. The information (retrieved using id-ns) is
needed to form IO commands for passthrough interface.

Signed-off-by: Kanchan Joshi <joshi.k@samsung.com>
---
 drivers/nvme/host/ioctl.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
index 9c581b1a8956..9273db147872 100644
--- a/drivers/nvme/host/ioctl.c
+++ b/drivers/nvme/host/ioctl.c
@@ -15,9 +15,19 @@ bool nvme_cmd_allowed(struct nvme_ns *ns, struct nvme_command *c, fmode_t mode)
 	if (capable(CAP_SYS_ADMIN))
 		return true;
 
-	/* admin commands are not allowed */
-	if (!ns)
+	/* policy for admin commands */
+	if (!ns) {
+		if (opcode == nvme_admin_identify) {
+			switch (c->identify.cns) {
+			case NVME_ID_CNS_NS:
+			case NVME_ID_CNS_CS_NS:
+			case NVME_ID_CNS_NS_CS_INDEP:
+				return true;
+			}
+		}
+		/* other admin commands are not allowed */
 		return false;
+	}
 
 	/* exclude vendor-specific io and fabrics commands */
 	if (opcode >= nvme_cmd_vendor_start || opcode == nvme_fabrics_command)
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 0/2] Granular CAP_SYS_ADMIN
  2022-10-20  7:02 ` [PATCH 0/2] Granular CAP_SYS_ADMIN Kanchan Joshi
       [not found]   ` <CGME20221020071343epcas5p3722073ab4822d39d6ca91606869f0379@epcas5p3.samsung.com>
       [not found]   ` <CGME20221020071346epcas5p4c3b8da5e60f94947ad570cbd151eb38d@epcas5p4.samsung.com>
@ 2022-10-25 19:43   ` Jens Axboe
  2022-10-25 20:07   ` Keith Busch
  3 siblings, 0 replies; 8+ messages in thread
From: Jens Axboe @ 2022-10-25 19:43 UTC (permalink / raw)
  To: Kanchan Joshi, hch, kbusch, sagi; +Cc: linux-nvme, gost.dev

On 10/20/22 1:02 AM, Kanchan Joshi wrote:
> Hi,
> 
> Patch 1 is for io-commands. It implements the shift to file-mode based
> policy.
> Patch 2 is to allow identify-namespace command. This is based on the feedback
> received during ALPSS.
> 
> @Sagi: Since patch 1 is changed a bit (changelog below), I did not
> apply the reviewed-by tag. Please take a look again.

I generally despise any kind of listing of commands, but this looks
pretty reasonable.

Reviewed-by: Jens Axboe <axboe@kernel.dk>

-- 
Jens Axboe




^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 0/2] Granular CAP_SYS_ADMIN
  2022-10-20  7:02 ` [PATCH 0/2] Granular CAP_SYS_ADMIN Kanchan Joshi
                     ` (2 preceding siblings ...)
  2022-10-25 19:43   ` [PATCH 0/2] Granular CAP_SYS_ADMIN Jens Axboe
@ 2022-10-25 20:07   ` Keith Busch
  3 siblings, 0 replies; 8+ messages in thread
From: Keith Busch @ 2022-10-25 20:07 UTC (permalink / raw)
  To: Kanchan Joshi; +Cc: hch, sagi, axboe, linux-nvme, gost.dev

On Thu, Oct 20, 2022 at 12:32:03PM +0530, Kanchan Joshi wrote:
> #1: Two NS, one with 666 another with 600
> $: ls -l /dev/ng*
> crw-rw-rw- 1 root root 242, 0 Oct 20 12:04 /dev/ng0n1
> crw------- 1 root root 242, 1 Oct 20 12:04 /dev/ng0n2
> 
> #2: this should fail
> $: nvme id-ns /dev/ng0n2
> /dev/ng0n2: Permission denied

This looks good to me. The only additional thought I had was to restrict
the identification's nsid parameter to ones readable to the user because
they could just open /dev/ng0n1 instead and override the nsid with the
'--nampespace-id=2' parameter.

But that doesn't look very straight now that I look at it again.

Reviewed-by: Keith Busch <kbusch@kernel.org>


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] nvme: identify-namespace without CAP_SYS_ADMIN
  2022-10-20  7:02     ` [PATCH 2/2] nvme: identify-namespace without CAP_SYS_ADMIN Kanchan Joshi
@ 2022-10-31  6:55       ` Chaitanya Kulkarni
  2022-10-31 13:47         ` Kanchan Joshi
  0 siblings, 1 reply; 8+ messages in thread
From: Chaitanya Kulkarni @ 2022-10-31  6:55 UTC (permalink / raw)
  To: Kanchan Joshi; +Cc: linux-nvme, hch, axboe, sagi, kbusch, gost.dev

On 10/20/22 00:02, Kanchan Joshi wrote:
> Allow all identify-namespace variants (CNS 00h, 05h and 08h) without
> requiring CAP_SYS_ADMIN. The information (retrieved using id-ns) is
> needed to form IO commands for passthrough interface.
> 
> Signed-off-by: Kanchan Joshi <joshi.k@samsung.com>
> ---
>   drivers/nvme/host/ioctl.c | 14 ++++++++++++--
>   1 file changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
> index 9c581b1a8956..9273db147872 100644
> --- a/drivers/nvme/host/ioctl.c
> +++ b/drivers/nvme/host/ioctl.c
> @@ -15,9 +15,19 @@ bool nvme_cmd_allowed(struct nvme_ns *ns, struct nvme_command *c, fmode_t mode)
>   	if (capable(CAP_SYS_ADMIN))
>   		return true;
>   
> -	/* admin commands are not allowed */
> -	if (!ns)
> +	/* policy for admin commands */

above comment is not needed as it is clear from the opcode below
you are dealing with admin commands only that too specific cns
values ..

> +	if (!ns) {
> +		if (opcode == nvme_admin_identify) {
> +			switch (c->identify.cns) {
> +			case NVME_ID_CNS_NS:
> +			case NVME_ID_CNS_CS_NS:
> +			case NVME_ID_CNS_NS_CS_INDEP:
> +				return true;
> +			}
> +		}
> +		/* other admin commands are not allowed */

same here..

>   		return false;

if and swicth and two returns are looking confusing, I'd use
nested switch case default here..

> +	}
>   
>   	/* exclude vendor-specific io and fabrics commands */
>   	if (opcode >= nvme_cmd_vendor_start || opcode == nvme_fabrics_command)


-ck


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] nvme: identify-namespace without CAP_SYS_ADMIN
  2022-10-31  6:55       ` Chaitanya Kulkarni
@ 2022-10-31 13:47         ` Kanchan Joshi
  2022-11-01  5:20           ` Chaitanya Kulkarni
  0 siblings, 1 reply; 8+ messages in thread
From: Kanchan Joshi @ 2022-10-31 13:47 UTC (permalink / raw)
  To: Chaitanya Kulkarni; +Cc: linux-nvme, hch, axboe, sagi, kbusch, gost.dev

[-- Attachment #1: Type: text/plain, Size: 2309 bytes --]

On Mon, Oct 31, 2022 at 06:55:56AM +0000, Chaitanya Kulkarni wrote:
>On 10/20/22 00:02, Kanchan Joshi wrote:
>> Allow all identify-namespace variants (CNS 00h, 05h and 08h) without
>> requiring CAP_SYS_ADMIN. The information (retrieved using id-ns) is
>> needed to form IO commands for passthrough interface.
>>
>> Signed-off-by: Kanchan Joshi <joshi.k@samsung.com>
>> ---
>>   drivers/nvme/host/ioctl.c | 14 ++++++++++++--
>>   1 file changed, 12 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
>> index 9c581b1a8956..9273db147872 100644
>> --- a/drivers/nvme/host/ioctl.c
>> +++ b/drivers/nvme/host/ioctl.c
>> @@ -15,9 +15,19 @@ bool nvme_cmd_allowed(struct nvme_ns *ns, struct nvme_command *c, fmode_t mode)
>>   	if (capable(CAP_SYS_ADMIN))
>>   		return true;
>>
>> -	/* admin commands are not allowed */
>> -	if (!ns)
>> +	/* policy for admin commands */
>
>above comment is not needed as it is clear from the opcode below
>you are dealing with admin commands only that too specific cns
>values ..
>
>> +	if (!ns) {
>> +		if (opcode == nvme_admin_identify) {
>> +			switch (c->identify.cns) {
>> +			case NVME_ID_CNS_NS:
>> +			case NVME_ID_CNS_CS_NS:
>> +			case NVME_ID_CNS_NS_CS_INDEP:
>> +				return true;
>> +			}
>> +		}
>> +		/* other admin commands are not allowed */
>
>same here..

All right, will kill these. 
>
>>   		return false;
>
>if and swicth and two returns are looking confusing, I'd use
>nested switch case default here..

Do you think that'll give better looking code?
I did not write that because it did not seem good fit for the
situtation. It involved aligning more curly braces: 

-       /* admin commands are not allowed */
-       if (!ns)
+       if (!ns) {
+               switch (opcode) {
+               case nvme_admin_identify: {
+                       switch (c->identify.cns) {
+                       case NVME_ID_CNS_NS:
+                       case NVME_ID_CNS_CS_NS:
+                       case NVME_ID_CNS_NS_CS_INDEP:
+                               return true;
+                       }
+               }
+               }
                return false;
+       }

Above is without default. And with two defaults, it just gets more
wordy.
And future growth in above admin opcodes is not expected too.

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] nvme: identify-namespace without CAP_SYS_ADMIN
  2022-10-31 13:47         ` Kanchan Joshi
@ 2022-11-01  5:20           ` Chaitanya Kulkarni
  0 siblings, 0 replies; 8+ messages in thread
From: Chaitanya Kulkarni @ 2022-11-01  5:20 UTC (permalink / raw)
  To: Kanchan Joshi; +Cc: linux-nvme, hch, axboe, sagi, kbusch, gost.dev


> Do you think that'll give better looking code?
> I did not write that because it did not seem good fit for the
> situtation. It involved aligning more curly braces:
> -       /* admin commands are not allowed */
> -       if (!ns)
> +       if (!ns) {
> +               switch (opcode) {
> +               case nvme_admin_identify: {
> +                       switch (c->identify.cns) {
> +                       case NVME_ID_CNS_NS:
> +                       case NVME_ID_CNS_CS_NS:
> +                       case NVME_ID_CNS_NS_CS_INDEP:
> +                               return true;
> +                       }
> +               }
> +               }
>                 return false;
> +       }
> 

this is exact pattern we have used in the target when it comes to
nvme_admin_identify handling, so it makes sense to keep the same,
unless there is any strong objection..

> Above is without default. And with two defaults, it just gets more
> wordy.
> And future growth in above admin opcodes is not expected too.
> 

-ck


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2022-11-01  5:21 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20221020071338epcas5p16d72f5d4d868b889e3a98688bc454a98@epcas5p1.samsung.com>
2022-10-20  7:02 ` [PATCH 0/2] Granular CAP_SYS_ADMIN Kanchan Joshi
     [not found]   ` <CGME20221020071343epcas5p3722073ab4822d39d6ca91606869f0379@epcas5p3.samsung.com>
2022-10-20  7:02     ` [PATCH 1/2] nvme: fine-granular CAP_SYS_ADMIN for nvme io commands Kanchan Joshi
     [not found]   ` <CGME20221020071346epcas5p4c3b8da5e60f94947ad570cbd151eb38d@epcas5p4.samsung.com>
2022-10-20  7:02     ` [PATCH 2/2] nvme: identify-namespace without CAP_SYS_ADMIN Kanchan Joshi
2022-10-31  6:55       ` Chaitanya Kulkarni
2022-10-31 13:47         ` Kanchan Joshi
2022-11-01  5:20           ` Chaitanya Kulkarni
2022-10-25 19:43   ` [PATCH 0/2] Granular CAP_SYS_ADMIN Jens Axboe
2022-10-25 20:07   ` Keith Busch

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.