diff options
author | Jack Steiner <steiner@sgi.com> | 2009-06-17 19:28:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-18 16:04:04 -0400 |
commit | 1926ee85a903d189c5702eed6531be321e33eb47 (patch) | |
tree | 1ae951591d3be09b86479800e2a4f03f119f4d78 /drivers/misc/sgi-gru/grufault.c | |
parent | b1b19fcfa417cf62447413d6e8b9b6598adf00b9 (diff) |
gru: fix potential use-after-free when purging GRU tlbs
Fix potential SGI GRU bug that could cause a use-after-free. If one
thread in a task is flushing the GRU and another thread destroys the GRU
context, there is the potential to access a table after it has been freed.
Copy the gms pointer to a local variable before unlocking the gts table.
Note that no refcnt is needed for the gms - the reference is held
indirectly by the task's mm_struct.
Signed-off-by: Jack Steiner <steiner@sgi.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc/sgi-gru/grufault.c')
-rw-r--r-- | drivers/misc/sgi-gru/grufault.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c index 1ad360cd3183..679e01778286 100644 --- a/drivers/misc/sgi-gru/grufault.c +++ b/drivers/misc/sgi-gru/grufault.c | |||
@@ -702,6 +702,7 @@ int gru_user_flush_tlb(unsigned long arg) | |||
702 | { | 702 | { |
703 | struct gru_thread_state *gts; | 703 | struct gru_thread_state *gts; |
704 | struct gru_flush_tlb_req req; | 704 | struct gru_flush_tlb_req req; |
705 | struct gru_mm_struct *gms; | ||
705 | 706 | ||
706 | STAT(user_flush_tlb); | 707 | STAT(user_flush_tlb); |
707 | if (copy_from_user(&req, (void __user *)arg, sizeof(req))) | 708 | if (copy_from_user(&req, (void __user *)arg, sizeof(req))) |
@@ -714,8 +715,9 @@ int gru_user_flush_tlb(unsigned long arg) | |||
714 | if (!gts) | 715 | if (!gts) |
715 | return -EINVAL; | 716 | return -EINVAL; |
716 | 717 | ||
717 | gru_flush_tlb_range(gts->ts_gms, req.vaddr, req.len); | 718 | gms = gts->ts_gms; |
718 | gru_unlock_gts(gts); | 719 | gru_unlock_gts(gts); |
720 | gru_flush_tlb_range(gms, req.vaddr, req.len); | ||
719 | 721 | ||
720 | return 0; | 722 | return 0; |
721 | } | 723 | } |