Commit b789ebfc authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] fix current->user->processes leak

Patch from: Eric Lammerts <eric@lammerts.org>

Every time you do a loop mount, a kernel thread is started (those
processes are called "loop0", "loop1", etc.). The problem is that when
it starts, it's counted as one of your processes. Then, it's
changed to be a root-owned process without correcting that count.

Patch below fixes the problem. It moves the bookkeeping of changing
current->user to a new function switch_uid() (which is now also used
by exec_usermodehelper() in kmod.c). The patch is tested.
parent 3322be32
...@@ -509,6 +509,7 @@ extern void __set_special_pids(pid_t session, pid_t pgrp); ...@@ -509,6 +509,7 @@ extern void __set_special_pids(pid_t session, pid_t pgrp);
/* per-UID process charging. */ /* per-UID process charging. */
extern struct user_struct * alloc_uid(uid_t); extern struct user_struct * alloc_uid(uid_t);
extern void free_uid(struct user_struct *); extern void free_uid(struct user_struct *);
extern void switch_uid(struct user_struct *);
#include <asm/current.h> #include <asm/current.h>
......
...@@ -249,7 +249,7 @@ void reparent_to_init(void) ...@@ -249,7 +249,7 @@ void reparent_to_init(void)
/* signals? */ /* signals? */
security_task_reparent_to_init(current); security_task_reparent_to_init(current);
memcpy(current->rlim, init_task.rlim, sizeof(*(current->rlim))); memcpy(current->rlim, init_task.rlim, sizeof(*(current->rlim)));
current->user = INIT_USER; switch_uid(INIT_USER);
write_unlock_irq(&tasklist_lock); write_unlock_irq(&tasklist_lock);
} }
......
...@@ -121,15 +121,7 @@ int exec_usermodehelper(char *program_path, char *argv[], char *envp[]) ...@@ -121,15 +121,7 @@ int exec_usermodehelper(char *program_path, char *argv[], char *envp[])
if (curtask->files->fd[i]) close(i); if (curtask->files->fd[i]) close(i);
} }
/* Drop the "current user" thing */ switch_uid(INIT_USER);
{
struct user_struct *user = curtask->user;
curtask->user = INIT_USER;
atomic_inc(&INIT_USER->__count);
atomic_inc(&INIT_USER->processes);
atomic_dec(&user->processes);
free_uid(user);
}
/* Give kmod all effective privileges.. */ /* Give kmod all effective privileges.. */
curtask->euid = curtask->fsuid = 0; curtask->euid = curtask->fsuid = 0;
......
...@@ -561,19 +561,12 @@ asmlinkage long sys_setgid(gid_t gid) ...@@ -561,19 +561,12 @@ asmlinkage long sys_setgid(gid_t gid)
static int set_user(uid_t new_ruid, int dumpclear) static int set_user(uid_t new_ruid, int dumpclear)
{ {
struct user_struct *new_user, *old_user; struct user_struct *new_user;
/* What if a process setreuid()'s and this brings the
* new uid over his NPROC rlimit? We can check this now
* cheaply with the new uid cache, so if it matters
* we should be checking for it. -DaveM
*/
new_user = alloc_uid(new_ruid); new_user = alloc_uid(new_ruid);
if (!new_user) if (!new_user)
return -EAGAIN; return -EAGAIN;
old_user = current->user; switch_uid(new_user);
atomic_dec(&old_user->processes);
atomic_inc(&new_user->processes);
if(dumpclear) if(dumpclear)
{ {
...@@ -581,8 +574,6 @@ static int set_user(uid_t new_ruid, int dumpclear) ...@@ -581,8 +574,6 @@ static int set_user(uid_t new_ruid, int dumpclear)
wmb(); wmb();
} }
current->uid = new_ruid; current->uid = new_ruid;
current->user = new_user;
free_uid(old_user);
return 0; return 0;
} }
......
...@@ -116,6 +116,23 @@ struct user_struct * alloc_uid(uid_t uid) ...@@ -116,6 +116,23 @@ struct user_struct * alloc_uid(uid_t uid)
return up; return up;
} }
void switch_uid(struct user_struct *new_user)
{
struct user_struct *old_user;
/* What if a process setreuid()'s and this brings the
* new uid over his NPROC rlimit? We can check this now
* cheaply with the new uid cache, so if it matters
* we should be checking for it. -DaveM
*/
old_user = current->user;
atomic_inc(&new_user->__count);
atomic_inc(&new_user->processes);
atomic_dec(&old_user->processes);
current->user = new_user;
free_uid(old_user);
}
static int __init uid_cache_init(void) static int __init uid_cache_init(void)
{ {
......
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