[PATCH for-next 2/2] nvme: Make CAP_SYS_ADMIN fine-granular

Chaitanya Kulkarni chaitanyak at nvidia.com
Mon Sep 26 15:30:14 PDT 2022


On 9/26/22 07:54, Kanchan Joshi wrote:
> Change all the callers of CAP_SYS_ADMIN to go through nvme_cmd_allowed
> for any decision making.
> Since file open mode is taken into consideration for any
> approval/denial, change at various places to keep file-mode information
> handy.
> 
> Signed-off-by: Kanchan Joshi <joshi.k at samsung.com>
> ---
>   drivers/nvme/host/ioctl.c | 70 +++++++++++++++++++++------------------
>   1 file changed, 38 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
> index 6ca6477dd899..4e53a01e702d 100644
> --- a/drivers/nvme/host/ioctl.c
> +++ b/drivers/nvme/host/ioctl.c
> @@ -259,7 +259,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;
> @@ -267,10 +267,10 @@ 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 (!nvme_cmd_allowed(ns, cmd.opcode, mode))
> +		return -EACCES;

you are chaning the order of the check CAP_SYS_ADMIN, unless there is a
specific reason for it (that is not listed in the commit log) move
nvme_cmd_allowed() where CAP_SYS_ADMIN is to retain the original
behaviour which seems right since you are avoiding kernel copy in case
cmds are not allowed.

>   	if (cmd.flags)
>   		return -EINVAL;
>   	if (!nvme_validate_passthru_nsid(ctrl, ns, cmd.nsid))
> @@ -306,17 +306,18 @@ 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 (!nvme_cmd_allowed(ns, cmd.opcode, mode))
> +		return -EACCES;

same as above.

>   	if (cmd.flags)
>   		return -EINVAL;
>   	if (!nvme_validate_passthru_nsid(ctrl, ns, cmd.nsid))
> @@ -438,14 +439,14 @@ static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
>   	blk_mq_req_flags_t blk_flags = 0;
>   	void *meta = NULL;
>   
> -	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)
>   		return -EINVAL;
>   
> +	if (!nvme_cmd_allowed(ns, c.common.opcode, ioucmd->file->f_mode))
> +		return -EACCES;
> +

same as above, why initialize c.common.xxx if cmd is not allowed.

>   	c.common.command_id = 0;
>   	c.common.nsid = cpu_to_le32(cmd->nsid);
>   	if (!nvme_validate_passthru_nsid(ctrl, ns, le32_to_cpu(c.common.nsid)))
> @@ -517,13 +518,13 @@ static bool is_ctrl_ioctl(unsigned int cmd)
>   }
>   

-ck






More information about the Linux-nvme mailing list