Commit bde0d2c98bcfc9acc83ac79c33a6ac1335b95a92

Authored by Eric W. Biederman
Committed by Linus Torvalds
1 parent 81af8d67d4

[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>

Showing 3 changed files with 6 additions and 5 deletions Side-by-side Diff

... ... @@ -903,6 +903,7 @@
903 903 if (vc_cons_allocated(currcons)) {
904 904 struct vc_data *vc = vc_cons[currcons].d;
905 905 vc->vc_sw->con_deinit(vc);
  906 + put_pid(vc->vt_pid);
906 907 module_put(vc->vc_sw->owner);
907 908 if (vc->vc_kmalloced)
908 909 kfree(vc->vc_screenbuf);
drivers/char/vt_ioctl.c
... ... @@ -672,7 +672,7 @@
672 672 vc->vt_mode = tmp;
673 673 /* the frsig is ignored, so we set it to 0 */
674 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 676 /* no switch is required -- saw@shade.msu.ru */
677 677 vc->vt_newvt = -1;
678 678 release_console_sem();
... ... @@ -1063,7 +1063,7 @@
1063 1063 vc->vt_mode.relsig = 0;
1064 1064 vc->vt_mode.acqsig = 0;
1065 1065 vc->vt_mode.frsig = 0;
1066   - vc->vt_pid = -1;
  1066 + put_pid(xchg(&vc->vt_pid, NULL));
1067 1067 vc->vt_newvt = -1;
1068 1068 if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */
1069 1069 reset_palette(vc);
... ... @@ -1114,7 +1114,7 @@
1114 1114 * tell us if the process has gone or something else
1115 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 1119 * The controlling process has died, so we revert back to
1120 1120 * normal operation. In this case, we'll also change back
... ... @@ -1174,7 +1174,7 @@
1174 1174 * tell us if the process has gone or something else
1175 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 1179 * It worked. Mark the vt to switch to and
1180 1180 * return. The process needs to send us a
include/linux/console_struct.h
... ... @@ -54,7 +54,7 @@
54 54 struct tty_struct *vc_tty; /* TTY we are attached to */
55 55 /* data for manual vt switching */
56 56 struct vt_mode vt_mode;
57   - int vt_pid;
  57 + struct pid *vt_pid;
58 58 int vt_newvt;
59 59 wait_queue_head_t paste_wait;
60 60 /* mode flags */