Commit 475c3656 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] find_user locking and leak fix

find_user() is being called from set/get_priority(), but it doesn't take the
needed lock, and those callers were forgetting to drop the refcount which
find_user() took.
parent 5a80c2ea
...@@ -348,6 +348,8 @@ asmlinkage long sys_setpriority(int which, int who, int niceval) ...@@ -348,6 +348,8 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
if (p->uid == who) if (p->uid == who)
error = set_one_prio(p, niceval, error); error = set_one_prio(p, niceval, error);
while_each_thread(g, p); while_each_thread(g, p);
if (who)
free_uid(user); /* For find_user() */
break; break;
} }
out_unlock: out_unlock:
...@@ -410,6 +412,8 @@ asmlinkage long sys_getpriority(int which, int who) ...@@ -410,6 +412,8 @@ asmlinkage long sys_getpriority(int which, int who)
retval = niceval; retval = niceval;
} }
while_each_thread(g, p); while_each_thread(g, p);
if (who)
free_uid(user); /* for find_user() */
break; break;
} }
out_unlock: out_unlock:
......
...@@ -64,9 +64,20 @@ static inline struct user_struct *uid_hash_find(uid_t uid, struct list_head *has ...@@ -64,9 +64,20 @@ static inline struct user_struct *uid_hash_find(uid_t uid, struct list_head *has
return NULL; return NULL;
} }
/*
* Locate the user_struct for the passed UID. If found, take a ref on it. The
* caller must undo that ref with free_uid().
*
* If the user_struct could not be found, return NULL.
*/
struct user_struct *find_user(uid_t uid) struct user_struct *find_user(uid_t uid)
{ {
return uid_hash_find(uid, uidhashentry(uid)); struct user_struct *ret;
spin_lock(&uidhash_lock);
ret = uid_hash_find(uid, uidhashentry(uid));
spin_unlock(&uidhash_lock);
return ret;
} }
void free_uid(struct user_struct *up) void free_uid(struct user_struct *up)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment