[RFC][PATCH 07/20] tty: Update the tty layer to work with pspaces.

From: Eric W. Biederman
Date: Mon Feb 06 2006 - 14:42:24 EST



Of kernel subsystems that work with pids the tty layer
is probably the largest consumer. But it has the nice
virtue that the association with a session only lasts until
the session leader exits. Which means that no reference
counting is required. Only caching of the pspace,
and a few extra comparisons.

Signed-off-by: Eric W. Biederman <ebiederm@xxxxxxxxxxxx>


---

drivers/char/n_tty.c | 9 ++++---
drivers/char/tty_io.c | 62 ++++++++++++++++++++++++++++++-------------------
include/linux/tty.h | 1 +
3 files changed, 44 insertions(+), 28 deletions(-)

5de29104be4f33d4dca8246e13d2996c1ce745b3
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index ccad7ae..5edfd13 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -580,7 +580,7 @@ static void eraser(unsigned char c, stru
static inline void isig(int sig, struct tty_struct *tty, int flush)
{
if (tty->pgrp > 0)
- kill_pg(tty->pgrp, sig, 1);
+ kill_pg(tty->pspace, tty->pgrp, sig, 1);
if (flush || !L_NOFLSH(tty)) {
n_tty_flush_buffer(tty);
if (tty->driver->flush_buffer)
@@ -1187,11 +1187,12 @@ static int job_control(struct tty_struct
current->signal->tty == tty) {
if (tty->pgrp <= 0)
printk("read_chan: tty->pgrp <= 0!\n");
- else if (process_group(current) != tty->pgrp) {
+ else if ((process_group(current) != tty->pgrp) ||
+ (current->pspace != tty->pspace)) {
if (is_ignored(SIGTTIN) ||
- is_orphaned_pgrp(process_group(current)))
+ is_orphaned_pgrp(current->pspace, process_group(current)))
return -EIO;
- kill_pg(process_group(current), SIGTTIN, 1);
+ kill_pg(current->pspace, process_group(current), SIGTTIN, 1);
return -ERESTARTSYS;
}
}
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 1d83cd5..b6f3004 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -95,6 +95,7 @@
#include <linux/wait.h>
#include <linux/bitops.h>
#include <linux/delay.h>
+#include <linux/pspace.h>

#include <asm/uaccess.h>
#include <asm/system.h>
@@ -858,13 +859,14 @@ int tty_check_change(struct tty_struct *
printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n");
return 0;
}
- if (process_group(current) == tty->pgrp)
+ if ((process_group(current) == tty->pgrp) &&
+ (current->pspace == tty->pspace))
return 0;
if (is_ignored(SIGTTOU))
return 0;
- if (is_orphaned_pgrp(process_group(current)))
+ if (is_orphaned_pgrp(current->pspace, process_group(current)))
return -EIO;
- (void) kill_pg(process_group(current), SIGTTOU, 1);
+ (void) kill_pg(current->pspace, process_group(current), SIGTTOU, 1);
return -ERESTARTSYS;
}

@@ -1070,7 +1072,7 @@ static void do_tty_hangup(void *data)

read_lock(&tasklist_lock);
if (tty->session > 0) {
- do_each_task_pid(tty->session, PIDTYPE_SID, p) {
+ do_each_task_pid(tty->pspace, tty->session, PIDTYPE_SID, p) {
if (p->signal->tty == tty)
p->signal->tty = NULL;
if (!p->signal->leader)
@@ -1079,11 +1081,12 @@ static void do_tty_hangup(void *data)
group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
if (tty->pgrp > 0)
p->signal->tty_old_pgrp = tty->pgrp;
- } while_each_task_pid(tty->session, PIDTYPE_SID, p);
+ } while_each_task_pid(tty->pspace, tty->session, PIDTYPE_SID, p);
}
read_unlock(&tasklist_lock);

tty->flags = 0;
+ tty->pspace = NULL;
tty->session = 0;
tty->pgrp = -1;
tty->ctrl_status = 0;
@@ -1162,6 +1165,7 @@ void disassociate_ctty(int on_exit)
{
struct tty_struct *tty;
struct task_struct *p;
+ struct pspace *tty_pspace = NULL;
int tty_pgrp = -1;

lock_kernel();
@@ -1170,35 +1174,37 @@ void disassociate_ctty(int on_exit)
tty = current->signal->tty;
if (tty) {
tty_pgrp = tty->pgrp;
+ tty_pspace = tty->pspace;
up(&tty_sem);
if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
tty_vhangup(tty);
} else {
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);
+ kill_pg(current->pspace, current->signal->tty_old_pgrp, SIGHUP, on_exit);
+ kill_pg(current->pspace, current->signal->tty_old_pgrp, SIGCONT, on_exit);
}
up(&tty_sem);
unlock_kernel();
return;
}
if (tty_pgrp > 0) {
- kill_pg(tty_pgrp, SIGHUP, on_exit);
+ kill_pg(tty_pspace, tty_pgrp, SIGHUP, on_exit);
if (!on_exit)
- kill_pg(tty_pgrp, SIGCONT, on_exit);
+ kill_pg(tty_pspace, tty_pgrp, SIGCONT, on_exit);
}

/* Must lock changes to tty_old_pgrp */
down(&tty_sem);
current->signal->tty_old_pgrp = 0;
+ tty->pspace = NULL;
tty->session = 0;
tty->pgrp = -1;

/* Now clear signal->tty under the lock */
read_lock(&tasklist_lock);
- do_each_task_pid(current->signal->session, PIDTYPE_SID, p) {
+ do_each_task_pid(current->pspace, current->signal->session, PIDTYPE_SID, p) {
p->signal->tty = NULL;
- } while_each_task_pid(current->signal->session, PIDTYPE_SID, p);
+ } while_each_task_pid(current->pspace, current->signal->session, PIDTYPE_SID, p);
read_unlock(&tasklist_lock);
up(&tty_sem);
unlock_kernel();
@@ -1905,13 +1911,13 @@ static void release_dev(struct file * fi
struct task_struct *p;

read_lock(&tasklist_lock);
- do_each_task_pid(tty->session, PIDTYPE_SID, p) {
+ do_each_task_pid(tty->pspace, tty->session, PIDTYPE_SID, p) {
p->signal->tty = NULL;
- } while_each_task_pid(tty->session, PIDTYPE_SID, p);
+ } while_each_task_pid(tty->pspace, tty->session, PIDTYPE_SID, p);
if (o_tty)
- do_each_task_pid(o_tty->session, PIDTYPE_SID, p) {
+ do_each_task_pid(o_tty->pspace, o_tty->session, PIDTYPE_SID, p) {
p->signal->tty = NULL;
- } while_each_task_pid(o_tty->session, PIDTYPE_SID, p);
+ } while_each_task_pid(o_tty->pspace, o_tty->session, PIDTYPE_SID, p);
read_unlock(&tasklist_lock);
}

@@ -2110,6 +2116,7 @@ got_driver:
current->signal->tty = tty;
task_unlock(current);
current->signal->tty_old_pgrp = 0;
+ tty->pspace = current->pspace;
tty->session = current->signal->session;
tty->pgrp = process_group(current);
}
@@ -2270,9 +2277,9 @@ static int tiocswinsz(struct tty_struct
}
#endif
if (tty->pgrp > 0)
- kill_pg(tty->pgrp, SIGWINCH, 1);
+ kill_pg(tty->pspace, tty->pgrp, SIGWINCH, 1);
if ((real_tty->pgrp != tty->pgrp) && (real_tty->pgrp > 0))
- kill_pg(real_tty->pgrp, SIGWINCH, 1);
+ kill_pg(real_tty->pspace, real_tty->pgrp, SIGWINCH, 1);
tty->winsize = tmp_ws;
real_tty->winsize = tmp_ws;
return 0;
@@ -2342,9 +2349,9 @@ static int tiocsctty(struct tty_struct *
*/

read_lock(&tasklist_lock);
- do_each_task_pid(tty->session, PIDTYPE_SID, p) {
+ do_each_task_pid(tty->pspace, tty->session, PIDTYPE_SID, p) {
p->signal->tty = NULL;
- } while_each_task_pid(tty->session, PIDTYPE_SID, p);
+ } while_each_task_pid(tty->pspace, tty->session, PIDTYPE_SID, p);
read_unlock(&tasklist_lock);
} else
return -EPERM;
@@ -2353,6 +2360,7 @@ static int tiocsctty(struct tty_struct *
current->signal->tty = tty;
task_unlock(current);
current->signal->tty_old_pgrp = 0;
+ tty->pspace = current->pspace;
tty->session = current->signal->session;
tty->pgrp = process_group(current);
return 0;
@@ -2360,17 +2368,22 @@ static int tiocsctty(struct tty_struct *

static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
{
+ pid_t pgrp;
/*
* (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(real_tty->pgrp, p);
+ pgrp = real_tty->pgrp;
+ if (real_tty->pspace != current->pspace)
+ pgrp = -1;
+ return put_user(pgrp, p);
}

static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
{
+ struct pspace *pspace = current->pspace;
pid_t pgrp;
int retval = tty_check_change(real_tty);

@@ -2380,13 +2393,14 @@ static int tiocspgrp(struct tty_struct *
return retval;
if (!current->signal->tty ||
(current->signal->tty != real_tty) ||
- (real_tty->session != current->signal->session))
+ (real_tty->session != current->signal->session) ||
+ (real_tty->pspace != pspace))
return -ENOTTY;
if (get_user(pgrp, p))
return -EFAULT;
if (pgrp < 0)
return -EINVAL;
- if (session_of_pgrp(pgrp) != current->signal->session)
+ if (session_of_pgrp(pspace, pgrp) != current->signal->session)
return -EPERM;
real_tty->pgrp = pgrp;
return 0;
@@ -2676,12 +2690,12 @@ static void __do_SAK(void *arg)

read_lock(&tasklist_lock);
/* Kill the entire session */
- do_each_task_pid(session, PIDTYPE_SID, p) {
+ do_each_task_pid(tty->pspace, session, PIDTYPE_SID, p) {
printk(KERN_NOTICE "SAK: killed process %d"
" (%s): p->signal->session==tty->session\n",
p->pid, p->comm);
send_sig(SIGKILL, p, 1);
- } while_each_task_pid(session, PIDTYPE_SID, p);
+ } while_each_task_pid(tty->pspace, session, PIDTYPE_SID, p);
/* Now kill any processes that happen to have the
* tty open.
*/
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 898d593..bc9e9c4 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -184,6 +184,7 @@ struct tty_struct {
struct semaphore termios_sem;
struct termios *termios, *termios_locked;
char name[64];
+ struct pspace *pspace;
int pgrp;
int session;
unsigned long flags;
--
1.1.5.g3480

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/