mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
accel/rocket: Validate task regcmd address and count on submission
The regcmd fields in drm_rocket_task come from userspace and are programmed into the PC unit without any validation. Bits 31:4 of PC_BASE_ADDRESS hold the register command DMA address and bit 0 selects slave mode, so a misaligned regcmd silently drops its low bits, and an odd address flips the PC unit into slave mode. Similarly, pc_data_amount is a 16-bit field holding (regcmd_count + 1) / 2 - 1, so a larger regcmd_count is silently truncated by the register encoding. Reject unaligned regcmd addresses and out-of-range regcmd_count with -EINVAL at submission time. Existing userspace is not affected: Mesa places regcmd buffers at 64-byte aligned offsets, and its regcmd counts stay far below the limit. Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai> Signed-off-by: Heiko Stuebner <heiko@sntech.de> Link: https://patch.msgid.link/20261004164727.466164-4-sidong.yang@furiosa.ai
This commit is contained in:
parent
f31a7b1f27
commit
725953d4da
|
|
@ -7,6 +7,7 @@
|
|||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/rocket_accel.h>
|
||||
#include <linux/align.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/iommu.h>
|
||||
|
|
@ -21,6 +22,15 @@
|
|||
|
||||
#define JOB_TIMEOUT_MS 500
|
||||
|
||||
/*
|
||||
* The PC unit fetches two 64-bit register commands per pc_data_amount unit,
|
||||
* and the field holds (regcmd_count + 1) / 2 - 1.
|
||||
*/
|
||||
#define ROCKET_MAX_REGCMDS ((PC_REGISTER_AMOUNTS_PC_DATA_AMOUNT__MASK + 1) * 2U)
|
||||
|
||||
/* Bits 3:0 of PC_BASE_ADDRESS hold the mode selection bit and reserved bits */
|
||||
#define ROCKET_REGCMD_ALIGN 16
|
||||
|
||||
static struct rocket_job *
|
||||
to_rocket_job(struct drm_sched_job *sched_job)
|
||||
{
|
||||
|
|
@ -95,6 +105,20 @@ rocket_copy_tasks(struct drm_device *dev,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (task.regcmd_count > ROCKET_MAX_REGCMDS) {
|
||||
drm_dbg(dev, "regcmd_count field in drm_rocket_task should be <= %u.\n",
|
||||
ROCKET_MAX_REGCMDS);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!IS_ALIGNED(task.regcmd, ROCKET_REGCMD_ALIGN)) {
|
||||
drm_dbg(dev, "regcmd field in drm_rocket_task should be aligned to %u bytes.\n",
|
||||
ROCKET_REGCMD_ALIGN);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rjob->tasks[i].regcmd = task.regcmd;
|
||||
rjob->tasks[i].regcmd_count = task.regcmd_count;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user