Commit 81af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44
Committed by
Linus Torvalds
1 parent
5feb8f5f84
[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>
Showing 3 changed files with 25 additions and 7 deletions Side-by-side Diff
drivers/char/keyboard.c
... | ... | @@ -108,7 +108,11 @@ |
108 | 108 | struct kbd_struct kbd_table[MAX_NR_CONSOLES]; |
109 | 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 | 118 | * Variables exported for vt.c |
... | ... | @@ -578,9 +582,13 @@ |
578 | 582 | |
579 | 583 | static void fn_spawn_con(struct vc_data *vc, struct pt_regs *regs) |
580 | 584 | { |
581 | - if (spawnpid) | |
582 | - if (kill_proc(spawnpid, spawnsig, 1)) | |
583 | - spawnpid = 0; | |
585 | + spin_lock(&vt_spawn_con.lock); | |
586 | + if (vt_spawn_con.pid) | |
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 | 594 | static void fn_SAK(struct vc_data *vc, struct pt_regs *regs) |
drivers/char/vt_ioctl.c
... | ... | @@ -645,13 +645,16 @@ |
645 | 645 | */ |
646 | 646 | case KDSIGACCEPT: |
647 | 647 | { |
648 | - extern int spawnpid, spawnsig; | |
649 | 648 | if (!perm || !capable(CAP_KILL)) |
650 | 649 | return -EPERM; |
651 | 650 | if (!valid_signal(arg) || arg < 1 || arg == SIGKILL) |
652 | 651 | return -EINVAL; |
653 | - spawnpid = current->pid; | |
654 | - spawnsig = arg; | |
652 | + | |
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 | 658 | return 0; |
656 | 659 | } |
657 | 660 |
include/linux/vt_kern.h