]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amdkfd: Let driver decide buffer size at AMDKFD_IOC_GET_DMABUF_INFO ioctl
authorXiaogang Chen <xiaogang.chen@amd.com>
Wed, 27 May 2026 03:50:02 +0000 (22:50 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 17 Jun 2026 22:24:38 +0000 (18:24 -0400)
amdkfd driver needs allocate buffer to return bo metadata to user space. The
buffer size is controlled by user currently. It is a potential security issue
that hostile value (e.g. 2 GiB) lets any render-group user trigger order-MAX
allocation/OOM in kernel context.

This patch first finds bo metadata size. If the size is smaller than user
provided value drive can safely allocate buffer in kernel space and copy to
user space buffer. If not, driver will let user know, not allocate and copy.
User will redo with new buffer in user space.

This patch lets driver decide buffer allocation size to avoid potential hostile
size from user space.

Signed-off-by: Xiaogang Chen <xiaogang.chen@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit f54ce9e8cbd3abe0eda3a285f54dc4f572fe589a)

drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c

index 9783a3cefb04b0c2dc75c419a9cb716a894440d3..da325863ad7645a4ae161114bb0b4bab42a46f9b 100644 (file)
@@ -558,7 +558,7 @@ uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev)
 
 int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
                                  struct amdgpu_device **dmabuf_adev,
-                                 uint64_t *bo_size, void *metadata_buffer,
+                                 uint64_t *bo_size, void **metadata_buffer,
                                  size_t buffer_size, uint32_t *metadata_size,
                                  uint32_t *flags, int8_t *xcp_id)
 {
@@ -593,9 +593,24 @@ int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
                *dmabuf_adev = adev;
        if (bo_size)
                *bo_size = amdgpu_bo_size(bo);
-       if (metadata_buffer)
-               r = amdgpu_bo_get_metadata(bo, metadata_buffer, buffer_size,
-                                          metadata_size, &metadata_flags);
+       if (metadata_buffer) {
+               /* first get metadata_size by buffer = NULL */
+               r = amdgpu_bo_get_metadata(bo, NULL, 0,
+                                          metadata_size, NULL);
+
+               /* user buf_size is bigger than bo metadata_size
+                * allocate a buf at kernel space and copy */
+               if (*metadata_size <= buffer_size) {
+                       *metadata_buffer = kzalloc(*metadata_size, GFP_KERNEL);
+
+                       if (!*metadata_buffer)
+                               return -ENOMEM;
+
+                       r = amdgpu_bo_get_metadata(bo, *metadata_buffer, *metadata_size,
+                                                  NULL, &metadata_flags);
+               } else
+                       r = -EINVAL;
+       }
        if (flags) {
                *flags = (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) ?
                                KFD_IOC_ALLOC_MEM_FLAGS_VRAM
index 5333e052d56db6a988a07c077d24f59d1f0efe32..e443a72772994b7562c2c9be588a0ddf5ace7b5b 100644 (file)
@@ -262,7 +262,7 @@ uint64_t amdgpu_amdkfd_get_gpu_clock_counter(struct amdgpu_device *adev);
 uint32_t amdgpu_amdkfd_get_max_engine_clock_in_mhz(struct amdgpu_device *adev);
 int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
                                  struct amdgpu_device **dmabuf_adev,
-                                 uint64_t *bo_size, void *metadata_buffer,
+                                 uint64_t *bo_size, void **metadata_buffer,
                                  size_t buffer_size, uint32_t *metadata_size,
                                  uint32_t *flags, int8_t *xcp_id);
 int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct amdgpu_device *adev, bool is_min);
index a2b100d1442581c76486ffead7557506e40a8ac1..6a991ffa53fc122e47783a0ed46d405d83f9b06f 100644 (file)
@@ -1562,16 +1562,10 @@ static int kfd_ioctl_get_dmabuf_info(struct file *filep,
        if (!dev)
                return -EINVAL;
 
-       if (args->metadata_ptr) {
-               metadata_buffer = kzalloc(args->metadata_size, GFP_KERNEL);
-               if (!metadata_buffer)
-                       return -ENOMEM;
-       }
-
        /* Get dmabuf info from KGD */
        r = amdgpu_amdkfd_get_dmabuf_info(dev->adev, args->dmabuf_fd,
                                          &dmabuf_adev, &args->size,
-                                         metadata_buffer, args->metadata_size,
+                                         &metadata_buffer, args->metadata_size,
                                          &args->metadata_size, &flags, &xcp_id);
        if (r)
                goto exit;
@@ -1583,7 +1577,7 @@ static int kfd_ioctl_get_dmabuf_info(struct file *filep,
        args->flags = flags;
 
        /* Copy metadata buffer to user mode */
-       if (metadata_buffer) {
+       if (metadata_buffer && args->metadata_ptr) {
                r = copy_to_user((void __user *)args->metadata_ptr,
                                 metadata_buffer, args->metadata_size);
                if (r != 0)