[bug report] drm/v3d: Create a CPU job extension for the reset timestamp job

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



[ The Smatch integer overflow are too garbage to publish.  We're going to have
  a BoF about integer overflows at plumbers. - dan ]

Hello Maíra Canal,

Commit 34a101e64296 ("drm/v3d: Create a CPU job extension for the
reset timestamp job") from Nov 30, 2023 (linux-next), leads to the
following Smatch static checker warning:

	drivers/gpu/drm/v3d/v3d_submit.c:551 v3d_get_cpu_reset_timestamp_params()
	warn: potential integer overflow from user (local copy) 'reset.offset + 8 * i'

drivers/gpu/drm/v3d/v3d_submit.c
    515 static int
    516 v3d_get_cpu_reset_timestamp_params(struct drm_file *file_priv,
    517                                    struct drm_v3d_extension __user *ext,
    518                                    struct v3d_cpu_job *job)
    519 {
    520         u32 __user *syncs;
    521         struct drm_v3d_reset_timestamp_query reset;
    522         unsigned int i;
    523         int err;
    524 
    525         if (!job) {
    526                 DRM_DEBUG("CPU job extension was attached to a GPU job.\n");
    527                 return -EINVAL;
    528         }
    529 
    530         if (job->job_type) {
    531                 DRM_DEBUG("Two CPU job extensions were added to the same CPU job.\n");
    532                 return -EINVAL;
    533         }
    534 
    535         if (copy_from_user(&reset, ext, sizeof(reset)))
                                    ^^^^^
reset.offset is a u32 that comes from the user

    536                 return -EFAULT;
    537 
    538         job->job_type = V3D_CPU_JOB_TYPE_RESET_TIMESTAMP_QUERY;
    539 
    540         job->timestamp_query.queries = kvmalloc_array(reset.count,
    541                                                       sizeof(struct v3d_timestamp_query),
    542                                                       GFP_KERNEL);
    543         if (!job->timestamp_query.queries)
    544                 return -ENOMEM;
    545 
    546         syncs = u64_to_user_ptr(reset.syncs);
    547 
    548         for (i = 0; i < reset.count; i++) {
    549                 u32 sync;
    550 
--> 551                 job->timestamp_query.queries[i].offset = reset.offset + 8 * i;
                                                                 ^^^^^^^^^^^^^^^^^^^^

This addition operation could be > U32_MAX.  There needs to be some checking
that it's within bounds.

    552 
    553                 if (copy_from_user(&sync, syncs++, sizeof(sync))) {
    554                         err = -EFAULT;
    555                         goto error;
    556                 }
    557 
    558                 job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync);
    559                 if (!job->timestamp_query.queries[i].syncobj) {
    560                         err = -ENOENT;
    561                         goto error;
    562                 }
    563         }
    564         job->timestamp_query.count = reset.count;
    565 
    566         return 0;
    567 
    568 error:
    569         v3d_timestamp_query_info_free(&job->timestamp_query, i);
    570         return err;
    571 }

regards,
dan carpenter



[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux