Commit 04a2e6a5 authored by Eric W. Biederman's avatar Eric W. Biederman Committed by Linus Torvalds
Browse files

[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: default avatarEric W. Biederman <ebiederm@xmission.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 8d42db18
Loading
Loading
Loading
Loading
+17 −7
Original line number Diff line number Diff line
@@ -2990,7 +2990,8 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t

static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
{
	pid_t pgrp;
	struct pid *pgrp;
	pid_t pgrp_nr;
	int retval = tty_check_change(real_tty);

	if (retval == -EIO)
@@ -3001,14 +3002,23 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
	    (current->signal->tty != real_tty) ||
	    (real_tty->session != process_session(current)))
		return -ENOTTY;
	if (get_user(pgrp, p))
	if (get_user(pgrp_nr, p))
		return -EFAULT;
	if (pgrp < 0)
	if (pgrp_nr < 0)
		return -EINVAL;
	if (session_of_pgrp(pgrp) != process_session(current))
		return -EPERM;
	real_tty->pgrp = pgrp;
	return 0;
	rcu_read_lock();
	pgrp = find_pid(pgrp_nr);
	retval = -ESRCH;
	if (!pgrp)
		goto out_unlock;
	retval = -EPERM;
	if (session_of_pgrp(pgrp) != task_session(current))
		goto out_unlock;
	retval = 0;
	real_tty->pgrp = pgrp_nr;
out_unlock:
	rcu_read_unlock();
	return retval;
}

/**
+2 −1
Original line number Diff line number Diff line
@@ -134,7 +134,8 @@ extern unsigned long long memparse(char *ptr, char **retptr);
extern int core_kernel_text(unsigned long addr);
extern int __kernel_text_address(unsigned long addr);
extern int kernel_text_address(unsigned long addr);
extern int session_of_pgrp(int pgrp);
struct pid;
extern struct pid *session_of_pgrp(struct pid *pgrp);

extern void dump_thread(struct pt_regs *regs, struct user *dump);

+7 −9
Original line number Diff line number Diff line
@@ -185,21 +185,19 @@ repeat:
 * This checks not only the pgrp, but falls back on the pid if no
 * satisfactory pgrp is found. I dunno - gdb doesn't work correctly
 * without this...
 *
 * The caller must hold rcu lock or the tasklist lock.
 */
int session_of_pgrp(int pgrp)
struct pid *session_of_pgrp(struct pid *pgrp)
{
	struct task_struct *p;
	int sid = 0;

	read_lock(&tasklist_lock);
	struct pid *sid = NULL;

	p = find_task_by_pid_type(PIDTYPE_PGID, pgrp);
	p = pid_task(pgrp, PIDTYPE_PGID);
	if (p == NULL)
		p = find_task_by_pid(pgrp);
		p = pid_task(pgrp, PIDTYPE_PID);
	if (p != NULL)
		sid = process_session(p);

	read_unlock(&tasklist_lock);
		sid = task_session(p);

	return sid;
}