summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/changelog8
-rw-r--r--debian/patches/from-debian-qemu/62_fix-ptyblocking.patch169
-rw-r--r--debian/patches/series1
3 files changed, 178 insertions, 0 deletions
diff --git a/debian/changelog b/debian/changelog
index fa49a00..5ef6f32 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+kvm (72+dfsg-3) unstable; urgency=medium
+
+ * Apply patch from qemu (62_fix-ptyblocking.patch) which fixes a lockup
+ when using a pty as serial console, which caused problems for libvirt
+ users. Thanks to Peter Palfrader and Riku Voipio (closes: #494831)
+
+ -- Jan Lübbe <jluebbe@debian.org> Thu, 20 Nov 2008 16:41:26 +0100
+
kvm (72+dfsg-2) unstable; urgency=medium
* Merge changes from NMU, thanks to Thomas Viehmann
diff --git a/debian/patches/from-debian-qemu/62_fix-ptyblocking.patch b/debian/patches/from-debian-qemu/62_fix-ptyblocking.patch
new file mode 100644
index 0000000..1fbc713
--- /dev/null
+++ b/debian/patches/from-debian-qemu/62_fix-ptyblocking.patch
@@ -0,0 +1,169 @@
+--- qemu/vl.c 2008/07/23 15:19:59 4927
++++ qemu/vl.c 2008/07/28 18:55:32 4956
+@@ -2464,21 +2464,162 @@
+ #endif
+
+ #if defined(__linux__) || defined(__sun__)
++
++typedef struct {
++ int fd;
++ int connected;
++ int polling;
++ int read_bytes;
++ QEMUTimer *timer;
++} PtyCharDriver;
++
++static void pty_chr_update_read_handler(CharDriverState *chr);
++static void pty_chr_state(CharDriverState *chr, int connected);
++
++static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
++{
++ PtyCharDriver *s = chr->opaque;
++
++ if (!s->connected) {
++ /* guest sends data, check for (re-)connect */
++ pty_chr_update_read_handler(chr);
++ return 0;
++ }
++ return unix_write(s->fd, buf, len);
++}
++
++static int pty_chr_read_poll(void *opaque)
++{
++ CharDriverState *chr = opaque;
++ PtyCharDriver *s = chr->opaque;
++
++ s->read_bytes = qemu_chr_can_read(chr);
++ return s->read_bytes;
++}
++
++static void pty_chr_read(void *opaque)
++{
++ CharDriverState *chr = opaque;
++ PtyCharDriver *s = chr->opaque;
++ int size, len;
++ uint8_t buf[1024];
++
++ len = sizeof(buf);
++ if (len > s->read_bytes)
++ len = s->read_bytes;
++ if (len == 0)
++ return;
++ size = read(s->fd, buf, len);
++ if ((size == -1 && errno == EIO) ||
++ (size == 0)) {
++ pty_chr_state(chr, 0);
++ return;
++ }
++ if (size > 0) {
++ pty_chr_state(chr, 1);
++ qemu_chr_read(chr, buf, size);
++ }
++}
++
++static void pty_chr_update_read_handler(CharDriverState *chr)
++{
++ PtyCharDriver *s = chr->opaque;
++
++ qemu_set_fd_handler2(s->fd, pty_chr_read_poll,
++ pty_chr_read, NULL, chr);
++ s->polling = 1;
++ /*
++ * Short timeout here: just need wait long enougth that qemu makes
++ * it through the poll loop once. When reconnected we want a
++ * short timeout so we notice it almost instantly. Otherwise
++ * read() gives us -EIO instantly, making pty_chr_state() reset the
++ * timeout to the normal (much longer) poll interval before the
++ * timer triggers.
++ */
++ qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 10);
++}
++
++static void pty_chr_state(CharDriverState *chr, int connected)
++{
++ PtyCharDriver *s = chr->opaque;
++
++ if (!connected) {
++ qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
++ s->connected = 0;
++ s->polling = 0;
++ /* (re-)connect poll interval for idle guests: once per second.
++ * We check more frequently in case the guests sends data to
++ * the virtual device linked to our pty. */
++ qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 1000);
++ } else {
++ if (!s->connected)
++ qemu_chr_reset(chr);
++ s->connected = 1;
++ }
++}
++
++void pty_chr_timer(void *opaque)
++{
++ struct CharDriverState *chr = opaque;
++ PtyCharDriver *s = chr->opaque;
++
++ if (s->connected)
++ return;
++ if (s->polling) {
++ /* If we arrive here without polling being cleared due
++ * read returning -EIO, then we are (re-)connected */
++ pty_chr_state(chr, 1);
++ return;
++ }
++
++ /* Next poll ... */
++ pty_chr_update_read_handler(chr);
++}
++
++static void pty_chr_close(struct CharDriverState *chr)
++{
++ PtyCharDriver *s = chr->opaque;
++
++ qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
++ close(s->fd);
++ qemu_free(s);
++}
++
+ static CharDriverState *qemu_chr_open_pty(void)
+ {
++ CharDriverState *chr;
++ PtyCharDriver *s;
+ struct termios tty;
+- int master_fd, slave_fd;
++ int slave_fd;
+
+- if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) < 0) {
++ chr = qemu_mallocz(sizeof(CharDriverState));
++ if (!chr)
++ return NULL;
++ s = qemu_mallocz(sizeof(PtyCharDriver));
++ if (!s) {
++ qemu_free(chr);
++ return NULL;
++ }
++
++ if (openpty(&s->fd, &slave_fd, NULL, NULL, NULL) < 0) {
+ return NULL;
+ }
+
+ /* Set raw attributes on the pty. */
+ cfmakeraw(&tty);
+ tcsetattr(slave_fd, TCSAFLUSH, &tty);
++ close(slave_fd);
++
++ fprintf(stderr, "char device redirected to %s\n", ptsname(s->fd));
+
+- fprintf(stderr, "char device redirected to %s\n", ptsname(master_fd));
+- return qemu_chr_open_fd(master_fd, master_fd);
++ chr->opaque = s;
++ chr->chr_write = pty_chr_write;
++ chr->chr_update_read_handler = pty_chr_update_read_handler;
++ chr->chr_close = pty_chr_close;
++
++ s->timer = qemu_new_timer(rt_clock, pty_chr_timer, chr);
++
++ return chr;
+ }
+
+ static void tty_serial_init(int fd, int speed,
diff --git a/debian/patches/series b/debian/patches/series
index 057cae9..2cf341c 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -5,6 +5,7 @@
06_no_system_linux_kvm_h.patch -p0
from-debian-qemu/22_net_tuntap_stall.patch -p0
from-debian-qemu/62_linux_boot_nasm.patch -p0
+from-debian-qemu/62_fix-ptyblocking.patch -p0
07_change_qemu_docdir.patch
CVE-2008-0928.patch
SECURITY_CVE-2007-1321+1322+1366+2893.patch