Commit e730c373 authored by Jiri Slaby (SUSE)'s avatar Jiri Slaby (SUSE) Committed by Greg Kroah-Hartman
Browse files

tty/vt: use guard()s



Having all the new guards, use them in the vt code. This improves
readability, makes error handling easier, and marks locked portions of
code explicit.

A local free_page_ptr __free guard is introduced for
__get_free_page/free_page (with proper casts). This could be made public
in include/. But I am not sure if there are more possible users, so
keeping completely private here.

Signed-off-by: default avatar"Jiri Slaby (SUSE)" <jirislaby@kernel.org>
Link: https://lore.kernel.org/r/20250814072456.182853-16-jirislaby@kernel.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2fe16088
Loading
Loading
Loading
Loading
+13 −19
Original line number Diff line number Diff line
@@ -361,10 +361,10 @@ int con_set_trans_old(unsigned char __user * arg)
		inbuf[i] = UNI_DIRECT_BASE | ch;
	}

	console_lock();
	guard(console_lock)();
	memcpy(translations[USER_MAP], inbuf, sizeof(inbuf));
	update_user_maps();
	console_unlock();

	return 0;
}

@@ -374,13 +374,11 @@ int con_get_trans_old(unsigned char __user * arg)
	unsigned short *p = translations[USER_MAP];
	unsigned char outbuf[E_TABSZ];

	console_lock();
	for (i = 0; i < ARRAY_SIZE(outbuf); i++)
	{
	scoped_guard(console_lock)
		for (i = 0; i < ARRAY_SIZE(outbuf); i++) {
			ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
			outbuf[i] = (ch & ~0xff) ? 0 : ch;
		}
	console_unlock();

	return copy_to_user(arg, outbuf, sizeof(outbuf)) ? -EFAULT : 0;
}
@@ -392,10 +390,10 @@ int con_set_trans_new(ushort __user * arg)
	if (copy_from_user(inbuf, arg, sizeof(inbuf)))
		return -EFAULT;

	console_lock();
	guard(console_lock)();
	memcpy(translations[USER_MAP], inbuf, sizeof(inbuf));
	update_user_maps();
	console_unlock();

	return 0;
}

@@ -403,9 +401,8 @@ int con_get_trans_new(ushort __user * arg)
{
	unsigned short outbuf[E_TABSZ];

	console_lock();
	scoped_guard(console_lock)
		memcpy(outbuf, translations[USER_MAP], sizeof(outbuf));
	console_unlock();

	return copy_to_user(arg, outbuf, sizeof(outbuf)) ? -EFAULT : 0;
}
@@ -571,11 +568,8 @@ static int con_do_clear_unimap(struct vc_data *vc)

int con_clear_unimap(struct vc_data *vc)
{
	int ret;
	console_lock();
	ret = con_do_clear_unimap(vc);
	console_unlock();
	return ret;
	guard(console_lock)();
	return con_do_clear_unimap(vc);
}

static struct uni_pagedict *con_unshare_unimap(struct vc_data *vc,
+6 −14
Original line number Diff line number Diff line
@@ -127,9 +127,8 @@ int sel_loadlut(u32 __user *lut)
	if (copy_from_user(tmplut, lut, sizeof(inwordLut)))
		return -EFAULT;

	console_lock();
	guard(console_lock)();
	memcpy(inwordLut, tmplut, sizeof(inwordLut));
	console_unlock();

	return 0;
}
@@ -375,15 +374,9 @@ static int vc_selection(struct vc_data *vc, struct tiocl_selection *v,

int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
{
	int ret;

	mutex_lock(&vc_sel.lock);
	console_lock();
	ret = vc_selection(vc_cons[fg_console].d, v, tty);
	console_unlock();
	mutex_unlock(&vc_sel.lock);

	return ret;
	guard(mutex)(&vc_sel.lock);
	guard(console_lock)();
	return vc_selection(vc_cons[fg_console].d, v, tty);
}
EXPORT_SYMBOL_GPL(set_selection_kernel);

@@ -409,9 +402,8 @@ int paste_selection(struct tty_struct *tty)
	const char *bps = bp ? bracketed_paste_start : NULL;
	const char *bpe = bp ? bracketed_paste_end : NULL;

	console_lock();
	scoped_guard(console_lock)
		poke_blanked_console();
	console_unlock();

	ld = tty_ldisc_ref_wait(tty);
	if (!ld)
+29 −45
Original line number Diff line number Diff line
@@ -53,6 +53,8 @@
#define HEADER_SIZE	4u
#define CON_BUF_SIZE (IS_ENABLED(CONFIG_BASE_SMALL) ? 256 : PAGE_SIZE)

DEFINE_FREE(free_page_ptr, void *, if (_T) free_page((unsigned long)_T));

/*
 * Our minor space:
 *
@@ -72,7 +74,6 @@
#define use_unicode(inode)	(iminor(inode) & 64)
#define use_attributes(inode)	(iminor(inode) & 128)


struct vcs_poll_data {
	struct notifier_block notifier;
	unsigned int cons_num;
@@ -231,15 +232,13 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
	struct vc_data *vc;
	int size;

	console_lock();
	scoped_guard(console_lock) {
		vc = vcs_vc(inode, NULL);
	if (!vc) {
		console_unlock();
		if (!vc)
			return -ENXIO;
	}

		size = vcs_size(vc, use_attributes(inode), use_unicode(inode));
	console_unlock();
	}
	if (size < 0)
		return size;
	return fixed_size_llseek(file, offset, orig, size);
@@ -369,11 +368,10 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
	struct vcs_poll_data *poll;
	unsigned int read;
	ssize_t ret;
	char *con_buf;
	loff_t pos;
	bool viewed, attr, uni_mode;

	con_buf = (char *) __get_free_page(GFP_KERNEL);
	char *con_buf __free(free_page_ptr) = (char *)__get_free_page(GFP_KERNEL);
	if (!con_buf)
		return -ENOMEM;

@@ -382,17 +380,16 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
	/* Select the proper current console and verify
	 * sanity of the situation under the console lock.
	 */
	console_lock();
	guard(console_lock)();

	uni_mode = use_unicode(inode);
	attr = use_attributes(inode);

	ret = -EINVAL;
	if (pos < 0)
		goto unlock_out;
		return -EINVAL;
	/* we enforce 32-bit alignment for pos and count in unicode mode */
	if (uni_mode && (pos | count) & 3)
		goto unlock_out;
		return -EINVAL;

	poll = file->private_data;
	if (count && poll)
@@ -468,10 +465,8 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
	}
	*ppos += read;
	if (read)
		ret = read;
unlock_out:
	console_unlock();
	free_page((unsigned long) con_buf);
		return read;

	return ret;
}

@@ -591,7 +586,6 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
	struct inode *inode = file_inode(file);
	struct vc_data *vc;
	char *con_buf;
	u16 *org0, *org;
	unsigned int written;
	int size;
@@ -602,7 +596,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
	if (use_unicode(inode))
		return -EOPNOTSUPP;

	con_buf = (char *) __get_free_page(GFP_KERNEL);
	char *con_buf __free(free_page_ptr) = (char *)__get_free_page(GFP_KERNEL);
	if (!con_buf)
		return -ENOMEM;

@@ -611,22 +605,18 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
	/* Select the proper current console and verify
	 * sanity of the situation under the console lock.
	 */
	console_lock();
	guard(console_lock)();

	attr = use_attributes(inode);
	ret = -ENXIO;
	vc = vcs_vc(inode, &viewed);
	if (!vc)
		goto unlock_out;
		return -ENXIO;

	size = vcs_size(vc, attr, false);
	if (size < 0) {
		ret = size;
		goto unlock_out;
	}
	ret = -EINVAL;
	if (size < 0)
		return size;
	if (pos < 0 || pos > size)
		goto unlock_out;
		return -EINVAL;
	if (count > size - pos)
		count = size - pos;
	written = 0;
@@ -651,8 +641,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
				 */
				if (written)
					break;
				ret = -EFAULT;
				goto unlock_out;
				return -EFAULT;
			}
		}

@@ -664,15 +653,13 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
		if (!vc) {
			if (written)
				break;
			ret = -ENXIO;
			goto unlock_out;
			return -ENXIO;
		}
		size = vcs_size(vc, attr, false);
		if (size < 0) {
			if (written)
				break;
			ret = size;
			goto unlock_out;
			return size;
		}
		if (pos >= size)
			break;
@@ -702,9 +689,6 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
	if (written)
		vcs_scr_updated(vc);

unlock_out:
	console_unlock();
	free_page((unsigned long) con_buf);
	return ret;
}

@@ -754,17 +738,17 @@ vcs_open(struct inode *inode, struct file *filp)
	unsigned int currcons = console(inode);
	bool attr = use_attributes(inode);
	bool uni_mode = use_unicode(inode);
	int ret = 0;

	/* we currently don't support attributes in unicode mode */
	if (attr && uni_mode)
		return -EOPNOTSUPP;

	console_lock();
	guard(console_lock)();

	if (currcons && !vc_cons_allocated(currcons - 1))
		ret = -ENXIO;
	console_unlock();
	return ret;
		return -ENXIO;

	return 0;
}

static int vcs_release(struct inode *inode, struct file *file)
+38 −60
Original line number Diff line number Diff line
@@ -1317,12 +1317,9 @@ EXPORT_SYMBOL(__vc_resize);
static int vt_resize(struct tty_struct *tty, struct winsize *ws)
{
	struct vc_data *vc = tty->driver_data;
	int ret;

	console_lock();
	ret = vc_do_resize(tty, vc, ws->ws_col, ws->ws_row, false);
	console_unlock();
	return ret;
	guard(console_lock)();
	return vc_do_resize(tty, vc, ws->ws_col, ws->ws_row, false);
}

struct vc_data *vc_deallocate(unsigned int currcons)
@@ -3135,12 +3132,11 @@ static int do_con_write(struct tty_struct *tty, const u8 *buf, int count)
	if (in_interrupt())
		return count;

	console_lock();
	guard(console_lock)();
	currcons = vc->vc_num;
	if (!vc_cons_allocated(currcons)) {
		/* could this happen? */
		pr_warn_once("con_write: tty %d not allocated\n", currcons+1);
		console_unlock();
		return 0;
	}

@@ -3184,7 +3180,7 @@ static int do_con_write(struct tty_struct *tty, const u8 *buf, int count)
	con_flush(vc, &draw);
	console_conditional_schedule();
	notify_update(vc);
	console_unlock();

	return n;
}

@@ -3199,7 +3195,7 @@ static int do_con_write(struct tty_struct *tty, const u8 *buf, int count)
 */
static void console_callback(struct work_struct *ignored)
{
	console_lock();
	guard(console_lock)();

	if (want_console >= 0) {
		if (want_console != fg_console &&
@@ -3228,8 +3224,6 @@ static void console_callback(struct work_struct *ignored)
		blank_timer_expired = 0;
	}
	notify_update(vc_cons[fg_console].d);

	console_unlock();
}

int set_console(int nr)
@@ -3433,9 +3427,8 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
			return -EPERM;
		return paste_selection(tty);
	case TIOCL_UNBLANKSCREEN:
		console_lock();
		scoped_guard(console_lock)
			unblank_screen();
		console_unlock();
		break;
	case TIOCL_SELLOADLUT:
		if (!capable(CAP_SYS_ADMIN))
@@ -3451,9 +3444,8 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
		data = vt_get_shift_state();
		return put_user(data, p);
	case TIOCL_GETMOUSEREPORTING:
		console_lock();	/* May be overkill */
		scoped_guard(console_lock)	/* May be overkill */
			data = mouse_reporting();
		console_unlock();
		return put_user(data, p);
	case TIOCL_SETVESABLANK:
		return set_vesa_blanking(param);
@@ -3484,15 +3476,14 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
		 * Needs the console lock here. Note that lots of other calls
		 * need fixing before the lock is actually useful!
		 */
		console_lock();
		scoped_guard(console_lock)
			scrollfront(vc_cons[fg_console].d, lines);
		console_unlock();
		break;
	case TIOCL_BLANKSCREEN:	/* until explicitly unblanked, not only poked */
		console_lock();
		scoped_guard(console_lock) {
			ignore_poke = 1;
			do_blank_screen(0);
		console_unlock();
		}
		break;
	case TIOCL_BLANKEDSCREEN:
		return console_blanked;
@@ -3582,9 +3573,8 @@ static void con_flush_chars(struct tty_struct *tty)
	if (in_interrupt())	/* from flush_to_ldisc */
		return;

	console_lock();
	guard(console_lock)();
	set_cursor(vc);
	console_unlock();
}

/*
@@ -3596,22 +3586,20 @@ static int con_install(struct tty_driver *driver, struct tty_struct *tty)
	struct vc_data *vc;
	int ret;

	console_lock();
	guard(console_lock)();
	ret = vc_allocate(currcons);
	if (ret)
		goto unlock;
		return ret;

	vc = vc_cons[currcons].d;

	/* Still being freed */
	if (vc->port.tty) {
		ret = -ERESTARTSYS;
		goto unlock;
	}
	if (vc->port.tty)
		return -ERESTARTSYS;

	ret = tty_port_install(&vc->port, driver, tty);
	if (ret)
		goto unlock;
		return ret;

	tty->driver_data = vc;
	vc->port.tty = tty;
@@ -3625,9 +3613,8 @@ static int con_install(struct tty_driver *driver, struct tty_struct *tty)
		tty->termios.c_iflag |= IUTF8;
	else
		tty->termios.c_iflag &= ~IUTF8;
unlock:
	console_unlock();
	return ret;

	return 0;
}

static int con_open(struct tty_struct *tty, struct file *filp)
@@ -3646,9 +3633,9 @@ static void con_shutdown(struct tty_struct *tty)
{
	struct vc_data *vc = tty->driver_data;
	BUG_ON(vc == NULL);
	console_lock();

	guard(console_lock)();
	vc->port.tty = NULL;
	console_unlock();
}

static void con_cleanup(struct tty_struct *tty)
@@ -4137,15 +4124,13 @@ static ssize_t store_bind(struct device *dev, struct device_attribute *attr,
	struct con_driver *con = dev_get_drvdata(dev);
	int bind = simple_strtoul(buf, NULL, 0);

	console_lock();
	guard(console_lock)();

	if (bind)
		vt_bind(con);
	else
		vt_unbind(con);

	console_unlock();

	return count;
}

@@ -4155,9 +4140,8 @@ static ssize_t show_bind(struct device *dev, struct device_attribute *attr,
	struct con_driver *con = dev_get_drvdata(dev);
	int bind;

	console_lock();
	scoped_guard(console_lock)
		bind = con_is_bound(con->con);
	console_unlock();

	return sysfs_emit(buf, "%i\n", bind);
}
@@ -4429,7 +4413,7 @@ static void con_driver_unregister_callback(struct work_struct *ignored)
{
	int i;

	console_lock();
	guard(console_lock)();

	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
		struct con_driver *con_driver = &registered_con_driver[i];
@@ -4454,8 +4438,6 @@ static void con_driver_unregister_callback(struct work_struct *ignored)
		con_driver->first = 0;
		con_driver->last = 0;
	}

	console_unlock();
}

/*
@@ -4491,9 +4473,8 @@ EXPORT_SYMBOL_GPL(do_take_over_console);
 */
void give_up_console(const struct consw *csw)
{
	console_lock();
	guard(console_lock)();
	do_unregister_con_driver(csw);
	console_unlock();
}
EXPORT_SYMBOL(give_up_console);

@@ -4541,9 +4522,8 @@ static int set_vesa_blanking(u8 __user *mode_user)
	if (get_user(mode, mode_user))
		return -EFAULT;

	console_lock();
	guard(console_lock)();
	vesa_blank_mode = (mode <= VESA_BLANK_MAX) ? mode : VESA_NO_BLANKING;
	console_unlock();

	return 0;
}
@@ -4729,7 +4709,7 @@ int con_set_cmap(unsigned char __user *arg)
	if (copy_from_user(colormap, arg, sizeof(colormap)))
		return -EFAULT;

	console_lock();
	guard(console_lock)();
	for (i = k = 0; i < 16; i++) {
		default_red[i] = colormap[k++];
		default_grn[i] = colormap[k++];
@@ -4745,7 +4725,6 @@ int con_set_cmap(unsigned char __user *arg)
		}
		set_palette(vc_cons[i].d);
	}
	console_unlock();

	return 0;
}
@@ -4755,13 +4734,12 @@ int con_get_cmap(unsigned char __user *arg)
	int i, k;
	unsigned char colormap[3*16];

	console_lock();
	scoped_guard(console_lock)
		for (i = k = 0; i < 16; i++) {
			colormap[k++] = default_red[i];
			colormap[k++] = default_grn[i];
			colormap[k++] = default_blu[i];
		}
	console_unlock();

	if (copy_to_user(arg, colormap, sizeof(colormap)))
		return -EFAULT;
+84 −106
Original line number Diff line number Diff line
@@ -373,15 +373,13 @@ static int vt_k_ioctl(struct tty_struct *tty, unsigned int cmd,
		break;
	}

	case KDSETMODE:
	case KDSETMODE: {
		if (!perm)
			return -EPERM;

		console_lock();
		ret = vt_kdsetmode(vc, arg);
		console_unlock();
		return ret;

		guard(console_lock)();
		return vt_kdsetmode(vc, arg);
	}
	case KDGETMODE:
		return put_user(vc->vc_mode, (int __user *)arg);

@@ -601,12 +599,10 @@ static int vt_setactivate(struct vt_setactivate __user *sa)

	vsa.console--;
	vsa.console = array_index_nospec(vsa.console, MAX_NR_CONSOLES);
	console_lock();
	scoped_guard(console_lock) {
		ret = vc_allocate(vsa.console);
	if (ret) {
		console_unlock();
		if (ret)
			return ret;
	}

		/*
		 * This is safe providing we don't drop the console sem between
@@ -617,7 +613,7 @@ static int vt_setactivate(struct vt_setactivate __user *sa)
		nvc->vt_mode.frsig = 0;
		put_pid(nvc->vt_pid);
		nvc->vt_pid = get_pid(task_pid(current));
	console_unlock();
	}

	/* Commence switch and lock */
	/* Review set_console locks */
@@ -630,19 +626,18 @@ static int vt_setactivate(struct vt_setactivate __user *sa)
static int vt_disallocate(unsigned int vc_num)
{
	struct vc_data *vc = NULL;
	int ret = 0;

	console_lock();
	scoped_guard(console_lock) {
		if (vt_busy(vc_num))
		ret = -EBUSY;
	else if (vc_num)
			return -EBUSY;
		if (vc_num)
			vc = vc_deallocate(vc_num);
	console_unlock();
	}

	if (vc && vc_num >= MIN_NR_CONSOLES)
		tty_port_put(&vc->port);

	return ret;
	return 0;
}

/* deallocate all unused consoles, but leave 0 */
@@ -651,13 +646,12 @@ static void vt_disallocate_all(void)
	struct vc_data *vc[MAX_NR_CONSOLES];
	int i;

	console_lock();
	scoped_guard(console_lock)
		for (i = 1; i < MAX_NR_CONSOLES; i++)
			if (!vt_busy(i))
				vc[i] = vc_deallocate(i);
			else
				vc[i] = NULL;
	console_unlock();

	for (i = 1; i < MAX_NR_CONSOLES; i++) {
		if (vc[i] && i >= MIN_NR_CONSOLES)
@@ -703,7 +697,7 @@ static int vt_resizex(struct vc_data *vc, struct vt_consize __user *cs)

		if (!vc_cons[i].d)
			continue;
		console_lock();
		guard(console_lock)();
		vcp = vc_cons[i].d;
		if (vcp) {
			int ret;
@@ -718,11 +712,9 @@ static int vt_resizex(struct vc_data *vc, struct vt_consize __user *cs)
			if (ret) {
				vcp->vc_scan_lines = save_scan_lines;
				vcp->vc_cell_height = save_cell_height;
				console_unlock();
				return ret;
			}
		}
		console_unlock();
	}

	return 0;
@@ -770,7 +762,7 @@ int vt_ioctl(struct tty_struct *tty,
		if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS)
			return -EINVAL;

		console_lock();
		guard(console_lock)();
		vc->vt_mode = tmp;
		/* the frsig is ignored, so we set it to 0 */
		vc->vt_mode.frsig = 0;
@@ -778,7 +770,6 @@ int vt_ioctl(struct tty_struct *tty,
		vc->vt_pid = get_pid(task_pid(current));
		/* no switch is required -- saw@shade.msu.ru */
		vc->vt_newvt = -1;
		console_unlock();
		break;
	}

@@ -787,9 +778,8 @@ int vt_ioctl(struct tty_struct *tty,
		struct vt_mode tmp;
		int rc;

		console_lock();
		scoped_guard(console_lock)
			memcpy(&tmp, &vc->vt_mode, sizeof(struct vt_mode));
		console_unlock();

		rc = copy_to_user(up, &tmp, sizeof(struct vt_mode));
		if (rc)
@@ -811,12 +801,10 @@ int vt_ioctl(struct tty_struct *tty,
			return -EFAULT;

		state = 1;	/* /dev/tty0 is always open */
		console_lock(); /* required by vt_in_use() */
		for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask;
				++i, mask <<= 1)
		scoped_guard(console_lock) /* required by vt_in_use() */
			for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
				if (vt_in_use(i))
					state |= mask;
		console_unlock();
		return put_user(state, &vtstat->v_state);
	}

@@ -824,11 +812,10 @@ int vt_ioctl(struct tty_struct *tty,
	 * Returns the first available (non-opened) console.
	 */
	case VT_OPENQRY:
		console_lock(); /* required by vt_in_use() */
		scoped_guard(console_lock) /* required by vt_in_use() */
			for (i = 0; i < MAX_NR_CONSOLES; ++i)
				if (!vt_in_use(i))
					break;
		console_unlock();
		i = i < MAX_NR_CONSOLES ? (i+1) : -1;
		return put_user(i, (int __user *)arg);

@@ -845,11 +832,11 @@ int vt_ioctl(struct tty_struct *tty,

		arg--;
		arg = array_index_nospec(arg, MAX_NR_CONSOLES);
		console_lock();
		scoped_guard(console_lock) {
			ret = vc_allocate(arg);
		console_unlock();
			if (ret)
				return ret;
		}
		set_console(arg);
		break;

@@ -880,15 +867,13 @@ int vt_ioctl(struct tty_struct *tty,
	 *	2:	completed switch-to OK
	 */
	case VT_RELDISP:
	{
		if (!perm)
			return -EPERM;

		console_lock();
		ret = vt_reldisp(vc, arg);
		console_unlock();

		return ret;

		guard(console_lock)();
		return vt_reldisp(vc, arg);
	}

	 /*
	  * Disallocate memory associated to VT (but leave VT1)
@@ -917,7 +902,7 @@ int vt_ioctl(struct tty_struct *tty,
		    get_user(cc, &vtsizes->v_cols))
			return -EFAULT;

		console_lock();
		guard(console_lock)();
		for (i = 0; i < MAX_NR_CONSOLES; i++) {
			vc = vc_cons[i].d;

@@ -926,7 +911,6 @@ int vt_ioctl(struct tty_struct *tty,
				__vc_resize(vc_cons[i].d, cc, ll, true);
			}
		}
		console_unlock();
		break;
	}

@@ -996,21 +980,18 @@ void vc_SAK(struct work_struct *work)
	struct vc_data *vc;
	struct tty_struct *tty;

	console_lock();
	guard(console_lock)();
	vc = vc_con->d;
	if (vc) {
	if (!vc)
		return;

	/* FIXME: review tty ref counting */
	tty = vc->port.tty;
		/*
		 * SAK should also work in all raw modes and reset
		 * them properly.
		 */
	/* SAK should also work in all raw modes and reset them properly. */
	if (tty)
		__do_SAK(tty);
	reset_vc(vc);
}
	console_unlock();
}

#ifdef CONFIG_COMPAT

@@ -1287,31 +1268,29 @@ int vt_move_to_console(unsigned int vt, int alloc)
{
	int prev;

	console_lock();
	scoped_guard(console_lock) {
		/* Graphics mode - up to X */
	if (disable_vt_switch) {
		console_unlock();
		if (disable_vt_switch)
			return 0;
	}

		prev = fg_console;

		if (alloc && vc_allocate(vt)) {
		/* we can't have a free VC for now. Too bad,
		 * we don't want to mess the screen for now. */
		console_unlock();
			/*
			 * We can't have a free VC for now. Too bad, we don't want to mess the
			 * screen for now.
			 */
			return -ENOSPC;
		}

		if (set_console(vt)) {
			/*
		 * We're unable to switch to the SUSPEND_CONSOLE.
		 * Let the calling function know so it can decide
		 * what to do.
			 * We're unable to switch to the SUSPEND_CONSOLE. Let the calling function
			 * know so it can decide what to do.
			 */
		console_unlock();
			return -EIO;
		}
	console_unlock();
	}
	if (vt_waitactive(vt + 1)) {
		pr_debug("Suspend: Can't switch VCs.");
		return -EINTR;
@@ -1328,8 +1307,7 @@ int vt_move_to_console(unsigned int vt, int alloc)
 */
void pm_set_vt_switch(int do_switch)
{
	console_lock();
	guard(console_lock)();
	disable_vt_switch = !do_switch;
	console_unlock();
}
EXPORT_SYMBOL(pm_set_vt_switch);