Commit 81af8d67d4fc35b1ee6e0feb1f1b34b3a33eeb44

Authored by Eric W. Biederman
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
... ... @@ -84,5 +84,12 @@
84 84 extern char con_buf[CON_BUF_SIZE];
85 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 94 #endif /* _VT_KERN_H */