aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-10-02 05:17:14 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-02 10:57:14 -0400
commitbde0d2c98bcfc9acc83ac79c33a6ac1335b95a92 (patch)
tree1bacec61e5bd5fadaef630e95e8cc1ae618b94ff /drivers/char
parent81af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44 (diff)
[PATCH] vt: Make vt_pid a struct pid (making it pid wrap around safe).
I took a good hard look at the locking and it appears the locking on vt_pid is the console semaphore. Every modified path is called under the console semaphore except reset_vc when it is called from fn_SAK or do_SAK both of which appear to be in interrupt context. In addition I need to be careful because in the presence of an oops the console_sem may be arbitrarily dropped. Which leads me to conclude the current locking is inadequate for my needs. Given the weird cases we could hit because of oops printing instead of introducing an extra spin lock to protect the data and keep the pid to signal and the signal to send in sync, I have opted to use xchg on just the struct pid * pointer instead. Due to console_sem we will stay in sync between vt_pid and vt_mode except for a small window during a SAK, or oops handling. SAK handling should kill any user space process that care, and oops handling we are broken anyway. Besides the worst that can happen is that I try to send the wrong signal. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Cc: Oleg Nesterov <oleg@tv-sign.ru> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/vt.c1
-rw-r--r--drivers/char/vt_ioctl.c8
2 files changed, 5 insertions, 4 deletions
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index fb75da940b59..303956d34569 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -903,6 +903,7 @@ void vc_deallocate(unsigned int currcons)
903 if (vc_cons_allocated(currcons)) { 903 if (vc_cons_allocated(currcons)) {
904 struct vc_data *vc = vc_cons[currcons].d; 904 struct vc_data *vc = vc_cons[currcons].d;
905 vc->vc_sw->con_deinit(vc); 905 vc->vc_sw->con_deinit(vc);
906 put_pid(vc->vt_pid);
906 module_put(vc->vc_sw->owner); 907 module_put(vc->vc_sw->owner);
907 if (vc->vc_kmalloced) 908 if (vc->vc_kmalloced)
908 kfree(vc->vc_screenbuf); 909 kfree(vc->vc_screenbuf);
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index dc408af165ab..ac5d60edbafa 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -672,7 +672,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
672 vc->vt_mode = tmp; 672 vc->vt_mode = tmp;
673 /* the frsig is ignored, so we set it to 0 */ 673 /* the frsig is ignored, so we set it to 0 */
674 vc->vt_mode.frsig = 0; 674 vc->vt_mode.frsig = 0;
675 vc->vt_pid = current->pid; 675 put_pid(xchg(&vc->vt_pid, get_pid(task_pid(current))));
676 /* no switch is required -- saw@shade.msu.ru */ 676 /* no switch is required -- saw@shade.msu.ru */
677 vc->vt_newvt = -1; 677 vc->vt_newvt = -1;
678 release_console_sem(); 678 release_console_sem();
@@ -1063,7 +1063,7 @@ void reset_vc(struct vc_data *vc)
1063 vc->vt_mode.relsig = 0; 1063 vc->vt_mode.relsig = 0;
1064 vc->vt_mode.acqsig = 0; 1064 vc->vt_mode.acqsig = 0;
1065 vc->vt_mode.frsig = 0; 1065 vc->vt_mode.frsig = 0;
1066 vc->vt_pid = -1; 1066 put_pid(xchg(&vc->vt_pid, NULL));
1067 vc->vt_newvt = -1; 1067 vc->vt_newvt = -1;
1068 if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */ 1068 if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */
1069 reset_palette(vc); 1069 reset_palette(vc);
@@ -1114,7 +1114,7 @@ static void complete_change_console(struct vc_data *vc)
1114 * tell us if the process has gone or something else 1114 * tell us if the process has gone or something else
1115 * is awry 1115 * is awry
1116 */ 1116 */
1117 if (kill_proc(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) { 1117 if (kill_pid(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) {
1118 /* 1118 /*
1119 * The controlling process has died, so we revert back to 1119 * The controlling process has died, so we revert back to
1120 * normal operation. In this case, we'll also change back 1120 * normal operation. In this case, we'll also change back
@@ -1174,7 +1174,7 @@ void change_console(struct vc_data *new_vc)
1174 * tell us if the process has gone or something else 1174 * tell us if the process has gone or something else
1175 * is awry 1175 * is awry
1176 */ 1176 */
1177 if (kill_proc(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { 1177 if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {
1178 /* 1178 /*
1179 * It worked. Mark the vt to switch to and 1179 * It worked. Mark the vt to switch to and
1180 * return. The process needs to send us a 1180 * return. The process needs to send us a