diff options
Diffstat (limited to 'kernel/user.c')
| -rw-r--r-- | kernel/user.c | 34 | 
1 files changed, 26 insertions, 8 deletions
diff --git a/kernel/user.c b/kernel/user.c index 3551ac74239..850e0ba41c1 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -20,7 +20,7 @@  struct user_namespace init_user_ns = {  	.kref = { -		.refcount	= ATOMIC_INIT(1), +		.refcount	= ATOMIC_INIT(2),  	},  	.creator = &root_user,  }; @@ -286,14 +286,12 @@ int __init uids_sysfs_init(void)  /* work function to remove sysfs directory for a user and free up   * corresponding structures.   */ -static void remove_user_sysfs_dir(struct work_struct *w) +static void cleanup_user_struct(struct work_struct *w)  {  	struct user_struct *up = container_of(w, struct user_struct, work);  	unsigned long flags;  	int remove_user = 0; -	if (up->user_ns != &init_user_ns) -		return;  	/* Make uid_hash_remove() + sysfs_remove_file() + kobject_del()  	 * atomic.  	 */ @@ -312,9 +310,11 @@ static void remove_user_sysfs_dir(struct work_struct *w)  	if (!remove_user)  		goto done; -	kobject_uevent(&up->kobj, KOBJ_REMOVE); -	kobject_del(&up->kobj); -	kobject_put(&up->kobj); +	if (up->user_ns == &init_user_ns) { +		kobject_uevent(&up->kobj, KOBJ_REMOVE); +		kobject_del(&up->kobj); +		kobject_put(&up->kobj); +	}  	sched_destroy_user(up);  	key_put(up->uid_keyring); @@ -335,7 +335,7 @@ static void free_user(struct user_struct *up, unsigned long flags)  	atomic_inc(&up->__count);  	spin_unlock_irqrestore(&uidhash_lock, flags); -	INIT_WORK(&up->work, remove_user_sysfs_dir); +	INIT_WORK(&up->work, cleanup_user_struct);  	schedule_work(&up->work);  } @@ -362,6 +362,24 @@ static void free_user(struct user_struct *up, unsigned long flags)  #endif +#if defined(CONFIG_RT_GROUP_SCHED) && defined(CONFIG_USER_SCHED) +/* + * We need to check if a setuid can take place. This function should be called + * before successfully completing the setuid. + */ +int task_can_switch_user(struct user_struct *up, struct task_struct *tsk) +{ + +	return sched_rt_can_attach(up->tg, tsk); + +} +#else +int task_can_switch_user(struct user_struct *up, struct task_struct *tsk) +{ +	return 1; +} +#endif +  /*   * Locate the user_struct for the passed UID.  If found, take a ref on it.  The   * caller must undo that ref with free_uid().  |