diff options
| -rw-r--r-- | recipes-extended/libvirt/libvirt/lxc_monitor-Avoid-AB-BA-lock-race.patch | 106 | ||||
| -rw-r--r-- | recipes-extended/libvirt/libvirt_4.7.0.bb | 1 |
2 files changed, 107 insertions, 0 deletions
diff --git a/recipes-extended/libvirt/libvirt/lxc_monitor-Avoid-AB-BA-lock-race.patch b/recipes-extended/libvirt/libvirt/lxc_monitor-Avoid-AB-BA-lock-race.patch new file mode 100644 index 00000000..fc3880fb --- /dev/null +++ b/recipes-extended/libvirt/libvirt/lxc_monitor-Avoid-AB-BA-lock-race.patch | |||
| @@ -0,0 +1,106 @@ | |||
| 1 | From 7882c6eca53fe9abe253497a50f6c5ae062176d3 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Mark Asselstine <mark.asselstine@windriver.com> | ||
| 3 | Date: Mon, 24 Sep 2018 11:11:35 -0400 | ||
| 4 | Subject: [PATCH] lxc_monitor: Avoid AB / BA lock race | ||
| 5 | |||
| 6 | A deadlock situation can occur when autostarting a LXC domain 'guest' | ||
| 7 | due to two threads attempting to take opposing locks while holding | ||
| 8 | opposing locks (AB BA problem). Thread A takes and holds the 'vm' lock | ||
| 9 | while attempting to take the 'client' lock, meanwhile, thread B takes | ||
| 10 | and holds the 'client' lock while attempting to take the 'vm' lock. | ||
| 11 | |||
| 12 | The potential for this can be seen as follows: | ||
| 13 | |||
| 14 | Thread A: | ||
| 15 | virLXCProcessAutostartDomain (takes vm lock) | ||
| 16 | --> virLXCProcessStart | ||
| 17 | --> virLXCProcessConnectMonitor | ||
| 18 | --> virLXCMonitorNew | ||
| 19 | --> virNetClientSetCloseCallback (wants client lock) | ||
| 20 | |||
| 21 | Thread B: | ||
| 22 | virNetClientIncomingEvent (takes client lock) | ||
| 23 | --> virNetClientIOHandleInput | ||
| 24 | --> virNetClientCallDispatch | ||
| 25 | --> virNetClientCallDispatchMessage | ||
| 26 | --> virNetClientProgramDispatch | ||
| 27 | --> virLXCMonitorHandleEventInit | ||
| 28 | --> virLXCProcessMonitorInitNotify (wants vm lock) | ||
| 29 | |||
| 30 | Since these threads are scheduled independently and are preemptible it | ||
| 31 | is possible for the deadlock scenario to occur where each thread locks | ||
| 32 | their first lock but both will fail to get their second lock and just | ||
| 33 | spin forever. You get something like: | ||
| 34 | |||
| 35 | virLXCProcessAutostartDomain (takes vm lock) | ||
| 36 | --> virLXCProcessStart | ||
| 37 | --> virLXCProcessConnectMonitor | ||
| 38 | --> virLXCMonitorNew | ||
| 39 | <...> | ||
| 40 | virNetClientIncomingEvent (takes client lock) | ||
| 41 | --> virNetClientIOHandleInput | ||
| 42 | --> virNetClientCallDispatch | ||
| 43 | --> virNetClientCallDispatchMessage | ||
| 44 | --> virNetClientProgramDispatch | ||
| 45 | --> virLXCMonitorHandleEventInit | ||
| 46 | --> virLXCProcessMonitorInitNotify (wants vm lock but spins) | ||
| 47 | <...> | ||
| 48 | --> virNetClientSetCloseCallback (wants client lock but spins) | ||
| 49 | |||
| 50 | Neither thread ever gets the lock it needs to be able to continue | ||
| 51 | while holding the lock that the other thread needs. | ||
| 52 | |||
| 53 | The actual window for preemption which can cause this deadlock is | ||
| 54 | rather small, between the calls to virNetClientProgramNew() and | ||
| 55 | execution of virNetClientSetCloseCallback(), both in | ||
| 56 | virLXCMonitorNew(). But it can be seen in real world use that this | ||
| 57 | small window is enough. | ||
| 58 | |||
| 59 | By moving the call to virNetClientSetCloseCallback() ahead of | ||
| 60 | virNetClientProgramNew() we can close any possible chance of the | ||
| 61 | deadlock taking place. There should be no other implications to the | ||
| 62 | move since the close callback (in the unlikely event was called) will | ||
| 63 | spin on the vm lock. The remaining work that takes place between the | ||
| 64 | old call location of virNetClientSetCloseCallback() and the new | ||
| 65 | location is unaffected by the move. | ||
| 66 | |||
| 67 | Upstream-Status: Backport commit 7882c6eca53f | ||
| 68 | |||
| 69 | Signed-off-by: Mark Asselstine <mark.asselstine@windriver.com> | ||
| 70 | Signed-off-by: Michal Privoznik <mprivozn@redhat.com> | ||
| 71 | --- | ||
| 72 | src/lxc/lxc_monitor.c | 11 +++++++---- | ||
| 73 | 1 file changed, 7 insertions(+), 4 deletions(-) | ||
| 74 | |||
| 75 | diff --git a/src/lxc/lxc_monitor.c b/src/lxc/lxc_monitor.c | ||
| 76 | index e765c16..0b18a14 100644 | ||
| 77 | --- a/src/lxc/lxc_monitor.c | ||
| 78 | +++ b/src/lxc/lxc_monitor.c | ||
| 79 | @@ -161,6 +161,13 @@ virLXCMonitorPtr virLXCMonitorNew(virDomainObjPtr vm, | ||
| 80 | if (virNetClientRegisterAsyncIO(mon->client) < 0) | ||
| 81 | goto error; | ||
| 82 | |||
| 83 | + /* avoid deadlock by making this call before assigning virLXCMonitorEvents */ | ||
| 84 | + virNetClientSetCloseCallback(mon->client, virLXCMonitorEOFNotify, mon, | ||
| 85 | + virLXCMonitorCloseFreeCallback); | ||
| 86 | + | ||
| 87 | + /* close callback now has its own reference */ | ||
| 88 | + virObjectRef(mon); | ||
| 89 | + | ||
| 90 | if (!(mon->program = virNetClientProgramNew(VIR_LXC_MONITOR_PROGRAM, | ||
| 91 | VIR_LXC_MONITOR_PROGRAM_VERSION, | ||
| 92 | virLXCMonitorEvents, | ||
| 93 | @@ -175,10 +182,6 @@ virLXCMonitorPtr virLXCMonitorNew(virDomainObjPtr vm, | ||
| 94 | mon->vm = virObjectRef(vm); | ||
| 95 | memcpy(&mon->cb, cb, sizeof(mon->cb)); | ||
| 96 | |||
| 97 | - virObjectRef(mon); | ||
| 98 | - virNetClientSetCloseCallback(mon->client, virLXCMonitorEOFNotify, mon, | ||
| 99 | - virLXCMonitorCloseFreeCallback); | ||
| 100 | - | ||
| 101 | cleanup: | ||
| 102 | VIR_FREE(sockpath); | ||
| 103 | return mon; | ||
| 104 | -- | ||
| 105 | 2.7.4 | ||
| 106 | |||
diff --git a/recipes-extended/libvirt/libvirt_4.7.0.bb b/recipes-extended/libvirt/libvirt_4.7.0.bb index 14565dae..47275ae6 100644 --- a/recipes-extended/libvirt/libvirt_4.7.0.bb +++ b/recipes-extended/libvirt/libvirt_4.7.0.bb | |||
| @@ -35,6 +35,7 @@ SRC_URI = "http://libvirt.org/sources/libvirt-${PV}.tar.xz;name=libvirt \ | |||
| 35 | file://install-missing-file.patch \ | 35 | file://install-missing-file.patch \ |
| 36 | file://0001-ptest-Remove-Windows-1252-check-from-esxutilstest.patch \ | 36 | file://0001-ptest-Remove-Windows-1252-check-from-esxutilstest.patch \ |
| 37 | file://configure.ac-search-for-rpc-rpc.h-in-the-sysroot.patch \ | 37 | file://configure.ac-search-for-rpc-rpc.h-in-the-sysroot.patch \ |
| 38 | file://lxc_monitor-Avoid-AB-BA-lock-race.patch \ | ||
| 38 | " | 39 | " |
| 39 | 40 | ||
| 40 | SRC_URI[libvirt.md5sum] = "38da6c33250dcbc0a6d68de5c758262b" | 41 | SRC_URI[libvirt.md5sum] = "38da6c33250dcbc0a6d68de5c758262b" |
