diff options
author | Thomas Fleury <tfleury@nvidia.com> | 2016-04-28 12:54:13 -0400 |
---|---|---|
committer | Terje Bergstrom <tbergstrom@nvidia.com> | 2016-05-21 14:33:46 -0400 |
commit | f71ac07972c5818cca9a652ca649b61d6572dc9b (patch) | |
tree | 869c107809a41c57d468f5ca5b03a6a5c924edc3 /drivers | |
parent | 989f7f70c3b7a77467cb216932490e48dc03c64c (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/ctxsw_trace_gk20a.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/ctxsw_trace_gk20a.c b/drivers/gpu/nvgpu/gk20a/ctxsw_trace_gk20a.c index 19ba6dde..028763a2 100644 --- a/drivers/gpu/nvgpu/gk20a/ctxsw_trace_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/ctxsw_trace_gk20a.c | |||
@@ -43,6 +43,7 @@ struct gk20a_ctxsw_dev { | |||
43 | bool write_enabled; | 43 | bool write_enabled; |
44 | wait_queue_head_t readout_wq; | 44 | wait_queue_head_t readout_wq; |
45 | size_t size; | 45 | size_t size; |
46 | u32 num_ents; | ||
46 | 47 | ||
47 | atomic_t vma_ref; | 48 | atomic_t vma_ref; |
48 | 49 | ||
@@ -165,6 +166,7 @@ static int gk20a_ctxsw_dev_alloc_buffer(struct gk20a_ctxsw_dev *dev, | |||
165 | dev->hdr = buf; | 166 | dev->hdr = buf; |
166 | dev->ents = (struct nvgpu_ctxsw_trace_entry *) (dev->hdr + 1); | 167 | dev->ents = (struct nvgpu_ctxsw_trace_entry *) (dev->hdr + 1); |
167 | dev->size = size; | 168 | dev->size = size; |
169 | dev->num_ents = dev->hdr->num_ents; | ||
168 | 170 | ||
169 | gk20a_dbg(gpu_dbg_ctxsw, "size=%zu hdr=%p ents=%p num_ents=%d", | 171 | gk20a_dbg(gpu_dbg_ctxsw, "size=%zu hdr=%p ents=%p num_ents=%d", |
170 | dev->size, dev->hdr, dev->ents, dev->hdr->num_ents); | 172 | dev->size, dev->hdr, dev->ents, dev->hdr->num_ents); |
@@ -553,6 +555,7 @@ int gk20a_ctxsw_trace_write(struct gk20a *g, | |||
553 | struct gk20a_ctxsw_dev *dev; | 555 | struct gk20a_ctxsw_dev *dev; |
554 | int ret = 0; | 556 | int ret = 0; |
555 | const char *reason; | 557 | const char *reason; |
558 | u32 write_idx; | ||
556 | 559 | ||
557 | if (unlikely(entry->vmid >= GK20A_CTXSW_TRACE_NUM_DEVS)) | 560 | if (unlikely(entry->vmid >= GK20A_CTXSW_TRACE_NUM_DEVS)) |
558 | return -ENODEV; | 561 | return -ENODEV; |
@@ -571,6 +574,16 @@ int gk20a_ctxsw_trace_write(struct gk20a *g, | |||
571 | goto done; | 574 | goto done; |
572 | } | 575 | } |
573 | 576 | ||
577 | write_idx = hdr->write_idx; | ||
578 | if (write_idx >= dev->num_ents) { | ||
579 | gk20a_err(dev_from_gk20a(dev->g), | ||
580 | "write_idx=%u out of range [0..%u]", | ||
581 | write_idx, dev->num_ents); | ||
582 | ret = -ENOSPC; | ||
583 | reason = "write_idx out of range"; | ||
584 | goto disable; | ||
585 | } | ||
586 | |||
574 | entry->seqno = hdr->write_seqno++; | 587 | entry->seqno = hdr->write_seqno++; |
575 | 588 | ||
576 | if (!dev->write_enabled) { | 589 | if (!dev->write_enabled) { |
@@ -595,20 +608,24 @@ int gk20a_ctxsw_trace_write(struct gk20a *g, | |||
595 | entry->seqno, entry->context_id, entry->pid, | 608 | entry->seqno, entry->context_id, entry->pid, |
596 | entry->tag, entry->timestamp); | 609 | entry->tag, entry->timestamp); |
597 | 610 | ||
598 | dev->ents[hdr->write_idx] = *entry; | 611 | dev->ents[write_idx] = *entry; |
599 | 612 | ||
600 | /* ensure record is written before updating write index */ | 613 | /* ensure record is written before updating write index */ |
601 | smp_wmb(); | 614 | smp_wmb(); |
602 | 615 | ||
603 | hdr->write_idx++; | 616 | write_idx++; |
604 | if (unlikely(hdr->write_idx >= hdr->num_ents)) | 617 | if (unlikely(write_idx >= hdr->num_ents)) |
605 | hdr->write_idx = 0; | 618 | write_idx = 0; |
619 | hdr->write_idx = write_idx; | ||
606 | gk20a_dbg(gpu_dbg_ctxsw, "added: read=%d write=%d len=%d", | 620 | gk20a_dbg(gpu_dbg_ctxsw, "added: read=%d write=%d len=%d", |
607 | hdr->read_idx, hdr->write_idx, ring_len(hdr)); | 621 | hdr->read_idx, hdr->write_idx, ring_len(hdr)); |
608 | 622 | ||
609 | mutex_unlock(&dev->write_lock); | 623 | mutex_unlock(&dev->write_lock); |
610 | return ret; | 624 | return ret; |
611 | 625 | ||
626 | disable: | ||
627 | g->ops.fecs_trace.disable(g); | ||
628 | |||
612 | drop: | 629 | drop: |
613 | hdr->drop_count++; | 630 | hdr->drop_count++; |
614 | 631 | ||