Subject: [PATCH] Rewrite pspace handling so no mapping of process ids is required. From: Eric W. Biederman Date: 1130172167 -0600 --- arch/alpha/kernel/asm-offsets.c | 1 arch/alpha/kernel/entry.S | 25 ++++- arch/alpha/kernel/process.c | 11 -- arch/i386/kernel/crash.c | 2 arch/i386/kernel/process.c | 14 +-- arch/i386/kernel/ptrace.c | 3 - arch/i386/kernel/traps.c | 2 arch/i386/mm/fault.c | 2 drivers/block/cfq-iosched.c | 4 - drivers/block/ll_rw_blk.c | 2 drivers/char/keyboard.c | 7 + drivers/char/n_tty.c | 9 +- drivers/char/random.c | 2 drivers/char/sysrq.c | 2 drivers/char/tty_io.c | 92 +++++++++++++------ drivers/char/vt.c | 9 +- drivers/char/vt_ioctl.c | 24 ++++- fs/binfmt_elf.c | 8 +- fs/dnotify.c | 2 fs/exec.c | 2 fs/ext2/inode.c | 2 fs/ext3/inode.c | 2 fs/fcntl.c | 26 +++-- fs/file_table.c | 2 fs/fs-writeback.c | 2 fs/ioprio.c | 16 +-- fs/lockd/clntproc.c | 6 + fs/lockd/svc.c | 10 +- fs/locks.c | 2 fs/nfs/file.c | 4 - fs/nfs/nfs3proc.c | 2 fs/nfs/nfs4proc.c | 4 - fs/proc/array.c | 41 ++++----- fs/proc/base.c | 117 +++++++++++++++---------- fs/proc/internal.h | 8 +- fs/proc/root.c | 16 ++- include/linux/console_struct.h | 2 include/linux/fs.h | 1 include/linux/kernel.h | 3 - include/linux/pid.h | 25 +++-- include/linux/proc_fs.h | 2 include/linux/pspace.h | 55 +++++------- include/linux/sched.h | 31 +++---- include/linux/tty.h | 3 - ipc/msg.c | 10 +- ipc/sem.c | 2 ipc/shm.c | 8 +- kernel/capability.c | 185 ++++++++++++++++++++------------------- kernel/exit.c | 91 ++++++++++--------- kernel/fork.c | 38 +++----- kernel/futex.c | 2 kernel/kexec.c | 2 kernel/kthread.c | 2 kernel/pid.c | 178 +++++++++++++++----------------------- kernel/posix-cpu-timers.c | 10 +- kernel/posix-timers.c | 2 kernel/ptrace.c | 3 - kernel/sched.c | 14 +-- kernel/signal.c | 82 ++++++++--------- kernel/stop_machine.c | 2 kernel/sys.c | 65 ++++++-------- kernel/sysctl.c | 2 kernel/timer.c | 22 +++-- mm/oom_kill.c | 6 + mm/vmscan.c | 2 net/core/rtnetlink.c | 2 net/ipv4/devinet.c | 2 net/ipv4/fib_semantics.c | 2 net/ipv4/tcp.c | 2 net/netlink/af_netlink.c | 2 net/sunrpc/sched.c | 2 security/commoncap.c | 2 72 files changed, 697 insertions(+), 650 deletions(-) 8e378e4cd9d031949a1c4976046da74c28cd4a36 diff --git a/arch/alpha/kernel/asm-offsets.c b/arch/alpha/kernel/asm-offsets.c index 8f2e5c7..6c56c75 100644 --- a/arch/alpha/kernel/asm-offsets.c +++ b/arch/alpha/kernel/asm-offsets.c @@ -28,6 +28,7 @@ void foo(void) DEFINE(TASK_GID, offsetof(struct task_struct, gid)); DEFINE(TASK_EGID, offsetof(struct task_struct, egid)); DEFINE(TASK_REAL_PARENT, offsetof(struct task_struct, real_parent)); + DEFINE(TASK_GROUP_LEADER, offsetof(struct task_struct, group_leader)); DEFINE(TASK_TGID, offsetof(struct task_struct, tgid)); BLANK(); diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 780cb93..abaebee 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -874,15 +874,28 @@ sys_getxgid: .globl sys_getxpid .ent sys_getxpid sys_getxpid: - lda $sp, -16($sp) - stq $26, 0($sp) .prologue 0 + ldq $2, TI_TASK($8) - lda $16, 96($sp) - jsr $26, do_getxpid - ldq $26, 0($sp) + /* See linux/kernel/timer.c sys_getppid for discussion + about this loop. */ + ldq $3, TASK_GROUP_LEADER($2) + ldq $4, TASK_REAL_PARENT($3) + ldl $0, TASK_TGID($2) +1: ldl $1, TASK_TGID($4) +#ifdef CONFIG_SMP + mov $4, $5 + mb + + ldq $3, TASK_GROUP_LEADER($2) + ldq $4, TASK_REAL_PARENT($3) + cmpeq $4, $5, $5 + beq $5, 1b +#endif + cmpeq $0, 1, $5 + cmoveq $5, 0, $1 - lda $sp, 16($sp) + stq $1, 80($sp) ret .end sys_getxpid diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index dd7baf0..eb20c3a 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -528,13 +527,3 @@ get_wchan(struct task_struct *p) } return pc; } - -asmlinkage long do_getxpid(long *ppid) -{ - /* The assembly version as getting out of sync with - * sys_getpid and sys_getppid in timer.c so just call - * them and stop optimizing infrequently called functions. - */ - *ppid = sys_getppid(); - return sys_getpid(); -} diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c index 0248e08..7c64287 100644 --- a/arch/i386/kernel/crash.c +++ b/arch/i386/kernel/crash.c @@ -74,7 +74,7 @@ static void crash_save_this_cpu(struct p */ buf = &crash_notes[cpu][0]; memset(&prstatus, 0, sizeof(prstatus)); - prstatus.pr_pid = current->pid; + prstatus.pr_pid = current->tid; elf_core_copy_regs(&prstatus.pr_reg, regs); buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus, sizeof(prstatus)); diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index c250e71..b9b4726 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include @@ -297,7 +296,7 @@ void show_regs(struct pt_regs * regs) unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; printk("\n"); - printk("Pid: %d, comm: %20s\n", current->pid, current->comm); + printk("Pid: %d, comm: %20s\n", current->tid, current->comm); printk("EIP: %04x:[<%08lx>] CPU: %d\n",0xffff & regs->xcs,regs->eip, smp_processor_id()); print_symbol("EIP is at %s\n", regs->eip); @@ -739,13 +738,11 @@ struct task_struct fastcall * __switch_t asmlinkage int sys_fork(struct pt_regs regs) { - int ret = do_fork(SIGCHLD, regs.esp, ®s, 0, NULL, NULL); - return (ret > 0)? pid_to_user(ret) : ret; + return do_fork(SIGCHLD, regs.esp, ®s, 0, NULL, NULL); } asmlinkage int sys_clone(struct pt_regs regs) { - int ret; unsigned long clone_flags; unsigned long newsp; int __user *parent_tidptr, *child_tidptr; @@ -756,8 +753,7 @@ asmlinkage int sys_clone(struct pt_regs child_tidptr = (int __user *)regs.edi; if (!newsp) newsp = regs.esp; - ret = do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr); - return (ret > 0)? pid_to_user(ret) : ret; + return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr); } /* @@ -772,9 +768,7 @@ asmlinkage int sys_clone(struct pt_regs */ asmlinkage int sys_vfork(struct pt_regs regs) { - int ret; - ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0, NULL, NULL); - return (ret > 0)? pid_to_user(ret) : ret; + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0, NULL, NULL); } /* diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index bc6646b..e77a4a1 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -362,7 +362,6 @@ asmlinkage int sys_ptrace(long request, int i, ret; unsigned long __user *datap = (unsigned long __user *)data; - pid = pid_from_user(pid); lock_kernel(); ret = -EPERM; if (request == PTRACE_TRACEME) { @@ -379,7 +378,7 @@ asmlinkage int sys_ptrace(long request, } ret = -ESRCH; read_lock(&tasklist_lock); - child = find_task_by_pid(pid); + child = find_task_by_pid(current->pspace, pid); if (child) get_task_struct(child); read_unlock(&tasklist_lock); diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 19e90bd..36b1078 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -228,7 +228,7 @@ void show_registers(struct pt_regs *regs printk("ds: %04x es: %04x ss: %04x\n", regs->xds & 0xffff, regs->xes & 0xffff, ss); printk("Process %s (pid: %d, threadinfo=%p task=%p)", - current->comm, current->pid, current_thread_info(), current); + current->comm, current->tid, current_thread_info(), current); /* * When in-kernel, we also print out the stack and code at the * time of the fault.. diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index 9edd448..f64208f 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -485,7 +485,7 @@ no_context: */ out_of_memory: up_read(&mm->mmap_sem); - if (tsk->pid == 1) { + if (tsk->wid == 1) { yield(); down_read(&mm->mmap_sem); goto survive; diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c index cd056e7..a69c660 100644 --- a/drivers/block/cfq-iosched.c +++ b/drivers/block/cfq-iosched.c @@ -654,7 +654,7 @@ cfq_reposition_crq_rb(struct cfq_queue * static struct request *cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector) { - struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, current->pid, CFQ_KEY_ANY); + struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, current->tid, CFQ_KEY_ANY); struct rb_node *n; if (!cfqq) @@ -1952,7 +1952,7 @@ static void cfq_prio_boost(struct cfq_qu static inline pid_t cfq_queue_pid(struct task_struct *task, int rw) { if (rw == READ || process_sync(task)) - return task->pid; + return task->tid; return CFQ_KEY_ASYNC; } diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index baedac5..2da40e7 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -3022,7 +3022,7 @@ void submit_bio(int rw, struct bio *bio) if (unlikely(block_dump)) { char b[BDEVNAME_SIZE]; printk(KERN_DEBUG "%s(%d): %s block %Lu on %s\n", - current->comm, current->pid, + current->comm, current->tid, (rw & WRITE) ? "WRITE" : "READ", (unsigned long long)bio->bi_sector, bdevname(bio->bi_bdev,b)); diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 449d029..3eaff2e 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -109,6 +110,7 @@ struct kbd_struct kbd_table[MAX_NR_CONSO static struct kbd_struct *kbd = kbd_table; static struct kbd_struct kbd0; +struct pspace *spawn_pspace = NULL; int spawnpid, spawnsig; /* @@ -568,8 +570,11 @@ static void fn_compose(struct vc_data *v static void fn_spawn_con(struct vc_data *vc, struct pt_regs *regs) { if (spawnpid) - if (kill_proc(spawnpid, spawnsig, 1)) + if (kill_proc(spawn_pspace, spawnpid, spawnsig, 1)) { + put_pspace(spawn_pspace); + spawn_pspace = NULL; spawnpid = 0; + } } static void fn_SAK(struct vc_data *vc, struct pt_regs *regs) diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index c9bdf54..9713eca 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -554,7 +554,7 @@ static void eraser(unsigned char c, stru static inline void isig(int sig, struct tty_struct *tty, int flush) { if (tty->pgrp > 0) - kill_pg(tty->pgrp, sig, 1); + kill_pg(tty->pspace, tty->pgrp, sig, 1); if (flush || !L_NOFLSH(tty)) { n_tty_flush_buffer(tty); if (tty->driver->flush_buffer) @@ -1181,11 +1181,12 @@ static int job_control(struct tty_struct current->signal->tty == tty) { if (tty->pgrp <= 0) printk("read_chan: tty->pgrp <= 0!\n"); - else if (process_group(current) != tty->pgrp) { + else if ((process_group(current) != tty->pgrp) || (current->pspace != tty->pspace)) + { if (is_ignored(SIGTTIN) || - is_orphaned_pgrp(process_group(current))) + is_orphaned_pgrp(current->pspace, process_group(current))) return -EIO; - kill_pg(process_group(current), SIGTTIN, 1); + kill_pg(current->pspace, process_group(current), SIGTTIN, 1); return -ERESTARTSYS; } } diff --git a/drivers/char/random.c b/drivers/char/random.c index 7999da2..913e749 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1640,7 +1640,7 @@ unsigned int get_random_int(void) * drain on it), and uses halfMD4Transform within the second. We * also mix it with jiffies and the PID: */ - return secure_ip_id(current->pid + jiffies); + return secure_ip_id(current->tid + jiffies); } /* diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index feb2515..2f32ab9 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -207,7 +207,7 @@ static void send_sig_all(int sig) struct task_struct *p; for_each_process(p) { - if (p->mm && p->pid != 1) + if (p->mm && p->wid != 1) /* Not swapper, init nor kernel thread */ force_sig(sig, p); } diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index c9eb74a..7a27461 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -651,13 +651,14 @@ int tty_check_change(struct tty_struct * printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n"); return 0; } - if (process_group(current) == tty->pgrp) + if ((process_group(current) == tty->pgrp) && + (current->pspace == tty->pspace)) return 0; if (is_ignored(SIGTTOU)) return 0; - if (is_orphaned_pgrp(process_group(current))) + if (is_orphaned_pgrp(current->pspace, process_group(current))) return -EIO; - (void) kill_pg(process_group(current), SIGTTOU, 1); + (void) kill_pg(current->pspace, process_group(current), SIGTTOU, 1); return -ERESTARTSYS; } @@ -863,7 +864,7 @@ static void do_tty_hangup(void *data) read_lock(&tasklist_lock); if (tty->session > 0) { - do_each_task_pid(tty->session, PIDTYPE_SID, p) { + do_each_task_pid(tty->pspace, tty->session, PIDTYPE_SID, p) { if (p->signal->tty == tty) p->signal->tty = NULL; if (!p->signal->leader) @@ -872,13 +873,15 @@ static void do_tty_hangup(void *data) send_group_sig_info(SIGCONT, SEND_SIG_PRIV, p); if (tty->pgrp > 0) p->signal->tty_old_pgrp = tty->pgrp; - } while_each_task_pid(tty->session, PIDTYPE_SID, p); + } while_each_task_pid(tty->pspace, tty->session, PIDTYPE_SID, p); } read_unlock(&tasklist_lock); tty->flags = 0; + put_pspace(tty->pspace); + tty->pspace = NULL; tty->session = 0; - tty->pgrp = -1; + tty->pgrp = -1; tty->ctrl_status = 0; /* * If one of the devices matches a console pointer, we @@ -955,6 +958,7 @@ void disassociate_ctty(int on_exit) { struct tty_struct *tty; struct task_struct *p; + struct pspace *tty_pspace = NULL; int tty_pgrp = -1; lock_kernel(); @@ -963,35 +967,42 @@ void disassociate_ctty(int on_exit) tty = current->signal->tty; if (tty) { tty_pgrp = tty->pgrp; + tty_pspace = tty->pspace; + get_pspace(tty_pspace); up(&tty_sem); if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) tty_vhangup(tty); } else { if (current->signal->tty_old_pgrp) { - kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit); - kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit); + kill_pg(current->pspace, current->signal->tty_old_pgrp, SIGHUP, on_exit); + kill_pg(current->pspace, current->signal->tty_old_pgrp, SIGCONT, on_exit); } up(&tty_sem); unlock_kernel(); return; } if (tty_pgrp > 0) { - kill_pg(tty_pgrp, SIGHUP, on_exit); + kill_pg(tty_pspace, tty_pgrp, SIGHUP, on_exit); if (!on_exit) - kill_pg(tty_pgrp, SIGCONT, on_exit); + kill_pg(tty_pspace, tty_pgrp, SIGCONT, on_exit); + } + if (tty_pspace) { + put_pspace(tty_pspace); } /* Must lock changes to tty_old_pgrp */ down(&tty_sem); current->signal->tty_old_pgrp = 0; + put_pspace(tty->pspace); + tty->pspace = NULL; tty->session = 0; tty->pgrp = -1; /* Now clear signal->tty under the lock */ read_lock(&tasklist_lock); - do_each_task_pid(current->signal->session, PIDTYPE_SID, p) { + do_each_task_pid(current->pspace, current->signal->session, PIDTYPE_SID, p) { p->signal->tty = NULL; - } while_each_task_pid(current->signal->session, PIDTYPE_SID, p); + } while_each_task_pid(current->pspace, current->signal->session, PIDTYPE_SID, p); read_unlock(&tasklist_lock); up(&tty_sem); unlock_kernel(); @@ -1701,13 +1712,22 @@ static void release_dev(struct file * fi struct task_struct *p; read_lock(&tasklist_lock); - do_each_task_pid(tty->session, PIDTYPE_SID, p) { + do_each_task_pid(tty->pspace, tty->session, PIDTYPE_SID, p) { p->signal->tty = NULL; - } while_each_task_pid(tty->session, PIDTYPE_SID, p); - if (o_tty) - do_each_task_pid(o_tty->session, PIDTYPE_SID, p) { + } while_each_task_pid(tty->pspace, tty->session, PIDTYPE_SID, p); + put_pspace(tty->pspace); + tty->pspace = NULL; + tty->session = 0; + tty->pgrp = -1; + if (o_tty) { + do_each_task_pid(o_tty->pspace, o_tty->session, PIDTYPE_SID, p) { p->signal->tty = NULL; - } while_each_task_pid(o_tty->session, PIDTYPE_SID, p); + } while_each_task_pid(o_tty->pspace, o_tty->session, PIDTYPE_SID, p); + put_pspace(o_tty->pspace); + o_tty->pspace = NULL; + o_tty->session = 0; + o_tty->pgrp = -1; + } read_unlock(&tasklist_lock); } @@ -1906,6 +1926,8 @@ got_driver: current->signal->tty = tty; task_unlock(current); current->signal->tty_old_pgrp = 0; + get_pspace(current->pspace); + tty->pspace = current->pspace; tty->session = current->signal->session; tty->pgrp = process_group(current); } @@ -2013,7 +2035,7 @@ static int tty_fasync(int fd, struct fil if (on) { if (!waitqueue_active(&tty->read_wait)) tty->minimum_to_wake = 1; - retval = f_setown(filp, (-tty->pgrp) ? : current->pid, 0); + retval = f_setown(filp, (-tty->pgrp) ? : current->tid, 0); if (retval) return retval; } else { @@ -2066,9 +2088,9 @@ static int tiocswinsz(struct tty_struct } #endif if (tty->pgrp > 0) - kill_pg(tty->pgrp, SIGWINCH, 1); + kill_pg(tty->pspace, tty->pgrp, SIGWINCH, 1); if ((real_tty->pgrp != tty->pgrp) && (real_tty->pgrp > 0)) - kill_pg(real_tty->pgrp, SIGWINCH, 1); + kill_pg(real_tty->pspace, real_tty->pgrp, SIGWINCH, 1); tty->winsize = tmp_ws; real_tty->winsize = tmp_ws; return 0; @@ -2138,10 +2160,14 @@ static int tiocsctty(struct tty_struct * */ read_lock(&tasklist_lock); - do_each_task_pid(tty->session, PIDTYPE_SID, p) { + do_each_task_pid(tty->pspace, tty->session, PIDTYPE_SID, p) { p->signal->tty = NULL; - } while_each_task_pid(tty->session, PIDTYPE_SID, p); + } while_each_task_pid(tty->pspace, tty->session, PIDTYPE_SID, p); read_unlock(&tasklist_lock); + put_pspace(tty->pspace); + tty->pspace = NULL; + tty->session = 0; + tty->pgrp = -1; } else return -EPERM; } @@ -2149,6 +2175,8 @@ static int tiocsctty(struct tty_struct * current->signal->tty = tty; task_unlock(current); current->signal->tty_old_pgrp = 0; + get_pspace(current->pspace); + tty->pspace = current->pspace; tty->session = current->signal->session; tty->pgrp = process_group(current); return 0; @@ -2156,13 +2184,17 @@ static int tiocsctty(struct tty_struct * static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) { + pid_t pgrp; /* * (tty == real_tty) is a cheap way of * testing if the tty is NOT a master pty. */ if (tty == real_tty && current->signal->tty != real_tty) return -ENOTTY; - return put_user(pid_to_user(real_tty->pgrp), p); + pgrp = real_tty->pgrp; + if (real_tty->pspace != current->pspace) + pgrp = -1; + return put_user(pgrp, p); } static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) @@ -2176,14 +2208,14 @@ static int tiocspgrp(struct tty_struct * return retval; if (!current->signal->tty || (current->signal->tty != real_tty) || - (real_tty->session != current->signal->session)) + (real_tty->session != current->signal->session) || + (real_tty->pspace != current->pspace)) return -ENOTTY; if (get_user(pgrp, p)) return -EFAULT; if (pgrp < 0) return -EINVAL; - pgrp = pid_from_user(pgrp); - if (session_of_pgrp(pgrp) != current->signal->session) + if (session_of_pgrp(current->pspace, pgrp) != current->signal->session) return -EPERM; real_tty->pgrp = pgrp; return 0; @@ -2472,11 +2504,11 @@ static void __do_SAK(void *arg) tty->driver->flush_buffer(tty); read_lock(&tasklist_lock); - do_each_task_pid(session, PIDTYPE_SID, p) { + do_each_task_pid(tty->pspace, session, PIDTYPE_SID, p) { if (p->signal->tty == tty || session > 0) { printk(KERN_NOTICE "SAK: killed process %d" " (%s): p->signal->session==tty->session\n", - p->pid, p->comm); + p->tid, p->comm); send_sig(SIGKILL, p, 1); continue; } @@ -2492,7 +2524,7 @@ static void __do_SAK(void *arg) filp->private_data == tty) { printk(KERN_NOTICE "SAK: killed process %d" " (%s): fd#%d opened to the tty\n", - p->pid, p->comm, i); + p->tid, p->comm, i); send_sig(SIGKILL, p, 1); break; } @@ -2500,7 +2532,7 @@ static void __do_SAK(void *arg) rcu_read_unlock(); } task_unlock(p); - } while_each_task_pid(session, PIDTYPE_SID, p); + } while_each_task_pid(tty->pspace, session, PIDTYPE_SID, p); read_unlock(&tasklist_lock); #endif } diff --git a/drivers/char/vt.c b/drivers/char/vt.c index e91268e..494e8f7 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -93,6 +93,7 @@ #include #include #include +#include #include #include @@ -856,7 +857,7 @@ int vc_resize(struct vc_data *vc, unsign ws.ws_ypixel = vc->vc_scan_lines; if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) && vc->vc_tty->pgrp > 0) - kill_pg(vc->vc_tty->pgrp, SIGWINCH, 1); + kill_pg(vc->vc_tty->pspace, vc->vc_tty->pgrp, SIGWINCH, 1); *cws = ws; } @@ -873,10 +874,12 @@ void vc_disallocate(unsigned int currcon if (vc_cons_allocated(currcons)) { struct vc_data *vc = vc_cons[currcons].d; vc->vc_sw->con_deinit(vc); + put_pspace(vc->vt_pspace); + vc->vt_pspace = NULL; + vc->vt_pid = -1; if (vc->vc_kmalloced) kfree(vc->vc_screenbuf); - if (currcons >= MIN_NR_CONSOLES) - kfree(vc); + kfree(vc); vc_cons[currcons].d = NULL; } } diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 1d44f69..695e06a 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -640,12 +641,16 @@ int vt_ioctl(struct tty_struct *tty, str */ case KDSIGACCEPT: { + extern struct pspace *spawn_pspace; extern int spawnpid, spawnsig; if (!perm || !capable(CAP_KILL)) return -EPERM; if (!valid_signal(arg) || arg < 1 || arg == SIGKILL) return -EINVAL; - spawnpid = current->pid; + put_pspace(spawn_pspace); + get_pspace(current->pspace); + spawn_pspace = current->pspace; + spawnpid = current->tgid; spawnsig = arg; return 0; } @@ -661,10 +666,19 @@ int vt_ioctl(struct tty_struct *tty, str if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) return -EINVAL; acquire_console_sem(); + if (vc->vt_mode.mode == VT_PROCESS) { + put_pspace(vc->vt_pspace); + vc->vt_pspace = NULL; + vc->vt_pid = -1; + } vc->vt_mode = tmp; /* the frsig is ignored, so we set it to 0 */ vc->vt_mode.frsig = 0; - vc->vt_pid = current->pid; + if (vc->vt_mode.mode == VT_PROCESS) { + get_pspace(current->pspace); + vc->vt_pspace = current->pspace; + vc->vt_pid = current->tgid; + } /* no switch is required -- saw@shade.msu.ru */ vc->vt_newvt = -1; release_console_sem(); @@ -1056,6 +1070,8 @@ void reset_vc(struct vc_data *vc) vc->vt_mode.relsig = 0; vc->vt_mode.acqsig = 0; vc->vt_mode.frsig = 0; + put_pspace(vc->vt_pspace); + vc->vt_pspace = NULL; vc->vt_pid = -1; vc->vt_newvt = -1; if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */ @@ -1107,7 +1123,7 @@ static void complete_change_console(stru * tell us if the process has gone or something else * is awry */ - if (kill_proc(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) { + if (kill_proc(vc->vt_pspace, vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) { /* * The controlling process has died, so we revert back to * normal operation. In this case, we'll also change back @@ -1167,7 +1183,7 @@ void change_console(struct vc_data *new_ * tell us if the process has gone or something else * is awry */ - if (kill_proc(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { + if (kill_proc(vc->vt_pspace, vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { /* * It worked. Mark the vt to switch to and * return. The process needs to send us a diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 7976a23..29b34f3 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1272,8 +1272,8 @@ static void fill_prstatus(struct elf_prs prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; prstatus->pr_sigpend = p->pending.signal.sig[0]; prstatus->pr_sighold = p->blocked.sig[0]; - prstatus->pr_pid = p->pid; - prstatus->pr_ppid = p->parent->pid; + prstatus->pr_pid = p->tid; + prstatus->pr_ppid = p->parent->tid; prstatus->pr_pgrp = process_group(p); prstatus->pr_sid = p->signal->session; if (thread_group_leader(p)) { @@ -1318,8 +1318,8 @@ static int fill_psinfo(struct elf_prpsin psinfo->pr_psargs[i] = ' '; psinfo->pr_psargs[len] = 0; - psinfo->pr_pid = p->pid; - psinfo->pr_ppid = p->parent->pid; + psinfo->pr_pid = p->tid; + psinfo->pr_ppid = p->parent->tid; psinfo->pr_pgrp = process_group(p); psinfo->pr_sid = p->signal->session; diff --git a/fs/dnotify.c b/fs/dnotify.c index f3b540d..3320d86 100644 --- a/fs/dnotify.c +++ b/fs/dnotify.c @@ -92,7 +92,7 @@ int fcntl_dirnotify(int fd, struct file prev = &odn->dn_next; } - error = f_setown(filp, current->pid, 0); + error = f_setown(filp, current->tid, 0); if (error) goto out_free; diff --git a/fs/exec.c b/fs/exec.c index b872f2c..c9001c2 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -688,7 +688,7 @@ static inline int de_thread(struct task_ write_lock_irq(&tasklist_lock); BUG_ON(leader->tgid != current->tgid); - BUG_ON(current->pid == current->tgid); + BUG_ON(current->tid == current->tgid); /* * An exec() starts a new thread group with the * TGID of the previous thread group. Rehash the diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index fdba4d1..73a760d 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -344,7 +344,7 @@ static unsigned long ext2_find_near(stru */ bg_start = (ei->i_block_group * EXT2_BLOCKS_PER_GROUP(inode->i_sb)) + le32_to_cpu(EXT2_SB(inode->i_sb)->s_es->s_first_data_block); - colour = (current->pid % 16) * + colour = (current->tgid % 16) * (EXT2_BLOCKS_PER_GROUP(inode->i_sb) / 16); return bg_start + colour; } diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index b5177c9..ab5c560 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -443,7 +443,7 @@ static unsigned long ext3_find_near(stru */ bg_start = (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) + le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block); - colour = (current->pid % 16) * + colour = (current->tgid % 16) * (EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16); return bg_start + colour; } diff --git a/fs/fcntl.c b/fs/fcntl.c index b79c2ab..9a4c22a 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -248,11 +248,14 @@ static int setfl(int fd, struct file * f return error; } -static void f_modown(struct file *filp, unsigned long pid, +static void f_modown(struct file *filp, struct pspace *pspace, unsigned long pid, uid_t uid, uid_t euid, int force) { write_lock_irq(&filp->f_owner.lock); if (force || !filp->f_owner.pid) { + put_pspace(filp->f_owner.pspace); + get_pspace(pspace); + filp->f_owner.pspace = pspace; filp->f_owner.pid = pid; filp->f_owner.uid = uid; filp->f_owner.euid = euid; @@ -268,7 +271,7 @@ int f_setown(struct file *filp, unsigned if (err) return err; - f_modown(filp, arg, current->uid, current->euid, force); + f_modown(filp, current->pspace, arg, current->uid, current->euid, force); return 0; } @@ -276,7 +279,7 @@ EXPORT_SYMBOL(f_setown); void f_delown(struct file *filp) { - f_modown(filp, 0, 0, 0, 1); + f_modown(filp, NULL, 0, 0, 0, 1); } static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, @@ -318,11 +321,12 @@ static long do_fcntl(int fd, unsigned in * to fix this will be in libc. */ err = filp->f_owner.pid; - err = (err >= 0)? pid_to_user(err) : -pid_to_user(-err); + /* Don't return an owner in a different pspace */ + if (filp->f_owner.pspace != current->pspace) + err = 0; force_successful_syscall_return(); break; case F_SETOWN: - arg = (arg >= 0)? pid_from_user(arg) : -pid_from_user(-arg); err = f_setown(filp, arg, 1); break; case F_GETSIG: @@ -480,14 +484,14 @@ void send_sigio(struct fown_struct *fown read_lock(&tasklist_lock); if (pid > 0) { - p = find_task_by_pid(pid); + p = find_task_by_pid(fown->pspace, pid); if (p) { send_sigio_to_task(p, fown, fd, band); } } else { - do_each_task_pid(-pid, PIDTYPE_PGID, p) { + do_each_task_pid(fown->pspace, -pid, PIDTYPE_PGID, p) { send_sigio_to_task(p, fown, fd, band); - } while_each_task_pid(-pid, PIDTYPE_PGID, p); + } while_each_task_pid(fown->pspace, -pid, PIDTYPE_PGID, p); } read_unlock(&tasklist_lock); out_unlock_fown: @@ -515,14 +519,14 @@ int send_sigurg(struct fown_struct *fown read_lock(&tasklist_lock); if (pid > 0) { - p = find_task_by_pid(pid); + p = find_task_by_pid(fown->pspace, pid); if (p) { send_sigurg_to_task(p, fown); } } else { - do_each_task_pid(-pid, PIDTYPE_PGID, p) { + do_each_task_pid(fown->pspace, -pid, PIDTYPE_PGID, p) { send_sigurg_to_task(p, fown); - } while_each_task_pid(-pid, PIDTYPE_PGID, p); + } while_each_task_pid(fown->pspace, -pid, PIDTYPE_PGID, p); } read_unlock(&tasklist_lock); out_unlock_fown: diff --git a/fs/file_table.c b/fs/file_table.c index 86ec8ae..e5b2ad2 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -18,6 +18,7 @@ #include #include #include +#include /* sysctl tunables... */ struct files_stat_struct files_stat = { @@ -145,6 +146,7 @@ void fastcall __fput(struct file *file) if (file->f_op && file->f_op->release) file->f_op->release(inode, file); security_file_free(file); + put_pspace(file->f_owner.pspace); if (unlikely(inode->i_cdev != NULL)) cdev_put(inode->i_cdev); fops_put(file->f_op); diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index e94ab39..6384bfd 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -89,7 +89,7 @@ void __mark_inode_dirty(struct inode *in if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) printk(KERN_DEBUG "%s(%d): dirtied inode %lu (%s) on %s\n", - current->comm, current->pid, inode->i_ino, + current->comm, current->tid, inode->i_ino, name, inode->i_sb->s_id); } diff --git a/fs/ioprio.c b/fs/ioprio.c index 21e4cfe..2ba8dd2 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c @@ -77,20 +77,18 @@ asmlinkage long sys_ioprio_set(int which if (!who) p = current; else - p = find_task_by_pid(pid_from_user(who)); + p = find_task_by_pid(current->pspace, who); if (p) ret = set_task_ioprio(p, ioprio); break; case IOPRIO_WHO_PGRP: if (!who) who = process_group(current); - else - who = pid_from_user(who); - do_each_task_pid(who, PIDTYPE_PGID, p) { + do_each_task_pid(current->pspace, who, PIDTYPE_PGID, p) { ret = set_task_ioprio(p, ioprio); if (ret) break; - } while_each_task_pid(who, PIDTYPE_PGID, p); + } while_each_task_pid(current->pspace, who, PIDTYPE_PGID, p); break; case IOPRIO_WHO_USER: if (!who) @@ -132,21 +130,19 @@ asmlinkage long sys_ioprio_get(int which if (!who) p = current; else - p = find_task_by_pid(pid_from_user(who)); + p = find_task_by_pid(current->pspace, who); if (p) ret = p->ioprio; break; case IOPRIO_WHO_PGRP: if (!who) who = process_group(current); - else - who = pid_from_user(who); - do_each_task_pid(who, PIDTYPE_PGID, p) { + do_each_task_pid(current->pspace, who, PIDTYPE_PGID, p) { if (ret == -ESRCH) ret = p->ioprio; else ret = ioprio_best(ret, p->ioprio); - } while_each_task_pid(who, PIDTYPE_PGID, p); + } while_each_task_pid(current->pspace, who, PIDTYPE_PGID, p); break; case IOPRIO_WHO_USER: if (!who) diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 87332f3..26d0be5 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -131,7 +131,7 @@ static void nlmclnt_setlockargs(struct n lock->caller = system_utsname.nodename; lock->oh.data = req->a_owner; lock->oh.len = sprintf(req->a_owner, "%d@%s", - current->pid, system_utsname.nodename); + current->tid, system_utsname.nodename); locks_copy_lock(&lock->fl, fl); } @@ -524,8 +524,8 @@ static void do_vfs_lock(struct file_lock BUG(); } if (res < 0) - printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", - __FUNCTION__); + printk(KERN_WARNING "%s:%s: VFS is out of sync with lock manager!\n", + __FILE__, __func__); } /* diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 12a857c..7645512 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -111,7 +112,8 @@ lockd(struct svc_rqst *rqstp) /* * Let our maker know we're running. */ - nlmsvc_pid = current->pid; + nlmsvc_pid = current->tid; + BUG_ON(current->pspace != &init_pspace); up(&lockd_start); daemonize("lockd"); @@ -135,7 +137,7 @@ lockd(struct svc_rqst *rqstp) * NFS mount or NFS daemon has gone away, and we've been sent a * signal, or else another process has taken over our job. */ - while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->pid) { + while ((nlmsvc_users || !signalled()) && nlmsvc_pid == current->tid) { long timeout = MAX_SCHEDULE_TIMEOUT; if (signalled()) { @@ -182,7 +184,7 @@ lockd(struct svc_rqst *rqstp) * Check whether there's a new lockd process before * shutting down the hosts and clearing the slot. */ - if (!nlmsvc_pid || current->pid == nlmsvc_pid) { + if (!nlmsvc_pid || current->tid == nlmsvc_pid) { if (nlmsvc_ops) nlmsvc_invalidate_all(); nlm_shutdown_hosts(); @@ -299,7 +301,7 @@ lockd_down(void) } warned = 0; - kill_proc(nlmsvc_pid, SIGKILL, 1); + kill_proc(&init_pspace, nlmsvc_pid, SIGKILL, 1); /* * Wait for the lockd process to exit, but since we're holding * the lockd semaphore, we can't wait around forever ... diff --git a/fs/locks.c b/fs/locks.c index f7daa5f..8423e0f 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1430,7 +1430,7 @@ int fcntl_setlease(unsigned int fd, stru goto out_unlock; } - error = f_setown(filp, current->pid, 0); + error = f_setown(filp, current->tid, 0); out_unlock: unlock_kernel(); return error; diff --git a/fs/nfs/file.c b/fs/nfs/file.c index f6b9eda..1eaa166 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -407,8 +407,8 @@ static int do_vfs_lock(struct file *file BUG(); } if (res < 0) - printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", - __FUNCTION__); + printk(KERN_WARNING "%s:%s: VFS is out of sync with lock manager!\n", + __FILE__, __func__); return res; } diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index edc9551..dea7de0 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -323,7 +323,7 @@ nfs3_proc_create(struct inode *dir, stru if (flags & O_EXCL) { arg.createmode = NFS3_CREATE_EXCLUSIVE; arg.verifier[0] = jiffies; - arg.verifier[1] = current->pid; + arg.verifier[1] = current->tid; } sattr->ia_mode &= ~current->fs->umask; diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 9701ca8..f5d68ea 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2691,8 +2691,8 @@ static int do_vfs_lock(struct file *file BUG(); } if (res < 0) - printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", - __FUNCTION__); + printk(KERN_WARNING "%s:%s: VFS is out of sync with lock manager!\n", + __FILE__, __func__); return res; } diff --git a/fs/proc/array.c b/fs/proc/array.c index 3224fc5..3a7d50d 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -75,7 +75,6 @@ #include #include #include -#include #include #include @@ -157,18 +156,13 @@ static inline const char * get_task_stat return *p; } -static inline char * task_state(struct pspace *pspace, struct task_struct *p, char *buffer) +static inline char * task_state(struct task_struct *p, char *buffer) { struct group_info *group_info; int g; - pid_t pid, ptgid, tppid, tgid; struct fdtable *fdt = NULL; read_lock(&tasklist_lock); - tgid = pspace_pid_to_user(pspace, p->tgid); - pid = pspace_pid_to_user(pspace, p->pid); - ptgid = pid_alive(p) ? pspace_pid_to_user(pspace, p->group_leader->real_parent->tgid) : 0; - tppid = pid_alive(p) ? pspace_pid_to_user(pspace, p->parent->pid) : 0; buffer += sprintf(buffer, "State:\t%s\n" "SleepAVG:\t%lu%%\n" @@ -180,7 +174,9 @@ static inline char * task_state(struct p "Gid:\t%d\t%d\t%d\t%d\n", get_task_state(p), (p->sleep_avg/1024)*100/(1020000000/1024), - tgid, pid, ptgid, tppid, + p->tgid, + p->tid, task_alive(p) ? p->group_leader->real_parent->tgid : 0, + task_alive(p) && p->ptrace ? p->parent->tid : 0, p->uid, p->euid, p->suid, p->fsuid, p->gid, p->egid, p->sgid, p->fsgid); read_unlock(&tasklist_lock); @@ -297,13 +293,13 @@ static inline char *task_cap(struct task cap_t(p->cap_effective)); } -int proc_pid_status(struct pspace *pspace, struct task_struct *task, char * buffer) +int proc_pid_status(struct task_struct *task, char * buffer) { char * orig = buffer; struct mm_struct *mm = get_task_mm(task); buffer = task_name(task, buffer); - buffer = task_state(pspace, task, buffer); + buffer = task_state(task, buffer); if (mm) { buffer = task_mem(mm, buffer); @@ -318,7 +314,7 @@ int proc_pid_status(struct pspace *pspac return buffer - orig; } -static int do_task_stat(struct pspace *pspace, struct task_struct *task, char * buffer, int whole) +static int do_task_stat(struct task_struct *task, char * buffer, int whole) { unsigned long vsize, eip, esp, wchan = ~0UL; long priority, nice; @@ -373,12 +369,12 @@ static int do_task_stat(struct pspace *p spin_unlock_irq(&task->sighand->siglock); } if (task->signal) { - if (task->signal->tty) { - tty_pgrp = pspace_pid_to_user(pspace, task->signal->tty->pgrp); + if (task->signal->tty) { + tty_pgrp = task->signal->tty->pgrp; tty_nr = new_encode_dev(tty_devnum(task->signal->tty)); } - pgid = pspace_pid_to_user(pspace, process_group(task)); - sid = pspace_pid_to_user(pspace, task->signal->session); + pgid = process_group(task); + sid = task->signal->session; cmin_flt = task->signal->cmin_flt; cmaj_flt = task->signal->cmaj_flt; cutime = task->signal->cutime; @@ -392,8 +388,7 @@ static int do_task_stat(struct pspace *p } it_real_value = task->signal->it_real_value; } - ppid = pid_alive(task) ? - pspace_pid_to_user(pspace, task->group_leader->real_parent->tgid) : 0; + ppid = task_alive(task) ? task->group_leader->real_parent->tgid : 0; read_unlock(&tasklist_lock); if (!whole || num_threads<2) @@ -420,7 +415,7 @@ static int do_task_stat(struct pspace *p res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ %lu %lu %lu %lu %lu %ld %ld %ld %ld %d %ld %llu %lu %ld %lu %lu %lu %lu %lu \ %lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %lu\n", - pspace_pid_to_user(pspace, task->pid), + task->tid, tcomm, state, ppid, @@ -470,17 +465,17 @@ static int do_task_stat(struct pspace *p return res; } -int proc_tid_stat(struct pspace *pspace, struct task_struct *task, char * buffer) +int proc_tid_stat(struct task_struct *task, char * buffer) { - return do_task_stat(pspace, task, buffer, 0); + return do_task_stat(task, buffer, 0); } -int proc_tgid_stat(struct pspace *pspace, struct task_struct *task, char * buffer) +int proc_tgid_stat(struct task_struct *task, char * buffer) { - return do_task_stat(pspace, task, buffer, 1); + return do_task_stat(task, buffer, 1); } -int proc_pid_statm(struct pspace *pspace, struct task_struct *task, char *buffer) +int proc_pid_statm(struct task_struct *task, char *buffer) { int size = 0, resident = 0, shared = 0, text = 0, lib = 0, data = 0; struct mm_struct *mm = get_task_mm(task); diff --git a/fs/proc/base.c b/fs/proc/base.c index d56862d..5e139a6 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -182,7 +182,6 @@ struct pid_entry { static struct pid_entry tgid_base_stuff[] = { E(PROC_TGID_TASK, "task", S_IFDIR|S_IRUGO|S_IXUGO), - E(PROC_TGID_PSPACE, "pspace", S_IFDIR|S_IRUGO|S_IXUGO), E(PROC_TGID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR), E(PROC_TGID_ENVIRON, "environ", S_IFREG|S_IRUSR), E(PROC_TGID_AUXV, "auxv", S_IFREG|S_IRUSR), @@ -263,6 +262,11 @@ static struct pid_entry tid_base_stuff[] {0,0,NULL,0} }; +static struct pid_entry pspace_base_stuff[] = { + E(PROC_TGID_PSPACE, "pspace", S_IFDIR|S_IRUGO|S_IXUGO), + {0,0,NULL,0} +}; + #ifdef CONFIG_SECURITY static struct pid_entry tgid_attr_stuff[] = { E(PROC_TGID_ATTR_CURRENT, "current", S_IFREG|S_IRUGO|S_IWUGO), @@ -366,7 +370,7 @@ static int proc_task_root_link(struct in /* Try to get fs from other threads */ task_unlock(leader); read_lock(&tasklist_lock); - if (pid_alive(leader)) { + if (task_alive(leader)) { struct task_struct *task = leader; while ((task = next_thread(task)) != leader) { @@ -402,7 +406,7 @@ static int proc_task_root_link(struct in (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \ security_ptrace(current,task) == 0)) -static int proc_pid_environ(struct pspace *pspace, struct task_struct *task, char * buffer) +static int proc_pid_environ(struct task_struct *task, char * buffer) { int res = 0; struct mm_struct *mm = get_task_mm(task); @@ -418,7 +422,7 @@ static int proc_pid_environ(struct pspac return res; } -static int proc_pid_cmdline(struct pspace *pspace, struct task_struct *task, char * buffer) +static int proc_pid_cmdline(struct task_struct *task, char * buffer) { int res = 0; unsigned int len; @@ -455,7 +459,7 @@ out: return res; } -static int proc_pid_auxv(struct pspace *pspace, struct task_struct *task, char *buffer) +static int proc_pid_auxv(struct task_struct *task, char *buffer) { int res = 0; struct mm_struct *mm = get_task_mm(task); @@ -479,7 +483,7 @@ static int proc_pid_auxv(struct pspace * * Provides a wchan file via kallsyms in a proper one-value-per-file format. * Returns the resolved symbol. If that fails, simply return the address. */ -static int proc_pid_wchan(struct pspace *pspace, struct task_struct *task, char *buffer) +static int proc_pid_wchan(struct task_struct *task, char *buffer) { char *modname; const char *sym_name; @@ -510,7 +514,7 @@ static int proc_pid_schedstat(struct tas /* The badness from the OOM killer */ unsigned long badness(struct task_struct *p, unsigned long uptime); -static int proc_oom_score(struct pspace *pspace, struct task_struct *task, char *buffer) +static int proc_oom_score(struct task_struct *task, char *buffer) { unsigned long points; struct timespec uptime; @@ -704,7 +708,6 @@ static ssize_t proc_info_read(struct fil struct inode * inode = file->f_dentry->d_inode; unsigned long page; ssize_t length; - struct pspace *pspace = proc_pspace(inode); struct task_struct *task = proc_task(inode); if (count > PROC_BLOCK_SIZE) @@ -712,7 +715,7 @@ static ssize_t proc_info_read(struct fil if (!(page = __get_free_page(GFP_KERNEL))) return -ENOMEM; - length = PROC_I(inode)->op.proc_read(pspace, task, (char*)page); + length = PROC_I(inode)->op.proc_read(task, (char*)page); if (length >= 0) length = simple_read_from_buffer(buf, count, ppos, (char *)page, length); @@ -1123,10 +1126,10 @@ static int proc_readfd(struct file * fil struct fdtable *fdt; retval = -ENOENT; - if (!pid_alive(p)) + if (!task_alive(p)) goto out; retval = 0; - tid = p->pid; + tid = p->tid; fd = filp->f_pos; switch (fd) { @@ -1189,11 +1192,11 @@ static int proc_pident_readdir(struct fi int ret; ret = -ENOENT; - if (!pid_alive(proc_task(inode))) + if (!task_alive(proc_task(inode))) goto out; ret = 0; - pid = proc_task(inode)->pid; + pid = proc_task(inode)->tid; i = filp->f_pos; switch (i) { case 0: @@ -1245,6 +1248,13 @@ static int proc_tid_base_readdir(struct tid_base_stuff,ARRAY_SIZE(tid_base_stuff)); } +static int proc_pspace_base_readdir(struct file * filp, + void * dirent, filldir_t filldir) +{ + return proc_pident_readdir(filp,dirent,filldir, + pspace_base_stuff,ARRAY_SIZE(pspace_base_stuff)); +} + /* building an inode */ static int task_dumpable(struct task_struct *task) @@ -1279,9 +1289,9 @@ static struct inode *proc_pid_make_inode ei = PROC_I(inode); ei->task = NULL; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; - inode->i_ino = fake_ino(task->pid - pspace->offset, ino); + inode->i_ino = fake_ino(task->tid, ino); - if (!pid_alive(task)) + if (!task_alive(task)) goto out_unlock; /* @@ -1323,7 +1333,7 @@ static int pid_revalidate(struct dentry { struct inode *inode = dentry->d_inode; struct task_struct *task = proc_task(inode); - if (pid_alive(task)) { + if (task_alive(task)) { if (proc_type(inode) == PROC_TGID_INO || proc_type(inode) == PROC_TID_INO || task_dumpable(task)) { inode->i_uid = task->euid; inode->i_gid = task->egid; @@ -1384,7 +1394,7 @@ static int pid_delete_dentry(struct dent * If so, then don't put the dentry on the lru list, * kill it immediately. */ - return !pid_alive(proc_task(dentry->d_inode)); + return !task_alive(proc_task(dentry->d_inode)); } static struct dentry_operations tid_fd_dentry_operations = @@ -1443,7 +1453,7 @@ static struct dentry *proc_lookupfd(stru if (fd == ~0U) goto out; - if (!pid_alive(task)) + if (!task_alive(task)) goto out; inode = proc_pid_make_inode(dir->i_sb, pspace, task, PROC_TID_FD_DIR+fd); @@ -1538,7 +1548,7 @@ static struct inode_operations proc_task * Magic pspace link/mount */ static struct inode_operations proc_pspace_inode_operations = { - .follow_link = proc_pspace_follow_link, + .follow_link = proc_pspace_follow_link, }; #ifdef CONFIG_SECURITY @@ -1621,7 +1631,7 @@ static struct dentry *proc_pident_lookup error = -ENOENT; inode = NULL; - if (!pid_alive(task)) + if (!task_alive(task)) goto out; for (p = ents; p->name; p++) { @@ -1653,6 +1663,7 @@ static struct dentry *proc_pident_lookup case PROC_TGID_PSPACE: inode->i_nlink = 2; inode->i_op = &proc_pspace_inode_operations; + inode->i_ino = PROC_ROOT_INO; break; case PROC_TID_FD: case PROC_TGID_FD: @@ -1815,6 +1826,10 @@ static struct dentry *proc_tid_base_look return proc_pident_lookup(dir, dentry, tid_base_stuff); } +static struct dentry *proc_pspace_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ + return proc_pident_lookup(dir, dentry, pspace_base_stuff); +} + static struct file_operations proc_tgid_base_operations = { .read = generic_read_dir, .readdir = proc_tgid_base_readdir, @@ -1825,6 +1840,11 @@ static struct file_operations proc_tid_b .readdir = proc_tid_base_readdir, }; +static struct file_operations proc_pspace_base_operations = { + .read = generic_read_dir, + .readdir = proc_pspace_base_readdir, +}; + static struct inode_operations proc_tgid_base_inode_operations = { .lookup = proc_tgid_base_lookup, }; @@ -1833,6 +1853,10 @@ static struct inode_operations proc_tid_ .lookup = proc_tid_base_lookup, }; +static struct inode_operations proc_pspace_base_inode_operations = { + .lookup = proc_pspace_base_lookup, +}; + #ifdef CONFIG_SECURITY static int proc_tgid_attr_readdir(struct file * filp, void * dirent, filldir_t filldir) @@ -1885,17 +1909,15 @@ static struct inode_operations proc_tid_ static int proc_self_readlink(struct dentry *dentry, char __user *buffer, int buflen) { - struct pspace *pspace = proc_pspace(dentry->d_parent->d_inode); char tmp[30]; - sprintf(tmp, "%d", pspace_pid_to_user(pspace, current->tgid)); + sprintf(tmp, "%d", current->tgid); return vfs_readlink(dentry,buffer,buflen,tmp); } static void *proc_self_follow_link(struct vfsmount *mnt, struct dentry *dentry, struct nameidata *nd) { - struct pspace *pspace = proc_pspace(nd->dentry->d_inode); char tmp[30]; - sprintf(tmp, "%d", pspace_pid_to_user(pspace, current->tgid)); + sprintf(tmp, "%d", current->tgid); return ERR_PTR(vfs_follow_link(nd,tmp)); } @@ -1988,10 +2010,9 @@ struct dentry *proc_pid_lookup(struct in tgid = name_to_int(&dentry->d_name); if (tgid == ~0U) goto out; - tgid = pspace_pid_from_user(pspace, tgid); read_lock(&tasklist_lock); - task = find_task_by_pid(tgid); + task = find_task_by_pid(pspace, tgid); if (task) get_task_struct(task); read_unlock(&tasklist_lock); @@ -2006,14 +2027,20 @@ struct dentry *proc_pid_lookup(struct in goto out; } inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO; - inode->i_op = &proc_tgid_base_inode_operations; - inode->i_fop = &proc_tgid_base_operations; inode->i_flags|=S_IMMUTABLE; + if (pspace_leader(task) && (task->pspace != pspace)) { + inode->i_op = &proc_pspace_base_inode_operations; + inode->i_fop = &proc_pspace_base_operations; + inode->i_nlink = 3; + } else { + inode->i_op = &proc_tgid_base_inode_operations; + inode->i_fop = &proc_tgid_base_operations; #ifdef CONFIG_SECURITY - inode->i_nlink = 5; + inode->i_nlink = 5; #else - inode->i_nlink = 4; + inode->i_nlink = 4; #endif + } dentry->d_op = &pid_base_dentry_operations; @@ -2021,7 +2048,7 @@ struct dentry *proc_pid_lookup(struct in d_add(dentry, inode); spin_lock(&task->proc_lock); task->proc_dentry = dentry; - if (!pid_alive(task)) { + if (!task_alive(task)) { dentry = proc_pid_unhash(task); died = 1; } @@ -2049,10 +2076,9 @@ static struct dentry *proc_task_lookup(s tid = name_to_int(&dentry->d_name); if (tid == ~0U) goto out; - tid = pspace_pid_from_user(pspace, tid); read_lock(&tasklist_lock); - task = find_task_by_pid(tid); + task = find_task_by_pid(pspace, tid); if (task) get_task_struct(task); read_unlock(&tasklist_lock); @@ -2105,7 +2131,7 @@ static int get_tgid_list(struct pspace * read_lock(&tasklist_lock); p = NULL; if (version) { - p = find_task_by_pid(version); + p = find_task_by_pid(pspace, version); if (p && !thread_group_leader(p)) p = NULL; } @@ -2116,14 +2142,13 @@ static int get_tgid_list(struct pspace * p = next_task(&init_task); for ( ; p != &init_task; p = next_task(p)) { - int tgid = p->pid; - if (!pid_alive(p)) + if (!task_alive(p)) continue; - if (!pspace_pid_visible(pspace, p->tgid)) + if (!pspace_task_visible(pspace, p)) continue; if (--index >= 0) continue; - tgids[nr_tgids] = pspace_pid_to_user(pspace, tgid); + tgids[nr_tgids] = (p->pspace == pspace)? p->tid : p->wid; nr_tgids++; if (nr_tgids >= PROC_MAXPIDS) break; @@ -2150,13 +2175,13 @@ static int get_tid_list(struct pspace *p * unlinked task, which cannot be used to access the task-list * via next_thread(). */ - if (pid_alive(task) && pspace_pid_visible(pspace, task->pid)) do { - int tid = task->pid; + if (task_alive(task) && pspace_task_visible(pspace, task)) do { + int tid = task->tid; if (--index >= 0) continue; if (tids != NULL) - tids[nr_tids] = pspace_pid_to_user(pspace, tid); + tids[nr_tids] = tid; nr_tids++; if (nr_tids >= PROC_MAXPIDS) break; @@ -2176,9 +2201,11 @@ int proc_pid_readdir(struct file * filp, int next_tgid; if (!nr) { - ino_t ino = fake_ino(0,PROC_TGID_INO); - if (filldir(dirent, "self", 4, filp->f_pos, ino, DT_LNK) < 0) - return 0; + if (current->pspace == pspace) { + ino_t ino = fake_ino(0,PROC_TGID_INO); + if (filldir(dirent, "self", 4, filp->f_pos, ino, DT_LNK) < 0) + return 0; + } filp->f_pos++; nr++; } @@ -2239,7 +2266,7 @@ static int proc_task_readdir(struct file ino_t ino; unsigned long pos = filp->f_pos; /* avoiding "long long" filp->f_pos */ - if (!pid_alive(proc_task(inode))) + if (!task_alive(proc_task(inode))) goto out; retval = 0; diff --git a/fs/proc/internal.h b/fs/proc/internal.h index f39dd98..18bab3f 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -32,10 +32,10 @@ do { \ extern void create_seq_entry(char *name, mode_t mode, struct file_operations *f); extern int proc_exe_link(struct inode *, struct dentry **, struct vfsmount **); -extern int proc_tid_stat(struct pspace *, struct task_struct *, char *); -extern int proc_tgid_stat(struct pspace *, struct task_struct *, char *); -extern int proc_pid_status(struct pspace *, struct task_struct *, char *); -extern int proc_pid_statm(struct pspace *,struct task_struct *, char *); +extern int proc_tid_stat(struct task_struct *, char *); +extern int proc_tgid_stat(struct task_struct *, char *); +extern int proc_pid_status(struct task_struct *, char *); +extern int proc_pid_statm(struct task_struct *, char *); extern struct dentry *get_pspace_root_dentry(struct super_block *, struct pspace *); static inline struct task_struct *proc_task(struct inode *inode) diff --git a/fs/proc/root.c b/fs/proc/root.c index 21735dd..042a4ca 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -125,10 +125,10 @@ struct dentry *get_pspace_root_dentry(st inode->i_uid = 0; inode->i_gid = 0; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; - inode->i_nlink = 2; inode->i_op = &pspace_root_inode_operations; inode->i_fop = &pspace_root_operations; inode->i_ino = PROC_ROOT_INO; + inode->i_nlink = proc_root.nlink; d_add(dentry, inode); } else { dput(dentry); @@ -167,17 +167,22 @@ static void *proc_root_follow_link(struc return NULL; } -static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd) +static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { - struct pspace *pspace = proc_pspace(nd->dentry->d_inode); + struct inode *inode = dentry->d_inode; + struct pspace *pspace = proc_pspace(inode); + generic_fillattr(inode, stat); /* * nr_processes is actually protected by the tasklist_lock; * however, it's conventional to do reads, especially for * reporting, without any locking whatsoever. */ - if (dir->i_ino == PROC_ROOT_INO) /* check for safety... */ - dir->i_nlink = proc_root.nlink + pspace->nr_processes; + stat->nlink = proc_root.nlink + pspace->nr_processes; + return 0; +} +static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd) +{ if (!proc_lookup(dir, dentry, nd)) { return NULL; } @@ -222,6 +227,7 @@ static struct file_operations pspace_roo */ static struct inode_operations pspace_root_inode_operations = { .lookup = proc_root_lookup, + .getattr = proc_root_getattr, }; /* diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index 725be90..55ac70c 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -9,6 +9,7 @@ * to achieve effects such as fast scrolling by changing the origin. */ +struct pspace; struct vt_struct; #define NPAR 16 @@ -51,6 +52,7 @@ struct vc_data { struct tty_struct *vc_tty; /* TTY we are attached to */ /* data for manual vt switching */ struct vt_mode vt_mode; + struct pspace *vt_pspace; int vt_pid; int vt_newvt; wait_queue_head_t paste_wait; diff --git a/include/linux/fs.h b/include/linux/fs.h index 3f392de..1ff9913 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -549,6 +549,7 @@ extern struct block_device *I_BDEV(struc struct fown_struct { rwlock_t lock; /* protects pid, uid, euid fields */ + struct pspace *pspace; /* process space of owner pid */ int pid; /* pid or -pgrp where SIGIO should be sent */ uid_t uid, euid; /* uid/euid of process setting the owner */ void *security; diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 4367ce4..7fd97a2 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -121,7 +121,8 @@ extern unsigned long long memparse(char extern int __kernel_text_address(unsigned long addr); extern int kernel_text_address(unsigned long addr); -extern int session_of_pgrp(int pgrp); +struct pspace; +extern int session_of_pgrp(struct pspace *pspace, int pgrp); #ifdef CONFIG_PRINTK asmlinkage int vprintk(const char *fmt, va_list args) diff --git a/include/linux/pid.h b/include/linux/pid.h index 460fee8..fff7805 100644 --- a/include/linux/pid.h +++ b/include/linux/pid.h @@ -3,33 +3,36 @@ enum pid_type { - PIDTYPE_PID, - PIDTYPE_ALTPID, + PIDTYPE_TID, + PIDTYPE_WID, PIDTYPE_TGID, PIDTYPE_PGID, PIDTYPE_SID, PIDTYPE_MAX }; +struct pspace; struct pid { /* Try to keep pid_chain in the same cacheline as nr for find_pid */ int nr; + struct pspace *pspace; struct hlist_node pid_chain; /* list of pids with the same nr, only one of them is in the hash */ struct list_head pid_list; }; -struct pspace; - #define pid_task(elem, type) \ list_entry(elem, struct task_struct, pids[type].pid_list) +#define pid_nr(tsk, type) (tsk->pids[type].nr) +#define pid_pspace(tsk, type) (tsk->pids[type].pspace) + /* * attach_pid() and detach_pid() must be called with the tasklist_lock * write-held. */ -extern int FASTCALL(attach_pid(struct task_struct *task, enum pid_type type, int nr)); +extern int FASTCALL(attach_pid(struct task_struct *task, struct pspace *pspace, enum pid_type type, int nr)); extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type)); @@ -37,18 +40,18 @@ extern void FASTCALL(detach_pid(struct t * look up a PID in the hash table. Must be called with the tasklist_lock * held. */ -extern struct pid *FASTCALL(find_pid(enum pid_type, int)); +extern struct pid *FASTCALL(find_pid(struct pspace *, enum pid_type, int)); -extern int alloc_pidmap(struct pspace *pspace, int count); -extern void FASTCALL(free_pidmap(struct pspace *pspace, int pid, int count)); +extern int alloc_pidmap(struct pspace *pspace); +extern void FASTCALL(free_pidmap(struct pspace *pspace, int pid)); extern void switch_exec_pids(struct task_struct *leader, struct task_struct *thread); -#define do_each_task_pid(who, type, task) \ - if ((task = find_task_by_pid_type(type, who))) { \ +#define do_each_task_pid(pspace, who, type, task) \ + if ((task = find_task_by_pid_type(pspace, type, who))) { \ prefetch((task)->pids[type].pid_list.next); \ do { -#define while_each_task_pid(who, type, task) \ +#define while_each_task_pid(pspace, who, type, task) \ } while (task = pid_task((task)->pids[type].pid_list.next,\ type), \ prefetch((task)->pids[type].pid_list.next), \ diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index ef48ded..1cf2680 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -249,7 +249,7 @@ struct proc_inode { int type; union { int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **); - int (*proc_read)(struct pspace *pspace, struct task_struct *task, char *page); + int (*proc_read)(struct task_struct *task, char *page); } op; struct proc_dir_entry *pde; struct inode vfs_inode; diff --git a/include/linux/pspace.h b/include/linux/pspace.h index b6043bc..5283aaa 100644 --- a/include/linux/pspace.h +++ b/include/linux/pspace.h @@ -20,7 +20,6 @@ struct pspace int nr_threads; int nr_processes; int last_pid; - int offset; int min; int max; struct pidmap pidmap[PIDMAP_ENTRIES]; @@ -30,45 +29,21 @@ extern struct pspace init_pspace; #define INVALID_PID 0x7fffffff -static inline int pspace_pid_from_user(struct pspace *pspace, int pid) +static inline int pspace_task_visible(struct pspace *pspace, struct task_struct *tsk) { - if (pid < pspace->max) - pid += pspace->offset; - else - pid = INVALID_PID; - return pid; + return (tsk->pspace == pspace) || + ((tsk->tid == 1) && (tsk->pspace->parent == pspace)); } -static inline int pspace_pid_to_user(struct pspace *pspace, int pid) +static inline int task_visible(struct task_struct *tsk) { - pid = pid - pspace->offset; - if ((pid <= 0) || (pid >= pspace->max)) - pid = 0; - return pid; -} - -static inline int pspace_pid_visible(struct pspace *pspace, int pid) -{ - return pspace_pid_to_user(pspace, pid) > 0; -} - -static inline int pid_from_user(int pid) -{ - return pspace_pid_from_user(current->pspace, pid); -} - -static inline int pid_to_user(int pid) -{ - return pspace_pid_to_user(current->pspace, pid); -} - -static inline int pid_visible(int pid) -{ - return pspace_pid_visible(current->pspace, pid); + return pspace_task_visible(current->pspace, tsk); } static inline void get_pspace(struct pspace *pspace) { + if (!pspace) + return; atomic_inc(&pspace->count); } @@ -76,6 +51,8 @@ extern void __put_pspace(struct pspace * static inline void put_pspace(struct pspace *pspace) { + if (!pspace) + return; if (atomic_dec_and_test(&pspace->count)) { __put_pspace(pspace); } @@ -94,6 +71,20 @@ static inline int pspace_leader(struct t return tsk == tsk->pspace->child_reaper; } +static inline int current_pspace_leader(struct task_struct *tsk) +{ + return tsk == current->pspace->child_reaper; +} + +static inline int in_pspace(struct pspace *pspace, struct task_struct *tsk) +{ + struct pspace *test; + test = tsk->pspace; + while(test && (test != pspace)) + test = test->parent; + return test == pspace; +} + static inline int delay_pspace_leader(struct task_struct *tsk) { return pspace_leader(tsk) && (tsk->pspace->nr_processes > 1); diff --git a/include/linux/sched.h b/include/linux/sched.h index 270e0b3..9388018 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -687,8 +687,9 @@ struct task_struct { /* ??? */ unsigned long personality; unsigned did_exec:1; - pid_t pid; - pid_t tgid; + pid_t tid; /* task id */ + pid_t wid; /* wait id */ + pid_t tgid; /* thread group id */ /* * pointers to (original) parent process, youngest child, younger sibling, * older sibling, respectively. (p->father can be replaced with @@ -822,16 +823,16 @@ static inline pid_t process_group(struct } /** - * pid_alive - check that a task structure is not stale + * task_alive - check that a task structure is not stale * @p: Task structure to be checked. * * Test if a process is not yet dead (at most zombie state) * If pid_alive fails, then pointers within the task structure * can be stale and must not be dereferenced. */ -static inline int pid_alive(struct task_struct *p) +static inline int task_alive(struct task_struct *p) { - return p->pids[PIDTYPE_PID].nr != 0; + return p->pids[PIDTYPE_TID].nr != 0; } extern void free_task(struct task_struct *tsk); @@ -957,8 +958,8 @@ extern struct task_struct init_task; extern struct mm_struct init_mm; -#define find_task_by_pid(nr) find_task_by_pid_type(PIDTYPE_PID, nr) -extern struct task_struct *find_task_by_pid_type(int type, int pid); +extern struct task_struct *find_task_by_pid(struct pspace *, int pid); +extern struct task_struct *find_task_by_pid_type(struct pspace *, int type, int pid); extern void set_special_pids(pid_t session, pid_t pgrp); extern void __set_special_pids(pid_t session, pid_t pgrp); @@ -1016,19 +1017,19 @@ extern int send_sig_info(int, struct sig extern int send_group_sig_info(int, struct siginfo *, struct task_struct *); extern int force_sigsegv(int, struct task_struct *); extern int force_sig_info(int, struct siginfo *, struct task_struct *); -extern int __kill_pspace_info(int sig, struct siginfo *info, struct pspace *pspace); -extern int kill_pspace_info(int sig, struct siginfo *info, struct pspace *pspace); -extern int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp); -extern int kill_pg_info(int, struct siginfo *, pid_t); -extern int kill_proc_info(int, struct siginfo *, pid_t); +extern int __kill_pspace_info(int , struct siginfo *, struct pspace *); +extern int kill_pspace_info(int , struct siginfo *, struct pspace *); +extern int __kill_pg_info(int, struct siginfo *, struct pspace *, pid_t); +extern int kill_pg_info(int, struct siginfo *, struct pspace *, pid_t); +extern int kill_proc_info(int, struct siginfo *, struct pspace *, pid_t); extern void do_notify_parent(struct task_struct *, int); extern void force_sig(int, struct task_struct *); extern void force_sig_specific(int, struct task_struct *); extern int send_sig(int, struct task_struct *, int); extern void zap_other_threads(struct task_struct *p); -extern int kill_pg(pid_t, int, int); +extern int kill_pg(struct pspace *, pid_t, int, int); extern int kill_sl(pid_t, int, int); -extern int kill_proc(pid_t, int, int); +extern int kill_proc(struct pspace *, pid_t, int, int); extern struct sigqueue *sigqueue_alloc(void); extern void sigqueue_free(struct sigqueue *); extern int send_sigqueue(int, struct sigqueue *, struct task_struct *); @@ -1152,7 +1153,7 @@ extern void wait_task_inactive(task_t * extern task_t * FASTCALL(next_thread(const task_t *p)); -#define thread_group_leader(p) (p->pid == p->tgid) +#define thread_group_leader(p) (p->tid == p->tgid) static inline int thread_group_empty(task_t *p) { diff --git a/include/linux/tty.h b/include/linux/tty.h index 1267f88..7d7491a 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -248,6 +248,7 @@ struct tty_struct { struct semaphore termios_sem; struct termios *termios, *termios_locked; char name[64]; + struct pspace *pspace; int pgrp; int session; unsigned long flags; @@ -355,7 +356,7 @@ extern int tty_read_raw_data(struct tty_ int buflen); extern void tty_write_message(struct tty_struct *tty, char *msg); -extern int is_orphaned_pgrp(int pgrp); +extern int is_orphaned_pgrp(struct pspace *pspace, int pgrp); extern int is_ignored(int sig); extern int tty_signal(int sig, struct tty_struct *tty); extern void tty_hangup(struct tty_struct * tty); diff --git a/ipc/msg.c b/ipc/msg.c index acfa2bd..aa22703 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -417,8 +417,8 @@ asmlinkage long sys_msgctl (int msqid, i tbuf.msg_cbytes = msq->q_cbytes; tbuf.msg_qnum = msq->q_qnum; tbuf.msg_qbytes = msq->q_qbytes; - tbuf.msg_lspid = pid_to_user(msq->q_lspid); - tbuf.msg_lrpid = pid_to_user(msq->q_lrpid); + tbuf.msg_lspid = msq->q_lspid; + tbuf.msg_lrpid = msq->q_lrpid; msg_unlock(msq); if (copy_msqid_to_user(buf, &tbuf, version)) return -EFAULT; @@ -540,7 +540,7 @@ static inline int pipelined_send(struct msr->r_msg = ERR_PTR(-E2BIG); } else { msr->r_msg = NULL; - msq->q_lrpid = msr->r_tsk->pid; + msq->q_lrpid = msr->r_tsk->tgid; msq->q_rtime = get_seconds(); wake_up_process(msr->r_tsk); smp_mb(); @@ -822,8 +822,8 @@ static int sysvipc_msg_proc_show(struct msq->q_perm.mode, msq->q_cbytes, msq->q_qnum, - pid_to_user(msq->q_lspid), - pid_to_user(msq->q_lrpid), + msq->q_lspid, + msq->q_lrpid, msq->q_perm.uid, msq->q_perm.gid, msq->q_perm.cuid, diff --git a/ipc/sem.c b/ipc/sem.c index 77b4161..68d12e1 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -722,7 +722,7 @@ static int semctl_main(int semid, int se err = curr->semval; goto out_unlock; case GETPID: - err = pid_to_user(curr->sempid); + err = curr->sempid; goto out_unlock; case GETNCNT: err = count_semncnt(sma,semnum); diff --git a/ipc/shm.c b/ipc/shm.c index 795a779..5afdfbe 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -500,8 +500,8 @@ asmlinkage long sys_shmctl (int shmid, i tbuf.shm_atime = shp->shm_atim; tbuf.shm_dtime = shp->shm_dtim; tbuf.shm_ctime = shp->shm_ctim; - tbuf.shm_cpid = pid_to_user(shp->shm_cprid); - tbuf.shm_lpid = pid_to_user(shp->shm_lprid); + tbuf.shm_cpid = shp->shm_cprid; + tbuf.shm_lpid = shp->shm_lprid; if (!is_file_hugepages(shp->shm_file)) tbuf.shm_nattch = shp->shm_nattch; else @@ -888,8 +888,8 @@ static int sysvipc_shm_proc_show(struct shp->id, shp->shm_flags, shp->shm_segsz, - pid_to_user(shp->shm_cprid), - pid_to_user(shp->shm_lprid), + shp->shm_cprid, + shp->shm_lprid, is_file_hugepages(shp->shm_file) ? (file_count(shp->shm_file) - 1) : shp->shm_nattch, shp->shm_perm.uid, shp->shm_perm.gid, diff --git a/kernel/capability.c b/kernel/capability.c index e4c70fa..3775659 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -63,13 +63,12 @@ asmlinkage long sys_capget(cap_user_head if (pid < 0) return -EINVAL; - pid = pid_from_user(pid); spin_lock(&task_capability_lock); read_lock(&tasklist_lock); - if (pid && pid != current->pid) { - target = find_task_by_pid(pid); + if (pid && pid != current->tid) { + target = find_task_by_pid(current->pspace, pid); if (!target) { ret = -ESRCH; goto out; @@ -97,11 +96,12 @@ static inline int cap_set_pg(int pgrp, k kernel_cap_t *inheritable, kernel_cap_t *permitted) { + struct pspace *pspace = current->pspace; task_t *g, *target; int ret = -EPERM; int found = 0; - do_each_task_pid(pgrp, PIDTYPE_PGID, g) { + do_each_task_pid(pspace, pgrp, PIDTYPE_PGID, g) { target = g; while_each_thread(g, target) { if (!security_capset_check(target, effective, @@ -114,7 +114,7 @@ static inline int cap_set_pg(int pgrp, k } found = 1; } - } while_each_task_pid(pgrp, PIDTYPE_PGID, g); + } while_each_task_pid(pspace, pgrp, PIDTYPE_PGID, g); if (!found) ret = 0; @@ -122,31 +122,37 @@ static inline int cap_set_pg(int pgrp, k } /* - * cap_set_all - set capabilities for all processes other than init - * and self. We call this holding task_capability_lock and tasklist_lock. + * cap_set_pspace - set capabilities for all processes in pspace + * other than init and self. We call this holding + * task_capability_lock and tasklist_lock. */ -static inline int cap_set_all(kernel_cap_t *effective, - kernel_cap_t *inheritable, - kernel_cap_t *permitted) +static inline int cap_set_pspace( struct pspace *pspace, + kernel_cap_t *effective, + kernel_cap_t *inheritable, + kernel_cap_t *permitted) { - task_t *g, *target; - int ret = -EPERM; - int found = 0; - - do_each_thread(g, target) { - if (target == current || target->pid == 1) - continue; - found = 1; - if (security_capset_check(target, effective, inheritable, - permitted)) - continue; - ret = 0; - security_capset_set(target, effective, inheritable, permitted); - } while_each_thread(g, target); - - if (!found) - ret = 0; - return ret; + task_t *g, *target; + int ret = -EPERM; + int found = 0; + + do_each_thread(g, target) { + if (target == current) + continue; + if (current_pspace_leader(target)) + continue; + if (!in_pspace(pspace, target)) + continue; + found = 1; + if (security_capset_check(target, effective, inheritable, + permitted)) + continue; + ret = 0; + security_capset_set(target, effective, inheritable, permitted); + } while_each_thread(g, target); + + if (!found) + ret = 0; + return ret; } /** @@ -171,66 +177,69 @@ static inline int cap_set_all(kernel_cap */ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data) { - kernel_cap_t inheritable, permitted, effective; - __u32 version; - task_t *target; - int ret; - pid_t pid; - - if (get_user(version, &header->version)) - return -EFAULT; - - if (version != _LINUX_CAPABILITY_VERSION) { - if (put_user(_LINUX_CAPABILITY_VERSION, &header->version)) - return -EFAULT; - return -EINVAL; - } - - if (get_user(pid, &header->pid)) - return -EFAULT; - - if (pid && pid_from_user(pid) != current->pid && !capable(CAP_SETPCAP)) - return -EPERM; - - if (copy_from_user(&effective, &data->effective, sizeof(effective)) || - copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) || - copy_from_user(&permitted, &data->permitted, sizeof(permitted))) - return -EFAULT; - - spin_lock(&task_capability_lock); - read_lock(&tasklist_lock); - - if (pid > 0 && pid_from_user(pid) != current->pid) { - target = find_task_by_pid(pid_from_user(pid)); - if (!target) { - ret = -ESRCH; - goto out; - } - } else - target = current; - - ret = 0; - - /* having verified that the proposed changes are legal, + kernel_cap_t inheritable, permitted, effective; + __u32 version; + task_t *target; + int ret; + pid_t pid; + + if (get_user(version, &header->version)) + return -EFAULT; + + if (version != _LINUX_CAPABILITY_VERSION) { + if (put_user(_LINUX_CAPABILITY_VERSION, &header->version)) + return -EFAULT; + return -EINVAL; + } + + if (get_user(pid, &header->pid)) + return -EFAULT; + + if (pid && pid != current->tid && !capable(CAP_SETPCAP)) + return -EPERM; + + if (copy_from_user(&effective, &data->effective, sizeof(effective)) || + copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) || + copy_from_user(&permitted, &data->permitted, sizeof(permitted))) + return -EFAULT; + + spin_lock(&task_capability_lock); + read_lock(&tasklist_lock); + + if (pid > 0 && pid != current->tid) { + target = find_task_by_pid(current->pspace, pid); + if (!target) { + ret = -ESRCH; + goto out; + } + } else + target = current; + + ret = 0; + + /* having verified that the proposed changes are legal, we now put them into effect. */ - if (pid < 0) { - if (pid == -1) /* all procs other than current and init */ - ret = cap_set_all(&effective, &inheritable, &permitted); - - else /* all procs in process group */ - ret = cap_set_pg(pid_from_user(-pid), &effective, &inheritable, - &permitted); - } else { - ret = security_capset_check(target, &effective, &inheritable, - &permitted); - if (!ret) - security_capset_set(target, &effective, &inheritable, - &permitted); - } - -out: - read_unlock(&tasklist_lock); - spin_unlock(&task_capability_lock); + if (pid < 0) { + struct task_struct *p; - return ret; + p = find_task_by_pid(current->pspace, -pid); + if (p && pspace_leader(p)) /* all procs other than current and init */ + ret = cap_set_pspace(p->pspace, &effective, &inheritable, &permitted); + + else /* all procs in process group */ + ret = cap_set_pg(-pid, &effective, &inheritable, + &permitted); + } else { + ret = security_capset_check(target, &effective, &inheritable, + &permitted); + if (!ret) + security_capset_set(target, &effective, &inheritable, + &permitted); + } + + out: + read_unlock(&tasklist_lock); + spin_unlock(&task_capability_lock); + + return ret; } diff --git a/kernel/exit.c b/kernel/exit.c index 19068c5..bfee5fd 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -43,15 +43,18 @@ static void exit_mm(struct task_struct * static void __unhash_process(struct task_struct *p) { - current->pspace->nr_threads--; + p->pspace->nr_threads--; nr_threads--; - detach_pid(p, PIDTYPE_PID); + detach_pid(p, PIDTYPE_TID); detach_pid(p, PIDTYPE_TGID); if (thread_group_leader(p)) { detach_pid(p, PIDTYPE_PGID); detach_pid(p, PIDTYPE_SID); - if (p->pid) - current->pspace->nr_processes--; + if (p->tid) + p->pspace->nr_processes--; + } + if (pspace_leader(p)) { + detach_pid(p, PIDTYPE_WID); } exit_pspace(p); @@ -134,19 +137,19 @@ void unhash_process(struct task_struct * * satisfactory pgrp is found. I dunno - gdb doesn't work correctly * without this... */ -int session_of_pgrp(int pgrp) +int session_of_pgrp(struct pspace *pspace, int pgrp) { struct task_struct *p; int sid = -1; read_lock(&tasklist_lock); - do_each_task_pid(pgrp, PIDTYPE_PGID, p) { + do_each_task_pid(pspace, pgrp, PIDTYPE_PGID, p) { if (p->signal->session > 0) { sid = p->signal->session; goto out; } - } while_each_task_pid(pgrp, PIDTYPE_PGID, p); - p = find_task_by_pid(pgrp); + } while_each_task_pid(pspace, pgrp, PIDTYPE_PGID, p); + p = find_task_by_pid(pspace, pgrp); if (p) sid = p->signal->session; out: @@ -163,42 +166,42 @@ out: * * "I ask you, have you ever known what it is to be an orphan?" */ -static int will_become_orphaned_pgrp(int pgrp, task_t *ignored_task) +static int will_become_orphaned_pgrp(struct pspace *pspace, int pgrp, task_t *ignored_task) { struct task_struct *p; int ret = 1; - do_each_task_pid(pgrp, PIDTYPE_PGID, p) { + do_each_task_pid(pspace, pgrp, PIDTYPE_PGID, p) { if (p == ignored_task || p->exit_state - || p->real_parent->pid == 1) + || p->real_parent->tid == 1) continue; if (process_group(p->real_parent) != pgrp && p->real_parent->signal->session == p->signal->session) { ret = 0; break; } - } while_each_task_pid(pgrp, PIDTYPE_PGID, p); + } while_each_task_pid(pspace, pgrp, PIDTYPE_PGID, p); return ret; /* (sighing) "Often!" */ } -int is_orphaned_pgrp(int pgrp) +int is_orphaned_pgrp(struct pspace *pspace, int pgrp) { int retval; read_lock(&tasklist_lock); - retval = will_become_orphaned_pgrp(pgrp, NULL); + retval = will_become_orphaned_pgrp(pspace, pgrp, NULL); read_unlock(&tasklist_lock); return retval; } -static inline int has_stopped_jobs(int pgrp) +static inline int has_stopped_jobs(struct pspace *pspace, int pgrp) { int retval = 0; struct task_struct *p; - do_each_task_pid(pgrp, PIDTYPE_PGID, p) { + do_each_task_pid(pspace, pgrp, PIDTYPE_PGID, p) { if (p->state != TASK_STOPPED) continue; @@ -214,7 +217,7 @@ static inline int has_stopped_jobs(int p retval = 1; break; - } while_each_task_pid(pgrp, PIDTYPE_PGID, p); + } while_each_task_pid(pspace, pgrp, PIDTYPE_PGID, p); return retval; } @@ -264,12 +267,12 @@ void __set_special_pids(pid_t session, p if (curr->signal->session != session) { detach_pid(curr, PIDTYPE_SID); curr->signal->session = session; - attach_pid(curr, PIDTYPE_SID, session); + attach_pid(curr, curr->pspace, PIDTYPE_SID, session); } if (process_group(curr) != pgrp) { detach_pid(curr, PIDTYPE_PGID); curr->signal->pgrp = pgrp; - attach_pid(curr, PIDTYPE_PGID, pgrp); + attach_pid(curr, curr->pspace, PIDTYPE_PGID, pgrp); } } @@ -592,11 +595,13 @@ static inline void reparent_thread(task_ */ if ((process_group(p) != process_group(father)) && (p->signal->session == father->signal->session)) { + struct pspace *pspace = p->pspace; int pgrp = process_group(p); - if (will_become_orphaned_pgrp(pgrp, NULL) && has_stopped_jobs(pgrp)) { - __kill_pg_info(SIGHUP, (void *)1, pgrp); - __kill_pg_info(SIGCONT, (void *)1, pgrp); + if (will_become_orphaned_pgrp(pspace, pgrp, NULL) && + has_stopped_jobs(pspace, pgrp)) { + __kill_pg_info(SIGHUP, (void *)1, pspace, pgrp); + __kill_pg_info(SIGCONT, (void *)1, pspace, pgrp); } } } @@ -730,10 +735,10 @@ static void exit_notify(struct task_stru if ((process_group(t) != process_group(tsk)) && (t->signal->session == tsk->signal->session) && - will_become_orphaned_pgrp(process_group(tsk), tsk) && - has_stopped_jobs(process_group(tsk))) { - __kill_pg_info(SIGHUP, (void *)1, process_group(tsk)); - __kill_pg_info(SIGCONT, (void *)1, process_group(tsk)); + will_become_orphaned_pgrp(tsk->pspace, process_group(tsk), tsk) && + has_stopped_jobs(tsk->pspace, process_group(tsk))) { + __kill_pg_info(SIGHUP, (void *)1, tsk->pspace, process_group(tsk)); + __kill_pg_info(SIGCONT, (void *)1, tsk->pspace, process_group(tsk)); } @@ -817,9 +822,9 @@ fastcall NORET_TYPE void do_exit(long co if (unlikely(in_interrupt())) panic("Aiee, killing interrupt handler!"); - if (unlikely(!tsk->pid)) + if (unlikely(!tsk->tid)) panic("Attempted to kill the idle task!"); - if (unlikely((tsk->pid == 1) && (tsk->pspace == &init_pspace))) + if (unlikely((tsk->tid == 1) && (tsk->pspace == &init_pspace))) panic("Attempted to kill init!"); if (tsk->io_context) exit_io_context(); @@ -852,7 +857,7 @@ fastcall NORET_TYPE void do_exit(long co if (unlikely(in_atomic())) printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n", - current->comm, current->pid, + current->comm, current->tid, preempt_count()); acct_update_integrals(tsk); @@ -962,13 +967,13 @@ asmlinkage void sys_exit_group(int error static int eligible_child(pid_t pid, int options, task_t *p) { if (pid > 0) { - if (p->pid != pid_from_user(pid)) + if (p->wid != pid) return 0; - } else if (!pid) { + } else if (!pid && (current->pspace == p->pspace)) { if (process_group(p) != process_group(current)) return 0; - } else if (pid != -1) { - if (process_group(p) != pid_from_user(-pid)) + } else if ((pid != -1) && (current->pspace == p->pspace)) { + if (process_group(p) != -pid) return 0; } @@ -1022,7 +1027,7 @@ static int wait_noreap_copyout(task_t *p if (!retval) retval = put_user((short)why, &infop->si_code); if (!retval) - retval = put_user(pid_to_user(pid), &infop->si_pid); + retval = put_user(pid, &infop->si_pid); if (!retval) retval = put_user(uid, &infop->si_uid); if (!retval) @@ -1047,7 +1052,7 @@ static int wait_task_zombie(task_t *p, i int status; if (unlikely(noreap)) { - pid_t pid = p->pid; + pid_t pid = p->wid; uid_t uid = p->uid; int exit_code = p->exit_code; int why, status; @@ -1154,7 +1159,7 @@ static int wait_task_zombie(task_t *p, i retval = put_user(status, &infop->si_status); } if (!retval && infop) - retval = put_user(pid_to_user(p->pid), &infop->si_pid); + retval = put_user(p->wid, &infop->si_pid); if (!retval && infop) retval = put_user(p->uid, &infop->si_uid); if (retval) { @@ -1162,7 +1167,7 @@ static int wait_task_zombie(task_t *p, i p->exit_state = EXIT_ZOMBIE; return retval; } - retval = p->pid; + retval = p->wid; if (p->real_parent != p->parent) { write_lock_irq(&tasklist_lock); /* Double-check with lock held. */ @@ -1222,7 +1227,7 @@ static int wait_task_stopped(task_t *p, read_unlock(&tasklist_lock); if (unlikely(noreap)) { - pid_t pid = p->pid; + pid_t pid = p->wid; uid_t uid = p->uid; int why = (p->ptrace & PT_PTRACED) ? CLD_TRAPPED : CLD_STOPPED; @@ -1293,11 +1298,11 @@ bail_ref: if (!retval && infop) retval = put_user(exit_code, &infop->si_status); if (!retval && infop) - retval = put_user(pid_to_user(p->pid), &infop->si_pid); + retval = put_user(p->wid, &infop->si_pid); if (!retval && infop) retval = put_user(p->uid, &infop->si_uid); if (!retval) - retval = p->pid; + retval = p->wid; put_task_struct(p); BUG_ON(!retval); @@ -1334,7 +1339,7 @@ static int wait_task_continued(task_t *p p->signal->flags &= ~SIGNAL_STOP_CONTINUED; spin_unlock_irq(&p->sighand->siglock); - pid = p->pid; + pid = p->wid; uid = p->uid; get_task_struct(p); read_unlock(&tasklist_lock); @@ -1345,7 +1350,7 @@ static int wait_task_continued(task_t *p if (!retval && stat_addr) retval = put_user(0xffff, stat_addr); if (!retval) - retval = p->pid; + retval = pid; } else { retval = wait_noreap_copyout(p, pid, uid, CLD_CONTINUED, SIGCONT, @@ -1518,8 +1523,6 @@ end: retval = put_user(0, &infop->si_status); } } - if (retval > 0) - retval = pid_to_user(retval); return retval; } diff --git a/kernel/fork.c b/kernel/fork.c index 97aef76..ee9cc65 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -847,7 +847,7 @@ asmlinkage long sys_set_tid_address(int { current->clear_child_tid = tidptr; - return pid_to_user(current->pid); + return current->tid; } /* @@ -932,13 +932,13 @@ static task_t *copy_process(unsigned lon p->did_exec = 0; copy_flags(clone_flags, p); - p->pid = pid; + p->wid = p->tid = pid; if ((retval = copy_pspace(clone_flags, p))) goto bad_fork_cleanup; retval = -EFAULT; if (clone_flags & CLONE_PARENT_SETTID) - if (put_user(pid_to_user(p->pid), parent_tidptr)) + if (put_user(p->wid, parent_tidptr)) goto bad_fork_cleanup_pspace; p->proc_dentry = NULL; @@ -983,7 +983,7 @@ static task_t *copy_process(unsigned lon } #endif - p->tgid = p->pid; + p->tgid = p->tid; if (clone_flags & CLONE_THREAD) p->tgid = current->tgid; @@ -1137,30 +1137,27 @@ static task_t *copy_process(unsigned lon cpuset_fork(p); if (clone_flags & CLONE_NEWPSPACE) { - /* Free the pid in the wrong process space */ - free_pidmap(current->pspace, pid, 1); - pid = 0; /* Allocate new session and process groups */ p->signal->leader = 0; - p->signal->pgrp = p->pid; - p->signal->session = p->pid; + p->signal->pgrp = 0; + p->signal->session = 0; p->signal->tty = NULL; p->signal->tty_old_pgrp = 0; - attach_pid(p, PIDTYPE_ALTPID, p->pid); + attach_pid(p, p->pspace->parent, PIDTYPE_WID, p->wid); } - attach_pid(p, PIDTYPE_PID, p->pid); - attach_pid(p, PIDTYPE_TGID, p->tgid); + attach_pid(p, p->pspace, PIDTYPE_TID, p->tid); + attach_pid(p, p->pspace, PIDTYPE_TGID, p->tgid); if (thread_group_leader(p)) { - attach_pid(p, PIDTYPE_PGID, process_group(p)); - attach_pid(p, PIDTYPE_SID, p->signal->session); - if (p->pid) - current->pspace->nr_processes++; + attach_pid(p, p->pspace, PIDTYPE_PGID, process_group(p)); + attach_pid(p, p->pspace, PIDTYPE_SID, p->signal->session); + if (p->tid) + p->pspace->nr_processes++; } if (!current->signal->tty && p->signal->tty) p->signal->tty = NULL; - current->pspace->nr_threads++; + p->pspace->nr_threads++; nr_threads++; total_forks++; write_unlock_irq(&tasklist_lock); @@ -1262,10 +1259,8 @@ long do_fork(unsigned long clone_flags, { struct task_struct *p; int trace = 0; - long pid; + long pid = alloc_pidmap(current->pspace); - pid = alloc_pidmap(current->pspace, 1); - if (pid < 0) return -EAGAIN; if (unlikely(current->ptrace)) { @@ -1282,7 +1277,6 @@ long do_fork(unsigned long clone_flags, if (!IS_ERR(p)) { struct completion vfork; - pid = p->pid; if (clone_flags & CLONE_VFORK) { p->vfork_done = &vfork; init_completion(&vfork); @@ -1312,7 +1306,7 @@ long do_fork(unsigned long clone_flags, ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP); } } else { - free_pidmap(current->pspace, pid, 1); + free_pidmap(current->pspace, pid); pid = PTR_ERR(p); } return pid; diff --git a/kernel/futex.c b/kernel/futex.c index ca05fe6..66e82ed 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -786,7 +786,7 @@ static int futex_fd(unsigned long uaddr, filp->f_mapping = filp->f_dentry->d_inode->i_mapping; if (signal) { - err = f_setown(filp, current->pid, 1); + err = f_setown(filp, current->tid, 1); if (err < 0) { goto error; } diff --git a/kernel/kexec.c b/kernel/kexec.c index cdd4dcd..b8f8890 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -36,7 +36,7 @@ struct resource crashk_res = { int kexec_should_crash(struct task_struct *p) { - if (in_interrupt() || !p->pid || p->pid == 1 || panic_on_oops) + if (in_interrupt() || !p->wid || p->wid == 1 || panic_on_oops) return 1; return 0; } diff --git a/kernel/kthread.c b/kernel/kthread.c index f50f174..c75ce8a 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -114,7 +114,7 @@ static void keventd_create_kthread(void create->result = ERR_PTR(pid); } else { wait_for_completion(&create->started); - create->result = find_task_by_pid(pid); + create->result = find_task_by_pid(current->pspace, pid); } complete(&create->done); } diff --git a/kernel/pid.c b/kernel/pid.c index 2f13c43..604c005 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -31,7 +31,8 @@ #include #include -#define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift) +#define pid_hashfn(pspace, nr) \ + hash_long(((unsigned long)pspace) ^ ((unsigned long)nr), pidhash_shift) static struct hlist_head *pid_hash[PIDTYPE_MAX]; static int pidhash_shift; @@ -59,7 +60,6 @@ struct pspace init_pspace = { .nr_threads = 0, .nr_processes = 0, .last_pid = 0, - .offset = 0, .min = RESERVED_PIDS, .max = PID_MAX_DEFAULT, .pidmap = { @@ -69,33 +69,20 @@ struct pspace init_pspace = { static __cacheline_aligned_in_smp DEFINE_SPINLOCK(pidmap_lock); -fastcall void free_pidmap(struct pspace *pspace, int pid, int count) +fastcall void free_pidmap(struct pspace *pspace, int pid) { - struct pidmap *map; - int offset; - if (pid == 0) - return; - pid -= pspace->offset; - map = pspace->pidmap + pid/BITS_PER_PAGE; - offset = pid & BITS_PER_PAGE_MASK; - - for(;count; --count) { - clear_bit(offset, map->page); - atomic_inc(&map->nr_free); + struct pidmap *map = pspace->pidmap + pid / BITS_PER_PAGE; + int offset = pid & BITS_PER_PAGE_MASK; - if (++offset == BITS_PER_PAGE) { - offset = 0; - ++map; - } - } + clear_bit(offset, map->page); + atomic_inc(&map->nr_free); } -int alloc_pidmap(struct pspace *pspace, int count) +int alloc_pidmap(struct pspace *pspace) { - int i, offset, max_scan, pid, spid, lpid, last = pspace->last_pid; + int i, offset, max_scan, pid, last = pspace->last_pid; struct pidmap *map; - spid = lpid = 0; pid = last + 1; if (pid >= pspace->max) pid = pspace->min; @@ -121,20 +108,9 @@ int alloc_pidmap(struct pspace *pspace, if (likely(atomic_read(&map->nr_free))) { do { if (!test_and_set_bit(offset, map->page)) { - /* If there was a hole free the previous allocation */ - if (spid && (pid != (lpid + 1))) { - free_pidmap(pspace, - pspace->offset + spid, - lpid - spid + 1); - spid = 0; - } - if (!spid) spid = pid; - lpid = pid; atomic_dec(&map->nr_free); - if ((lpid - spid + 1) == count) { - pspace->last_pid = lpid; - return pspace->offset + spid; - } + pspace->last_pid = pid; + return pid; } offset = find_next_offset(map, offset); pid = mk_pid(map, offset); @@ -162,34 +138,35 @@ int alloc_pidmap(struct pspace *pspace, return -1; } -struct pid * fastcall find_pid(enum pid_type type, int nr) +struct pid * fastcall find_pid(struct pspace *pspace, enum pid_type type, int nr) { struct hlist_node *elem; struct pid *pid; hlist_for_each_entry(pid, elem, - &pid_hash[type][pid_hashfn(nr)], pid_chain) { - if (pid->nr == nr) + &pid_hash[type][pid_hashfn(pspace, nr)], pid_chain) { + if ((pid->nr == nr) && (pid->pspace == pspace)) return pid; } return NULL; } -int fastcall attach_pid(task_t *task, enum pid_type type, int nr) +int fastcall attach_pid(task_t *task, struct pspace *pspace, enum pid_type type, int nr) { struct pid *pid, *task_pid; task_pid = &task->pids[type]; - pid = find_pid(type, nr); + pid = find_pid(pspace, type, nr); if (pid == NULL) { hlist_add_head(&task_pid->pid_chain, - &pid_hash[type][pid_hashfn(nr)]); + &pid_hash[type][pid_hashfn(pspace, nr)]); INIT_LIST_HEAD(&task_pid->pid_list); } else { INIT_HLIST_NODE(&task_pid->pid_chain); list_add_tail(&task_pid->pid_list, &pid->pid_list); } task_pid->nr = nr; + task_pid->pspace = pspace; return 0; } @@ -210,7 +187,7 @@ static fastcall int __detach_pid(task_t struct pid, pid_list); /* insert next pid from pid_list to hash */ hlist_add_head(&pid_next->pid_chain, - &pid_hash[type][pid_hashfn(pid_next->nr)]); + &pid_hash[type][pid_hashfn(pid->pspace, pid_next->nr)]); } } @@ -220,8 +197,9 @@ static fastcall int __detach_pid(task_t return nr; } -void fastcall detach_pid(task_t *task, enum pid_type type) +void fastcall detach_pid(task_t *task, enum pid_type type) { + struct pspace *pspace = pid_pspace(task, type); int tmp, nr; nr = __detach_pid(task, type); @@ -229,17 +207,17 @@ void fastcall detach_pid(task_t *task, e return; for (tmp = PIDTYPE_MAX; --tmp >= 0; ) - if (tmp != type && find_pid(tmp, nr)) + if (tmp != type && find_pid(pspace, tmp, nr)) return; - free_pidmap(task->pspace, nr, 1); + free_pidmap(pspace, nr); } -task_t *find_task_by_pid_type(int type, int nr) +struct task_struct *find_task_by_pid_type(struct pspace *pspace, int type, int nr) { struct pid *pid; - pid = find_pid(type, nr); + pid = find_pid(pspace, type, nr); if (!pid) return NULL; @@ -248,6 +226,17 @@ task_t *find_task_by_pid_type(int type, EXPORT_SYMBOL(find_task_by_pid_type); +struct task_struct *find_task_by_pid(struct pspace *pspace, int nr) +{ + struct task_struct *task; + task = find_task_by_pid_type(pspace, PIDTYPE_TID, nr); + if (!task) + task = find_task_by_pid_type(pspace, PIDTYPE_WID, nr); + return task; +} + +EXPORT_SYMBOL(find_task_by_pid); + /* * This function switches the PIDs if a non-leader thread calls * sys_execve() - this must be done without releasing the PID. @@ -255,37 +244,43 @@ EXPORT_SYMBOL(find_task_by_pid_type); */ void switch_exec_pids(task_t *leader, task_t *thread) { - __detach_pid(leader, PIDTYPE_PID); + int wid; + __detach_pid(leader, PIDTYPE_TID); __detach_pid(leader, PIDTYPE_TGID); __detach_pid(leader, PIDTYPE_PGID); __detach_pid(leader, PIDTYPE_SID); + __detach_pid(leader, PIDTYPE_WID); - __detach_pid(thread, PIDTYPE_PID); + __detach_pid(thread, PIDTYPE_TID); __detach_pid(thread, PIDTYPE_TGID); - leader->pid = leader->tgid = thread->pid; - thread->pid = thread->tgid; - - attach_pid(thread, PIDTYPE_PID, thread->pid); - attach_pid(thread, PIDTYPE_TGID, thread->tgid); - attach_pid(thread, PIDTYPE_PGID, thread->signal->pgrp); - attach_pid(thread, PIDTYPE_SID, thread->signal->session); + wid = leader->wid; + leader->wid = leader->tid = leader->tgid = thread->tid; + thread->tid = thread->tgid; + thread->wid = wid; + + attach_pid(thread, thread->pspace, PIDTYPE_TID, thread->tid); + attach_pid(thread, thread->pspace, PIDTYPE_TGID, thread->tgid); + attach_pid(thread, thread->pspace, PIDTYPE_PGID, thread->signal->pgrp); + attach_pid(thread, thread->pspace, PIDTYPE_SID, thread->signal->session); list_add_tail(&thread->tasks, &init_task.tasks); - attach_pid(leader, PIDTYPE_PID, leader->pid); - attach_pid(leader, PIDTYPE_TGID, leader->tgid); - attach_pid(leader, PIDTYPE_PGID, leader->signal->pgrp); - attach_pid(leader, PIDTYPE_SID, leader->signal->session); + attach_pid(leader, leader->pspace, PIDTYPE_TID, leader->tid); + attach_pid(leader, leader->pspace, PIDTYPE_TGID, leader->tgid); + attach_pid(leader, leader->pspace, PIDTYPE_PGID, leader->signal->pgrp); + attach_pid(leader, leader->pspace, PIDTYPE_SID, leader->signal->session); + + if (pspace_leader(leader)) { + attach_pid(thread, thread->pspace->parent, PIDTYPE_WID, thread->wid); + thread->pspace->child_reaper = thread; + } } -static struct pspace *new_pspace(int pids, int offset) +static struct pspace *new_pspace(void) { struct pspace *pspace; - int pages, i; - size_t bytes; - pages = (pids + 8*PAGE_SIZE - 1)/PAGE_SIZE/8; - bytes = offsetof(struct pspace, pidmap) + pages*sizeof(struct pidmap); - pspace = kmalloc(bytes, GFP_KERNEL); + int i; + pspace = kmalloc(sizeof(struct pspace), GFP_KERNEL); if (!pspace) return NULL; atomic_set(&pspace->count, 1); @@ -294,62 +289,39 @@ static struct pspace *new_pspace(int pid pspace->nr_threads = 0; pspace->nr_processes = 0; pspace->last_pid = 0; - pspace->offset = offset; - pspace->min = 1; - pspace->max = pids; - for (i = 0; i < pages; i++) { + pspace->min = RESERVED_PIDS; + pspace->max = PID_MAX_DEFAULT; + for (i = 0; i < PIDMAP_ENTRIES; i++) { atomic_set(&pspace->pidmap[i].nr_free, BITS_PER_PAGE); pspace->pidmap[i].page = NULL; } + return pspace; } int copy_pspace(int flags, struct task_struct *p) { struct pspace *new; - int pids, pid; + int pid; get_pspace(p->pspace); if (!(flags & CLONE_NEWPSPACE)) return 0; - /* Figure out how many pids I can allocate for the pspace */ - if (p->signal->rlim[RLIMIT_NPROC].rlim_cur != RLIM_INFINITY) { - pids = p->signal->rlim[RLIMIT_NPROC].rlim_cur; - } else { - /* Default to 1/256 of the pspace */ - pids = p->pspace->max >> 8; - } - - /* Verify I am allocating at least one pid */ - if (pids < 1) { - put_pspace(p->pspace); - return -EAGAIN; - } - - pid = -1; - if (pids > 0) - pid = alloc_pidmap(p->pspace, pids); - if (pid <= 0) { - put_pspace(p->pspace); - return -EAGAIN; - } - /* Allocate the new pidspace structure */ - new = new_pspace(pids, pid - 1); + new = new_pspace(); if (!new) { - free_pidmap(p->pspace, pid, pids); put_pspace(p->pspace); return -ENOMEM; } /* Allocate the new pid */ - pid = alloc_pidmap(new, 1); + pid = alloc_pidmap(new); /* Setup the new pspace and pid */ new->parent = p->pspace; p->pspace = new; - p->pid = pid; + p->tid = pid; p->pspace->child_reaper = p; return 0; @@ -359,21 +331,17 @@ void __put_pspace(struct pspace *pspace) { struct pspace *parent; struct pidmap *map; - int i, offset, pids, pages; + int i; BUG_ON(atomic_read(&pspace->count) != 0); - map = pspace->pidmap; parent = pspace->parent; - offset = pspace->offset; - pids = pspace->max; - pages = (pids + 8*PAGE_SIZE - 1)/PAGE_SIZE/8; - for (i = 0; i < pages; i++) { + map = pspace->pidmap; + for (i = 0; i < PIDMAP_ENTRIES; i++) { BUG_ON(atomic_read(&map[i].nr_free) != BITS_PER_PAGE); free_page((unsigned long)map[i].page); } kfree(pspace); - free_pidmap(parent, offset, pids); put_pspace(parent); } @@ -418,5 +386,5 @@ void __init pidmap_init(void) */ for (i = 0; i < PIDTYPE_MAX; i++) - attach_pid(current, i, 0); + attach_pid(current, current->pspace, i, 0); } diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index ac239c7..257cd61 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -21,7 +21,7 @@ static int check_clock(clockid_t which_c return 0; read_lock(&tasklist_lock); - p = find_task_by_pid(pid_from_user(pid)); + p = find_task_by_pid(current->pspace, pid); if (!p || (CPUCLOCK_PERTHREAD(which_clock) ? p->tgid != current->tgid : p->tgid != pid)) { error = -EINVAL; @@ -304,7 +304,7 @@ int posix_cpu_clock_get(clockid_t which_ */ struct task_struct *p; read_lock(&tasklist_lock); - p = find_task_by_pid(pid_from_user(pid)); + p = find_task_by_pid(current->pspace, pid); if (p) { if (CPUCLOCK_PERTHREAD(which_clock)) { if (p->tgid == current->tgid) { @@ -348,7 +348,7 @@ int posix_cpu_timer_create(struct k_itim if (pid == 0) { p = current; } else { - p = find_task_by_pid(pid_from_user(pid)); + p = find_task_by_pid(current->pspace, pid); if (p && p->tgid != current->tgid) p = NULL; } @@ -356,7 +356,7 @@ int posix_cpu_timer_create(struct k_itim if (pid == 0) { p = current->group_leader; } else { - p = find_task_by_pid(pid_from_user(pid)); + p = find_task_by_pid(current->pspace, pid); if (p && p->tgid != pid) p = NULL; } @@ -1407,7 +1407,7 @@ int posix_cpu_nsleep(clockid_t which_clo */ if (CPUCLOCK_PERTHREAD(which_clock) && (CPUCLOCK_PID(which_clock) == 0 || - CPUCLOCK_PID(which_clock) == current->pid)) + CPUCLOCK_PID(which_clock) == current->tid)) return -EINVAL; /* diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 2258a68..8b8ac6b 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -519,7 +519,7 @@ static inline struct task_struct * good_ struct task_struct *rtn = current->group_leader; if ((event->sigev_notify & SIGEV_THREAD_ID ) && - (!(rtn = find_task_by_pid(pid_from_user(event->sigev_notify_thread_id))) || + (!(rtn = find_task_by_pid(current->pspace, event->sigev_notify_thread_id)) || rtn->tgid != current->tgid || (event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_SIGNAL)) return NULL; diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 019e04e..34681cc 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -150,7 +151,7 @@ int ptrace_attach(struct task_struct *ta int retval; task_lock(task); retval = -EPERM; - if (task->pid <= 1) + if ((task->tid <= 0) || current_pspace_leader(task)) goto bad; if (task == current) goto bad; diff --git a/kernel/sched.c b/kernel/sched.c index 0b7c257..1dc71b9 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1556,7 +1556,7 @@ asmlinkage void schedule_tail(task_t *pr preempt_enable(); #endif if (current->set_child_tid) - put_user(pid_to_user(current->pid), current->set_child_tid); + put_user(current->wid, current->set_child_tid); } /* @@ -2865,7 +2865,7 @@ asmlinkage void __sched schedule(void) if (unlikely(in_atomic())) { printk(KERN_ERR "scheduling while atomic: " "%s/0x%08x/%d\n", - current->comm, preempt_count(), current->pid); + current->comm, preempt_count(), current->tid); dump_stack(); } } @@ -3583,7 +3583,7 @@ task_t *idle_task(int cpu) */ static inline task_t *find_process_by_pid(pid_t pid) { - return pid ? find_task_by_pid(pid_from_user(pid)) : current; + return pid ? find_task_by_pid(current->pspace, pid) : current; } /* Actually do priority change: must hold rq lock. */ @@ -4236,17 +4236,17 @@ static void show_task(task_t *p) free = (unsigned long) n - (unsigned long)(p->thread_info+1); } #endif - printk("%5lu %5d %6d ", free, p->pid, p->parent->pid); + printk("%5lu %5d %6d ", free, p->tid, p->parent->tid); if ((relative = eldest_child(p))) - printk("%5d ", relative->pid); + printk("%5d ", relative->tid); else printk(" "); if ((relative = younger_sibling(p))) - printk("%7d", relative->pid); + printk("%7d", relative->tid); else printk(" "); if ((relative = older_sibling(p))) - printk(" %5d", relative->pid); + printk(" %5d", relative->tid); else printk(" "); if (!p->mm) diff --git a/kernel/signal.c b/kernel/signal.c index 32fcb92..101d627 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -663,6 +663,8 @@ static int check_kill_permission(int sig if (!valid_signal(sig)) return error; error = -EPERM; + if (current_pspace_leader(t) && sig_kernel_only(sig)) + return error; if ((!info || ((unsigned long)info != 1 && (unsigned long)info != 2 && SI_FROMUSER(info))) && ((sig != SIGCONT) || @@ -822,7 +824,7 @@ static int send_signal(int sig, struct s q->info.si_signo = sig; q->info.si_errno = 0; q->info.si_code = SI_USER; - q->info.si_pid = current->pid; + q->info.si_pid = current->tid; q->info.si_uid = current->uid; break; case 1: @@ -1155,10 +1157,9 @@ int __kill_pspace_info(int sig, struct s int retval = 0, count = 0; for_each_process(p) { - struct pspace *test; int err; - /* Skip init */ - if (pspace_leader(p)) + /* Skip the current pspace leader */ + if (current_pspace_leader(p)) continue; /* Skip the sender of the signal */ @@ -1166,10 +1167,7 @@ int __kill_pspace_info(int sig, struct s continue; /* Skip processes outside the target process space */ - test = p->pspace; - while(test && (test != pspace)) - test = test->parent; - if (test != pspace) + if (!in_pspace(pspace, p)) continue; /* Finally it is a good process send the signal. */ @@ -1197,7 +1195,7 @@ int kill_pspace_info(int sig, struct sig * control characters do (^C, ^Z etc) */ -int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp) +int __kill_pg_info(int sig, struct siginfo *info, struct pspace *pspace, pid_t pgrp) { struct task_struct *p = NULL; int retval, success; @@ -1207,34 +1205,34 @@ int __kill_pg_info(int sig, struct sigin success = 0; retval = -ESRCH; - do_each_task_pid(pgrp, PIDTYPE_PGID, p) { + do_each_task_pid(pspace, pgrp, PIDTYPE_PGID, p) { int err = group_send_sig_info(sig, info, p); success |= !err; retval = err; - } while_each_task_pid(pgrp, PIDTYPE_PGID, p); + } while_each_task_pid(pspace, pgrp, PIDTYPE_PGID, p); return success ? 0 : retval; } int -kill_pg_info(int sig, struct siginfo *info, pid_t pgrp) +kill_pg_info(int sig, struct siginfo *info, struct pspace *pspace, pid_t pgrp) { int retval; read_lock(&tasklist_lock); - retval = __kill_pg_info(sig, info, pgrp); + retval = __kill_pg_info(sig, info, pspace, pgrp); read_unlock(&tasklist_lock); return retval; } int -kill_proc_info(int sig, struct siginfo *info, pid_t pid) +kill_proc_info(int sig, struct siginfo *info, struct pspace *pspace, pid_t pid) { int error; struct task_struct *p; read_lock(&tasklist_lock); - p = find_task_by_pid(pid); + p = find_task_by_pid(pspace, pid); error = -ESRCH; if (p) error = group_send_sig_info(sig, info, p); @@ -1255,22 +1253,21 @@ kill_proc_info(int sig, struct siginfo * static int kill_something_info(int sig, struct siginfo *info, int pid) { if (!pid) { - return kill_pg_info(sig, info, process_group(current)); + return kill_pg_info(sig, info, current->pspace, process_group(current)); } else if (pid < 0) { struct task_struct *p; int retval; - pid = pid_from_user(-pid); read_lock(&tasklist_lock); - p = find_task_by_pid(pid); + p = find_task_by_pid(current->pspace, -pid); if (!p || !pspace_leader(p)) - retval = __kill_pg_info(sig, info, pid); + retval = __kill_pg_info(sig, info, current->pspace, -pid); else retval = __kill_pspace_info(sig, info, p->pspace); read_unlock(&tasklist_lock); return retval; } else { - return kill_proc_info(sig, info, pid_from_user(pid)); + return kill_proc_info(sig, info, current->pspace, pid); } } @@ -1355,15 +1352,15 @@ force_sigsegv(int sig, struct task_struc } int -kill_pg(pid_t pgrp, int sig, int priv) +kill_pg(struct pspace *pspace, pid_t pgrp, int sig, int priv) { - return kill_pg_info(sig, (void *)(long)(priv != 0), pgrp); + return kill_pg_info(sig, (void *)(long)(priv != 0), pspace, pgrp); } int -kill_proc(pid_t pid, int sig, int priv) +kill_proc(struct pspace *pspace, pid_t pid, int sig, int priv) { - return kill_proc_info(sig, (void *)(long)(priv != 0), pid); + return kill_proc_info(sig, (void *)(long)(priv != 0), pspace, pid); } /* @@ -1526,7 +1523,7 @@ void do_notify_parent(struct task_struct info.si_signo = sig; info.si_errno = 0; - info.si_pid = tsk->pid; + info.si_pid = tsk->wid; info.si_uid = tsk->uid; /* FIXME: find out whether or not this is supposed to be c*time. */ @@ -1591,7 +1588,7 @@ static void do_notify_parent_cldstop(str info.si_signo = SIGCHLD; info.si_errno = 0; - info.si_pid = tsk->pid; + info.si_pid = tsk->wid; info.si_uid = tsk->uid; /* FIXME: find out whether or not this is supposed to be c*time. */ @@ -1694,7 +1691,7 @@ void ptrace_notify(int exit_code) memset(&info, 0, sizeof info); info.si_signo = SIGTRAP; info.si_code = exit_code; - info.si_pid = current->pid; + info.si_pid = current->tid; info.si_uid = current->uid; /* Let the debugger run. */ @@ -1919,7 +1916,7 @@ relock: info->si_signo = signr; info->si_errno = 0; info->si_code = SI_USER; - info->si_pid = current->parent->pid; + info->si_pid = current->parent->tgid; info->si_uid = current->parent->uid; } @@ -1949,8 +1946,11 @@ relock: if (sig_kernel_ignore(signr)) /* Default is nothing. */ continue; - /* Init gets no signals it doesn't want. */ - if (current->pid == 1) + /* Init gets no signals it doesn't want. + * Other pspace leaders can't ignore SIGKILL and SIGSTOP + */ + if (pspace_leader(current) && + ((current->wid == 1) || !sig_kernel_only(signr))) continue; if (sig_kernel_stop(signr)) { @@ -1969,7 +1969,7 @@ relock: /* signals can be posted during this window */ - if (is_orphaned_pgrp(process_group(current))) + if (is_orphaned_pgrp(current->pspace, process_group(current))) goto relock; spin_lock_irq(¤t->sighand->siglock); @@ -2175,7 +2175,7 @@ int copy_siginfo_to_user(siginfo_t __use err |= __put_user((short)from->si_code, &to->si_code); switch (from->si_code & __SI_MASK) { case __SI_KILL: - err |= __put_user(pid_to_user(from->si_pid), &to->si_pid); + err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); break; case __SI_TIMER: @@ -2194,7 +2194,7 @@ int copy_siginfo_to_user(siginfo_t __use #endif break; case __SI_CHLD: - err |= __put_user(pid_to_user(from->si_pid), &to->si_pid); + err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_status, &to->si_status); err |= __put_user(from->si_utime, &to->si_utime); @@ -2202,12 +2202,12 @@ int copy_siginfo_to_user(siginfo_t __use break; case __SI_RT: /* This is not generated by the kernel as of now. */ case __SI_MESGQ: /* But this is */ - err |= __put_user(pid_to_user(from->si_pid), &to->si_pid); + err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_ptr, &to->si_ptr); break; default: /* this is just in case for now ... */ - err |= __put_user(pid_to_user(from->si_pid), &to->si_pid); + err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); break; } @@ -2328,9 +2328,6 @@ asmlinkage long sys_tgkill(int tgid, int if (pid <= 0 || tgid <= 0) return -EINVAL; - pid = pid_from_user(pid); - tgid = pid_from_user(tgid); - info.si_signo = sig; info.si_errno = 0; info.si_code = SI_TKILL; @@ -2338,7 +2335,7 @@ asmlinkage long sys_tgkill(int tgid, int info.si_uid = current->uid; read_lock(&tasklist_lock); - p = find_task_by_pid(pid); + p = find_task_by_pid(current->pspace, pid); error = -ESRCH; if (p && (p->tgid == tgid)) { error = check_kill_permission(sig, &info, p); @@ -2371,8 +2368,6 @@ sys_tkill(int pid, int sig) if (pid <= 0) return -EINVAL; - pid = pid_from_user(pid); - info.si_signo = sig; info.si_errno = 0; info.si_code = SI_TKILL; @@ -2380,7 +2375,7 @@ sys_tkill(int pid, int sig) info.si_uid = current->uid; read_lock(&tasklist_lock); - p = find_task_by_pid(pid); + p = find_task_by_pid(current->pspace, pid); error = -ESRCH; if (p) { error = check_kill_permission(sig, &info, p); @@ -2403,7 +2398,6 @@ asmlinkage long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t __user *uinfo) { siginfo_t info; - pid = pid_from_user(pid); if (copy_from_user(&info, uinfo, sizeof(siginfo_t))) return -EFAULT; @@ -2415,7 +2409,7 @@ sys_rt_sigqueueinfo(int pid, int sig, si info.si_signo = sig; /* POSIX.1b doesn't mention process groups. */ - return kill_proc_info(sig, &info, pid); + return kill_proc_info(sig, &info, current->pspace, pid); } int diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 84a9d18..8ea1b63 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -91,7 +91,7 @@ static int stop_machine(void) /* One high-prio thread per cpu. We'll do this one. */ set_fs(KERNEL_DS); - sys_sched_setscheduler(current->pid, SCHED_FIFO, + sys_sched_setscheduler(current->tid, SCHED_FIFO, (struct sched_param __user *)¶m); set_fs(old_fs); diff --git a/kernel/sys.c b/kernel/sys.c index fb2e896..d638185 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -249,6 +249,7 @@ out: asmlinkage long sys_setpriority(int which, int who, int niceval) { + struct pspace *pspace = current->pspace; struct task_struct *g, *p; struct user_struct *user; int error = -EINVAL; @@ -267,21 +268,17 @@ asmlinkage long sys_setpriority(int whic switch (which) { case PRIO_PROCESS: if (!who) - who = current->pid; - else - who = pid_from_user(who); - p = find_task_by_pid(who); + who = current->tid; + p = find_task_by_pid(pspace, who); if (p) error = set_one_prio(p, niceval, error); break; case PRIO_PGRP: if (!who) who = process_group(current); - else - who = pid_from_user(who); - do_each_task_pid(who, PIDTYPE_PGID, p) { + do_each_task_pid(pspace, who, PIDTYPE_PGID, p) { error = set_one_prio(p, niceval, error); - } while_each_task_pid(who, PIDTYPE_PGID, p); + } while_each_task_pid(pspace, who, PIDTYPE_PGID, p); break; case PRIO_USER: user = current->user; @@ -313,6 +310,7 @@ out: */ asmlinkage long sys_getpriority(int which, int who) { + struct pspace *pspace = current->pspace; struct task_struct *g, *p; struct user_struct *user; long niceval, retval = -ESRCH; @@ -324,10 +322,8 @@ asmlinkage long sys_getpriority(int whic switch (which) { case PRIO_PROCESS: if (!who) - who = current->pid; - else - who = pid_from_user(who); - p = find_task_by_pid(who); + who = current->tid; + p = find_task_by_pid(pspace, who); if (p) { niceval = 20 - task_nice(p); if (niceval > retval) @@ -337,13 +333,11 @@ asmlinkage long sys_getpriority(int whic case PRIO_PGRP: if (!who) who = process_group(current); - else - who = pid_from_user(who); - do_each_task_pid(who, PIDTYPE_PGID, p) { + do_each_task_pid(pspace, who, PIDTYPE_PGID, p) { niceval = 20 - task_nice(p); if (niceval > retval) retval = niceval; - } while_each_task_pid(who, PIDTYPE_PGID, p); + } while_each_task_pid(pspace, who, PIDTYPE_PGID, p); break; case PRIO_USER: user = current->user; @@ -568,7 +562,7 @@ void ctrl_alt_del(void) if (C_A_D) schedule_work(&cad_work); else - kill_proc(cad_pid, SIGINT, 1); + kill_proc(&init_pspace, cad_pid, SIGINT, 1); } @@ -1082,12 +1076,12 @@ asmlinkage long sys_setpgid(pid_t pid, p struct task_struct *p; int err = -EINVAL; - if (pid < 0) - return -EINVAL; + if (!pid) + pid = current->tid; + if (!pgid) + pgid = pid; if (pgid < 0) return -EINVAL; - pid = (!pid)? current->pid : pid_from_user(pid); - pgid = (!pgid)? pid : pid_from_user(pgid); /* From this point forward we keep holding onto the tasklist lock * so that our parent does not change from under us. -DaveM @@ -1095,7 +1089,7 @@ asmlinkage long sys_setpgid(pid_t pid, p write_lock_irq(&tasklist_lock); err = -ESRCH; - p = find_task_by_pid(pid); + p = find_task_by_pid(current->pspace, pid); if (!p) goto out; @@ -1121,12 +1115,13 @@ asmlinkage long sys_setpgid(pid_t pid, p goto out; if (pgid != pid) { + struct pspace *pspace = current->pspace; struct task_struct *p; - do_each_task_pid(pgid, PIDTYPE_PGID, p) { + do_each_task_pid(pspace, pgid, PIDTYPE_PGID, p) { if (p->signal->session == current->signal->session) goto ok_pgid; - } while_each_task_pid(pgid, PIDTYPE_PGID, p); + } while_each_task_pid(pspace, pgid, PIDTYPE_PGID, p); goto out; } @@ -1138,7 +1133,7 @@ ok_pgid: if (process_group(p) != pgid) { detach_pid(p, PIDTYPE_PGID); p->signal->pgrp = pgid; - attach_pid(p, PIDTYPE_PGID, pgid); + attach_pid(p, p->pspace, PIDTYPE_PGID, pgid); } err = 0; @@ -1151,21 +1146,19 @@ out: asmlinkage long sys_getpgid(pid_t pid) { if (!pid) { - return pid_to_user(process_group(current)); + return process_group(current); } else { int retval; struct task_struct *p; - pid = pid_from_user(pid); read_lock(&tasklist_lock); - p = find_task_by_pid(pid); + p = find_task_by_pid(current->pspace, pid); retval = -ESRCH; if (p) { retval = security_task_getpgid(p); if (!retval) retval = process_group(p); - retval = pid_to_user(retval); } read_unlock(&tasklist_lock); return retval; @@ -1177,7 +1170,7 @@ asmlinkage long sys_getpgid(pid_t pid) asmlinkage long sys_getpgrp(void) { /* SMP - assuming writes are word atomic this is fine */ - return pid_to_user(process_group(current)); + return process_group(current); } #endif @@ -1185,21 +1178,19 @@ asmlinkage long sys_getpgrp(void) asmlinkage long sys_getsid(pid_t pid) { if (!pid) { - return pid_to_user(current->signal->session); + return current->signal->session; } else { int retval; struct task_struct *p; - pid = pid_from_user(pid); read_lock(&tasklist_lock); - p = find_task_by_pid(pid); + p = find_task_by_pid(current->pspace, pid); retval = -ESRCH; - if (p) { + if(p) { retval = security_task_getsid(p); if (!retval) retval = p->signal->session; - retval = pid_to_user(retval); } read_unlock(&tasklist_lock); return retval; @@ -1217,12 +1208,12 @@ asmlinkage long sys_setsid(void) down(&tty_sem); write_lock_irq(&tasklist_lock); - pid = find_pid(PIDTYPE_PGID, current->pid); + pid = find_pid(current->pspace, PIDTYPE_PGID, current->tid); if (pid) goto out; current->signal->leader = 1; - __set_special_pids(current->pid, current->pid); + __set_special_pids(current->tid, current->tid); current->signal->tty = NULL; current->signal->tty_old_pgrp = 0; err = process_group(current); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 889eea9..01cdcec 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1686,7 +1686,7 @@ int proc_dointvec_bset(ctl_table *table, return -EPERM; } - op = (current->pid == 1) ? OP_SET : OP_AND; + op = (current->wid == 1) ? OP_SET : OP_AND; return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, do_proc_dointvec_bset_conv,&op); } diff --git a/kernel/timer.c b/kernel/timer.c index 72b5e6d..a8a08d0 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -979,6 +979,13 @@ asmlinkage unsigned long sys_alarm(unsig #endif +#ifndef __alpha__ + +/* + * The Alpha uses getxpid, getxuid, and getxgid instead. Maybe this + * should be moved into arch/i386 instead? + */ + /** * sys_getpid - return the thread group id of the current process * @@ -990,7 +997,7 @@ asmlinkage unsigned long sys_alarm(unsig */ asmlinkage long sys_getpid(void) { - return pid_to_user(current->tgid); + return current->tgid; } /* @@ -1034,16 +1041,11 @@ asmlinkage long sys_getppid(void) #endif break; } - return pid_to_user(pid); + if (current->tgid == 1) + pid = 0; + return pid; } -#ifndef __alpha__ - -/* - * The Alpha uses getxpid, getxuid, and getxgid instead. - * And is suffering bit-rot because of the difference. - */ - asmlinkage long sys_getuid(void) { /* Only we change this so SMP safe */ @@ -1175,7 +1177,7 @@ EXPORT_SYMBOL(schedule_timeout_uninterru /* Thread ID - the internal kernel "pid" */ asmlinkage long sys_gettid(void) { - return current->pid; + return current->tid; } static long __sched nanosleep_restart(struct restart_block *restart) diff --git a/mm/oom_kill.c b/mm/oom_kill.c index d348b90..11690fa 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -149,7 +149,7 @@ static struct task_struct * select_bad_p int releasing; /* skip the init task with pid == 1 */ - if (p->pid == 1) + if (p->wid == 1) continue; if (p->oomkilladj == OOM_DISABLE) continue; @@ -184,7 +184,7 @@ static struct task_struct * select_bad_p */ static void __oom_kill_task(task_t *p) { - if (p->pid == 1) { + if (p->wid == 1) { WARN_ON(1); printk(KERN_WARNING "tried to kill init!\n"); return; @@ -199,7 +199,7 @@ static void __oom_kill_task(task_t *p) } task_unlock(p); printk(KERN_ERR "Out of Memory: Killed process %d (%s).\n", - p->pid, p->comm); + p->tid, p->comm); /* * We give our sacrificial lamb high priority and access to diff --git a/mm/vmscan.c b/mm/vmscan.c index 0ea71e8..5b2e0c3 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1321,7 +1321,7 @@ static int __init kswapd_init(void) swap_setup(); for_each_pgdat(pgdat) pgdat->kswapd - = find_task_by_pid(kernel_thread(kswapd, pgdat, CLONE_KERNEL)); + = find_task_by_pid(current->pspace, kernel_thread(kswapd, pgdat, CLONE_KERNEL)); total_memory = nr_free_pagecache_pages(); hotcpu_notifier(cpu_callback, 0); return 0; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 9bed756..6c90700 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -454,7 +454,7 @@ void rtmsg_ifinfo(int type, struct net_d if (!skb) return; - if (rtnetlink_fill_ifinfo(skb, dev, type, current->pid, 0, change, 0) < 0) { + if (rtnetlink_fill_ifinfo(skb, dev, type, current->tid, 0, change, 0) < 0) { kfree_skb(skb); return; } diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 74f2207..e6949fa 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1112,7 +1112,7 @@ static void rtmsg_ifa(int event, struct if (!skb) netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS); - else if (inet_fill_ifaddr(skb, ifa, current->pid, 0, event, 0) < 0) { + else if (inet_fill_ifaddr(skb, ifa, current->tid, 0, event, 0) < 0) { kfree_skb(skb); netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL); } else { diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 186f20c..1107961 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -1043,7 +1043,7 @@ fib_convert_rtentry(int cmd, struct nlms } nl->nlmsg_flags = NLM_F_REQUEST; - nl->nlmsg_pid = current->pid; + nl->nlmsg_pid = current->tid; nl->nlmsg_seq = 0; nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm)); if (cmd == SIOCDELRT) { diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f3f0013..4abb706 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1299,7 +1299,7 @@ do_prequeue: if ((flags & MSG_PEEK) && peek_seq != tp->copied_seq) { if (net_ratelimit()) printk(KERN_DEBUG "TCP(%s:%d): Application bug, race in MSG_PEEK.\n", - current->comm, current->pid); + current->comm, current->tid); peek_seq = tp->copied_seq; } continue; diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 678c3f2..8e282c2 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -474,7 +474,7 @@ static int netlink_autobind(struct socke struct hlist_head *head; struct sock *osk; struct hlist_node *node; - s32 pid = current->pid; + s32 pid = current->tid; int err; static s32 rover = -4097; diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 54e60a6..dfae5c9 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -792,7 +792,7 @@ void rpc_init_task(struct rpc_task *task spin_unlock(&rpc_sched_lock); dprintk("RPC: %4d new task procpid %d\n", task->tk_pid, - current->pid); + current->tid); } static struct rpc_task * diff --git a/security/commoncap.c b/security/commoncap.c index 04c12f5..7361db0 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -169,7 +169,7 @@ void cap_bprm_apply_creds (struct linux_ /* For init, we want to retain the capabilities set * in the init_task struct. Thus we skip the usual * capability rules */ - if (current->pid != 1) { + if (current->wid != 1) { current->cap_permitted = new_permitted; current->cap_effective = cap_intersect (new_permitted, bprm->cap_effective); -- 1.0.GIT