diff options
Diffstat (limited to 'kernel/user.c')
| -rw-r--r-- | kernel/user.c | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/kernel/user.c b/kernel/user.c index 3551ac742395..fbb300e6191f 100644 --- a/kernel/user.c +++ b/kernel/user.c | |||
| @@ -286,14 +286,12 @@ int __init uids_sysfs_init(void) | |||
| 286 | /* 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 |
| 287 | * corresponding structures. | 287 | * corresponding structures. |
| 288 | */ | 288 | */ |
| 289 | static void remove_user_sysfs_dir(struct work_struct *w) | 289 | static void cleanup_user_struct(struct work_struct *w) |
| 290 | { | 290 | { |
| 291 | struct user_struct *up = container_of(w, struct user_struct, work); | 291 | struct user_struct *up = container_of(w, struct user_struct, work); |
| 292 | unsigned long flags; | 292 | unsigned long flags; |
| 293 | int remove_user = 0; | 293 | int remove_user = 0; |
| 294 | 294 | ||
| 295 | if (up->user_ns != &init_user_ns) | ||
| 296 | return; | ||
| 297 | /* Make uid_hash_remove() + sysfs_remove_file() + kobject_del() | 295 | /* Make uid_hash_remove() + sysfs_remove_file() + kobject_del() |
| 298 | * atomic. | 296 | * atomic. |
| 299 | */ | 297 | */ |
| @@ -312,9 +310,11 @@ static void remove_user_sysfs_dir(struct work_struct *w) | |||
| 312 | if (!remove_user) | 310 | if (!remove_user) |
| 313 | goto done; | 311 | goto done; |
| 314 | 312 | ||
| 315 | kobject_uevent(&up->kobj, KOBJ_REMOVE); | 313 | if (up->user_ns == &init_user_ns) { |
| 316 | kobject_del(&up->kobj); | 314 | kobject_uevent(&up->kobj, KOBJ_REMOVE); |
| 317 | kobject_put(&up->kobj); | 315 | kobject_del(&up->kobj); |
| 316 | kobject_put(&up->kobj); | ||
| 317 | } | ||
| 318 | 318 | ||
| 319 | sched_destroy_user(up); | 319 | sched_destroy_user(up); |
| 320 | key_put(up->uid_keyring); | 320 | key_put(up->uid_keyring); |
| @@ -335,7 +335,7 @@ static void free_user(struct user_struct *up, unsigned long flags) | |||
| 335 | atomic_inc(&up->__count); | 335 | atomic_inc(&up->__count); |
| 336 | spin_unlock_irqrestore(&uidhash_lock, flags); | 336 | spin_unlock_irqrestore(&uidhash_lock, flags); |
| 337 | 337 | ||
| 338 | INIT_WORK(&up->work, remove_user_sysfs_dir); | 338 | INIT_WORK(&up->work, cleanup_user_struct); |
| 339 | schedule_work(&up->work); | 339 | schedule_work(&up->work); |
| 340 | } | 340 | } |
| 341 | 341 | ||
| @@ -362,6 +362,24 @@ static void free_user(struct user_struct *up, unsigned long flags) | |||
| 362 | 362 | ||
| 363 | #endif | 363 | #endif |
| 364 | 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 | |||
| 365 | /* | 383 | /* |
| 366 | * 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 |
| 367 | * caller must undo that ref with free_uid(). | 385 | * caller must undo that ref with free_uid(). |
