lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-Id: <1427383391-5022-1-git-send-email-simone.weiss@fau.de>
Date:	Thu, 26 Mar 2015 16:23:11 +0100
From:	Simone Weiss <simone.weiss@....de>
To:	simone.weiss@....de
Cc:	gregkh@...uxfoundation.org, jslaby@...e.cz,
	linux-kernel@...r.kernel.org, linux-kernel@...cs.fau.de,
	helene.gsaenger@...dium.fau.de
Subject: [PATCH] Infrastructure to un-/lock vts in vt_ioctl.c

Makes it possible to lock and unlock specific VTs.
When someone tries to switch to a locked vt, he gets redirected to VT 12.

We added the three cases VT_LOCK, VT_UNLOCK and VT_IS_LOCKED to vt_ioctl().
To indicate if a VT is locked we also added a flag to the struct vc_data.

VT_LOCK: allows the owner of a sppecified VT to set the lock flag.
VT_UNLOCK: allows caller with root permissions to reset the lock flag
VT_ISLOCKED: returns the value of the lock flag

If anyone tries to switch to a locked VT he gets redirected to VT 12
in complete_change_console.

Signed-off-by: Simone Weiss <simone.weiss@....de>
Signed-off-by: Helene Gsaenger <helene.gsaenger@...dium.fau.de>
---
The implementation of the lock functionality in the kernel provides advantages
which are hard to realize in userspace programms.
Situation right now:
Screensavers that are implemented as userspace programs can die (for example
by segfault) and give unauthorized users access.
Our implementation makes it possiple to lock single VTs witchout having to
change existing userspace programms.
It makes it possiple to add a Secure acess Key later on.

Regards
Simone Weiss and Helene Gsaenger

 drivers/tty/vt/vt_ioctl.c      | 101 ++++++++++++++++++++++++++++++++++++++++-
 include/linux/console_struct.h |   1 +
 include/uapi/linux/vt.h        |   3 ++
 3 files changed, 104 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index 3e3b092..e1f6b5c 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -1039,6 +1039,101 @@ int vt_ioctl(struct tty_struct *tty,
 	case VT_WAITEVENT:
 		ret = vt_event_wait_ioctl((struct vt_event __user *)arg);
 		break;
+	case VT_LOCK:
+	{
+		struct tty_struct *target;
+
+		if (arg > MAX_NR_CONSOLES)
+			return -ENXIO;
+
+		/* Locking vt12 is fobidden*/
+		if (arg == 12)
+			return -EPERM;
+
+		/* redirect to vt12 after locking current vt */
+		if ((vc_cons[fg_console].d->vc_num == arg-1) || arg == 0) {
+			console_lock();
+			vc->vc_locked = 1;
+			console_unlock();
+			ret = vt_ioctl(tty, VT_ACTIVATE, 12);
+			break;
+		}
+
+		arg--;
+
+		/* check if target is allocated */
+		if (!vc_cons_allocated(arg)) {
+			ret = -ENXIO;
+			goto out;
+		}
+
+		/* check if caller = owner or root */
+		if (!uid_eq(current_uid(), GLOBAL_ROOT_UID)) {
+			target = vc_cons[arg].d->port.tty;
+			spin_lock(&tty_files_lock);
+			if (!list_empty(&target->tty_files)) {
+				struct tty_file_private *file_priv;
+				struct file *file;
+
+				file_priv = list_first_entry(&target->tty_files,
+							     struct tty_file_private,
+							     list);
+				file = file_priv->file;
+				if (!uid_eq(current_uid(),
+					    file->f_inode->i_uid)) {
+					spin_unlock(&tty_files_lock);
+					return -EPERM;
+				}
+			}
+			spin_unlock(&tty_files_lock);
+		}
+
+		/* lock target */
+		console_lock();
+		if (vc_cons[arg].d->vc_locked == 1) {
+			console_unlock();
+			return -EACCES;
+		}
+		vc_cons[arg].d->vc_locked = 1;
+		console_unlock();
+		break;
+	}
+
+	case VT_UNLOCK:
+		if (arg > MAX_NR_CONSOLES || arg == 0)
+			return -ENXIO;
+
+		/* only root can unlock vts */
+		if (!uid_eq(current_uid(), GLOBAL_ROOT_UID))
+			return -EPERM;
+
+		arg--;
+
+		/* check if target is allocated */
+		if (!vc_cons_allocated(arg)) {
+			ret = -ENXIO;
+			goto out;
+		}
+
+		/* unlock target */
+		console_lock();
+		vc_cons[arg].d->vc_locked = 0;
+		console_unlock();
+		break;
+	case VT_IS_LOCKED:
+		if (arg > MAX_NR_CONSOLES || arg == 0)
+			return -ENXIO;
+
+		arg--;
+
+		/* check if target is allocated */
+		if (!vc_cons_allocated(arg)) {
+			ret = -ENXIO;
+			goto out;
+		}
+
+		ret = vc_cons[arg].d->vc_locked;
+		break;
 	default:
 		ret = -ENOIOCTLCMD;
 	}
@@ -1288,9 +1383,13 @@ static void complete_change_console(struct vc_data *vc)
 {
 	unsigned char old_vc_mode;
 	int old = fg_console;
+	int backup_vtnum = vc->vc_num;
 
 	last_console = fg_console;
 
+	if (vc->vc_locked)
+		vc = vc_cons[11].d;
+
 	/*
 	 * If we're switching, we could be going from KD_GRAPHICS to
 	 * KD_TEXT mode or vice versa, which means we need to blank or
@@ -1351,7 +1450,7 @@ static void complete_change_console(struct vc_data *vc)
 	/*
 	 * Wake anyone waiting for their VT to activate
 	 */
-	vt_event_post(VT_EVENT_SWITCH, old, vc->vc_num);
+	vt_event_post(VT_EVENT_SWITCH, old, backup_vtnum);
 	return;
 }
 
diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
index e859c98..902a36c 100644
--- a/include/linux/console_struct.h
+++ b/include/linux/console_struct.h
@@ -59,6 +59,7 @@ struct vc_data {
 	/* VT terminal data */
 	unsigned int	vc_state;		/* Escape sequence parser state */
 	unsigned int	vc_npar,vc_par[NPAR];	/* Parameters of current escape sequence */
+	unsigned int	vc_locked;		/* Set if console is locked */
 	/* data for manual vt switching */
 	struct vt_mode	vt_mode;
 	struct pid 	*vt_pid;
diff --git a/include/uapi/linux/vt.h b/include/uapi/linux/vt.h
index 978578b..58832a7 100644
--- a/include/uapi/linux/vt.h
+++ b/include/uapi/linux/vt.h
@@ -42,6 +42,9 @@ struct vt_stat {
 #define VT_ACTIVATE	0x5606	/* make vt active */
 #define VT_WAITACTIVE	0x5607	/* wait for vt active */
 #define VT_DISALLOCATE	0x5608  /* free memory associated to vt */
+#define VT_LOCK		0x5610	/* lock vt */
+#define VT_UNLOCK	0x5611	/* unlock vt */
+#define VT_IS_LOCKED	0x5612	/* show if vt is locked */
 
 struct vt_sizes {
 	unsigned short v_rows;		/* number of rows */
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ