CVE-2026-46058
Description
In the Linux kernel, the following vulnerability has been resolved:
media: amphion: Fix race between m2m job_abort and device_run
Fix kernel panic caused by race condition where v4l2_m2m_ctx_release() frees m2m_ctx while v4l2_m2m_try_run() is about to call device_run with the same context.
Race sequence: v4l2_m2m_try_run(): v4l2_m2m_ctx_release(): lock/unlock v4l2_m2m_cancel_job() job_abort() v4l2_m2m_job_finish() kfree(m2m_ctx) <- frees ctx device_run() <- use-after-free crash at 0x538
Crash trace: Unable to handle kernel read from unreadable memory at virtual address 0000000000000538 v4l2_m2m_try_run+0x78/0x138 v4l2_m2m_device_run_work+0x14/0x20
The amphion vpu driver does not rely on the m2m framework's device_run callback to perform encode/decode operations.
Fix the race by preventing m2m framework job scheduling entirely: - Add job_ready callback returning 0 (no jobs ready for m2m framework) - Remove job_abort callback to avoid the race condition
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Race condition in Linux kernel's amphion driver leads to use-after-free crash during v4l2_m2m_ctx_release() and device_run.
Vulnerability
In the Linux kernel's amphion video driver, a race condition exists between v4l2_m2m_ctx_release() and the device_run callback in the V4L2 M2M framework. When v4l2_m2m_ctx_release() is called, it can free the m2m_ctx structure while v4l2_m2m_try_run() is about to invoke device_run with the same context, leading to a use-after-free crash. The vulnerability affects the amphion VPU driver in versions before the fix commit landed (stable tree).
Exploitation
An attacker (or a user-space process) triggers the race by concurrently initiating M2M job release and job execution on the same driver context. Specifically, the sequence requires: v4l2_m2m_ctx_release() (which calls v4l2_m2m_cancel_job(), job_abort(), v4l2_m2m_job_finish(), and kfree(m2m_ctx)) racing with v4l2_m2m_try_run() calling device_run(). The attacker may need local access to V4L2 device nodes and the ability to control the timing via threads or signals.
Impact
A successful exploit results in a kernel read from unreadable memory (crash at virtual address 0x538 in device_run), causing a kernel panic. This is a denial-of-service (DoS) condition. The reference trace shows "Unable to handle kernel read from unreadable memory at virtual address 0000000000000538" leading to system instability.
Mitigation
The fix is included in the Linux kernel stable commit [1]. The patch adds a job_ready callback that returns 0 (indicating no jobs are ready for the M2M framework) and removes the job_abort callback to prevent the race entirely. Users should apply the kernel update containing this commit, or cherry-pick the patch if possible. No workaround is documented; the amphion VPU driver does not rely on the M2M framework's device_run for encoding/decoding.
AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2Patches
108cd35ceadcfcmedia: amphion: Fix race between m2m job_abort and device_run
2 files changed · +6 −14
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 64fc88d89cccdc..7cccc994fc5029 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -447,17 +447,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 64fc88d89cccdc..7cccc994fc5029 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -447,17 +447,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
42dc622776f3media: amphion: Fix race between m2m job_abort and device_run
2 files changed · +6 −14
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 27c99f5c5b71d2..8ce1058475016b 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -441,17 +441,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 27c99f5c5b71d2..8ce1058475016b 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -441,17 +441,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
fdc150dac1admedia: amphion: Fix race between m2m job_abort and device_run
2 files changed · +6 −14
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 1fb887b9098c6b..369e7b1e61d469 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -448,17 +448,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 1fb887b9098c6b..369e7b1e61d469 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -448,17 +448,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
da4f46c5cf1dmedia: amphion: Fix race between m2m job_abort and device_run
2 files changed · +6 −14
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 72e23f95d6b727..24426782a98f5a 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -448,17 +448,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 72e23f95d6b727..24426782a98f5a 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -448,17 +448,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
6be2cb75bc13media: amphion: Fix race between m2m job_abort and device_run
2 files changed · +6 −14
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 64fc88d89cccdc..7cccc994fc5029 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -447,17 +447,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 64fc88d89cccdc..7cccc994fc5029 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -447,17 +447,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
42dc622776f3media: amphion: Fix race between m2m job_abort and device_run
2 files changed · +6 −14
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 27c99f5c5b71d2..8ce1058475016b 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -441,17 +441,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 27c99f5c5b71d2..8ce1058475016b 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -441,17 +441,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
8cd35ceadcfcmedia: amphion: Fix race between m2m job_abort and device_run
2 files changed · +6 −14
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 64fc88d89cccdc..7cccc994fc5029 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -447,17 +447,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 64fc88d89cccdc..7cccc994fc5029 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -447,17 +447,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
da4f46c5cf1dmedia: amphion: Fix race between m2m job_abort and device_run
2 files changed · +6 −14
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 72e23f95d6b727..24426782a98f5a 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -448,17 +448,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 72e23f95d6b727..24426782a98f5a 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -448,17 +448,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
fdc150dac1admedia: amphion: Fix race between m2m job_abort and device_run
2 files changed · +6 −14
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 1fb887b9098c6b..369e7b1e61d469 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -448,17 +448,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 1fb887b9098c6b..369e7b1e61d469 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -448,17 +448,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
6be2cb75bc13media: amphion: Fix race between m2m job_abort and device_run
2 files changed · +6 −14
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 64fc88d89cccdc..7cccc994fc5029 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -447,17 +447,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
drivers/media/platform/amphion/vpu_v4l2.c+3 −7 modifieddiff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c index 64fc88d89cccdc..7cccc994fc5029 100644 --- a/drivers/media/platform/amphion/vpu_v4l2.c +++ b/drivers/media/platform/amphion/vpu_v4l2.c @@ -447,17 +447,14 @@ static void vpu_m2m_device_run(void *priv) { } -static void vpu_m2m_job_abort(void *priv) +static int vpu_m2m_job_ready(void *priv) { - struct vpu_inst *inst = priv; - struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; - - v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); + return 0; } static const struct v4l2_m2m_ops vpu_m2m_ops = { .device_run = vpu_m2m_device_run, - .job_abort = vpu_m2m_job_abort + .job_ready = vpu_m2m_job_ready, }; static int vpu_vb2_queue_setup(struct vb2_queue *vq, -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Race condition between v4l2_m2m_try_run() and v4l2_m2m_ctx_release() where the m2m_ctx is freed before device_run completes, causing a use-after-free."
Attack vector
An attacker triggers a use-after-free by racing `v4l2_m2m_try_run()` against `v4l2_m2m_ctx_release()`. In the race window, `v4l2_m2m_ctx_release()` calls `vpu_m2m_job_abort` which finishes the job and then frees the `m2m_ctx` via `kfree()`, while `v4l2_m2m_try_run()` concurrently proceeds to call `device_run` on the already-freed context, causing a kernel panic at virtual address 0x538 [patch_id=2660063]. No special privileges are required beyond the ability to open and close a V4L2 M2M device node while video encode/decode operations are in flight.
Affected code
The vulnerability is in `drivers/media/platform/amphion/vpu_v4l2.c` in the `vpu_m2m_job_abort` callback and the `vpu_m2m_ops` structure. The `vpu_m2m_job_abort` function called `v4l2_m2m_job_finish()` using the `m2m_ctx` pointer, and the `vpu_m2m_ops` structure registered both `device_run` and `job_abort` callbacks without a `job_ready` callback [patch_id=2660063].
What the fix does
The patch replaces the `vpu_m2m_job_abort` callback with a new `vpu_m2m_job_ready` callback that always returns 0, and updates the `vpu_m2m_ops` structure accordingly [patch_id=2660063]. Because the amphion VPU driver does not rely on the M2M framework's `device_run` callback for actual encode/decode work, returning 0 from `job_ready` prevents the M2M framework from ever scheduling a job via `device_run`, eliminating the race entirely. Removing the `job_abort` callback also removes the code path that called `v4l2_m2m_job_finish()` and led to the use-after-free.
Preconditions
- inputAttacker must be able to open a V4L2 M2M device node on the amphion VPU driver and initiate video encode/decode operations
- inputAttacker must be able to concurrently close/release the device node while a job is being scheduled
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- git.kernel.org/stable/c/42dc622776f3ce1a6c31b13bdc686f7295e3b323nvd
- git.kernel.org/stable/c/6be2cb75bc1300080cfc8051579f22efae9401f7nvd
- git.kernel.org/stable/c/8cd35ceadcfc8c5da2eb7f7ce24525ce9d4ee62envd
- git.kernel.org/stable/c/da4f46c5cf1d26e6b09418ad453e152f2e75a02cnvd
- git.kernel.org/stable/c/fdc150dac1adb9a98be9d6956cff0348838b024anvd
News mentions
0No linked articles in our index yet.