diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 3d307b34854d2731e69249568e3a9d5d772e1ba5..45f2c6084aa7df0a62d31076c23ffb4eb9188751 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -290,11 +290,48 @@ int adreno_get_param(struct msm_gpu *gpu, struct msm_file_private *ctx, int adreno_set_param(struct msm_gpu *gpu, struct msm_file_private *ctx, uint32_t param, uint64_t value, uint32_t len) { - /* No pointer params yet */ - if (len != 0) - return -EINVAL; + switch (param) { + case MSM_PARAM_COMM: + case MSM_PARAM_CMDLINE: + /* kstrdup_quotable_cmdline() limits to PAGE_SIZE, so + * that should be a reasonable upper bound + */ + if (len > PAGE_SIZE) + return -EINVAL; + break; + default: + if (len != 0) + return -EINVAL; + } switch (param) { + case MSM_PARAM_COMM: + case MSM_PARAM_CMDLINE: { + char *str, **paramp; + + str = kmalloc(len + 1, GFP_KERNEL); + if (!str) + return -ENOMEM; + + if (copy_from_user(str, u64_to_user_ptr(value), len)) { + kfree(str); + return -EFAULT; + } + + /* Ensure string is null terminated: */ + str[len] = '\0'; + + if (param == MSM_PARAM_COMM) { + paramp = &ctx->comm; + } else { + paramp = &ctx->cmdline; + } + + kfree(*paramp); + *paramp = str; + + return 0; + } case MSM_PARAM_SYSPROF: if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 7a88dd6568c0f5be8f092a2597d1834766e003c1..f292b70c1e6d6eaa0f4057cca7927fbcfe62611a 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -353,14 +353,22 @@ static void retire_submits(struct msm_gpu *gpu); static void get_comm_cmdline(struct msm_gem_submit *submit, char **comm, char **cmd) { + struct msm_file_private *ctx = submit->queue->ctx; struct task_struct *task; + /* Note that kstrdup will return NULL if argument is NULL: */ + *comm = kstrdup(ctx->comm, GFP_KERNEL); + *cmd = kstrdup(ctx->cmdline, GFP_KERNEL); + task = get_pid_task(submit->pid, PIDTYPE_PID); if (!task) return; - *comm = kstrdup(task->comm, GFP_KERNEL); - *cmd = kstrdup_quotable_cmdline(task, GFP_KERNEL); + if (!*comm) + *comm = kstrdup(task->comm, GFP_KERNEL); + + if (!*cmd) + *cmd = kstrdup_quotable_cmdline(task, GFP_KERNEL); put_task_struct(task); } diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index ab5d31f5df813faf956e66fa58798bc17163751b..321e41de6d42369e7763ead585997ca3512f5560 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -355,6 +355,12 @@ struct msm_file_private { */ int sysprof; + /** comm: Overridden task comm, see MSM_PARAM_COMM */ + char *comm; + + /** cmdline: Overridden task cmdline, see MSM_PARAM_CMDLINE */ + char *cmdline; + /** * entities: * diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c index 79b6ccd6ce64f93a7456c9057a66fa7f4fbc982f..f486a3cd4e5508995c0edd23474d6a445fe705ae 100644 --- a/drivers/gpu/drm/msm/msm_submitqueue.c +++ b/drivers/gpu/drm/msm/msm_submitqueue.c @@ -61,6 +61,8 @@ void __msm_file_private_destroy(struct kref *kref) } msm_gem_address_space_put(ctx->aspace); + kfree(ctx->comm); + kfree(ctx->cmdline); kfree(ctx); } diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h index 0aa1a8cb4e0df9bd0a82f1a11ef45e1127f3a1f2..794ad1948497391061a6460faf0de91e5e89a007 100644 --- a/include/uapi/drm/msm_drm.h +++ b/include/uapi/drm/msm_drm.h @@ -82,6 +82,8 @@ struct drm_msm_timespec { #define MSM_PARAM_FAULTS 0x09 /* RO */ #define MSM_PARAM_SUSPENDS 0x0a /* RO */ #define MSM_PARAM_SYSPROF 0x0b /* WO: 1 preserves perfcntrs, 2 also disables suspend */ +#define MSM_PARAM_COMM 0x0c /* WO: override for task->comm */ +#define MSM_PARAM_CMDLINE 0x0d /* WO: override for task cmdline */ /* For backwards compat. The original support for preemption was based on * a single ring per priority level so # of priority levels equals the #