aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2006-04-11 01:54:26 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-11 09:18:45 -0400
commit1a26feb9622f1b1bc5e4f5f60f65557b73c38cbf (patch)
tree2404fc0d346127b71b9c30d9f9c95603c652ac93
parent25a80759c5c237f0ecf57eb11fdd4efb21079c88 (diff)
[PATCH] Keys: Improve usage of memory barriers and remove IRQ disablement
Remove an unnecessary memory barrier (implicit in rcu_dereference()) from install_session_keyring(). install_session_keyring() is also rearranged a little to make it slightly more efficient. As install_*_keyring() may schedule (in synchronize_rcu() or keyring_alloc()), they may not be entered with interrupts disabled - and so there's no point saving the interrupt disablement state over the critical section. exec_keys() will also be invoked with interrupts enabled, and so that doesn't need to save the interrupt state either. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--security/keys/process_keys.c41
1 files changed, 20 insertions, 21 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index f6940618e345..217a0bef3c82 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -168,11 +168,12 @@ error:
168 */ 168 */
169int install_process_keyring(struct task_struct *tsk) 169int install_process_keyring(struct task_struct *tsk)
170{ 170{
171 unsigned long flags;
172 struct key *keyring; 171 struct key *keyring;
173 char buf[20]; 172 char buf[20];
174 int ret; 173 int ret;
175 174
175 might_sleep();
176
176 if (!tsk->signal->process_keyring) { 177 if (!tsk->signal->process_keyring) {
177 sprintf(buf, "_pid.%u", tsk->tgid); 178 sprintf(buf, "_pid.%u", tsk->tgid);
178 179
@@ -183,12 +184,12 @@ int install_process_keyring(struct task_struct *tsk)
183 } 184 }
184 185
185 /* attach keyring */ 186 /* attach keyring */
186 spin_lock_irqsave(&tsk->sighand->siglock, flags); 187 spin_lock_irq(&tsk->sighand->siglock);
187 if (!tsk->signal->process_keyring) { 188 if (!tsk->signal->process_keyring) {
188 tsk->signal->process_keyring = keyring; 189 tsk->signal->process_keyring = keyring;
189 keyring = NULL; 190 keyring = NULL;
190 } 191 }
191 spin_unlock_irqrestore(&tsk->sighand->siglock, flags); 192 spin_unlock_irq(&tsk->sighand->siglock);
192 193
193 key_put(keyring); 194 key_put(keyring);
194 } 195 }
@@ -207,38 +208,37 @@ error:
207static int install_session_keyring(struct task_struct *tsk, 208static int install_session_keyring(struct task_struct *tsk,
208 struct key *keyring) 209 struct key *keyring)
209{ 210{
210 unsigned long flags;
211 struct key *old; 211 struct key *old;
212 char buf[20]; 212 char buf[20];
213 int ret; 213
214 might_sleep();
214 215
215 /* create an empty session keyring */ 216 /* create an empty session keyring */
216 if (!keyring) { 217 if (!keyring) {
217 sprintf(buf, "_ses.%u", tsk->tgid); 218 sprintf(buf, "_ses.%u", tsk->tgid);
218 219
219 keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL); 220 keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
220 if (IS_ERR(keyring)) { 221 if (IS_ERR(keyring))
221 ret = PTR_ERR(keyring); 222 return PTR_ERR(keyring);
222 goto error;
223 }
224 } 223 }
225 else { 224 else {
226 atomic_inc(&keyring->usage); 225 atomic_inc(&keyring->usage);
227 } 226 }
228 227
229 /* install the keyring */ 228 /* install the keyring */
230 spin_lock_irqsave(&tsk->sighand->siglock, flags); 229 spin_lock_irq(&tsk->sighand->siglock);
231 old = rcu_dereference(tsk->signal->session_keyring); 230 old = tsk->signal->session_keyring;
232 rcu_assign_pointer(tsk->signal->session_keyring, keyring); 231 rcu_assign_pointer(tsk->signal->session_keyring, keyring);
233 spin_unlock_irqrestore(&tsk->sighand->siglock, flags); 232 spin_unlock_irq(&tsk->sighand->siglock);
234 233
235 ret = 0; 234 /* we're using RCU on the pointer, but there's no point synchronising
235 * on it if it didn't previously point to anything */
236 if (old) {
237 synchronize_rcu();
238 key_put(old);
239 }
236 240
237 /* we're using RCU on the pointer */ 241 return 0;
238 synchronize_rcu();
239 key_put(old);
240error:
241 return ret;
242 242
243} /* end install_session_keyring() */ 243} /* end install_session_keyring() */
244 244
@@ -311,7 +311,6 @@ void exit_keys(struct task_struct *tsk)
311 */ 311 */
312int exec_keys(struct task_struct *tsk) 312int exec_keys(struct task_struct *tsk)
313{ 313{
314 unsigned long flags;
315 struct key *old; 314 struct key *old;
316 315
317 /* newly exec'd tasks don't get a thread keyring */ 316 /* newly exec'd tasks don't get a thread keyring */
@@ -323,10 +322,10 @@ int exec_keys(struct task_struct *tsk)
323 key_put(old); 322 key_put(old);
324 323
325 /* discard the process keyring from a newly exec'd task */ 324 /* discard the process keyring from a newly exec'd task */
326 spin_lock_irqsave(&tsk->sighand->siglock, flags); 325 spin_lock_irq(&tsk->sighand->siglock);
327 old = tsk->signal->process_keyring; 326 old = tsk->signal->process_keyring;
328 tsk->signal->process_keyring = NULL; 327 tsk->signal->process_keyring = NULL;
329 spin_unlock_irqrestore(&tsk->sighand->siglock, flags); 328 spin_unlock_irq(&tsk->sighand->siglock);
330 329
331 key_put(old); 330 key_put(old);
332 331