diff options
| author | Ingo Molnar <mingo@elte.hu> | 2009-03-26 10:45:22 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-03-26 10:45:22 -0400 |
| commit | a5ebc0b1a7843508b375f7ab8a36a628e5c9f372 (patch) | |
| tree | 04d3ab410e08b4d9174c663dd6bf95611dd16d0a /kernel/user.c | |
| parent | 5ba1ae92b6796b3367152ccd9baa022dde7eed4c (diff) | |
| parent | 8e0ee43bc2c3e19db56a4adaa9a9b04ce885cd84 (diff) | |
Merge commit 'v2.6.29' into timers/core
Diffstat (limited to 'kernel/user.c')
| -rw-r--r-- | kernel/user.c | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/kernel/user.c b/kernel/user.c index 477b6660f447..fbb300e6191f 100644 --- a/kernel/user.c +++ b/kernel/user.c | |||
| @@ -72,6 +72,7 @@ static void uid_hash_insert(struct user_struct *up, struct hlist_head *hashent) | |||
| 72 | static void uid_hash_remove(struct user_struct *up) | 72 | static void uid_hash_remove(struct user_struct *up) |
| 73 | { | 73 | { |
| 74 | hlist_del_init(&up->uidhash_node); | 74 | hlist_del_init(&up->uidhash_node); |
| 75 | put_user_ns(up->user_ns); | ||
| 75 | } | 76 | } |
| 76 | 77 | ||
| 77 | static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent) | 78 | static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent) |
| @@ -285,14 +286,12 @@ int __init uids_sysfs_init(void) | |||
| 285 | /* work function to remove sysfs directory for a user and free up | 286 | /* work function to remove sysfs directory for a user and free up |
| 286 | * corresponding structures. | 287 | * corresponding structures. |
| 287 | */ | 288 | */ |
| 288 | static void remove_user_sysfs_dir(struct work_struct *w) | 289 | static void cleanup_user_struct(struct work_struct *w) |
| 289 | { | 290 | { |
| 290 | struct user_struct *up = container_of(w, struct user_struct, work); | 291 | struct user_struct *up = container_of(w, struct user_struct, work); |
| 291 | unsigned long flags; | 292 | unsigned long flags; |
| 292 | int remove_user = 0; | 293 | int remove_user = 0; |
| 293 | 294 | ||
| 294 | if (up->user_ns != &init_user_ns) | ||
| 295 | return; | ||
| 296 | /* Make uid_hash_remove() + sysfs_remove_file() + kobject_del() | 295 | /* Make uid_hash_remove() + sysfs_remove_file() + kobject_del() |
| 297 | * atomic. | 296 | * atomic. |
| 298 | */ | 297 | */ |
| @@ -311,9 +310,11 @@ static void remove_user_sysfs_dir(struct work_struct *w) | |||
| 311 | if (!remove_user) | 310 | if (!remove_user) |
| 312 | goto done; | 311 | goto done; |
| 313 | 312 | ||
| 314 | kobject_uevent(&up->kobj, KOBJ_REMOVE); | 313 | if (up->user_ns == &init_user_ns) { |
| 315 | kobject_del(&up->kobj); | 314 | kobject_uevent(&up->kobj, KOBJ_REMOVE); |
| 316 | kobject_put(&up->kobj); | 315 | kobject_del(&up->kobj); |
| 316 | kobject_put(&up->kobj); | ||
| 317 | } | ||
| 317 | 318 | ||
| 318 | sched_destroy_user(up); | 319 | sched_destroy_user(up); |
| 319 | key_put(up->uid_keyring); | 320 | key_put(up->uid_keyring); |
| @@ -334,8 +335,7 @@ static void free_user(struct user_struct *up, unsigned long flags) | |||
| 334 | atomic_inc(&up->__count); | 335 | atomic_inc(&up->__count); |
| 335 | spin_unlock_irqrestore(&uidhash_lock, flags); | 336 | spin_unlock_irqrestore(&uidhash_lock, flags); |
| 336 | 337 | ||
| 337 | put_user_ns(up->user_ns); | 338 | INIT_WORK(&up->work, cleanup_user_struct); |
| 338 | INIT_WORK(&up->work, remove_user_sysfs_dir); | ||
| 339 | schedule_work(&up->work); | 339 | schedule_work(&up->work); |
| 340 | } | 340 | } |
| 341 | 341 | ||
| @@ -357,12 +357,29 @@ static void free_user(struct user_struct *up, unsigned long flags) | |||
| 357 | sched_destroy_user(up); | 357 | sched_destroy_user(up); |
| 358 | key_put(up->uid_keyring); | 358 | key_put(up->uid_keyring); |
| 359 | key_put(up->session_keyring); | 359 | key_put(up->session_keyring); |
| 360 | put_user_ns(up->user_ns); | ||
| 361 | kmem_cache_free(uid_cachep, up); | 360 | kmem_cache_free(uid_cachep, up); |
| 362 | } | 361 | } |
| 363 | 362 | ||
| 364 | #endif | 363 | #endif |
| 365 | 364 | ||
| 365 | #if defined(CONFIG_RT_GROUP_SCHED) && defined(CONFIG_USER_SCHED) | ||
| 366 | /* | ||
| 367 | * We need to check if a setuid can take place. This function should be called | ||
| 368 | * before successfully completing the setuid. | ||
| 369 | */ | ||
| 370 | int task_can_switch_user(struct user_struct *up, struct task_struct *tsk) | ||
| 371 | { | ||
| 372 | |||
| 373 | return sched_rt_can_attach(up->tg, tsk); | ||
| 374 | |||
| 375 | } | ||
| 376 | #else | ||
| 377 | int task_can_switch_user(struct user_struct *up, struct task_struct *tsk) | ||
| 378 | { | ||
| 379 | return 1; | ||
| 380 | } | ||
| 381 | #endif | ||
| 382 | |||
| 366 | /* | 383 | /* |
| 367 | * Locate the user_struct for the passed UID. If found, take a ref on it. The | 384 | * Locate the user_struct for the passed UID. If found, take a ref on it. The |
| 368 | * caller must undo that ref with free_uid(). | 385 | * caller must undo that ref with free_uid(). |
