aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorJack Steiner <steiner@sgi.com>2009-06-17 19:28:33 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-18 16:04:04 -0400
commit1926ee85a903d189c5702eed6531be321e33eb47 (patch)
tree1ae951591d3be09b86479800e2a4f03f119f4d78 /drivers/misc
parentb1b19fcfa417cf62447413d6e8b9b6598adf00b9 (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')
-rw-r--r--drivers/misc/sgi-gru/grufault.c4
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}