diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2007-02-12 03:52:56 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-12 12:48:31 -0500 |
commit | 04a2e6a5cbf84e85fe86de0a18f6509b147e1d89 (patch) | |
tree | 67dd67d2c4c18e5c36654dfe569e3085bd262ba5 | |
parent | 8d42db189ca99703f0f4f91c477cb54808c8eaaa (diff) |
[PATCH] pid: make session_of_pgrp use struct pid instead of pid_t
To properly implement a pid namespace I need to deal exclusively in terms of
struct pid, because pid_t values become ambiguous.
To this end session_of_pgrp is transformed to take and return a struct pid
pointer. To avoid the need to worry about reference counting I now require my
caller to hold the appropriate locks. Leaving callers repsonsible for
increasing the reference count if they need access to the result outside of
the locks.
Since session_of_pgrp currently only has one caller and that caller simply
uses only test the result for equality with another process group, the locking
change means I don't actually have to acquire the tasklist_lock at all.
tiocspgrp is also modified to take and release the lock. The logic there is a
little more complicated but nothing I won't need when I convert pgrp of a tty
to a struct pid pointer.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/char/tty_io.c | 24 | ||||
-rw-r--r-- | include/linux/kernel.h | 3 | ||||
-rw-r--r-- | kernel/exit.c | 16 |
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 | ||
2991 | static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) | 2991 | static 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; | ||
3019 | out_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); | |||
134 | extern int core_kernel_text(unsigned long addr); | 134 | extern int core_kernel_text(unsigned long addr); |
135 | extern int __kernel_text_address(unsigned long addr); | 135 | extern int __kernel_text_address(unsigned long addr); |
136 | extern int kernel_text_address(unsigned long addr); | 136 | extern int kernel_text_address(unsigned long addr); |
137 | extern int session_of_pgrp(int pgrp); | 137 | struct pid; |
138 | extern struct pid *session_of_pgrp(struct pid *pgrp); | ||
138 | 139 | ||
139 | extern void dump_thread(struct pt_regs *regs, struct user *dump); | 140 | extern 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 | */ |
189 | int session_of_pgrp(int pgrp) | 191 | struct 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 | } |