From 1bd563fd41bf28b72605b4c4b9254d31f20a3814 Mon Sep 17 00:00:00 2001 From: Andrew Morton <akpm@osdl.org> Date: Sat, 4 Oct 2003 21:04:11 -0700 Subject: [PATCH] [PATCH] move job control fields from task_struct to From: Roland McGrath <roland@redhat.com> This patch completes what was started with the `process_group' accessor function, moving all the job control-related fields from task_struct into signal_struct and using process_foo accessor functions to read them. All these things are per-process in POSIX, none per-thread. Off hand it's hard to come up with the hairy MT scenarios in which the existing code would do insane things, but trust me, they're there. At any rate, all the uses being done via inline accessor functions now has got to be all good. I did a "make allyesconfig" build and caught the few random drivers and whatnot that referred to these fields. I was surprised to find how few references to ->tty there really were to fix up. I'm sure there will be a few more fixups needed in non-x86 code. The only actual testing of a running kernel with these patches I've done is on my normal minimal x86 config. Everything works fine as it did before as far as I can tell. One issue that may be of concern is the lack of any locking on multiple threads diddling these fields. I don't think it really matters, though there might be some obscure races that could produce inconsistent job control results. Nothing shattering, I'm sure; probably only something like a multi-threaded program calling setsid while its other threads do tty i/o, which never happens in reality. This is the same situation we get by using ->group_leader->foo without other synchronization, which seemed to be the trend and noone was worried about it. --- arch/ia64/kernel/unaligned.c | 2 +- drivers/char/n_tty.c | 3 +- drivers/char/rocket.c | 2 +- drivers/char/tty_io.c | 88 ++++++++++++++++----------------- drivers/char/vt.c | 2 +- drivers/char/vt_ioctl.c | 3 +- drivers/net/slip.c | 2 +- fs/binfmt_elf.c | 4 +- fs/dquot.c | 10 ++-- fs/exec.c | 5 ++ fs/open.c | 2 +- fs/proc/array.c | 8 +-- include/linux/sched.h | 32 +++++++++--- kernel/acct.c | 2 +- kernel/exit.c | 22 ++++----- kernel/fork.c | 14 ++++-- kernel/pid.c | 8 +-- kernel/signal.c | 5 +- kernel/sys.c | 18 +++---- net/ipv4/netfilter/ipt_owner.c | 2 +- net/ipv6/netfilter/ip6t_owner.c | 2 +- 21 files changed, 132 insertions(+), 104 deletions(-) diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index 95f77b1dfa11..c6afad0dd189 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c @@ -1347,7 +1347,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) * be holding locks... */ if (user_mode(regs)) - tty_write_message(current->tty, buf); + tty_write_message(process_tty(current), buf); buf[len-1] = '\0'; /* drop '\r' */ printk(KERN_WARNING "%s", buf); /* watch for command names containing %s */ } diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 44d551ba1091..4a3fc4deb24a 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -974,7 +974,8 @@ static ssize_t read_chan(struct tty_struct *tty, struct file *file, /* NOTE: not yet done after every sleep pending a thorough check of the logic of this change. -- jlc */ /* don't stop on /dev/console */ - if (file->f_op->write != redirected_tty_write && current->tty == tty) { + if (file->f_op->write != redirected_tty_write && + process_tty(current) == tty) { if (tty->pgrp <= 0) printk("read_chan: tty->pgrp <= 0!\n"); else if (process_group(current) != tty->pgrp) { diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 843c4b5f8bd8..7c1f55bc1574 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -953,7 +953,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) /* * Info->count is now 1; so it's safe to sleep now. */ - info->session = current->session; + info->session = process_session(current); info->pgrp = process_group(current); if ((info->flags & ROCKET_INITIALIZED) == 0) { diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 31a43060d708..6191811d0ecf 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -314,7 +314,7 @@ struct tty_driver *get_tty_driver(dev_t device, int *index) */ int tty_check_change(struct tty_struct * tty) { - if (current->tty != tty) + if (process_tty(current) != tty) return 0; if (tty->pgrp <= 0) { printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n"); @@ -481,14 +481,14 @@ void do_tty_hangup(void *data) if (tty->session > 0) { struct list_head *l; for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) { - if (p->tty == tty) - p->tty = NULL; - if (!p->leader) + if (process_tty(p) == tty) + p->signal->tty = NULL; + if (!process_session_leader(p)) continue; send_group_sig_info(SIGHUP, SEND_SIG_PRIV, p); send_group_sig_info(SIGCONT, SEND_SIG_PRIV, p); if (tty->pgrp > 0) - p->tty_old_pgrp = tty->pgrp; + p->signal->tty_old_pgrp = tty->pgrp; } } read_unlock(&tasklist_lock); @@ -565,15 +565,15 @@ void disassociate_ctty(int on_exit) lock_kernel(); - tty = current->tty; + tty = process_tty(current); if (tty) { tty_pgrp = tty->pgrp; if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) tty_vhangup(tty); } else { - if (current->tty_old_pgrp) { - kill_pg(current->tty_old_pgrp, SIGHUP, on_exit); - kill_pg(current->tty_old_pgrp, SIGCONT, on_exit); + 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); } unlock_kernel(); return; @@ -584,13 +584,13 @@ void disassociate_ctty(int on_exit) kill_pg(tty_pgrp, SIGCONT, on_exit); } - current->tty_old_pgrp = 0; + current->signal->tty_old_pgrp = 0; tty->session = 0; tty->pgrp = -1; read_lock(&tasklist_lock); - for_each_task_pid(current->session, PIDTYPE_SID, p, l, pid) - p->tty = NULL; + for_each_task_pid(process_session(current), PIDTYPE_SID, p, l, pid) + p->signal->tty = NULL; read_unlock(&tasklist_lock); unlock_kernel(); } @@ -1218,10 +1218,10 @@ static void release_dev(struct file * filp) read_lock(&tasklist_lock); for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) - p->tty = NULL; + p->signal->tty = NULL; if (o_tty) for_each_task_pid(o_tty->session, PIDTYPE_SID, p,l, pid) - p->tty = NULL; + p->signal->tty = NULL; read_unlock(&tasklist_lock); } @@ -1292,10 +1292,10 @@ static int tty_open(struct inode * inode, struct file * filp) retry_open: noctty = filp->f_flags & O_NOCTTY; if (device == MKDEV(TTYAUX_MAJOR,0)) { - if (!current->tty) + if (!process_tty(current)) return -ENXIO; - driver = current->tty->driver; - index = current->tty->index; + driver = process_tty(current)->driver; + index = process_tty(current)->index; filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ /* noctty = 1; */ goto got_driver; @@ -1389,15 +1389,13 @@ static int tty_open(struct inode * inode, struct file * filp) filp->f_op = &tty_fops; goto retry_open; } - if (!noctty && - current->leader && - !current->tty && - tty->session == 0) { + if (!noctty && process_session_leader(current) && + !process_tty(current) && tty->session == 0) { task_lock(current); - current->tty = tty; + current->signal->tty = tty; task_unlock(current); - current->tty_old_pgrp = 0; - tty->session = current->session; + current->signal->tty_old_pgrp = 0; + tty->session = process_session(current); tty->pgrp = process_group(current); } return 0; @@ -1455,7 +1453,7 @@ static int tiocsti(struct tty_struct *tty, char * arg) { char ch, mbz = 0; - if ((current->tty != tty) && !capable(CAP_SYS_ADMIN)) + if ((process_tty(current) != tty) && !capable(CAP_SYS_ADMIN)) return -EPERM; if (get_user(ch, arg)) return -EFAULT; @@ -1541,14 +1539,14 @@ static int tiocsctty(struct tty_struct *tty, int arg) struct pid *pid; task_t *p; - if (current->leader && - (current->session == tty->session)) + if (process_session_leader(current) && + (process_session(current) == tty->session)) return 0; /* * The process must be a session leader and * not have a controlling tty already. */ - if (!current->leader || current->tty) + if (!process_session_leader(current) || process_tty(current)) return -EPERM; if (tty->session > 0) { /* @@ -1562,16 +1560,16 @@ static int tiocsctty(struct tty_struct *tty, int arg) read_lock(&tasklist_lock); for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) - p->tty = NULL; + p->signal->tty = NULL; read_unlock(&tasklist_lock); } else return -EPERM; } task_lock(current); - current->tty = tty; + current->signal->tty = tty; task_unlock(current); - current->tty_old_pgrp = 0; - tty->session = current->session; + current->signal->tty_old_pgrp = 0; + tty->session = process_session(current); tty->pgrp = process_group(current); return 0; } @@ -1582,12 +1580,13 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t * (tty == real_tty) is a cheap way of * testing if the tty is NOT a master pty. */ - if (tty == real_tty && current->tty != real_tty) + if (tty == real_tty && process_tty(current) != real_tty) return -ENOTTY; return put_user(real_tty->pgrp, arg); } -static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t *arg) +static int tiocspgrp(struct tty_struct *tty, + struct tty_struct *real_tty, pid_t *arg) { pid_t pgrp; int retval = tty_check_change(real_tty); @@ -1596,15 +1595,14 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t return -ENOTTY; if (retval) return retval; - if (!current->tty || - (current->tty != real_tty) || - (real_tty->session != current->session)) + if (!process_tty(current) || (process_tty(current) != real_tty) || + (real_tty->session != process_session(current))) return -ENOTTY; if (get_user(pgrp, (pid_t *) arg)) return -EFAULT; if (pgrp < 0) return -EINVAL; - if (session_of_pgrp(pgrp) != current->session) + if (session_of_pgrp(pgrp) != process_session(current)) return -EPERM; real_tty->pgrp = pgrp; return 0; @@ -1616,7 +1614,7 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t * * (tty == real_tty) is a cheap way of * testing if the tty is NOT a master pty. */ - if (tty == real_tty && current->tty != real_tty) + if (tty == real_tty && process_tty(current) != real_tty) return -ENOTTY; if (real_tty->session <= 0) return -ENOTTY; @@ -1774,12 +1772,12 @@ int tty_ioctl(struct inode * inode, struct file * file, clear_bit(TTY_EXCLUSIVE, &tty->flags); return 0; case TIOCNOTTY: - if (current->tty != tty) + if (process_tty(current) != tty) return -ENOTTY; - if (current->leader) + if (process_session_leader(current)) disassociate_ctty(0); task_lock(current); - current->tty = NULL; + current->signal->tty = NULL; task_unlock(current); return 0; case TIOCSCTTY: @@ -1883,10 +1881,10 @@ static void __do_SAK(void *arg) tty->driver->flush_buffer(tty); read_lock(&tasklist_lock); for_each_task_pid(session, PIDTYPE_SID, p, l, pid) { - if (p->tty == tty || session > 0) { + if (process_tty(p) == tty || session > 0) { printk(KERN_NOTICE "SAK: killed process %d" - " (%s): p->session==tty->session\n", - p->pid, p->comm); + " (%s): process_session(p)==tty->session\n", + p->pid, p->comm); send_sig(SIGKILL, p, 1); continue; } diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 464c3404d4dc..1bbc8a6f51c8 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -2226,7 +2226,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) if (tty->driver->type != TTY_DRIVER_TYPE_CONSOLE) return -EINVAL; - if (current->tty != tty && !capable(CAP_SYS_ADMIN)) + if (process_tty(current) != tty && !capable(CAP_SYS_ADMIN)) return -EPERM; if (get_user(type, (char *)arg)) return -EFAULT; diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index ca817c0758ad..967d6ce1823c 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -380,7 +380,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. */ perm = 0; - if (current->tty == tty || capable(CAP_SYS_TTY_CONFIG)) + if (process_tty(current) == tty || capable(CAP_SYS_TTY_CONFIG)) perm = 1; kbd = kbd_table + console; @@ -1188,4 +1188,3 @@ void change_console(unsigned int new_console) complete_change_console(new_console); } - diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 601df52ebb29..2ca38bcdc848 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -1307,7 +1307,7 @@ static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd) /* Resolve race condition, when ioctl'ing hanged up and opened by another process device. */ - if (sl->tty != current->tty && sl->pid != current->pid) { + if (sl->tty != process_tty(current) && sl->pid != current->pid) { spin_unlock_bh(&sl->lock); return -EPERM; } diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 2cdd10da42fd..505c73aa94ee 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1084,7 +1084,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus, prstatus->pr_pid = p->pid; prstatus->pr_ppid = p->parent->pid; prstatus->pr_pgrp = process_group(p); - prstatus->pr_sid = p->session; + prstatus->pr_sid = process_session(p); jiffies_to_timeval(p->utime, &prstatus->pr_utime); jiffies_to_timeval(p->stime, &prstatus->pr_stime); jiffies_to_timeval(p->cutime, &prstatus->pr_cutime); @@ -1112,7 +1112,7 @@ static void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, psinfo->pr_pid = p->pid; psinfo->pr_ppid = p->parent->pid; psinfo->pr_pgrp = process_group(p); - psinfo->pr_sid = p->session; + psinfo->pr_sid = process_session(p); i = p->state ? ffz(~p->state) + 1 : 0; psinfo->pr_state = i; diff --git a/fs/dquot.c b/fs/dquot.c index 9b3a6aae6c5f..4110e97e3bf5 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -668,12 +668,12 @@ static void print_warning(struct dquot *dquot, const char warntype) if (!need_print_warning(dquot) || (flag && test_and_set_bit(flag, &dquot->dq_flags))) return; - tty_write_message(current->tty, dquot->dq_sb->s_id); + tty_write_message(process_tty(current), dquot->dq_sb->s_id); if (warntype == ISOFTWARN || warntype == BSOFTWARN) - tty_write_message(current->tty, ": warning, "); + tty_write_message(process_tty(current), ": warning, "); else - tty_write_message(current->tty, ": write failed, "); - tty_write_message(current->tty, quotatypes[dquot->dq_type]); + tty_write_message(process_tty(current), ": write failed, "); + tty_write_message(process_tty(current), quotatypes[dquot->dq_type]); switch (warntype) { case IHARDWARN: msg = " file limit reached.\n"; @@ -694,7 +694,7 @@ static void print_warning(struct dquot *dquot, const char warntype) msg = " block quota exceeded.\n"; break; } - tty_write_message(current->tty, msg); + tty_write_message(process_tty(current), msg); } static inline void flush_warnings(struct dquot **dquots, char *warntype) diff --git a/fs/exec.c b/fs/exec.c index 84d224e71d3a..e4bc842cd9c7 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -596,6 +596,11 @@ static inline int de_thread(struct task_struct *tsk) newsig->group_stop_count = 0; newsig->curr_target = NULL; init_sigpending(&newsig->shared_pending); + + newsig->pgrp = oldsig->pgrp; + newsig->session = oldsig->session; + newsig->leader = oldsig->leader; + newsig->tty_old_pgrp = oldsig->tty_old_pgrp; } if (thread_group_empty(current)) diff --git a/fs/open.c b/fs/open.c index b5550e9049af..cac72d129b71 100644 --- a/fs/open.c +++ b/fs/open.c @@ -1019,7 +1019,7 @@ asmlinkage long sys_close(unsigned int fd) asmlinkage long sys_vhangup(void) { if (capable(CAP_SYS_TTY_CONFIG)) { - tty_vhangup(current->tty); + tty_vhangup(process_tty(current)); return 0; } return -EPERM; diff --git a/fs/proc/array.c b/fs/proc/array.c index 1eba76a6f603..7029fc9eb211 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -304,9 +304,9 @@ int proc_pid_stat(struct task_struct *task, char * buffer) mm = task->mm; if(mm) mm = mmgrab(mm); - if (task->tty) { - tty_pgrp = task->tty->pgrp; - tty_nr = new_encode_dev(tty_devnum(task->tty)); + if (process_tty(task)) { + tty_pgrp = process_tty(task)->pgrp; + tty_nr = new_encode_dev(tty_devnum(process_tty(task))); } task_unlock(task); if (mm) { @@ -345,7 +345,7 @@ int proc_pid_stat(struct task_struct *task, char * buffer) state, ppid, process_group(task), - task->session, + process_session(task), tty_nr, tty_pgrp, task->flags, diff --git a/include/linux/sched.h b/include/linux/sched.h index 21a1c416594c..a504b6a92ccf 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -264,6 +264,15 @@ struct signal_struct { /* thread group stop support, overloads group_exit_code too */ int group_stop_count; + + /* job control IDs */ + pid_t pgrp; + pid_t tty_old_pgrp; + pid_t session; + /* boolean value for session group leader */ + int leader; + + struct tty_struct *tty; /* NULL if no tty */ }; /* @@ -366,12 +375,7 @@ struct task_struct { unsigned long personality; int did_exec:1; pid_t pid; - pid_t __pgrp; /* Accessed via process_group() */ - pid_t tty_old_pgrp; - pid_t session; pid_t tgid; - /* boolean value for session group leader */ - int leader; /* * pointers to (original) parent process, youngest child, younger sibling, * older sibling, respectively. (p->father can be replaced with @@ -415,7 +419,6 @@ struct task_struct { char comm[16]; /* file system info */ int link_count, total_link_count; - struct tty_struct *tty; /* NULL if no tty */ unsigned int locks; /* How many file locks are being held */ /* ipc stuff */ struct sysv_sem sysvsem; @@ -469,7 +472,22 @@ struct task_struct { static inline pid_t process_group(struct task_struct *tsk) { - return tsk->group_leader->__pgrp; + return tsk->signal->pgrp; +} + +static inline pid_t process_session(struct task_struct *tsk) +{ + return tsk->signal->session; +} + +static inline int process_session_leader(struct task_struct *tsk) +{ + return tsk->signal->leader; +} + +static inline struct tty_struct *process_tty(struct task_struct *tsk) +{ + return tsk->signal->tty; } extern void __put_task_struct(struct task_struct *tsk); diff --git a/kernel/acct.c b/kernel/acct.c index a679f4bb9854..37e98d713023 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -343,7 +343,7 @@ static void do_acct_process(long exitcode, struct file *file) /* we really need to bite the bullet and change layout */ ac.ac_uid = current->uid; ac.ac_gid = current->gid; - ac.ac_tty = current->tty ? old_encode_dev(tty_devnum(current->tty)) : 0; + ac.ac_tty = process_tty(current) ? old_encode_dev(tty_devnum(process_tty(current))) : 0; ac.ac_flag = 0; if (current->flags & PF_FORKNOEXEC) diff --git a/kernel/exit.c b/kernel/exit.c index c565fd69d559..a87c12eed85d 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -119,13 +119,13 @@ int session_of_pgrp(int pgrp) read_lock(&tasklist_lock); for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid) - if (p->session > 0) { - sid = p->session; + if (process_session(p) > 0) { + sid = process_session(p); goto out; } p = find_task_by_pid(pgrp); if (p) - sid = p->session; + sid = process_session(p); out: read_unlock(&tasklist_lock); @@ -153,7 +153,7 @@ static int will_become_orphaned_pgrp(int pgrp, task_t *ignored_task) || p->real_parent->pid == 1) continue; if (process_group(p->real_parent) != pgrp - && p->real_parent->session == p->session) { + && process_session(p->real_parent) == process_session(p)) { ret = 0; break; } @@ -242,14 +242,14 @@ void __set_special_pids(pid_t session, pid_t pgrp) { struct task_struct *curr = current; - if (curr->session != session) { + if (process_session(curr) != session) { detach_pid(curr, PIDTYPE_SID); - curr->session = session; + curr->signal->session = session; attach_pid(curr, PIDTYPE_SID, session); } if (process_group(curr) != pgrp) { detach_pid(curr, PIDTYPE_PGID); - curr->group_leader->__pgrp = pgrp; + curr->signal->pgrp = pgrp; attach_pid(curr, PIDTYPE_PGID, pgrp); } } @@ -303,7 +303,7 @@ void daemonize(const char *name, ...) exit_mm(current); set_special_pids(1, 1); - current->tty = NULL; + current->signal->tty = NULL; /* Block and flush all signals */ sigfillset(&blocked); @@ -509,7 +509,7 @@ static inline void reparent_thread(task_t *p, task_t *father, int traced) * outside, so the child pgrp is now orphaned. */ if ((process_group(p) != process_group(father)) && - (p->session == father->session)) { + (process_session(p) == process_session(father))) { int pgrp = process_group(p); if (will_become_orphaned_pgrp(pgrp, NULL) && has_stopped_jobs(pgrp)) { @@ -619,7 +619,7 @@ static void exit_notify(struct task_struct *tsk) t = tsk->real_parent; if ((process_group(t) != process_group(tsk)) && - (t->session == tsk->session) && + (process_session(t) == process_session(tsk)) && will_become_orphaned_pgrp(process_group(tsk), tsk) && has_stopped_jobs(process_group(tsk))) { __kill_pg_info(SIGHUP, (void *)1, process_group(tsk)); @@ -714,7 +714,7 @@ NORET_TYPE void do_exit(long code) exit_itimers(tsk); exit_thread(); - if (tsk->leader) + if (process_session_leader(tsk)) disassociate_ctty(1); module_put(tsk->thread_info->exec_domain->module); diff --git a/kernel/fork.c b/kernel/fork.c index 2005c5c180de..f804f3124820 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -725,6 +725,12 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts sig->curr_target = NULL; init_sigpending(&sig->shared_pending); + sig->tty = process_tty(current); + sig->pgrp = process_group(current); + sig->session = process_session(current); + sig->leader = 0; /* session leadership doesn't inherit */ + sig->tty_old_pgrp = 0; + return 0; } @@ -771,7 +777,9 @@ struct task_struct *copy_process(unsigned long clone_flags, * Thread groups must share signals as well, and detached threads * can only be started up within the thread group. */ - if ((clone_flags & CLONE_THREAD) && !(clone_flags & CLONE_SIGHAND)) + if ((clone_flags & CLONE_THREAD) && + (clone_flags & (CLONE_SIGHAND|CLONE_DETACHED)) != + (CLONE_SIGHAND|CLONE_DETACHED)) return ERR_PTR(-EINVAL); /* @@ -876,8 +884,6 @@ struct task_struct *copy_process(unsigned long clone_flags, init_timer(&p->real_timer); p->real_timer.data = (unsigned long) p; - p->leader = 0; /* session leadership doesn't inherit */ - p->tty_old_pgrp = 0; p->utime = p->stime = 0; p->cutime = p->cstime = 0; p->array = NULL; @@ -1022,7 +1028,7 @@ struct task_struct *copy_process(unsigned long clone_flags, if (thread_group_leader(p)) { attach_pid(p, PIDTYPE_TGID, p->tgid); attach_pid(p, PIDTYPE_PGID, process_group(p)); - attach_pid(p, PIDTYPE_SID, p->session); + attach_pid(p, PIDTYPE_SID, process_session(p)); if (p->pid) __get_cpu_var(process_counts)++; } else diff --git a/kernel/pid.c b/kernel/pid.c index 713f54eaeda9..97bdf534c9f3 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -250,14 +250,14 @@ void switch_exec_pids(task_t *leader, task_t *thread) attach_pid(thread, PIDTYPE_PID, thread->pid); attach_pid(thread, PIDTYPE_TGID, thread->tgid); - attach_pid(thread, PIDTYPE_PGID, leader->__pgrp); - attach_pid(thread, PIDTYPE_SID, thread->session); + attach_pid(thread, PIDTYPE_PGID, thread->signal->pgrp); + attach_pid(thread, 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->__pgrp); - attach_pid(leader, PIDTYPE_SID, leader->session); + attach_pid(leader, PIDTYPE_PGID, leader->signal->pgrp); + attach_pid(leader, PIDTYPE_SID, leader->signal->session); } /* diff --git a/kernel/signal.c b/kernel/signal.c index 852da1a009da..469deaeeff56 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -593,7 +593,8 @@ static int check_kill_permission(int sig, struct siginfo *info, error = -EPERM; if ((!info || ((unsigned long)info != 1 && (unsigned long)info != 2 && SI_FROMUSER(info))) - && ((sig != SIGCONT) || (current->session != t->session)) + && ((sig != SIGCONT) || + (process_session(current) != process_session(t))) && (current->euid ^ t->suid) && (current->euid ^ t->uid) && (current->uid ^ t->suid) && (current->uid ^ t->uid) && !capable(CAP_KILL)) @@ -1102,7 +1103,7 @@ kill_sl_info(int sig, struct siginfo *info, pid_t sid) retval = -ESRCH; read_lock(&tasklist_lock); for_each_task_pid(sid, PIDTYPE_SID, p, l, pid) { - if (!p->leader) + if (!process_session_leader(p)) continue; err = group_send_sig_info(sig, info, p); if (retval) diff --git a/kernel/sys.c b/kernel/sys.c index 9eda26d6745c..6f8f43156ab3 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -951,7 +951,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) if (p->parent == current || p->real_parent == current) { err = -EPERM; - if (p->session != current->session) + if (process_session(p) != process_session(current)) goto out; err = -EACCES; if (p->did_exec) @@ -963,7 +963,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) } err = -EPERM; - if (p->leader) + if (process_session_leader(p)) goto out; if (pgid != pid) { @@ -972,7 +972,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) struct list_head *l; for_each_task_pid(pgid, PIDTYPE_PGID, p, l, pid) - if (p->session == current->session) + if (process_session(p) == process_session(current)) goto ok_pgid; goto out; } @@ -984,7 +984,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) if (process_group(p) != pgid) { detach_pid(p, PIDTYPE_PGID); - p->group_leader->__pgrp = pgid; + p->signal->pgrp = pgid; attach_pid(p, PIDTYPE_PGID, pgid); } @@ -1026,7 +1026,7 @@ asmlinkage long sys_getpgrp(void) asmlinkage long sys_getsid(pid_t pid) { if (!pid) { - return current->session; + return process_session(current); } else { int retval; struct task_struct *p; @@ -1038,7 +1038,7 @@ asmlinkage long sys_getsid(pid_t pid) if(p) { retval = security_task_getsid(p); if (!retval) - retval = p->session; + retval = process_session(p); } read_unlock(&tasklist_lock); return retval; @@ -1059,10 +1059,10 @@ asmlinkage long sys_setsid(void) if (pid) goto out; - current->leader = 1; + current->signal->leader = 1; __set_special_pids(current->pid, current->pid); - current->tty = NULL; - current->tty_old_pgrp = 0; + current->signal->tty = NULL; + current->signal->tty_old_pgrp = 0; err = process_group(current); out: write_unlock_irq(&tasklist_lock); diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c index 279263f2d160..4e7f9558ab75 100644 --- a/net/ipv4/netfilter/ipt_owner.c +++ b/net/ipv4/netfilter/ipt_owner.c @@ -90,7 +90,7 @@ match_sid(const struct sk_buff *skb, pid_t sid) read_lock(&tasklist_lock); do_each_thread(g, p) { struct files_struct *files; - if (p->session != sid) + if (process_session(p) != sid) continue; task_lock(p); diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c index cf230014ccce..e05916bf7f49 100644 --- a/net/ipv6/netfilter/ip6t_owner.c +++ b/net/ipv6/netfilter/ip6t_owner.c @@ -56,7 +56,7 @@ match_sid(const struct sk_buff *skb, pid_t sid) read_lock(&tasklist_lock); do_each_thread(g, p) { struct files_struct *files; - if (p->session != sid) + if (process_session(p) != sid) continue; task_lock(p); -- 2.30.9