// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 1992 obz under the linux copyright
*
* Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
* Dynamic keymap and string allocation - aeb@cwi.nl - May 1994
* Restrict VT switching via ioctl() - grif@cs.ucr.edu - Dec 1995
* Some code moved for less code duplication - Andi Kleen - Mar 1997
* Check put/get_user, cleanups - acme@conectiva.com.br - Jun 2001
*/
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/sched/signal.h>
#include <linux/tty.h>
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/compat.h>
#include <linux/module.h>
#include <linux/kd.h>
#include <linux/vt.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/major.h>
#include <linux/fs.h>
#include <linux/console.h>
#include <linux/consolemap.h>
#include <linux/signal.h>
#include <linux/suspend.h>
#include <linux/timex.h>
#include <asm/io.h>
#include <linux/uaccess.h>
#include <linux/nospec.h>
#include <linux/kbd_kern.h>
#include <linux/vt_kern.h>
#include <linux/kbd_diacr.h>
#include <linux/selection.h>
bool vt_dont_switch;
static inline bool vt_in_use(unsigned int i)
{
const struct vc_data *vc = vc_cons[i].d;
/*
* console_lock must be held to prevent the vc from being deallocated
* while we're checking whether it's in-use.
*/
WARN_CONSOLE_UNLOCKED();
return vc && kref_read(&vc->port.kref) > 1;
}
static inline bool vt_busy(int i)
{
if (vt_in_use(i))
return true;
if (i == fg_console)
return true;
if (vc_is_sel(vc_cons[i].d))
return true;
return false;
}
/*
* Console (vt and kd) routines, as defined by USL SVR4 manual, and by
* experimentation and study of X386 SYSV handling.
*
* One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
* /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
* and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
* always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
* ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
* /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
* to the current console is done by the main ioctl code.
*/
#ifdef CONFIG_X86
#include <asm/syscalls.h>
#endif
static void complete_change_console(struct vc_data *vc);
/*
* User space VT_EVENT handlers
*/
struct vt_event_wait {
struct list_head list;
struct vt_event event;
int done;
};
static LIST_HEAD(vt_events);
static DEFINE_SPINLOCK(vt_event_lock);
static DECLARE_WAIT_QUEUE_HEAD(vt_event_waitqueue);
/**
* vt_event_post
* @event: the event that occurred
* @old: old console
* @new: new console
*
* Post an VT event to interested VT handlers
*/
void vt_event_post(unsigned int event, unsigned int old, unsigned int new)
{
struct list_head *pos, *head;
unsigned long flags;
int wake = 0;
spin_lock_irqsave(&vt_event_lock, flags);
head = &vt_events;
list_for_each(pos, head) {
struct vt_event_wait *ve = list_entry(pos,
struct vt_event_wait,<