diff --git a/vnc-client-iterator.patch b/vnc-client-iterator.patch new file mode 100644 index 0000000..fc0c454 --- /dev/null +++ b/vnc-client-iterator.patch @@ -0,0 +1,91 @@ +rfbClientIterator is swarming with bugs: +* Whoever added rfbClientListMutex didn't know what he was doing. +* Reference counting is broken +* The iterator normally skips closed entries (those with sock<0). But + rfbClientConnectionGone() neglects to reset cl->sock. +* Closed entries are *not* skipped when LIBVNCSERVER_HAVE_LIBPTHREAD + is undefined. + +diff -rup a/LibVNCServer-0.8.2/libvncserver/rfbserver.c b/LibVNCServer-0.8.2/libvncserver/rfbserver.c +--- a/LibVNCServer-0.8.2/libvncserver/rfbserver.c 2007-07-31 16:00:10.000000000 +0200 ++++ b/LibVNCServer-0.8.2/libvncserver/rfbserver.c 2007-07-31 15:14:47.000000000 +0200 +@@ -148,40 +148,42 @@ rfbGetClientIteratorWithClosed(rfbScreen + rfbClientPtr + rfbClientIteratorHead(rfbClientIteratorPtr i) + { ++ rfbClientPtr cl; ++ LOCK(rfbClientListMutex); + #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + if(i->next != 0) { + rfbDecrClientRef(i->next); +- rfbIncrClientRef(i->screen->clientHead); + } ++ rfbIncrClientRef(i->screen->clientHead); + #endif +- LOCK(rfbClientListMutex); +- i->next = i->screen->clientHead; ++ cl = i->next = i->screen->clientHead; + UNLOCK(rfbClientListMutex); +- return i->next; ++ return cl; + } + + rfbClientPtr + rfbClientIteratorNext(rfbClientIteratorPtr i) + { ++ rfbClientPtr cl; ++ LOCK(rfbClientListMutex); + if(i->next == 0) { +- LOCK(rfbClientListMutex); + i->next = i->screen->clientHead; +- UNLOCK(rfbClientListMutex); + } else { +- IF_PTHREADS(rfbClientPtr cl = i->next); ++ IF_PTHREADS(cl = i->next); + i->next = i->next->next; + IF_PTHREADS(rfbDecrClientRef(cl)); + } + ++ if(!i->closedToo) ++ while(i->next && i->next->sock<0) ++ i->next = i->next->next; + #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +- if(!i->closedToo) +- while(i->next && i->next->sock<0) +- i->next = i->next->next; +- if(i->next) +- rfbIncrClientRef(i->next); ++ if(i->next) ++ rfbIncrClientRef(i->next); + #endif +- +- return i->next; ++ cl = i->next; ++ UNLOCK(rfbClientListMutex); ++ return cl; + } + + void +@@ -474,8 +476,11 @@ rfbClientConnectionGone(rfbClientPtr cl) + if (cl->next) + cl->next->prev = cl->prev; + +- if(cl->sock>0) ++ if(cl->sock>=0) { ++ FD_CLR(cl->sock,&(cl->screen->allFds)); + close(cl->sock); ++ cl->sock = -1; ++ } + + if (cl->scaledScreen!=NULL) + cl->scaledScreen->scaledScreenRefCount--; +@@ -501,9 +506,6 @@ rfbClientConnectionGone(rfbClientPtr cl) + + UNLOCK(rfbClientListMutex); + +- if(cl->sock>=0) +- FD_CLR(cl->sock,&(cl->screen->allFds)); +- + cl->clientGoneHook(cl); + + rfbLog("Client %s gone\n",cl->host); diff --git a/vnc-double-cleanup.patch b/vnc-double-cleanup.patch new file mode 100644 index 0000000..297da38 --- /dev/null +++ b/vnc-double-cleanup.patch @@ -0,0 +1,27 @@ +Both clientInput() and rfbScreenCleanup() call +rfbClientConnectionGone(). This works only if clientInput() wins the +race with a sufficient margin to take the client off the list before +rfbScreenCleanup() sees it. Otherwise, rfbClientConnectionGone() is +called twice, with potentially disastrous results. + +diff -rup xen-3.1.0-src/LibVNCServer-0.8.2/libvncserver/main.c xen-3.1.0-hacked/LibVNCServer-0.8.2/libvncserver/main.c +--- xen-3.1.0-src/LibVNCServer-0.8.2/libvncserver/main.c 2007-07-30 14:41:46.000000000 +0200 ++++ xen-3.1.0-hacked/LibVNCServer-0.8.2/libvncserver/main.c 2007-07-31 15:52:51.000000000 +0200 +@@ -494,6 +494,8 @@ clientInput(void *data) + pthread_t output_thread; + pthread_create(&output_thread, NULL, clientOutput, (void *)cl); + ++ rfbIncrClientRef(cl); ++ + while (1) { + fd_set rfds, wfds, efds; + struct timeval tv; +@@ -555,7 +557,7 @@ clientInput(void *data) + UNLOCK(cl->updateMutex); + IF_PTHREADS(pthread_join(output_thread, NULL)); + +- rfbClientConnectionGone(cl); ++ rfbDecrClientRef(cl); + + return NULL; + } diff --git a/vnc-invalid-fd.patch b/vnc-invalid-fd.patch new file mode 100644 index 0000000..0e35fb6 --- /dev/null +++ b/vnc-invalid-fd.patch @@ -0,0 +1,43 @@ +When the socket has been closed already, cl->sock is -1. Don't pass +that to FD_SET() etc. + +diff -up a/LibVNCServer-0.8.2/libvncserver/main.c b/LibVNCServer-0.8.2/libvncserver/main.c +--- a/LibVNCServer-0.8.2/libvncserver/main.c 2007-07-24 20:33:55.000000000 +0200 ++++ b/LibVNCServer-0.8.2/libvncserver/main.c 2007-07-25 15:48:58.000000000 +0200 +@@ -497,9 +497,12 @@ clientInput(void *data) + int n, sock; + + LOCK(cl->updateMutex); +- sock = cl->sock; ++ sock = dup(cl->sock); + UNLOCK(cl->updateMutex); + ++ if (sock == -1) ++ break; ++ + FD_ZERO(&rfds); + FD_SET(sock, &rfds); + FD_ZERO(&efds); +@@ -515,11 +518,13 @@ clientInput(void *data) + n = select(sock + 1, &rfds, &wfds, &efds, &tv); + if (n < 0) { + rfbLogPerror("ReadExact: select"); ++ close(sock); + break; + } + if (n == 0) /* timeout */ + { + rfbSendFileTransferChunk(cl); ++ close(sock); + continue; + } + +@@ -530,6 +535,8 @@ clientInput(void *data) + if (FD_ISSET(sock, &rfds) || FD_ISSET(sock, &efds)) + rfbProcessClientMessage(cl); + ++ close(sock); ++ + LOCK(cl->updateMutex); + if (cl->sock == -1) { + UNLOCK(cl->updateMutex); diff --git a/vnc-ref-counting.patch b/vnc-ref-counting.patch new file mode 100644 index 0000000..2092c13 --- /dev/null +++ b/vnc-ref-counting.patch @@ -0,0 +1,37 @@ +Make the reference counting match the life range of cl. Before, other +threads could crash on accessing the prematurely freed cl. + +diff -up a/LibVNCServer-0.8.2/libvncserver/main.c b/LibVNCServer-0.8.2/libvncserver/main.c +--- a/LibVNCServer-0.8.2/libvncserver/main.c 2007-07-24 20:33:55.000000000 +0200 ++++ b/LibVNCServer-0.8.2/libvncserver/main.c 2007-07-25 15:53:02.000000000 +0200 +@@ -441,11 +441,14 @@ clientOutput(void *data) + rfbBool haveUpdate; + sraRegion* updateRegion; + ++ rfbIncrClientRef(cl); ++ + while (1) { + haveUpdate = false; + while (!haveUpdate) { + if (cl->sock == -1) { + /* Client has disconnected. */ ++ rfbDecrClientRef(cl); + return NULL; + } + LOCK(cl->updateMutex); +@@ -473,13 +476,13 @@ clientOutput(void *data) + UNLOCK(cl->updateMutex); + + /* Now actually send the update. */ +- rfbIncrClientRef(cl); + rfbSendFramebufferUpdate(cl, updateRegion); +- rfbDecrClientRef(cl); + + sraRgnDestroy(updateRegion); + } + ++ rfbDecrClientRef(cl); ++ + /* Not reached. */ + return NULL; + } diff --git a/xen-3.1.0-dev-native-protocol.patch b/xen-3.1.0-dev-native-protocol.patch new file mode 100644 index 0000000..77cefef --- /dev/null +++ b/xen-3.1.0-dev-native-protocol.patch @@ -0,0 +1,45 @@ +# HG changeset patch +# User Ian Campbell +# Date 1179252048 -3600 +# Node ID 5efb46bfbcac99e630a75a677401060fbec3cc2a +# Parent 5c7a1e3abd5433c7b2eff6950bd566ec9d500eba +[XEND] Write the default ABI to the xenstore entry for each frontend +device. + +This allows to run older kernels in a 32on64 mixed environment. + +Signed-off-by: Ian Campbell + +diff -r 5c7a1e3abd54 -r 5efb46bfbcac tools/python/xen/xend/XendDomainInfo.py +--- a/tools/python/xen/xend/XendDomainInfo.py Tue May 15 17:54:48 2007 +0100 ++++ b/tools/python/xen/xend/XendDomainInfo.py Tue May 15 19:00:48 2007 +0100 +@@ -357,6 +357,8 @@ class XendDomainInfo: + self.console_port = None + self.console_mfn = None + ++ self.native_protocol = None ++ + self.vmWatch = None + self.shutdownWatch = None + self.shutdownStartTime = None +@@ -1520,6 +1522,8 @@ class XendDomainInfo: + self.console_mfn = channel_details['console_mfn'] + if 'notes' in channel_details: + self.info.set_notes(channel_details['notes']) ++ if 'native_protocol' in channel_details: ++ self.native_protocol = channel_details['native_protocol']; + + self._introduceDomain() + +diff -r 5c7a1e3abd54 -r 5efb46bfbcac tools/python/xen/xend/server/DevController.py +--- a/tools/python/xen/xend/server/DevController.py Tue May 15 17:54:48 2007 +0100 ++++ b/tools/python/xen/xend/server/DevController.py Tue May 15 19:00:48 2007 +0100 +@@ -459,6 +459,8 @@ class DevController: + 'state' : str(xenbusState['Initialising']) + }) + ++ if self.vm.native_protocol: ++ frontDetails.update({'protocol' : self.vm.native_protocol}) + + backDetails.update({ + 'domain' : self.vm.getName(), diff --git a/xen-3.1.0-libxc-native-protocol.patch b/xen-3.1.0-libxc-native-protocol.patch new file mode 100644 index 0000000..a6cc98a --- /dev/null +++ b/xen-3.1.0-libxc-native-protocol.patch @@ -0,0 +1,98 @@ +# HG changeset patch +# User Ian Campbell +# Date 1179248088 -3600 +# Node ID 5c7a1e3abd5433c7b2eff6950bd566ec9d500eba +# Parent e1f43038f1d803aabbb9b25f1713cfea0123c053 +[BUILDER] Propagate the native protocol ABI for a guest out of the +domain builder and in to python code. + +This knowledge will be useful to allow us to pre-seed the protocol +field in a VBD entry in xenstore which will allow us to run older +kernels in a 32on64 mixed environment. + +Signed-off-by: Ian Campbell + +diff -r e1f43038f1d8 -r 5c7a1e3abd54 tools/libxc/xc_dom.h +--- a/tools/libxc/xc_dom.h Tue May 15 17:01:57 2007 +0100 ++++ b/tools/libxc/xc_dom.h Tue May 15 17:54:48 2007 +0100 +@@ -136,6 +136,7 @@ struct xc_dom_arch { + int (*vcpu) (struct xc_dom_image * dom, void *vcpu_ctxt); + + char *guest_type; ++ char *native_protocol; + int page_shift; + int sizeof_pfn; + +diff -r e1f43038f1d8 -r 5c7a1e3abd54 tools/libxc/xc_dom_x86.c +--- a/tools/libxc/xc_dom_x86.c Tue May 15 17:01:57 2007 +0100 ++++ b/tools/libxc/xc_dom_x86.c Tue May 15 17:54:48 2007 +0100 +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + #include "xg_private.h" + #include "xc_dom.h" +@@ -589,6 +590,7 @@ static int vcpu_x86_64(struct xc_dom_ima + + static struct xc_dom_arch xc_dom_32 = { + .guest_type = "xen-3.0-x86_32", ++ .native_protocol = XEN_IO_PROTO_ABI_X86_32, + .page_shift = PAGE_SHIFT_X86, + .sizeof_pfn = 4, + .alloc_magic_pages = alloc_magic_pages, +@@ -600,6 +602,7 @@ static struct xc_dom_arch xc_dom_32 = { + }; + static struct xc_dom_arch xc_dom_32_pae = { + .guest_type = "xen-3.0-x86_32p", ++ .native_protocol = XEN_IO_PROTO_ABI_X86_32, + .page_shift = PAGE_SHIFT_X86, + .sizeof_pfn = 4, + .alloc_magic_pages = alloc_magic_pages, +@@ -612,6 +615,7 @@ static struct xc_dom_arch xc_dom_32_pae + + static struct xc_dom_arch xc_dom_64 = { + .guest_type = "xen-3.0-x86_64", ++ .native_protocol = XEN_IO_PROTO_ABI_X86_64, + .page_shift = PAGE_SHIFT_X86, + .sizeof_pfn = 8, + .alloc_magic_pages = alloc_magic_pages, +diff -r e1f43038f1d8 -r 5c7a1e3abd54 tools/python/xen/lowlevel/xc/xc.c +--- a/tools/python/xen/lowlevel/xc/xc.c Tue May 15 17:01:57 2007 +0100 ++++ b/tools/python/xen/lowlevel/xc/xc.c Tue May 15 17:54:48 2007 +0100 +@@ -407,6 +407,7 @@ static PyObject *pyxc_linux_build(XcObje + unsigned long console_mfn = 0; + PyObject* elfnote_dict; + PyObject* elfnote = NULL; ++ PyObject* ret; + int i; + + static char *kwd_list[] = { "domid", "store_evtchn", "memsize", +@@ -455,12 +456,22 @@ static PyObject *pyxc_linux_build(XcObje + Py_DECREF(elfnote); + } + ++ ret = Py_BuildValue("{s:i,s:i,s:N}", ++ "store_mfn", store_mfn, ++ "console_mfn", console_mfn, ++ "notes", elfnote_dict); ++ ++ if ( dom->arch_hooks->native_protocol ) ++ { ++ PyObject *native_protocol = ++ Py_BuildValue("s", dom->arch_hooks->native_protocol); ++ PyDict_SetItemString(ret, "native_protocol", native_protocol); ++ Py_DECREF(native_protocol); ++ } ++ + xc_dom_release(dom); + +- return Py_BuildValue("{s:i,s:i,s:N}", +- "store_mfn", store_mfn, +- "console_mfn", console_mfn, +- "notes", elfnote_dict); ++ return ret; + + out: + xc_dom_release(dom); diff --git a/xen-keyboard.patch b/xen-keyboard.patch new file mode 100644 index 0000000..478cbb5 --- /dev/null +++ b/xen-keyboard.patch @@ -0,0 +1,87 @@ +Straight from xen-unstable.hg csets: + +changeset: 15146:1e418f7e0212 +user: kfraser@localhost.localdomain +date: Thu May 24 13:34:19 2007 +0100 +summary: vnc: Fix Zenkaku_Hankaku and add deadkey keysyms + +changeset: 15446:f85252ce203e +user: kfraser@localhost.localdomain +date: Tue Jul 03 10:06:48 2007 +0100 +summary: hvm: Fix keymap for Windows keys. + +changeset: 15474:2dee920e0fd7 +user: kfraser@localhost.localdomain +date: Fri Jul 06 14:37:47 2007 +0100 +summary: hvm: Fix vnc keymap for Japanese keyboards. + +Despite the summaries, this affects PVFB as well as HVM. + +diff -rup a/tools/ioemu/keymaps/ja b/tools/ioemu/keymaps/ja +--- a/tools/ioemu/keymaps/ja 2007-05-18 16:45:21.000000000 +0200 ++++ b/tools/ioemu/keymaps/ja 2007-07-13 18:48:11.000000000 +0200 +@@ -100,6 +100,7 @@ backslash 0x73 + bar 0x7d shift + underscore 0x73 shift + Henkan_Mode 0x79 ++Katakana_Real 0x70 + Katakana 0x70 + Muhenkan 0x7b + Henkan_Mode_Real 0x79 +diff -rup a/tools/ioemu/keymaps/modifiers b/tools/ioemu/keymaps/modifiers +--- a/tools/ioemu/keymaps/modifiers 2007-05-18 16:45:21.000000000 +0200 ++++ b/tools/ioemu/keymaps/modifiers 2007-07-13 15:54:10.000000000 +0200 +@@ -11,8 +11,8 @@ Control_L 0x1d + + # Translate Super to Windows keys. + # This is hardcoded. See documentation for details. +-Super_R 0xdb +-Super_L 0xdc ++Super_R 0xdc ++Super_L 0xdb + + # Translate Menu to the Windows Application key. + Menu 0xdd +diff -rup a/tools/ioemu/vnc_keysym.h b/tools/ioemu/vnc_keysym.h +--- a/tools/ioemu/vnc_keysym.h 2007-05-18 16:45:21.000000000 +0200 ++++ b/tools/ioemu/vnc_keysym.h 2007-07-24 20:58:53.000000000 +0200 +@@ -290,11 +290,37 @@ static name2keysym_t name2keysym[]={ + /* localized keys */ + {"BackApostrophe", 0xff21}, + {"Muhenkan", 0xff22}, +-{"Katakana", 0xff25}, +-{"Zenkaku_Hankaku", 0xff29}, ++{"Katakana", 0xff27}, ++{"Hankaku", 0xff29}, ++{"Zenkaku_Hankaku", 0xff2a}, + {"Henkan_Mode_Real", 0xff23}, + {"Henkan_Mode_Ultra", 0xff3e}, + {"backslash_ja", 0xffa5}, ++{"Katakana_Real", 0xff25}, ++{"Eisu_toggle", 0xff30}, ++ ++ /* dead keys */ ++{"dead_grave", 0xfe50}, ++{"dead_acute", 0xfe51}, ++{"dead_circumflex", 0xfe52}, ++{"dead_tilde", 0xfe53}, ++{"dead_macron", 0xfe54}, ++{"dead_brev", 0xfe55}, ++{"dead_abovedot", 0xfe56}, ++{"dead_diaeresis", 0xfe57}, ++{"dead_abovering", 0xfe58}, ++{"dead_doubleacute", 0xfe59}, ++{"dead_caron", 0xfe5a}, ++{"dead_cedilla", 0xfe5b}, ++{"dead_ogonek", 0xfe5c}, ++{"dead_iota", 0xfe5d}, ++{"dead_voiced_sound", 0xfe5e}, ++{"dead_semivoiced_sound", 0xfe5f}, ++{"dead_belowdot", 0xfe60}, ++{"dead_hook", 0xfe61}, ++{"dead_horn", 0xfe62}, ++ + + {0,0}, + }; ++ diff --git a/xen.spec b/xen.spec index 9e8ecf9..78a8e08 100644 --- a/xen.spec +++ b/xen.spec @@ -3,7 +3,7 @@ Summary: Xen is a virtual machine monitor Name: xen Version: 3.1.0 -Release: 2%{?dist} +Release: 3%{?dist} Group: Development/Libraries License: GPL URL: http://www.cl.cam.ac.uk/Research/SRG/netos/xen/index.html @@ -24,6 +24,9 @@ Patch21: xen-blktap-error-returns.patch Patch25: xen-qemu-vnc-delete.patch Patch26: xen-hvm-save-paths.patch Patch27: xen-console-log.patch +Patch28: xen-keyboard.patch +Patch29: xen-3.1.0-libxc-native-protocol.patch +Patch30: xen-3.1.0-dev-native-protocol.patch # Patches to modify the default config of xend Patch100: xen-config-dom0-minmem.patch @@ -43,6 +46,10 @@ Patch280: xen-xs-transactions.patch # libVNCserver patches Patch300: vnc-thread-fixes.patch +Patch301: vnc-invalid-fd.patch +Patch302: vnc-ref-counting.patch +Patch303: vnc-client-iterator.patch +Patch304: vnc-double-cleanup.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root BuildRequires: transfig libidn-devel zlib-devel texi2html SDL-devel curl-devel @@ -113,6 +120,9 @@ virtual machines. %patch25 -p1 %patch26 -p1 %patch27 -p1 +%patch28 -p1 +%patch29 -p1 +%patch30 -p1 # config patches %patch100 -p1 @@ -134,6 +144,14 @@ virtual machines. pushd LibVNCServer-0.8.2 # thread locking fixes %patch300 -p2 +# use of invalid fd (race condition) +%patch301 -p2 +# dangling pointer (race condition) +%patch302 -p2 +# client iterator fixes +%patch303 -p2 +# double cleanup (race condition) +%patch304 -p2 popd %build @@ -269,6 +287,12 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/*.a %changelog +* Wed Aug 1 2007 Markus Armbruster - 3.1.0-3.fc8 +- Put guest's native protocol ABI into xenstore, to provide for older + kernels running 32-on-64. +- VNC keymap fixes +- Fix race conditions in LibVNCServer on client disconnect + * Tue Jun 12 2007 Daniel P. Berrange - 3.1.0-2.fc8 - Remove patch which kills VNC monitor - Fix HVM save/restore file path to be /var/lib/xen instead of /tmp