[PATCH] lib: sbi_sse: fix shared memory double-fetch in sse_write_attrs
liutong <[email protected]> Sun, 28 Jun 2026 21:46:05 +0800
| Newsgroups | org.infradead.lists.opensbi |
|---|---|
| Message-ID | <[email protected]> |
sse_write_attrs() reads attribute values from S-mode shared memory in two passes: first to validate, then to apply. Since the shared memory remains writable by S-mode between the two reads, the values used for application may differ from what was validated. Fix this by snapshotting the shared memory data into a local buffer and performing both validation and application against that snapshot. Signed-off-by: liutong <[email protected]> --- lib/sbi/sbi_sse.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/sbi/sbi_sse.c b/lib/sbi/sbi_sse.c index 818afb87..0a6505b7 100644 --- a/lib/sbi/sbi_sse.c +++ b/lib/sbi/sbi_sse.c @@ -1064,25 +1064,28 @@ static int sse_write_attrs(struct sbi_sse_event *e, uint32_t base_attr_id, unsigned long attr = 0, val; uint32_t id, end_id = base_attr_id + attr_count; unsigned long *attrs = (unsigned long *)input_phys; + unsigned long local_attrs[SBI_SSE_ATTR_MAX]; sbi_hart_protection_map_range(input_phys, sizeof(unsigned long) * attr_count); + /* Snapshot shared memory into a local buffer to prevent TOCTOU */ + copy_attrs(local_attrs, attrs, attr_count); + + sbi_hart_protection_unmap_range(input_phys, sizeof(unsigned long) * attr_count); + for (id = base_attr_id; id < end_id; id++) { - val = attrs[attr++]; + val = local_attrs[attr++]; ret = sse_event_set_attr_check(e, id, val); if (ret) - goto out; + return ret; } attr = 0; for (id = base_attr_id; id < end_id; id++) { - val = attrs[attr++]; + val = local_attrs[attr++]; sse_event_set_attr(e, id, val); } -out: - sbi_hart_protection_unmap_range(input_phys, sizeof(unsigned long) * attr_count); - return ret; } -- 2.34.1 -- opensbi mailing list [email protected] http://lists.infradead.org/mailman/listinfo/opensbi