From: Iouri Tarassov <[email protected]>

D3DKMTEnumProcesses is used to enumerate PIDs for all processes,
which opened the /dev/dxg device.

Signed-off-by: Iouri Tarassov <[email protected]>
[kms: forward port to 6.6 from 6.1. No code changes made.]
Signed-off-by: Kelsey Steele <[email protected]>
---
 drivers/hv/dxgkrnl/dxgkrnl.h    |  1 +
 drivers/hv/dxgkrnl/dxgprocess.c |  2 +
 drivers/hv/dxgkrnl/ioctl.c      | 81 +++++++++++++++++++++++++++++++++
 include/uapi/misc/d3dkmthk.h    | 12 +++++
 4 files changed, 96 insertions(+)

diff --git a/drivers/hv/dxgkrnl/dxgkrnl.h b/drivers/hv/dxgkrnl/dxgkrnl.h
index 6af1e59b0a31..90bcd5377744 100644
--- a/drivers/hv/dxgkrnl/dxgkrnl.h
+++ b/drivers/hv/dxgkrnl/dxgkrnl.h
@@ -387,6 +387,7 @@ struct dxgprocess {
        pid_t                   pid;
        pid_t                   tgid;
        pid_t                   vpid; /* pdi from the current namespace */
+       struct pid_namespace    *nspid; /* namespace id */
        /* how many time the process was opened */
        struct kref             process_kref;
        /* protects the object memory */
diff --git a/drivers/hv/dxgkrnl/dxgprocess.c b/drivers/hv/dxgkrnl/dxgprocess.c
index 5a4c4cb0c2e8..9bfd53df1a54 100644
--- a/drivers/hv/dxgkrnl/dxgprocess.c
+++ b/drivers/hv/dxgkrnl/dxgprocess.c
@@ -13,6 +13,7 @@
 
 #include "dxgkrnl.h"
 #include "linux/sched.h"
+#include <linux/pid_namespace.h>
 
 #undef dev_fmt
 #define dev_fmt(fmt)   "dxgk: " fmt
@@ -33,6 +34,7 @@ struct dxgprocess *dxgprocess_create(void)
                process->pid = current->pid;
                process->tgid = current->tgid;
                process->vpid = task_pid_vnr(current);
+               process->nspid = task_active_pid_ns(current);
                ret = dxgvmb_send_create_process(process);
                if (ret < 0) {
                        DXG_TRACE("send_create_process failed");
diff --git a/drivers/hv/dxgkrnl/ioctl.c b/drivers/hv/dxgkrnl/ioctl.c
index 466bef6c14b3..24b84be2fb73 100644
--- a/drivers/hv/dxgkrnl/ioctl.c
+++ b/drivers/hv/dxgkrnl/ioctl.c
@@ -16,6 +16,7 @@
 #include <linux/fs.h>
 #include <linux/anon_inodes.h>
 #include <linux/mman.h>
+#include <linux/pid_namespace.h>
 
 #include "dxgkrnl.h"
 #include "dxgvmbus.h"
@@ -5238,6 +5239,85 @@ dxgkio_share_object_with_host(struct dxgprocess 
*process, void *__user inargs)
        return ret;
 }
 
+static int
+dxgkio_enum_processes(struct dxgprocess *process, void *__user inargs)
+{
+       struct d3dkmt_enumprocesses args;
+       struct d3dkmt_enumprocesses *__user input = inargs;
+       struct dxgadapter *adapter = NULL;
+       struct dxgadapter *entry;
+       struct dxgglobal *dxgglobal = dxggbl();
+       struct dxgprocess_adapter *pentry;
+       int nump = 0;   /* Current number of processes*/
+       struct ntstatus status;
+       int ret;
+
+       ret = copy_from_user(&args, inargs, sizeof(args));
+       if (ret) {
+               DXG_ERR("failed to copy input args");
+               ret = -EFAULT;
+               goto cleanup;
+       }
+
+       if (args.buffer_count == 0) {
+               DXG_ERR("Invalid buffer count");
+               ret = -EINVAL;
+               goto cleanup;
+       }
+
+       dxgglobal_acquire_adapter_list_lock(DXGLOCK_SHARED);
+       dxgglobal_acquire_process_adapter_lock();
+
+       list_for_each_entry(entry, &dxgglobal->adapter_list_head,
+                           adapter_list_entry) {
+               if (*(u64 *) &entry->luid == *(u64 *) &args.adapter_luid) {
+                       adapter = entry;
+                       break;
+               }
+       }
+
+       if (adapter == NULL) {
+               DXG_ERR("Failed to find dxgadapter");
+               ret = -EINVAL;
+               goto cleanup_locks;
+       }
+
+       list_for_each_entry(pentry, &adapter->adapter_process_list_head,
+                           adapter_process_list_entry) {
+               if (pentry->process->nspid != task_active_pid_ns(current))
+                       continue;
+               if (nump == args.buffer_count) {
+                       status.v = STATUS_BUFFER_TOO_SMALL;
+                       ret = ntstatus2int(status);
+                       goto cleanup_locks;
+               }
+               ret = copy_to_user(&args.buffer[nump], &pentry->process->vpid,
+                                  sizeof(u32));
+               if (ret) {
+                       DXG_ERR("failed to copy data to user");
+                       ret = -EFAULT;
+                       goto cleanup_locks;
+               }
+               nump++;
+       }
+
+cleanup_locks:
+
+       dxgglobal_release_process_adapter_lock();
+       dxgglobal_release_adapter_list_lock(DXGLOCK_SHARED);
+
+       if (ret == 0) {
+               ret = copy_to_user(&input->buffer_count, &nump, sizeof(u32));
+               if (ret)
+                       DXG_ERR("failed to copy buffer count to user");
+       }
+
+cleanup:
+
+       DXG_TRACE_IOCTL_END(ret);
+       return ret;
+}
+
 static struct ioctl_desc ioctls[] = {
 /* 0x00 */     {},
 /* 0x01 */     {dxgkio_open_adapter_from_luid, LX_DXOPENADAPTERFROMLUID},
@@ -5325,6 +5405,7 @@ static struct ioctl_desc ioctls[] = {
 /* 0x46 */     {dxgkio_wait_sync_file, LX_DXWAITSYNCFILE},
 /* 0x47 */     {dxgkio_open_syncobj_from_syncfile,
                 LX_DXOPENSYNCOBJECTFROMSYNCFILE},
+/* 0x48 */     {dxgkio_enum_processes, LX_DXENUMPROCESSES},
 };
 
 /*
diff --git a/include/uapi/misc/d3dkmthk.h b/include/uapi/misc/d3dkmthk.h
index 84fa07a46d3c..f9f817060fa9 100644
--- a/include/uapi/misc/d3dkmthk.h
+++ b/include/uapi/misc/d3dkmthk.h
@@ -1580,6 +1580,16 @@ struct d3dkmt_opensyncobjectfromsyncfile {
        __u64                   fence_value_gpu_va;     /* out */
 };
 
+ struct d3dkmt_enumprocesses {
+       struct winluid          adapter_luid;
+#ifdef __KERNEL__
+       __u32                   *buffer;
+#else
+       __u64                   buffer;
+#endif
+       __u64                   buffer_count;
+};
+
 struct d3dkmt_invalidatecache {
        struct d3dkmthandle     device;
        struct d3dkmthandle     allocation;
@@ -1718,5 +1728,7 @@ struct d3dkmt_invalidatecache {
        _IOWR(0x47, 0x46, struct d3dkmt_waitsyncfile)
 #define LX_DXOPENSYNCOBJECTFROMSYNCFILE        \
        _IOWR(0x47, 0x47, struct d3dkmt_opensyncobjectfromsyncfile)
+#define LX_DXENUMPROCESSES     \
+       _IOWR(0x47, 0x48, struct d3dkmt_enumprocesses)
 
 #endif /* _D3DKMTHK_H */

Reply via email to