From nobody Thu Apr 9 11:17:56 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C3A7D3939D2; Mon, 9 Mar 2026 11:15:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773054931; cv=none; b=M1S7ZHUX/nT3EjJIroqGft/V/YhcecxfSzzH3Huq7sQO0oUmyy2qp2fzRz1V4S+9C4CfMKujPZkcvQQhx3TSUw6u/7G1Jpud8uaaG69QlUqbMJZxGlss1JwNM6fCByxv3/nObk6ZMkAsSbodmboAMPBKUEkIt560rkhaEEQQRoc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773054931; c=relaxed/simple; bh=PoqZDprkyG97xhHd0xAhB5NUCone+g6NoPGHHatVjlw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=li5SRQR9t8JVP3uFic/HGsaxG8qmS13r0P6taZd/gh1kR2rQoc1gOgclENHyLlqxL8309i/Ue4NCkEIq5AKiyCBOXcbKqM0EAUUGgTcy3LccmfuXWtKBQSAfwIby9L3gpleG4MWy3l9RE5ok+0dwa3yr5JtefghisaY3aH65EPw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UOPvBKEx; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UOPvBKEx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 05C44C2BC9E; Mon, 9 Mar 2026 11:15:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773054931; bh=PoqZDprkyG97xhHd0xAhB5NUCone+g6NoPGHHatVjlw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UOPvBKExj/tOZiQXJCY0WqA337vztYbTXpIv6XkFbKvDgxbn3Us5XcAgKPmIZdzgO PQXKGbwhe3nT0ymhLQZWEvbdghOrMl2myltS2Slk43BMSODmqJgYWlDe3Spb/wuLkH yVVJpauYglzEXR8yoB49+w4VeNeLQQT/FYXOz4yRPTc43alOlGW42TYXTKJYWJ2I7L jkf4C+v35lYIxitbZpdo1tgMlO/ILy4i5xZylCLVilBds71Bb5rxGsFfYgiO5hSL51 X7tNwqHwUeXa4r2G8UIYq+bAAwWr/kSIKHAlEzGEZ2vjGLGB69DGt/8LvpgyydrJkg aKIFdJqk8fxbA== From: Leon Romanovsky To: Paul Moore , James Morris , "Serge E. Hallyn" , Leon Romanovsky , Jason Gunthorpe , Saeed Mahameed , Itay Avraham , Dave Jiang , Jonathan Cameron Cc: linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org, Chiara Meiohas , Maher Sanalla , Edward Srouji Subject: [PATCH 1/3] lsm: add hook for firmware command validation Date: Mon, 9 Mar 2026 13:15:18 +0200 Message-ID: <20260309-fw-lsm-hook-v1-1-4a6422e63725@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260309-fw-lsm-hook-v1-0-4a6422e63725@nvidia.com> References: <20260309-fw-lsm-hook-v1-0-4a6422e63725@nvidia.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" X-Mailer: b4 0.15-dev-18f8f Content-Transfer-Encoding: quoted-printable From: Chiara Meiohas Drivers typically communicate with device firmware either via register-based commands (writing parameters into device registers) or by passing a command buffer using shared-memory mechanisms. This hook targets the command buffer mechanism, which is commonly used on modern, complex devices. Add the LSM hook fw_validate_cmd. This hook allows inspecting firmware command buffers before they are sent to the device. The hook receives the command buffer, device, command class, and a class-specific id: - class_id (enum fw_cmd_class) allows security modules to differentiate between classes of firmware commands. In this series, class_id distinguishes between commands from the RDMA uverbs interface and from fwctl. - id is a class-specific device identifier. For uverbs, id is the RDMA driver identifier (enum rdma_driver_id). For fwctl, id is the device type (enum fwctl_device_type). Signed-off-by: Chiara Meiohas Reviewed-by: Maher Sanalla Signed-off-by: Edward Srouji Signed-off-by: Leon Romanovsky Reviewed-by: Dave Jiang Reviewed-by: Jonathan Cameron --- include/linux/lsm_hook_defs.h | 2 ++ include/linux/security.h | 25 +++++++++++++++++++++++++ security/security.c | 26 ++++++++++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 8c42b4bde09c0..93da090384ea1 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -445,6 +445,8 @@ LSM_HOOK(int, 0, bpf_token_capable, const struct bpf_to= ken *token, int cap) #endif /* CONFIG_BPF_SYSCALL */ =20 LSM_HOOK(int, 0, locked_down, enum lockdown_reason what) +LSM_HOOK(int, 0, fw_validate_cmd, const void *in, size_t in_len, + const struct device *dev, enum fw_cmd_class class_id, u32 id) =20 #ifdef CONFIG_PERF_EVENTS LSM_HOOK(int, 0, perf_event_open, int type) diff --git a/include/linux/security.h b/include/linux/security.h index 83a646d72f6f8..64786d013207a 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -67,6 +67,7 @@ enum fs_value_type; struct watch; struct watch_notification; struct lsm_ctx; +struct device; =20 /* Default (no) options for the capable function */ #define CAP_OPT_NONE 0x0 @@ -157,6 +158,21 @@ enum lockdown_reason { LOCKDOWN_CONFIDENTIALITY_MAX, }; =20 +/* + * enum fw_cmd_class - Class of the firmware command passed to + * security_fw_validate_cmd. + * This allows security modules to distinguish between different command + * classes. + * + * @FW_CMD_CLASS_UVERBS: Command originated from the RDMA uverbs interface + * @FW_CMD_CLASS_FWCTL: Command originated from the fwctl interface + */ +enum fw_cmd_class { + FW_CMD_CLASS_UVERBS, + FW_CMD_CLASS_FWCTL, + FW_CMD_CLASS_MAX, +}; + /* * Data exported by the security modules */ @@ -575,6 +591,9 @@ int security_inode_notifysecctx(struct inode *inode, vo= id *ctx, u32 ctxlen); int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); int security_inode_getsecctx(struct inode *inode, struct lsm_context *cp); int security_locked_down(enum lockdown_reason what); +int security_fw_validate_cmd(const void *in, size_t in_len, + const struct device *dev, + enum fw_cmd_class class_id, u32 id); int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, u32 *uctx_len, void *val, size_t val_len, u64 id, u64 flags); int security_bdev_alloc(struct block_device *bdev); @@ -1589,6 +1608,12 @@ static inline int security_locked_down(enum lockdown= _reason what) { return 0; } +static inline int security_fw_validate_cmd(const void *in, size_t in_len, + const struct device *dev, + enum fw_cmd_class class_id, u32 id) +{ + return 0; +} static inline int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, u32 *uctx_len, void *val, size_t val_len, u64 id, u64 flags) diff --git a/security/security.c b/security/security.c index 67af9228c4e94..d05941fe89a48 100644 --- a/security/security.c +++ b/security/security.c @@ -5373,6 +5373,32 @@ int security_locked_down(enum lockdown_reason what) } EXPORT_SYMBOL(security_locked_down); =20 +/** + * security_fw_validate_cmd() - Validate a firmware command + * @in: pointer to the firmware command input buffer + * @in_len: length of the firmware command input buffer + * @dev: device associated with the command + * @class_id: class of the firmware command + * @id: device identifier, specific to the command @class_id + * + * Check permissions before sending a firmware command generated by + * userspace to the device. + * + * Return: Returns 0 if permission is granted. + */ +int security_fw_validate_cmd(const void *in, size_t in_len, + const struct device *dev, + enum fw_cmd_class class_id, + u32 id) +{ + if (class_id >=3D FW_CMD_CLASS_MAX) + return -EINVAL; + + return call_int_hook(fw_validate_cmd, in, in_len, + dev, class_id, id); +} +EXPORT_SYMBOL_GPL(security_fw_validate_cmd); + /** * security_bdev_alloc() - Allocate a block device LSM blob * @bdev: block device --=20 2.53.0 From nobody Thu Apr 9 11:17:56 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B962339B49B; Mon, 9 Mar 2026 11:15:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773054938; cv=none; b=mV2RxSo8T0JKaQ8whSxnAkD4FCwgPGElHwmUjr9wRfJHSujW9eNesiCnXxk5CVyoonBmDufEHJyWFjISGEz2Z4I1gZ7wuQJNUMaqjscrk3ZFho0nqFRCu/0xxDj5EkTGfsQnfs9uq0An9f/L8SL0eMFX45SjMzWrJRLH3rCL/rA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773054938; c=relaxed/simple; bh=S9SXkqh0jZ7DCmptgsdJJmECrldsV8hZlxHrOWU+6z4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ruMzdpjI4D7K9FWMYmYwswO0i8WvMpeInDivLdNeYkNnooZf/PV1VcMfHQ+l5HS9pDLu+B7FrL2nWIZtgOFAACPNgmEf6vGk7GXh4hQPiyyCSIlJWQVZ/QH2/ZbYYRkregxXiXlIIJREy+FzCKrhJc05gntuEQfHEVlRQ1Vfe/s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Cd4Qu2Qq; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Cd4Qu2Qq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 33B29C2BC9E; Mon, 9 Mar 2026 11:15:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773054938; bh=S9SXkqh0jZ7DCmptgsdJJmECrldsV8hZlxHrOWU+6z4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Cd4Qu2QqjEqBHUxJwEfd4MdQNLC916btCHsFgwudmCHTwOhxr7WM2kbIW9CHHb7Pf 8y6IuTYcP5J6f6F9sT5ZPzqfyhUZ5ZLsOMML00bJSHkFcbIRzXamIs87K3o1cBf43Y D8NUmZ+4H4p046FUix3j90wLBQUAbdwuS1TsLPf1MmKXekjZJ6Vie6htBDgGTBgtRl OsX+y5jep5QB7IOUPorCfVCCwCuIO7/RB1XIggsjVJCxl28VxoFOrDzU1dMVbebVj7 7ENNt+j/+0/N7faguaNaPHBORK19rAOS0/hVgO/SidOlbvfuJ569yJU9Ks7wYjM1nz RvpkDSd+YDhYw== From: Leon Romanovsky To: Paul Moore , James Morris , "Serge E. Hallyn" , Leon Romanovsky , Jason Gunthorpe , Saeed Mahameed , Itay Avraham , Dave Jiang , Jonathan Cameron Cc: linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org, Chiara Meiohas , Maher Sanalla , Edward Srouji Subject: [PATCH 2/3] RDMA/mlx5: Invoke fw_validate_cmd LSM hook for DEVX commands Date: Mon, 9 Mar 2026 13:15:19 +0200 Message-ID: <20260309-fw-lsm-hook-v1-2-4a6422e63725@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260309-fw-lsm-hook-v1-0-4a6422e63725@nvidia.com> References: <20260309-fw-lsm-hook-v1-0-4a6422e63725@nvidia.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" X-Mailer: b4 0.15-dev-18f8f Content-Transfer-Encoding: quoted-printable From: Chiara Meiohas DEVX is an RDMA uverbs extension that allows userspace to submit firmware command buffers. The driver inspects the command and then passes the buffer through for firmware execution. Call security_fw_validate_cmd() before dispatching firmware commands through DEVX. This allows security modules to implement custom policies and enforce per-command security policy on user-triggered firmware commands. For example, a BPF LSM program could restrict specific firmware operations to privileged users. Signed-off-by: Chiara Meiohas Reviewed-by: Maher Sanalla Signed-off-by: Edward Srouji Signed-off-by: Leon Romanovsky Reviewed-by: Dave Jiang Reviewed-by: Jonathan Cameron --- drivers/infiniband/hw/mlx5/devx.c | 52 ++++++++++++++++++++++++++++++-----= ---- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5= /devx.c index 0066b2738ac89..48a2c4b4ad4eb 100644 --- a/drivers/infiniband/hw/mlx5/devx.c +++ b/drivers/infiniband/hw/mlx5/devx.c @@ -18,6 +18,7 @@ #include "devx.h" #include "qp.h" #include +#include =20 #define UVERBS_MODULE_NAME mlx5_ib #include @@ -1111,6 +1112,8 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)( struct mlx5_ib_dev *dev; void *cmd_in =3D uverbs_attr_get_alloced_ptr( attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN); + int cmd_in_len =3D uverbs_attr_get_len(attrs, + MLX5_IB_ATTR_DEVX_OTHER_CMD_IN); int cmd_out_len =3D uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT); void *cmd_out; @@ -1135,9 +1138,12 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)( return PTR_ERR(cmd_out); =20 MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); - err =3D mlx5_cmd_do(dev->mdev, cmd_in, - uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN), - cmd_out, cmd_out_len); + err =3D security_fw_validate_cmd(cmd_in, cmd_in_len, &dev->ib_dev.dev, + FW_CMD_CLASS_UVERBS, RDMA_DRIVER_MLX5); + if (err) + return err; + + err =3D mlx5_cmd_do(dev->mdev, cmd_in, cmd_in_len, cmd_out, cmd_out_len); if (err && err !=3D -EREMOTEIO) return err; =20 @@ -1570,6 +1576,12 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CR= EATE)( devx_set_umem_valid(cmd_in); } =20 + err =3D security_fw_validate_cmd(cmd_in, cmd_in_len, + &dev->ib_dev.dev, + FW_CMD_CLASS_UVERBS, RDMA_DRIVER_MLX5); + if (err) + goto obj_free; + if (opcode =3D=3D MLX5_CMD_OP_CREATE_DCT) { obj->flags |=3D DEVX_OBJ_FLAGS_DCT; err =3D mlx5_core_create_dct(dev, &obj->core_dct, cmd_in, @@ -1582,8 +1594,8 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CRE= ATE)( cmd_in, cmd_in_len, cmd_out, cmd_out_len); } else { - err =3D mlx5_cmd_do(dev->mdev, cmd_in, cmd_in_len, - cmd_out, cmd_out_len); + err =3D mlx5_cmd_do(dev->mdev, cmd_in, cmd_in_len, cmd_out, + cmd_out_len); } =20 if (err =3D=3D -EREMOTEIO) @@ -1646,6 +1658,8 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MOD= IFY)( struct uverbs_attr_bundle *attrs) { void *cmd_in =3D uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ= _MODIFY_CMD_IN); + int cmd_in_len =3D uverbs_attr_get_len(attrs, + MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN); int cmd_out_len =3D uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT); struct ib_uobject *uobj =3D uverbs_attr_get_uobject(attrs, @@ -1676,9 +1690,12 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MO= DIFY)( =20 MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); devx_set_umem_valid(cmd_in); + err =3D security_fw_validate_cmd(cmd_in, cmd_in_len, &mdev->ib_dev.dev, + FW_CMD_CLASS_UVERBS, RDMA_DRIVER_MLX5); + if (err) + return err; =20 - err =3D mlx5_cmd_do(mdev->mdev, cmd_in, - uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN), + err =3D mlx5_cmd_do(mdev->mdev, cmd_in, cmd_in_len, cmd_out, cmd_out_len); if (err && err !=3D -EREMOTEIO) return err; @@ -1693,6 +1710,8 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUE= RY)( struct uverbs_attr_bundle *attrs) { void *cmd_in =3D uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ= _QUERY_CMD_IN); + int cmd_in_len =3D uverbs_attr_get_len(attrs, + MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN); int cmd_out_len =3D uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT); struct ib_uobject *uobj =3D uverbs_attr_get_uobject(attrs, @@ -1722,8 +1741,12 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QU= ERY)( return PTR_ERR(cmd_out); =20 MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); - err =3D mlx5_cmd_do(mdev->mdev, cmd_in, - uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN), + err =3D security_fw_validate_cmd(cmd_in, cmd_in_len, &mdev->ib_dev.dev, + FW_CMD_CLASS_UVERBS, RDMA_DRIVER_MLX5); + if (err) + return err; + + err =3D mlx5_cmd_do(mdev->mdev, cmd_in, cmd_in_len, cmd_out, cmd_out_len); if (err && err !=3D -EREMOTEIO) return err; @@ -1832,6 +1855,8 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_ASY= NC_QUERY)( { void *cmd_in =3D uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN); + int cmd_in_len =3D uverbs_attr_get_len(attrs, + MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN); struct ib_uobject *uobj =3D uverbs_attr_get_uobject( attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_HANDLE); @@ -1894,9 +1919,12 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_AS= YNC_QUERY)( async_data->ev_file =3D ev_file; =20 MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, uid); - err =3D mlx5_cmd_exec_cb(&ev_file->async_ctx, cmd_in, - uverbs_attr_get_len(attrs, - MLX5_IB_ATTR_DEVX_OBJ_QUERY_ASYNC_CMD_IN), + err =3D security_fw_validate_cmd(cmd_in, cmd_in_len, &mdev->ib_dev.dev, + FW_CMD_CLASS_UVERBS, RDMA_DRIVER_MLX5); + if (err) + goto free_async; + + err =3D mlx5_cmd_exec_cb(&ev_file->async_ctx, cmd_in, cmd_in_len, async_data->hdr.out_data, async_data->cmd_out_len, devx_query_callback, &async_data->cb_work); --=20 2.53.0 From nobody Thu Apr 9 11:17:56 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B285639A05B; Mon, 9 Mar 2026 11:15:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773054935; cv=none; b=AWbSlEec0OiLHoPjrc0AdUbDCouOMu03f8q2svVpQpVNl6hlqVzOa4GqX45FGKdj8or/gO62Z645wvn27tepBj7x0RM9uBF5rUne98xPRV2p2jaPKK9L4C4RgtkJsme4u6j3Q5xjNuaAbyJsmXNKJ+Fn74cRNgMG49j6W4BXoRg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773054935; c=relaxed/simple; bh=YZqrFAi+xx1WasdQBcrBtpQgQLl0zbLLz0lMnsGCHt8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dWX2SAwnERPgqFYkauvcS0WX49dlSOyMUVDgwJXtv2JTs1cGfUjaFxlRt8iWxAP+C8PuAR4jOmeIVeA+yeHQX6GGoJvA6sSB7W80BoLdP0i06lyVShVmGygbJ2+jvN9wNcjIgM6qLteKzWVlTRBNDywZl+262kFEt5J9aDrOqWE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nCkqRQ/k; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="nCkqRQ/k" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B8F5EC4CEF7; Mon, 9 Mar 2026 11:15:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773054935; bh=YZqrFAi+xx1WasdQBcrBtpQgQLl0zbLLz0lMnsGCHt8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nCkqRQ/kDYnasY1FUbbys375EBYRCVztdy70T7qjDndxTBBSy3Z26gZOFIVm+0MrS OphQZjvAtzLYKW+PmwWHOuD0sQjwTZwkdqyLPkZJF88KSZ/4EeOeC/gBGFOdLRtdRP nao9/KeoIZnSDNOPssFj6WwGOA+0VbyHsDLCeXrCbDyXJA6Fn0n1QDNo7Q6A38XyoA HqsV94Pyk15yuYIDwnh6mvA1ejGppYXCZGPrUV3ImVYfFy623kgIW3qowWBW58/Y5a wUpSjDEMnPKCDT6H5BgI7o5nhBUw33K2xT1rGfmeHeXprgQjUjth9w8Yrkav/XFU4S 4a/hsEr9qo2Zw== From: Leon Romanovsky To: Paul Moore , James Morris , "Serge E. Hallyn" , Leon Romanovsky , Jason Gunthorpe , Saeed Mahameed , Itay Avraham , Dave Jiang , Jonathan Cameron Cc: linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org, Chiara Meiohas , Maher Sanalla , Edward Srouji Subject: [PATCH 3/3] fwctl/mlx5: Invoke fw_validate_cmd LSM hook for fwctl commands Date: Mon, 9 Mar 2026 13:15:20 +0200 Message-ID: <20260309-fw-lsm-hook-v1-3-4a6422e63725@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260309-fw-lsm-hook-v1-0-4a6422e63725@nvidia.com> References: <20260309-fw-lsm-hook-v1-0-4a6422e63725@nvidia.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" X-Mailer: b4 0.15-dev-18f8f Content-Transfer-Encoding: quoted-printable From: Chiara Meiohas fwctl is subsystem which exposes a firmware interface directly to userspace: it allows userspace to send device specific command buffers to firmware. Call security_fw_validate_cmd() before dispatching the user-provided firmware command. This allows security modules to implement custom policies and enforce per-command security policy on user-triggered firmware commands. For example, a BPF LSM program could filter firmware commands based on their opcode. Signed-off-by: Chiara Meiohas Reviewed-by: Maher Sanalla Signed-off-by: Edward Srouji Signed-off-by: Leon Romanovsky Reviewed-by: Dave Jiang Reviewed-by: Jonathan Cameron --- drivers/fwctl/mlx5/main.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/fwctl/mlx5/main.c b/drivers/fwctl/mlx5/main.c index e86ab703c767a..8ed17aaf48f1f 100644 --- a/drivers/fwctl/mlx5/main.c +++ b/drivers/fwctl/mlx5/main.c @@ -7,6 +7,7 @@ #include #include #include +#include =20 #define mlx5ctl_err(mcdev, format, ...) \ dev_err(&mcdev->fwctl.dev, format, ##__VA_ARGS__) @@ -324,6 +325,15 @@ static void *mlx5ctl_fw_rpc(struct fwctl_uctx *uctx, e= num fwctl_rpc_scope scope, if (!mlx5ctl_validate_rpc(rpc_in, scope)) return ERR_PTR(-EBADMSG); =20 + /* Enforce the user context for the command */ + MLX5_SET(mbox_in_hdr, rpc_in, uid, mfd->uctx_uid); + + ret =3D security_fw_validate_cmd(rpc_in, in_len, &mcdev->fwctl.dev, + FW_CMD_CLASS_FWCTL, + FWCTL_DEVICE_TYPE_MLX5); + if (ret) + return ERR_PTR(ret); + /* * mlx5_cmd_do() copies the input message to its own buffer before * executing it, so we can reuse the allocation for the output. @@ -336,8 +346,6 @@ static void *mlx5ctl_fw_rpc(struct fwctl_uctx *uctx, en= um fwctl_rpc_scope scope, return ERR_PTR(-ENOMEM); } =20 - /* Enforce the user context for the command */ - MLX5_SET(mbox_in_hdr, rpc_in, uid, mfd->uctx_uid); ret =3D mlx5_cmd_do(mcdev->mdev, rpc_in, in_len, rpc_out, *out_len); =20 mlx5ctl_dbg(mcdev, --=20 2.53.0