tty_io: fix remaining pid struct locking
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Wed, 30 Apr 2008 07:53:31 +0000 (00:53 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 30 Apr 2008 15:29:40 +0000 (08:29 -0700)
This fixes the last couple of pid struct locking failures I know about.

[oleg@tv-sign.ru: clean up do_task_stat()]
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/char/tty_io.c
fs/proc/array.c
include/linux/tty.h

index c8aa318..2460c4c 100644 (file)
@@ -3174,6 +3174,27 @@ unlock:
 }
 
 /**
+ *     tty_get_pgrp    -       return a ref counted pgrp pid
+ *     @tty: tty to read
+ *
+ *     Returns a refcounted instance of the pid struct for the process
+ *     group controlling the tty.
+ */
+
+struct pid *tty_get_pgrp(struct tty_struct *tty)
+{
+       unsigned long flags;
+       struct pid *pgrp;
+
+       spin_lock_irqsave(&tty->ctrl_lock, flags);
+       pgrp = get_pid(tty->pgrp);
+       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+
+       return pgrp;
+}
+EXPORT_SYMBOL_GPL(tty_get_pgrp);
+
+/**
  *     tiocgpgrp               -       get process group
  *     @tty: tty passed by user
  *     @real_tty: tty side of the tty pased by the user if a pty else the tty
@@ -3187,13 +3208,18 @@ unlock:
 
 static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
 {
+       struct pid *pid;
+       int ret;
        /*
         * (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_vnr(real_tty->pgrp), p);
+       pid = tty_get_pgrp(real_tty);
+       ret =  put_user(pid_vnr(pid), p);
+       put_pid(pid);
+       return ret;
 }
 
 /**
index b07a710..c135cbd 100644 (file)
@@ -429,7 +429,9 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
                struct signal_struct *sig = task->signal;
 
                if (sig->tty) {
-                       tty_pgrp = pid_nr_ns(sig->tty->pgrp, ns);
+                       struct pid *pgrp = tty_get_pgrp(sig->tty);
+                       tty_pgrp = pid_nr_ns(pgrp, ns);
+                       put_pid(pgrp);
                        tty_nr = new_encode_dev(tty_devnum(sig->tty));
                }
 
index 381085e..2699298 100644 (file)
@@ -297,6 +297,7 @@ extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
 extern void tty_write_message(struct tty_struct *tty, char *msg);
 
 extern int is_current_pgrp_orphaned(void);
+extern struct pid *tty_get_pgrp(struct tty_struct *tty);
 extern int is_ignored(int sig);
 extern int tty_signal(int sig, struct tty_struct *tty);
 extern void tty_hangup(struct tty_struct * tty);