- remote_driver: Restore special behavior of remoteDomainGetBlockIoTune() (RHEL-22800) - conf: Introduce dynamicMemslots attribute for virtio-mem (RHEL-15316) - qemu_capabilities: Add QEMU_CAPS_DEVICE_VIRTIO_MEM_PCI_DYNAMIC_MEMSLOTS capability (RHEL-15316) - qemu_validate: Check capability for virtio-mem dynamicMemslots (RHEL-15316) - qemu_command: Generate cmd line for virtio-mem dynamicMemslots (RHEL-15316) - qemu_snapshot: fix detection if non-leaf snapshot isn't in active chain (RHEL-23212) - qemu_snapshot: create: refactor external snapshot detection (RHEL-22797) - qemu_snapshot: create: don't require disk-only flag for offline external snapshot (RHEL-22797) - remoteDispatchAuthPolkit: Fix lock ordering deadlock if client closes connection during auth (RHEL-20337) - util: virtportallocator: Add VIR_DEBUG statements for port allocations and release (RHEL-21543) - qemu: migration: Properly handle reservation of manually specified NBD port (RHEL-21543) - qemuMigrationDstStartNBDServer: Refactor cleanup (RHEL-21543) - virPCIVPDResourceIsValidTextValue: Adjust comment to reflect actual code (RHEL-22314) - util: pcivpd: Refactor virPCIVPDResourceIsValidTextValue (RHEL-22314) - virNodeDeviceCapVPDFormatCustom*: Escape unsanitized strings (RHEL-22314) - virNodeDeviceCapVPDFormat: Properly escape system-originated strings (RHEL-22314) - schema: nodedev: Adjust allowed characters in 'vpdFieldValueFormat' (RHEL-22314) - tests: Test the previously mishandled PCI VPD characters (RHEL-22314) - Don't overwrite error message from 'virXPathNodeSet' (RHEL-22314) - tests: virpcivpdtest: Remove 'testVirPCIVPDReadVPDBytes' case (RHEL-22314) - util: virpcivpd: Unexport 'virPCIVPDReadVPDBytes' (RHEL-22314) - util: pcivpd: Unexport virPCIVPDParseVPDLargeResourceFields (RHEL-22314) - tests: virpcivpd: Remove 'testVirPCIVPDParseVPDStringResource' case (RHEL-22314) - util: virpcivpd: Unexport 'virPCIVPDParseVPDLargeResourceString' (RHEL-22314) - virPCIVPDResourceGetKeywordPrefix: Fix logging (RHEL-22314) - util: virpcivpd: Remove return value from virPCIVPDResourceCustomUpsertValue (RHEL-22314) - conf: virNodeDeviceCapVPDParse*: Remove pointless NULL checks (RHEL-22314) - virpcivpdtest: testPCIVPDResourceBasic: Remove tests for uninitialized 'ro'/'rw' section (RHEL-22314) - util: virPCIVPDResourceUpdateKeyword: Remove impossible checks (RHEL-22314) - conf: node_device: Refactor 'virNodeDeviceCapVPDParseCustomFields' to fix error reporting (RHEL-22314) - virNodeDeviceCapVPDParseXML: Fix error reporting (RHEL-22314) - util: virpcivpd: Remove return value from virPCIVPDResourceUpdateKeyword (RHEL-22314) - virPCIDeviceHasVPD: Refactor "debug" messages (RHEL-22314) - virPCIDeviceGetVPD: Fix multiple error handling bugs (RHEL-22314) - virPCIDeviceGetVPD: Handle errors in callers (RHEL-22314) - virPCIVPDReadVPDBytes: Refactor error handling (RHEL-22314) - virPCIVPDParseVPDLargeResourceString: Properly report errors (RHEL-22314) - virPCIVPDParseVPDLargeResourceFields: Merge logic conditions (RHEL-22314) - virPCIVPDParseVPDLargeResourceFields: Remove impossible 'default' switch case (RHEL-22314) - virPCIVPDParseVPDLargeResourceFields: Refactor processing of read data (RHEL-22314) - virPCIVPDParseVPDLargeResourceFields: Refactor return logic (RHEL-22314) - virPCIVPDParseVPDLargeResourceFields: Report proper errors (RHEL-22314) - virPCIVPDParse: Do reasonable error reporting (RHEL-22314) - virt-admin: Add warning when connection to default daemon fails (RHEL-23170) Resolves: RHEL-15316, RHEL-20337, RHEL-21543, RHEL-22314, RHEL-22797 Resolves: RHEL-22800, RHEL-23170, RHEL-23212
143 lines
5.1 KiB
Diff
143 lines
5.1 KiB
Diff
From 1b87b9821afe39c2af5c1893b11cb7f452c61014 Mon Sep 17 00:00:00 2001
|
|
Message-ID: <1b87b9821afe39c2af5c1893b11cb7f452c61014.1707394627.git.jdenemar@redhat.com>
|
|
From: Peter Krempa <pkrempa@redhat.com>
|
|
Date: Wed, 17 Jan 2024 15:55:35 +0100
|
|
Subject: [PATCH] remoteDispatchAuthPolkit: Fix lock ordering deadlock if
|
|
client closes connection during auth
|
|
|
|
Locks in following text:
|
|
A: virNetServer
|
|
B: virNetServerClient
|
|
C: daemonClientPrivate
|
|
|
|
'virNetServerSetClientAuthenticated' locks A then B
|
|
|
|
'remoteDispatchAuthPolkit' calls 'virNetServerSetClientAuthenticated'
|
|
while holding C.
|
|
|
|
If a client closes its connection 'virNetServerProcessClients' with the
|
|
lock A and B locked will call 'virNetServerClientCloseLocked' which will
|
|
try to dispose of the 'client' private data by:
|
|
|
|
ref(b);
|
|
unlock(b);
|
|
remoteClientFreePrivateCallbacks();
|
|
lock(b);
|
|
unref(b);
|
|
|
|
Unfortunately remoteClientFreePrivateCallbacks() tries lock C.
|
|
|
|
Thus the locks are held in the following order:
|
|
|
|
polkit auth: C -> A
|
|
connection close: A -> C
|
|
|
|
causing a textbook-example deadlock. To resolve it we can simply drop
|
|
lock 'C' before calling 'virNetServerSetClientAuthenticated' as the lock
|
|
is not needed any more.
|
|
|
|
Resolves: https://issues.redhat.com/browse/RHEL-20337
|
|
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
|
|
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
|
|
(cherry picked from commit c697aff8a1b5542d51c0b4a10046ad37089d12d5)
|
|
---
|
|
src/remote/remote_daemon_dispatch.c | 76 +++++++++++++++--------------
|
|
1 file changed, 39 insertions(+), 37 deletions(-)
|
|
|
|
diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c
|
|
index 7daf503b51..aaabd1e56c 100644
|
|
--- a/src/remote/remote_daemon_dispatch.c
|
|
+++ b/src/remote/remote_daemon_dispatch.c
|
|
@@ -3979,50 +3979,52 @@ remoteDispatchAuthPolkit(virNetServer *server,
|
|
struct daemonClientPrivate *priv =
|
|
virNetServerClientGetPrivateData(client);
|
|
int rv;
|
|
- VIR_LOCK_GUARD lock = virLockGuardLock(&priv->lock);
|
|
-
|
|
- action = virNetServerClientGetReadonly(client) ?
|
|
- "org.libvirt.unix.monitor" :
|
|
- "org.libvirt.unix.manage";
|
|
|
|
- VIR_DEBUG("Start PolicyKit auth %d", virNetServerClientGetFD(client));
|
|
- if (virNetServerClientGetAuth(client) != VIR_NET_SERVER_SERVICE_AUTH_POLKIT) {
|
|
- VIR_ERROR(_("client tried invalid PolicyKit init request"));
|
|
- goto authfail;
|
|
- }
|
|
+ VIR_WITH_MUTEX_LOCK_GUARD(&priv->lock) {
|
|
+ action = virNetServerClientGetReadonly(client) ?
|
|
+ "org.libvirt.unix.monitor" :
|
|
+ "org.libvirt.unix.manage";
|
|
|
|
- if (virNetServerClientGetUNIXIdentity(client, &callerUid, &callerGid,
|
|
- &callerPid, ×tamp) < 0) {
|
|
- goto authfail;
|
|
- }
|
|
+ VIR_DEBUG("Start PolicyKit auth %d", virNetServerClientGetFD(client));
|
|
+ if (virNetServerClientGetAuth(client) != VIR_NET_SERVER_SERVICE_AUTH_POLKIT) {
|
|
+ VIR_ERROR(_("client tried invalid PolicyKit init request"));
|
|
+ goto authfail;
|
|
+ }
|
|
|
|
- if (timestamp == 0) {
|
|
- VIR_WARN("Failing polkit auth due to missing client (pid=%lld) start time",
|
|
- (long long)callerPid);
|
|
- goto authfail;
|
|
- }
|
|
+ if (virNetServerClientGetUNIXIdentity(client, &callerUid, &callerGid,
|
|
+ &callerPid, ×tamp) < 0) {
|
|
+ goto authfail;
|
|
+ }
|
|
|
|
- VIR_INFO("Checking PID %lld running as %d",
|
|
- (long long) callerPid, callerUid);
|
|
+ if (timestamp == 0) {
|
|
+ VIR_WARN("Failing polkit auth due to missing client (pid=%lld) start time",
|
|
+ (long long)callerPid);
|
|
+ goto authfail;
|
|
+ }
|
|
|
|
- rv = virPolkitCheckAuth(action,
|
|
- callerPid,
|
|
- timestamp,
|
|
- callerUid,
|
|
- NULL,
|
|
- true);
|
|
- if (rv == -1)
|
|
- goto authfail;
|
|
- else if (rv == -2)
|
|
- goto authdeny;
|
|
+ VIR_INFO("Checking PID %lld running as %d",
|
|
+ (long long) callerPid, callerUid);
|
|
|
|
- PROBE(RPC_SERVER_CLIENT_AUTH_ALLOW,
|
|
- "client=%p auth=%d identity=%s",
|
|
- client, REMOTE_AUTH_POLKIT, ident);
|
|
- VIR_INFO("Policy allowed action %s from pid %lld, uid %d",
|
|
- action, (long long) callerPid, callerUid);
|
|
- ret->complete = 1;
|
|
+ rv = virPolkitCheckAuth(action,
|
|
+ callerPid,
|
|
+ timestamp,
|
|
+ callerUid,
|
|
+ NULL,
|
|
+ true);
|
|
+ if (rv == -1)
|
|
+ goto authfail;
|
|
+ else if (rv == -2)
|
|
+ goto authdeny;
|
|
+
|
|
+ PROBE(RPC_SERVER_CLIENT_AUTH_ALLOW,
|
|
+ "client=%p auth=%d identity=%s",
|
|
+ client, REMOTE_AUTH_POLKIT, ident);
|
|
+ VIR_INFO("Policy allowed action %s from pid %lld, uid %d",
|
|
+ action, (long long) callerPid, callerUid);
|
|
+ ret->complete = 1;
|
|
+ }
|
|
|
|
+ /* this must be called with the private data mutex unlocked */
|
|
virNetServerSetClientAuthenticated(server, client);
|
|
return 0;
|
|
|
|
--
|
|
2.43.0
|