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" |