diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2006-10-02 05:17:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-02 10:57:13 -0400 |
commit | 81af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44 (patch) | |
tree | 0217dde7d28427e9b6ac587fd4edb9fb1f8f11b4 | |
parent | 5feb8f5f8403d8874a04aac443692dfe83bd63d2 (diff) |
[PATCH] vt: rework the console spawning variables
This is such a rare path it took me a while to figure out how to test
this after soring out the locking.
This patch does several things.
- The variables used are moved into a structure and declared in vt_kern.h
- A spinlock is added so we don't have SMP races updating the values.
- Instead of raw pid_t value a struct_pid is used to guard against
pid wrap around issues, if the daemon to spawn a new console dies.
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>
-rw-r--r-- | drivers/char/keyboard.c | 16 | ||||
-rw-r--r-- | drivers/char/vt_ioctl.c | 9 | ||||
-rw-r--r-- | include/linux/vt_kern.h | 7 |
3 files changed, 25 insertions, 7 deletions
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 3e90aac37510..99fb070fdbf8 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
@@ -108,7 +108,11 @@ const int NR_TYPES = ARRAY_SIZE(max_vals); | |||
108 | struct kbd_struct kbd_table[MAX_NR_CONSOLES]; | 108 | struct kbd_struct kbd_table[MAX_NR_CONSOLES]; |
109 | static struct kbd_struct *kbd = kbd_table; | 109 | static struct kbd_struct *kbd = kbd_table; |
110 | 110 | ||
111 | int spawnpid, spawnsig; | 111 | struct vt_spawn_console vt_spawn_con = { |
112 | .lock = SPIN_LOCK_UNLOCKED, | ||
113 | .pid = NULL, | ||
114 | .sig = 0, | ||
115 | }; | ||
112 | 116 | ||
113 | /* | 117 | /* |
114 | * Variables exported for vt.c | 118 | * Variables exported for vt.c |
@@ -578,9 +582,13 @@ static void fn_compose(struct vc_data *vc, struct pt_regs *regs) | |||
578 | 582 | ||
579 | static void fn_spawn_con(struct vc_data *vc, struct pt_regs *regs) | 583 | static void fn_spawn_con(struct vc_data *vc, struct pt_regs *regs) |
580 | { | 584 | { |
581 | if (spawnpid) | 585 | spin_lock(&vt_spawn_con.lock); |
582 | if (kill_proc(spawnpid, spawnsig, 1)) | 586 | if (vt_spawn_con.pid) |
583 | spawnpid = 0; | 587 | if (kill_pid(vt_spawn_con.pid, vt_spawn_con.sig, 1)) { |
588 | put_pid(vt_spawn_con.pid); | ||
589 | vt_spawn_con.pid = NULL; | ||
590 | } | ||
591 | spin_unlock(&vt_spawn_con.lock); | ||
584 | } | 592 | } |
585 | 593 | ||
586 | static void fn_SAK(struct vc_data *vc, struct pt_regs *regs) | 594 | static void fn_SAK(struct vc_data *vc, struct pt_regs *regs) |
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index a53e382cc107..dc408af165ab 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c | |||
@@ -645,13 +645,16 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
645 | */ | 645 | */ |
646 | case KDSIGACCEPT: | 646 | case KDSIGACCEPT: |
647 | { | 647 | { |
648 | extern int spawnpid, spawnsig; | ||
649 | if (!perm || !capable(CAP_KILL)) | 648 | if (!perm || !capable(CAP_KILL)) |
650 | return -EPERM; | 649 | return -EPERM; |
651 | if (!valid_signal(arg) || arg < 1 || arg == SIGKILL) | 650 | if (!valid_signal(arg) || arg < 1 || arg == SIGKILL) |
652 | return -EINVAL; | 651 | return -EINVAL; |
653 | spawnpid = current->pid; | 652 | |
654 | spawnsig = arg; | 653 | spin_lock_irq(&vt_spawn_con.lock); |
654 | put_pid(vt_spawn_con.pid); | ||
655 | vt_spawn_con.pid = get_pid(task_pid(current)); | ||
656 | vt_spawn_con.sig = arg; | ||
657 | spin_unlock_irq(&vt_spawn_con.lock); | ||
655 | return 0; | 658 | return 0; |
656 | } | 659 | } |
657 | 660 | ||
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index 1009d3fe1fc2..37a1a41f5b65 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h | |||
@@ -84,4 +84,11 @@ void reset_vc(struct vc_data *vc); | |||
84 | extern char con_buf[CON_BUF_SIZE]; | 84 | extern char con_buf[CON_BUF_SIZE]; |
85 | extern struct semaphore con_buf_sem; | 85 | extern struct semaphore con_buf_sem; |
86 | 86 | ||
87 | struct vt_spawn_console { | ||
88 | spinlock_t lock; | ||
89 | struct pid *pid; | ||
90 | int sig; | ||
91 | }; | ||
92 | extern struct vt_spawn_console vt_spawn_con; | ||
93 | |||
87 | #endif /* _VT_KERN_H */ | 94 | #endif /* _VT_KERN_H */ |