mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-24 02:22:34 +03:00
gpu: nvgpu: fix out-of-bound idx for FECS trace
Fix a case where user space could potentially see an out of bounds write index for user facing context switch buffer. Check if write_idx is valid, and disable FECS tracing if corrupted. Bug 1757714 Change-Id: I5710c40121fa6935dba3918adf5290488e31e9f6 Signed-off-by: Thomas Fleury <tfleury@nvidia.com> Reviewed-on: http://git-master/r/1139305 (cherry picked from commit 47b65e5b59037932777be4911fe040e6acbc5651) Reviewed-on: http://git-master/r/1150048 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Richard Zhao <rizhao@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
This commit is contained in:
committed by
Terje Bergstrom
parent
989f7f70c3
commit
f71ac07972
@@ -43,6 +43,7 @@ struct gk20a_ctxsw_dev {
|
||||
bool write_enabled;
|
||||
wait_queue_head_t readout_wq;
|
||||
size_t size;
|
||||
u32 num_ents;
|
||||
|
||||
atomic_t vma_ref;
|
||||
|
||||
@@ -165,6 +166,7 @@ static int gk20a_ctxsw_dev_alloc_buffer(struct gk20a_ctxsw_dev *dev,
|
||||
dev->hdr = buf;
|
||||
dev->ents = (struct nvgpu_ctxsw_trace_entry *) (dev->hdr + 1);
|
||||
dev->size = size;
|
||||
dev->num_ents = dev->hdr->num_ents;
|
||||
|
||||
gk20a_dbg(gpu_dbg_ctxsw, "size=%zu hdr=%p ents=%p num_ents=%d",
|
||||
dev->size, dev->hdr, dev->ents, dev->hdr->num_ents);
|
||||
@@ -553,6 +555,7 @@ int gk20a_ctxsw_trace_write(struct gk20a *g,
|
||||
struct gk20a_ctxsw_dev *dev;
|
||||
int ret = 0;
|
||||
const char *reason;
|
||||
u32 write_idx;
|
||||
|
||||
if (unlikely(entry->vmid >= GK20A_CTXSW_TRACE_NUM_DEVS))
|
||||
return -ENODEV;
|
||||
@@ -571,6 +574,16 @@ int gk20a_ctxsw_trace_write(struct gk20a *g,
|
||||
goto done;
|
||||
}
|
||||
|
||||
write_idx = hdr->write_idx;
|
||||
if (write_idx >= dev->num_ents) {
|
||||
gk20a_err(dev_from_gk20a(dev->g),
|
||||
"write_idx=%u out of range [0..%u]",
|
||||
write_idx, dev->num_ents);
|
||||
ret = -ENOSPC;
|
||||
reason = "write_idx out of range";
|
||||
goto disable;
|
||||
}
|
||||
|
||||
entry->seqno = hdr->write_seqno++;
|
||||
|
||||
if (!dev->write_enabled) {
|
||||
@@ -595,20 +608,24 @@ int gk20a_ctxsw_trace_write(struct gk20a *g,
|
||||
entry->seqno, entry->context_id, entry->pid,
|
||||
entry->tag, entry->timestamp);
|
||||
|
||||
dev->ents[hdr->write_idx] = *entry;
|
||||
dev->ents[write_idx] = *entry;
|
||||
|
||||
/* ensure record is written before updating write index */
|
||||
smp_wmb();
|
||||
|
||||
hdr->write_idx++;
|
||||
if (unlikely(hdr->write_idx >= hdr->num_ents))
|
||||
hdr->write_idx = 0;
|
||||
write_idx++;
|
||||
if (unlikely(write_idx >= hdr->num_ents))
|
||||
write_idx = 0;
|
||||
hdr->write_idx = write_idx;
|
||||
gk20a_dbg(gpu_dbg_ctxsw, "added: read=%d write=%d len=%d",
|
||||
hdr->read_idx, hdr->write_idx, ring_len(hdr));
|
||||
|
||||
mutex_unlock(&dev->write_lock);
|
||||
return ret;
|
||||
|
||||
disable:
|
||||
g->ops.fecs_trace.disable(g);
|
||||
|
||||
drop:
|
||||
hdr->drop_count++;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user