aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/tty_io.c24
-rw-r--r--include/linux/kernel.h3
-rw-r--r--kernel/exit.c16
3 files changed, 26 insertions, 17 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index abfe24d28c51..95f3596189cf 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -2990,7 +2990,8 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
2990 2990
2991static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) 2991static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
2992{ 2992{
2993 pid_t pgrp; 2993 struct pid *pgrp;
2994 pid_t pgrp_nr;
2994 int retval = tty_check_change(real_tty); 2995 int retval = tty_check_change(real_tty);
2995 2996
2996 if (retval == -EIO) 2997 if (retval == -EIO)
@@ -3001,14 +3002,23 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
3001 (current->signal->tty != real_tty) || 3002 (current->signal->tty != real_tty) ||
3002 (real_tty->session != process_session(current))) 3003 (real_tty->session != process_session(current)))
3003 return -ENOTTY; 3004 return -ENOTTY;
3004 if (get_user(pgrp, p)) 3005 if (get_user(pgrp_nr, p))
3005 return -EFAULT; 3006 return -EFAULT;
3006 if (pgrp < 0) 3007 if (pgrp_nr < 0)
3007 return -EINVAL; 3008 return -EINVAL;
3008 if (session_of_pgrp(pgrp) != process_session(current)) 3009 rcu_read_lock();
3009 return -EPERM; 3010 pgrp = find_pid(pgrp_nr);
3010 real_tty->pgrp = pgrp; 3011 retval = -ESRCH;
3011 return 0; 3012 if (!pgrp)
3013 goto out_unlock;
3014 retval = -EPERM;
3015 if (session_of_pgrp(pgrp) != task_session(current))
3016 goto out_unlock;
3017 retval = 0;
3018 real_tty->pgrp = pgrp_nr;
3019out_unlock:
3020 rcu_read_unlock();
3021 return retval;
3012} 3022}
3013 3023
3014/** 3024/**
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 3531764318f2..9ddf25c21538 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -134,7 +134,8 @@ extern unsigned long long memparse(char *ptr, char **retptr);
134extern int core_kernel_text(unsigned long addr); 134extern int core_kernel_text(unsigned long addr);
135extern int __kernel_text_address(unsigned long addr); 135extern int __kernel_text_address(unsigned long addr);
136extern int kernel_text_address(unsigned long addr); 136extern int kernel_text_address(unsigned long addr);
137extern int session_of_pgrp(int pgrp); 137struct pid;
138extern struct pid *session_of_pgrp(struct pid *pgrp);
138 139
139extern void dump_thread(struct pt_regs *regs, struct user *dump); 140extern void dump_thread(struct pt_regs *regs, struct user *dump);
140 141
diff --git a/kernel/exit.c b/kernel/exit.c
index 14f17033f563..3ac6a7a6f857 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -185,21 +185,19 @@ repeat:
185 * This checks not only the pgrp, but falls back on the pid if no 185 * This checks not only the pgrp, but falls back on the pid if no
186 * satisfactory pgrp is found. I dunno - gdb doesn't work correctly 186 * satisfactory pgrp is found. I dunno - gdb doesn't work correctly
187 * without this... 187 * without this...
188 *
189 * The caller must hold rcu lock or the tasklist lock.
188 */ 190 */
189int session_of_pgrp(int pgrp) 191struct pid *session_of_pgrp(struct pid *pgrp)
190{ 192{
191 struct task_struct *p; 193 struct task_struct *p;
192 int sid = 0; 194 struct pid *sid = NULL;
193
194 read_lock(&tasklist_lock);
195 195
196 p = find_task_by_pid_type(PIDTYPE_PGID, pgrp); 196 p = pid_task(pgrp, PIDTYPE_PGID);
197 if (p == NULL) 197 if (p == NULL)
198 p = find_task_by_pid(pgrp); 198 p = pid_task(pgrp, PIDTYPE_PID);
199 if (p != NULL) 199 if (p != NULL)
200 sid = process_session(p); 200 sid = task_session(p);
201
202 read_unlock(&tasklist_lock);
203 201
204 return sid; 202 return sid;
205} 203}