Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 81af8d67 authored by Eric W. Biederman's avatar Eric W. Biederman Committed by Linus Torvalds
Browse files

[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: 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 5feb8f5f
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -108,7 +108,11 @@ const int NR_TYPES = ARRAY_SIZE(max_vals);
struct kbd_struct kbd_table[MAX_NR_CONSOLES];
static struct kbd_struct *kbd = kbd_table;

int spawnpid, spawnsig;
struct vt_spawn_console vt_spawn_con = {
	.lock = SPIN_LOCK_UNLOCKED,
	.pid  = NULL,
	.sig  = 0,
};

/*
 * Variables exported for vt.c
@@ -578,9 +582,13 @@ static void fn_compose(struct vc_data *vc, struct pt_regs *regs)

static void fn_spawn_con(struct vc_data *vc, struct pt_regs *regs)
{
	if (spawnpid)
		if (kill_proc(spawnpid, spawnsig, 1))
			spawnpid = 0;
	spin_lock(&vt_spawn_con.lock);
	if (vt_spawn_con.pid)
		if (kill_pid(vt_spawn_con.pid, vt_spawn_con.sig, 1)) {
			put_pid(vt_spawn_con.pid);
			vt_spawn_con.pid = NULL;
		}
	spin_unlock(&vt_spawn_con.lock);
}

static void fn_SAK(struct vc_data *vc, struct pt_regs *regs)
+6 −3
Original line number Diff line number Diff line
@@ -645,13 +645,16 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
	 */
	case KDSIGACCEPT:
	{
		extern int spawnpid, spawnsig;
		if (!perm || !capable(CAP_KILL))
		  return -EPERM;
		if (!valid_signal(arg) || arg < 1 || arg == SIGKILL)
		  return -EINVAL;
		spawnpid = current->pid;
		spawnsig = arg;

		spin_lock_irq(&vt_spawn_con.lock);
		put_pid(vt_spawn_con.pid);
		vt_spawn_con.pid = get_pid(task_pid(current));
		vt_spawn_con.sig = arg;
		spin_unlock_irq(&vt_spawn_con.lock);
		return 0;
	}

+7 −0
Original line number Diff line number Diff line
@@ -84,4 +84,11 @@ void reset_vc(struct vc_data *vc);
extern char con_buf[CON_BUF_SIZE];
extern struct semaphore con_buf_sem;

struct vt_spawn_console {
	spinlock_t lock;
	struct pid *pid;
	int sig;
};
extern struct vt_spawn_console vt_spawn_con;

#endif /* _VT_KERN_H */