summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorAlon Levy <alevy@redhat.com>2012-03-06 16:39:02 +0200
committerAlon Levy <alevy@redhat.com>2012-03-06 16:45:12 +0200
commit1029e7fd4d2ba837d5b14a4b8d93b6a9c4ab75ac (patch)
treed0e2182a492051d261e4210be67acb547bd6dd74 /server
parent1ab589f39ed0429ca08f13f093161098ac511ef1 (diff)
downloadspice-1029e7fd4d2ba837d5b14a4b8d93b6a9c4ab75ac.tar.gz
spice-1029e7fd4d2ba837d5b14a4b8d93b6a9c4ab75ac.tar.xz
spice-1029e7fd4d2ba837d5b14a4b8d93b6a9c4ab75ac.zip
server/red_worker: fix use after free for listeners
This fixes a core dumped observed once by repeated migration. So far 100 migrations and no recurrence. Core was generated by `/home/alon/spice/upstream/bin/qemu-system-x86_64 --enable-kvm -qmp unix:/tmp/mi'. Program terminated with signal 11, Segmentation fault. 11197 if (evt_listener && evt_listener->refs > 1) { Missing separate debuginfos, use: debuginfo-install bluez-libs-4.98-3.fc17.x86_64 brlapi-0.5.6-4.fc17.x86_64 bzip2-libs-1.0.6-4.fc17.x86_64 cryptopp-5.6.1-6.fc17.x86_64 keyutils-libs-1.5.5-2.fc17.x86_64 libssh2-1.4.0-1.fc17.x86_64 nss-softokn-freebl-3.13.1-20.fc17.x86_64 xen-libs-4.1.2-11.fc17.x86_64 xz-libs-5.1.1-2alpha.fc17.x86_64 (gdb) bt (gdb) l 11192 for (i = 0; i < MAX_EVENT_SOURCES; i++) { 11193 struct pollfd *pfd = worker.poll_fds + i; 11194 if (pfd->revents) { 11195 EventListener *evt_listener = worker.listeners[i]; 11196 11197 if (evt_listener && evt_listener->refs > 1) { 11198 evt_listener->action(evt_listener, pfd); 11199 if (--evt_listener->refs) { 11200 continue; 11201 } (gdb) p evt_listener $1 = (EventListener *) 0x7f15a9a5d1e0 (gdb) p *evt_listener Cannot access memory at address 0x7f15a9a5d1e0 (gdb) p i $2 = 2 (gdb) p worker.listeners $3 = {0x7f15bc832520, 0x7f15a406e1a0, 0x7f15a9a5d1e0, 0x0 <repeats 17 times>}
Diffstat (limited to 'server')
-rw-r--r--server/red_worker.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/server/red_worker.c b/server/red_worker.c
index e88dbc05..a2f31c0b 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -11194,7 +11194,7 @@ void *red_worker_main(void *arg)
if (pfd->revents) {
EventListener *evt_listener = worker.listeners[i];
- if (evt_listener->refs > 1) {
+ if (evt_listener && evt_listener->refs > 1) {
evt_listener->action(evt_listener, pfd);
if (--evt_listener->refs) {
continue;
@@ -11202,6 +11202,7 @@ void *red_worker_main(void *arg)
}
red_printf("freeing event listener");
evt_listener->free(evt_listener);
+ worker.listeners[i] = NULL;
}
}