From 675edd5053be6db6303b0eadcfe2606bfc473af8 Mon Sep 17 00:00:00 2001 From: Sagar Kamble Date: Sun, 9 Oct 2022 19:03:51 +0530 Subject: [PATCH] gpu: nvgpu: maintain authorized devices in TSG When the TSG is successfully created first time or is opened with share token, the device instance id associated with the CTRL fd will be added to the TSG private data structure as authorized device instance ids. This is used for a security check when creating a TSG share token with nvgpu_tsg_get_share_token. Bug 3677982 JIRA NVGPU-8681 Change-Id: I67bb0514e1272dab15023cd3828a6a51e9a4c928 Signed-off-by: Sagar Kamble Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2792080 Reviewed-by: svcacv Reviewed-by: svc-mobile-coverity Reviewed-by: svc-mobile-cert Reviewed-by: svc-mobile-misra Reviewed-by: Scott Long Reviewed-by: Vijayakumar Subbu GVS: Gerrit_Virtual_Submit --- drivers/gpu/nvgpu/common/fifo/tsg.c | 7 +++ drivers/gpu/nvgpu/include/nvgpu/tsg.h | 20 ++++++ drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c | 13 +++- drivers/gpu/nvgpu/os/linux/ioctl_ctrl.h | 8 ++- drivers/gpu/nvgpu/os/linux/ioctl_tsg.c | 82 ++++++++++++++++++++++++- drivers/gpu/nvgpu/os/linux/ioctl_tsg.h | 6 +- 6 files changed, 127 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/nvgpu/common/fifo/tsg.c b/drivers/gpu/nvgpu/common/fifo/tsg.c index 31719f365..86c23c02f 100644 --- a/drivers/gpu/nvgpu/common/fifo/tsg.c +++ b/drivers/gpu/nvgpu/common/fifo/tsg.c @@ -839,6 +839,9 @@ static void nvgpu_tsg_destroy(struct nvgpu_tsg *tsg) { #ifdef CONFIG_NVGPU_CHANNEL_TSG_CONTROL nvgpu_mutex_destroy(&tsg->event_id_list_lock); +#endif +#ifdef CONFIG_NVGPU_TSG_SHARING + nvgpu_mutex_destroy(&tsg->tsg_share_lock); #endif nvgpu_mutex_destroy(&tsg->ctx_init_lock); nvgpu_mutex_destroy(&tsg->veid_alloc_lock); @@ -902,6 +905,10 @@ static void nvgpu_tsg_init_support(struct gk20a *g, u32 tsgid) nvgpu_init_list_node(&tsg->event_id_list); nvgpu_mutex_init(&tsg->event_id_list_lock); #endif +#ifdef CONFIG_NVGPU_TSG_SHARING + nvgpu_init_list_node(&tsg->ctrl_devices_list); + nvgpu_mutex_init(&tsg->tsg_share_lock); +#endif } int nvgpu_tsg_setup_sw(struct gk20a *g) diff --git a/drivers/gpu/nvgpu/include/nvgpu/tsg.h b/drivers/gpu/nvgpu/include/nvgpu/tsg.h index 69c7d5140..4402e04e4 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/tsg.h +++ b/drivers/gpu/nvgpu/include/nvgpu/tsg.h @@ -169,6 +169,19 @@ struct nvgpu_tsg { */ struct nvgpu_mutex event_id_list_lock; #endif + +#ifdef CONFIG_NVGPU_TSG_SHARING + /** + * List of devices sharing this TSG (Opened TSG directly or through + * share token). + */ + struct nvgpu_list_node ctrl_devices_list; + /** + * Mutex used to access/modify #ctrl_devices_list. + */ + struct nvgpu_mutex tsg_share_lock; +#endif + /** * Read write type of semaphore lock used for accessing/modifying * #ch_list, #subctx_list and #ch_list in #nvgpu_tsg_subctx. @@ -275,6 +288,13 @@ struct nvgpu_tsg { #endif }; +#ifdef CONFIG_NVGPU_TSG_SHARING +struct nvgpu_tsg_ctrl_dev_node { + u64 device_instance_id; + struct nvgpu_list_node tsg_entry; +}; +#endif + /** * @brief Allocate subcontext VEID within a TSG. * diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c index 429538d14..c146169d0 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c @@ -705,7 +705,7 @@ clean_up: return err; } -static int gk20a_ctrl_open_tsg(struct gk20a *g, struct nvgpu_cdev *cdev, +static int gk20a_ctrl_open_tsg(struct gk20a *g, struct gk20a_ctrl_priv *priv, struct nvgpu_gpu_open_tsg_args *args) { int err; @@ -726,7 +726,7 @@ static int gk20a_ctrl_open_tsg(struct gk20a *g, struct nvgpu_cdev *cdev, goto clean_up; } - err = nvgpu_ioctl_tsg_open(g, cdev, file); + err = nvgpu_ioctl_tsg_open(g, priv, priv->cdev, file); if (err) goto clean_up_file; @@ -2450,7 +2450,7 @@ long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg (struct nvgpu_alloc_as_args *)buf); break; case NVGPU_GPU_IOCTL_OPEN_TSG: - err = gk20a_ctrl_open_tsg(g, priv->cdev, + err = gk20a_ctrl_open_tsg(g, priv, (struct nvgpu_gpu_open_tsg_args *)buf); break; case NVGPU_GPU_IOCTL_GET_TPC_MASKS: @@ -2798,3 +2798,10 @@ void nvgpu_restore_usermode_for_poweron(struct gk20a *g) { alter_usermode_mappings(g, false); } + +#ifdef CONFIG_NVGPU_TSG_SHARING +u64 nvgpu_gpu_get_device_instance_id(struct gk20a_ctrl_priv *priv) +{ + return priv ? priv->device_instance_id : 0ULL; +} +#endif diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.h b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.h index 3e1f798bf..bef7ab51e 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.h +++ b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011-2022, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -16,6 +16,8 @@ #ifndef __NVGPU_IOCTL_CTRL_H__ #define __NVGPU_IOCTL_CTRL_H__ +struct gk20a_ctrl_priv; + int gk20a_ctrl_dev_open(struct inode *inode, struct file *filp); int gk20a_ctrl_dev_release(struct inode *inode, struct file *filp); long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); @@ -24,4 +26,8 @@ int gk20a_ctrl_dev_mmap(struct file *filp, struct vm_area_struct *vma); void nvgpu_hide_usermode_for_poweroff(struct gk20a *g); void nvgpu_restore_usermode_for_poweron(struct gk20a *g); +#ifdef CONFIG_NVGPU_TSG_SHARING +u64 nvgpu_gpu_get_device_instance_id(struct gk20a_ctrl_priv *priv); +#endif + #endif diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_tsg.c b/drivers/gpu/nvgpu/os/linux/ioctl_tsg.c index 8085eb359..842f86de3 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_tsg.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_tsg.c @@ -39,6 +39,7 @@ #include #include "platform_gk20a.h" +#include "ioctl_ctrl.h" #include "ioctl_tsg.h" #include "ioctl_as.h" #include "ioctl_channel.h" @@ -50,6 +51,7 @@ struct tsg_private { struct gk20a *g; struct nvgpu_tsg *tsg; struct nvgpu_cdev *cdev; + struct gk20a_ctrl_priv *ctrl_priv; }; extern const struct file_operations gk20a_tsg_ops; @@ -450,8 +452,66 @@ static int gk20a_tsg_event_id_ctrl(struct gk20a *g, struct nvgpu_tsg *tsg, } #endif /* CONFIG_NVGPU_CHANNEL_TSG_CONTROL */ -int nvgpu_ioctl_tsg_open(struct gk20a *g, struct nvgpu_cdev *cdev, - struct file *filp) +#ifdef CONFIG_NVGPU_TSG_SHARING +static inline struct nvgpu_tsg_ctrl_dev_node * +nvgpu_tsg_ctrl_dev_node_from_tsg_entry(struct nvgpu_list_node *node) +{ + return (struct nvgpu_tsg_ctrl_dev_node *) + ((uintptr_t)node - offsetof(struct nvgpu_tsg_ctrl_dev_node, tsg_entry)); +}; + +static void nvgpu_tsg_remove_ctrl_dev_inst_id(struct nvgpu_tsg *tsg, + struct gk20a_ctrl_priv *ctrl_priv) +{ + struct nvgpu_tsg_ctrl_dev_node *node, *tmp; + struct gk20a *g = tsg->g; + + nvgpu_mutex_acquire(&tsg->tsg_share_lock); + + nvgpu_list_for_each_entry_safe(node, tmp, &tsg->ctrl_devices_list, + nvgpu_tsg_ctrl_dev_node, tsg_entry) { + if (node->device_instance_id == + nvgpu_gpu_get_device_instance_id(ctrl_priv)) { + nvgpu_log_info(g, "removing ctrl dev id %llx", + nvgpu_gpu_get_device_instance_id(ctrl_priv)); + nvgpu_list_del(&node->tsg_entry); + nvgpu_kfree(g, node); + } + } + + nvgpu_mutex_release(&tsg->tsg_share_lock); +} + +static int nvgpu_tsg_add_ctrl_dev_inst_id(struct nvgpu_tsg *tsg, + struct gk20a_ctrl_priv *ctrl_priv) +{ + struct nvgpu_tsg_ctrl_dev_node *ctrl_dev_node; + struct gk20a *g = tsg->g; + + ctrl_dev_node = (struct nvgpu_tsg_ctrl_dev_node *) nvgpu_kzalloc(g, + sizeof(struct nvgpu_tsg_ctrl_dev_node)); + if (ctrl_dev_node == NULL) { + nvgpu_err(g, "ctrl_dev_node alloc failed"); + return -ENOMEM; + } + + nvgpu_init_list_node(&ctrl_dev_node->tsg_entry); + ctrl_dev_node->device_instance_id = + nvgpu_gpu_get_device_instance_id(ctrl_priv); + + nvgpu_mutex_acquire(&tsg->tsg_share_lock); + nvgpu_list_add_tail(&ctrl_dev_node->tsg_entry, &tsg->ctrl_devices_list); + nvgpu_mutex_release(&tsg->tsg_share_lock); + + nvgpu_log_info(g, "added ctrl dev id %llx", + nvgpu_gpu_get_device_instance_id(ctrl_priv)); + + return 0; +} +#endif + +int nvgpu_ioctl_tsg_open(struct gk20a *g, struct gk20a_ctrl_priv *ctrl_priv, + struct nvgpu_cdev *cdev, struct file *filp) { struct tsg_private *priv; struct nvgpu_tsg *tsg; @@ -485,9 +545,21 @@ int nvgpu_ioctl_tsg_open(struct gk20a *g, struct nvgpu_cdev *cdev, goto free_mem; } +#ifdef CONFIG_NVGPU_TSG_SHARING + if (ctrl_priv != NULL) { + err = nvgpu_tsg_add_ctrl_dev_inst_id(tsg, ctrl_priv); + if (err != 0) { + nvgpu_err(g, "add ctrl dev failed %d", err); + nvgpu_ref_put(&tsg->refcount, nvgpu_tsg_release); + goto free_mem; + } + } +#endif + priv->g = g; priv->tsg = tsg; priv->cdev = cdev; + priv->ctrl_priv = ctrl_priv; filp->private_data = priv; gk20a_sched_ctrl_tsg_added(g, tsg); @@ -518,7 +590,7 @@ int nvgpu_ioctl_tsg_dev_open(struct inode *inode, struct file *filp) return ret; } - ret = nvgpu_ioctl_tsg_open(g, cdev, filp); + ret = nvgpu_ioctl_tsg_open(g, NULL, cdev, filp); gk20a_idle(g); nvgpu_log_fn(g, "done"); @@ -548,6 +620,10 @@ int nvgpu_ioctl_tsg_dev_release(struct inode *inode, struct file *filp) tsg = priv->tsg; +#ifdef CONFIG_NVGPU_TSG_SHARING + nvgpu_tsg_remove_ctrl_dev_inst_id(tsg, priv->ctrl_priv); +#endif + nvgpu_ref_put(&tsg->refcount, nvgpu_ioctl_tsg_release); nvgpu_kfree(tsg->g, priv); return 0; diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_tsg.h b/drivers/gpu/nvgpu/os/linux/ioctl_tsg.h index c0b0f173f..341d70c77 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_tsg.h +++ b/drivers/gpu/nvgpu/os/linux/ioctl_tsg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2022, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -18,12 +18,14 @@ struct file; struct gk20a; struct nvgpu_ref; struct nvgpu_cdev; +struct gk20a_ctrl_priv; struct nvgpu_tsg *nvgpu_tsg_get_from_file(int fd); int nvgpu_ioctl_tsg_dev_release(struct inode *inode, struct file *filp); int nvgpu_ioctl_tsg_dev_open(struct inode *inode, struct file *filp); -int nvgpu_ioctl_tsg_open(struct gk20a *g, struct nvgpu_cdev *cdev, struct file *filp); +int nvgpu_ioctl_tsg_open(struct gk20a *g, struct gk20a_ctrl_priv *ctrl_priv, + struct nvgpu_cdev *cdev, struct file *filp); long nvgpu_ioctl_tsg_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); void nvgpu_ioctl_tsg_release(struct nvgpu_ref *ref);