aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2012-10-18 17:53:58 -0400
committerKees Cook <keescook@chromium.org>2012-11-20 13:32:07 -0500
commit93b69d437effff11b1c37f330d3265c37ec2f84b (patch)
tree59473ffd3079719ebdff415fef688ee29f1f5eb8 /security
parentb5666502700855a1eb1a15482005b22478b9460e (diff)
Yama: add RCU to drop read locking
Stop using spinlocks in the read path. Add RCU list to handle the readers. Signed-off-by: Kees Cook <keescook@chromium.org> Reviewed-by: Serge E. Hallyn <serge.hallyn@ubuntu.com> Acked-by: John Johansen <john.johansen@canonical.com>
Diffstat (limited to 'security')
-rw-r--r--security/yama/yama_lsm.c47
1 files changed, 24 insertions, 23 deletions
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
index b4c29848b49d..70cd85e3ba30 100644
--- a/security/yama/yama_lsm.c
+++ b/security/yama/yama_lsm.c
@@ -30,6 +30,7 @@ struct ptrace_relation {
30 struct task_struct *tracer; 30 struct task_struct *tracer;
31 struct task_struct *tracee; 31 struct task_struct *tracee;
32 struct list_head node; 32 struct list_head node;
33 struct rcu_head rcu;
33}; 34};
34 35
35static LIST_HEAD(ptracer_relations); 36static LIST_HEAD(ptracer_relations);
@@ -48,32 +49,31 @@ static DEFINE_SPINLOCK(ptracer_relations_lock);
48static int yama_ptracer_add(struct task_struct *tracer, 49static int yama_ptracer_add(struct task_struct *tracer,
49 struct task_struct *tracee) 50 struct task_struct *tracee)
50{ 51{
51 int rc = 0; 52 struct ptrace_relation *relation, *added;
52 struct ptrace_relation *added;
53 struct ptrace_relation *entry, *relation = NULL;
54 53
55 added = kmalloc(sizeof(*added), GFP_KERNEL); 54 added = kmalloc(sizeof(*added), GFP_KERNEL);
56 if (!added) 55 if (!added)
57 return -ENOMEM; 56 return -ENOMEM;
58 57
58 added->tracee = tracee;
59 added->tracer = tracer;
60
59 spin_lock_bh(&ptracer_relations_lock); 61 spin_lock_bh(&ptracer_relations_lock);
60 list_for_each_entry(entry, &ptracer_relations, node) 62 rcu_read_lock();
61 if (entry->tracee == tracee) { 63 list_for_each_entry_rcu(relation, &ptracer_relations, node) {
62 relation = entry; 64 if (relation->tracee == tracee) {
63 break; 65 list_replace_rcu(&relation->node, &added->node);
66 kfree_rcu(relation, rcu);
67 goto out;
64 } 68 }
65 if (!relation) {
66 relation = added;
67 relation->tracee = tracee;
68 list_add(&relation->node, &ptracer_relations);
69 } 69 }
70 relation->tracer = tracer;
71 70
72 spin_unlock_bh(&ptracer_relations_lock); 71 list_add_rcu(&added->node, &ptracer_relations);
73 if (added != relation)
74 kfree(added);
75 72
76 return rc; 73out:
74 rcu_read_unlock();
75 spin_unlock_bh(&ptracer_relations_lock);
76 return 0;
77} 77}
78 78
79/** 79/**
@@ -84,15 +84,18 @@ static int yama_ptracer_add(struct task_struct *tracer,
84static void yama_ptracer_del(struct task_struct *tracer, 84static void yama_ptracer_del(struct task_struct *tracer,
85 struct task_struct *tracee) 85 struct task_struct *tracee)
86{ 86{
87 struct ptrace_relation *relation, *safe; 87 struct ptrace_relation *relation;
88 88
89 spin_lock_bh(&ptracer_relations_lock); 89 spin_lock_bh(&ptracer_relations_lock);
90 list_for_each_entry_safe(relation, safe, &ptracer_relations, node) 90 rcu_read_lock();
91 list_for_each_entry_rcu(relation, &ptracer_relations, node) {
91 if (relation->tracee == tracee || 92 if (relation->tracee == tracee ||
92 (tracer && relation->tracer == tracer)) { 93 (tracer && relation->tracer == tracer)) {
93 list_del(&relation->node); 94 list_del_rcu(&relation->node);
94 kfree(relation); 95 kfree_rcu(relation, rcu);
95 } 96 }
97 }
98 rcu_read_unlock();
96 spin_unlock_bh(&ptracer_relations_lock); 99 spin_unlock_bh(&ptracer_relations_lock);
97} 100}
98 101
@@ -217,11 +220,10 @@ static int ptracer_exception_found(struct task_struct *tracer,
217 struct task_struct *parent = NULL; 220 struct task_struct *parent = NULL;
218 bool found = false; 221 bool found = false;
219 222
220 spin_lock_bh(&ptracer_relations_lock);
221 rcu_read_lock(); 223 rcu_read_lock();
222 if (!thread_group_leader(tracee)) 224 if (!thread_group_leader(tracee))
223 tracee = rcu_dereference(tracee->group_leader); 225 tracee = rcu_dereference(tracee->group_leader);
224 list_for_each_entry(relation, &ptracer_relations, node) 226 list_for_each_entry_rcu(relation, &ptracer_relations, node)
225 if (relation->tracee == tracee) { 227 if (relation->tracee == tracee) {
226 parent = relation->tracer; 228 parent = relation->tracer;
227 found = true; 229 found = true;
@@ -231,7 +233,6 @@ static int ptracer_exception_found(struct task_struct *tracer,
231 if (found && (parent == NULL || task_is_descendant(parent, tracer))) 233 if (found && (parent == NULL || task_is_descendant(parent, tracer)))
232 rc = 1; 234 rc = 1;
233 rcu_read_unlock(); 235 rcu_read_unlock();
234 spin_unlock_bh(&ptracer_relations_lock);
235 236
236 return rc; 237 return rc;
237} 238}