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>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20090630000003.GA21004@omega>
Date:	Tue, 30 Jun 2009 02:00:04 +0200
From:	Lennart Poettering <lennart@...ttering.net>
To:	linux-kernel@...r.kernel.org
Cc:	Alan Cox <alan@...rguk.ukuu.org.uk>,
	William Jon McCann <jmccann@...hat.com>
Subject: [PATCH] vt: extend VT_WAITACTIVE ioctl to allow waiting until a
	specific VT becomes inactive

Currently, the VT_WAITACTIVE ioctl can be used to wait until a
specific VT becomes _active_. This is used by ConsoleKit to follow
which VT is the active one.  This patch extends this logic in a simple
way, so that it can be used to wait until a specific VT becomes
_inactive_.

If the argument passed to VT_WAITACTIVE is positive the current
behaviour (waiting until active) is exposed. However, if it is negative
the 'inverse' behaviour (waiting until inactive) is exposed.

Why all this?

Currently ConsoleKit creates 64 seperate threads, one for each
theoretical VT and calls VT_WAITACTIVE in them, once for each VT. It thus
will get a woken up once for each VT change. Having that many threads
around is certainly ugly and also racy, since multiple quick VT changes
might be processed in the wrong order. With this patch CK can simply call
VT_WAITACTIVE in a loop for whatever VT is currently considered active
and will then get a wakeup when it isn't anymore. Then it can reread the
current VT index and reenter VT_WAITACTIVE again. This allows CK to run
only one thread instead of 64 to watch the VT status and also fixes the
ordering race pointed out above.

How use this?

  /* this will wait until VT 5 is activated */
  ioctl(0, VT_WAITACTIVE, 5L);

  /* this will wait until VT 5 is deactivated again */
  ioctl(0, VT_WAITACTIVE, -5L);

ConsoleKit would probably just call it in a loop like this:

  for (;;) {
  	struct vt_stat st;
	ioctl(0, VT_GETSTATE, &st);
	printf("console %s is active.\n", st.v_active);
	ioctl(0, VT_WAITACTIVE, (signed long) - st.v_active);
  }

I tested this and it seems to work fine.

Signed-off-by: Lennart Poettering <lennart@...ttering.net>
---
 drivers/char/vt_ioctl.c |   17 +++++++++++++----
 include/linux/vt_kern.h |    2 +-
 kernel/power/console.c  |    4 ++--
 3 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index e6ce632..3fe8988 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -843,14 +843,22 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
 	/*
 	 * wait until the specified VT has been activated
 	 */
-	case VT_WAITACTIVE:
+	case VT_WAITACTIVE: {
+		signed long s_arg = arg;
+		bool active;
+
 		if (!perm)
 			goto eperm;
+
+		active = s_arg > 0;
+		arg = active ? s_arg : -s_arg;
+
 		if (arg == 0 || arg > MAX_NR_CONSOLES)
 			ret = -ENXIO;
 		else
-			ret = vt_waitactive(arg - 1);
+			ret = vt_waitactive(arg - 1, active);
 		break;
+	}
 
 	/*
 	 * If a vt is under process control, the kernel will not switch to it
@@ -1181,7 +1189,7 @@ static DECLARE_WAIT_QUEUE_HEAD(vt_activate_queue);
  * Sleeps until a vt is activated, or the task is interrupted. Returns
  * 0 if activation, -EINTR if interrupted by a signal handler.
  */
-int vt_waitactive(int vt)
+int vt_waitactive(int vt, bool active)
 {
 	int retval;
 	DECLARE_WAITQUEUE(wait, current);
@@ -1199,7 +1207,8 @@ int vt_waitactive(int vt)
 		 */
 		acquire_console_sem();
 		set_current_state(TASK_INTERRUPTIBLE);
-		if (vt == fg_console) {
+		if ((active && vt == fg_console) ||
+		   (!active && vt != fg_console)) {
 			release_console_sem();
 			break;
 		}
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index 2f11134..4d8a9b8 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -91,7 +91,7 @@ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc);
 #endif
 
 /* vt.c */
-int vt_waitactive(int vt);
+int vt_waitactive(int vt, bool active);
 void change_console(struct vc_data *new_vc);
 void reset_vc(struct vc_data *vc);
 extern int unbind_con_driver(const struct consw *csw, int first, int last,
diff --git a/kernel/power/console.c b/kernel/power/console.c
index a3961b2..146367e 100644
--- a/kernel/power/console.c
+++ b/kernel/power/console.c
@@ -60,7 +60,7 @@ int pm_prepare_console(void)
 	}
 	release_console_sem();
 
-	if (vt_waitactive(SUSPEND_CONSOLE)) {
+	if (vt_waitactive(SUSPEND_CONSOLE, true)) {
 		pr_debug("Suspend: Can't switch VCs.");
 		return 1;
 	}
@@ -79,7 +79,7 @@ void pm_restore_console(void)
 	set_console(orig_fgconsole);
 	release_console_sem();
 
-	if (vt_waitactive(orig_fgconsole)) {
+	if (vt_waitactive(orig_fgconsole, true)) {
 		pr_debug("Resume: Can't switch VCs.");
 		return;
 	}
-- 
1.6.3.2



Lennart

-- 
Lennart Poettering                        Red Hat, Inc.
lennart [at] poettering [dot] net         ICQ# 11060553
http://0pointer.net/lennart/           GnuPG 0x1A015CC4
--
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