diff options
Diffstat (limited to 'security/keys/process_keys.c')
| -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 | ||
