diff options
author | David Howells <dhowells@redhat.com> | 2006-04-11 01:54:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-04-11 09:18:45 -0400 |
commit | 1a26feb9622f1b1bc5e4f5f60f65557b73c38cbf (patch) | |
tree | 2404fc0d346127b71b9c30d9f9c95603c652ac93 | |
parent | 25a80759c5c237f0ecf57eb11fdd4efb21079c88 (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.c | 41 |
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 | */ |
169 | int install_process_keyring(struct task_struct *tsk) | 169 | int 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: | |||
207 | static int install_session_keyring(struct task_struct *tsk, | 208 | static 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); | ||
240 | error: | ||
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 | */ |
312 | int exec_keys(struct task_struct *tsk) | 312 | int 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 | ||