Commit bde0d2c9 authored by Eric W. Biederman's avatar Eric W. Biederman Committed by Linus Torvalds

[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: default avatarEric W. Biederman <ebiederm@xmission.com>
Cc: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 81af8d67
...@@ -903,6 +903,7 @@ void vc_deallocate(unsigned int currcons) ...@@ -903,6 +903,7 @@ void vc_deallocate(unsigned int currcons)
if (vc_cons_allocated(currcons)) { if (vc_cons_allocated(currcons)) {
struct vc_data *vc = vc_cons[currcons].d; struct vc_data *vc = vc_cons[currcons].d;
vc->vc_sw->con_deinit(vc); vc->vc_sw->con_deinit(vc);
put_pid(vc->vt_pid);
module_put(vc->vc_sw->owner); module_put(vc->vc_sw->owner);
if (vc->vc_kmalloced) if (vc->vc_kmalloced)
kfree(vc->vc_screenbuf); kfree(vc->vc_screenbuf);
......
...@@ -672,7 +672,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -672,7 +672,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
vc->vt_mode = tmp; vc->vt_mode = tmp;
/* the frsig is ignored, so we set it to 0 */ /* the frsig is ignored, so we set it to 0 */
vc->vt_mode.frsig = 0; vc->vt_mode.frsig = 0;
vc->vt_pid = current->pid; put_pid(xchg(&vc->vt_pid, get_pid(task_pid(current))));
/* no switch is required -- saw@shade.msu.ru */ /* no switch is required -- saw@shade.msu.ru */
vc->vt_newvt = -1; vc->vt_newvt = -1;
release_console_sem(); release_console_sem();
...@@ -1063,7 +1063,7 @@ void reset_vc(struct vc_data *vc) ...@@ -1063,7 +1063,7 @@ void reset_vc(struct vc_data *vc)
vc->vt_mode.relsig = 0; vc->vt_mode.relsig = 0;
vc->vt_mode.acqsig = 0; vc->vt_mode.acqsig = 0;
vc->vt_mode.frsig = 0; vc->vt_mode.frsig = 0;
vc->vt_pid = -1; put_pid(xchg(&vc->vt_pid, NULL));
vc->vt_newvt = -1; vc->vt_newvt = -1;
if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */ if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */
reset_palette(vc); reset_palette(vc);
...@@ -1114,7 +1114,7 @@ static void complete_change_console(struct vc_data *vc) ...@@ -1114,7 +1114,7 @@ static void complete_change_console(struct vc_data *vc)
* tell us if the process has gone or something else * tell us if the process has gone or something else
* is awry * is awry
*/ */
if (kill_proc(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) { if (kill_pid(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) {
/* /*
* The controlling process has died, so we revert back to * The controlling process has died, so we revert back to
* normal operation. In this case, we'll also change back * normal operation. In this case, we'll also change back
...@@ -1174,7 +1174,7 @@ void change_console(struct vc_data *new_vc) ...@@ -1174,7 +1174,7 @@ void change_console(struct vc_data *new_vc)
* tell us if the process has gone or something else * tell us if the process has gone or something else
* is awry * is awry
*/ */
if (kill_proc(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {
/* /*
* It worked. Mark the vt to switch to and * It worked. Mark the vt to switch to and
* return. The process needs to send us a * return. The process needs to send us a
......
...@@ -54,7 +54,7 @@ struct vc_data { ...@@ -54,7 +54,7 @@ struct vc_data {
struct tty_struct *vc_tty; /* TTY we are attached to */ struct tty_struct *vc_tty; /* TTY we are attached to */
/* data for manual vt switching */ /* data for manual vt switching */
struct vt_mode vt_mode; struct vt_mode vt_mode;
int vt_pid; struct pid *vt_pid;
int vt_newvt; int vt_newvt;
wait_queue_head_t paste_wait; wait_queue_head_t paste_wait;
/* mode flags */ /* mode flags */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment