fix: deadlock in virgl_resource_create_blob, remove Box::leak

BUG 1: virgl_resource_create_blob held device lock while calling
self.gem_create() which internally tries to lock device again.
Rust std::sync::Mutex is not reentrant — guaranteed deadlock.
Fix: release device lock before calling gem_create, using a
scoped block for the has_resource_blob feature check.

BUG 2: Box::leak in atomic_commit error paths converted
dynamically-formatted strings to &'static str at the cost of
a memory leak per error. Replaced with static &str literals.
This commit is contained in:
2026-06-02 15:46:38 +03:00
parent 149d30d840
commit 64fa2c49ef
@@ -902,12 +902,14 @@ impl GpuDriver for VirtioDriver {
fn virgl_resource_create_blob(
&self, blob_mem: u32, blob_flags: u32, blob_id: u64, size: u64,
) -> Result<(GemHandle, u32)> {
let mut device = self
.device
.lock()
.map_err(|_| DriverError::Initialization("VirtIO device state poisoned".into()))?;
if !device.has_resource_blob {
return Err(DriverError::Unsupported("virgl blob resource create"));
{
let device = self
.device
.lock()
.map_err(|_| DriverError::Initialization("VirtIO device state poisoned".into()))?;
if !device.has_resource_blob {
return Err(DriverError::Unsupported("virgl blob resource create"));
}
}
let gem_handle = self.gem_create(size, 0, 0)?;
let resource = self
@@ -916,6 +918,10 @@ impl GpuDriver for VirtioDriver {
.map_err(|_| DriverError::Initialization("VirtIO resource state poisoned".into()))?
.find_by_handle(gem_handle)
.ok_or(DriverError::NotFound(format!("resource for GEM handle {}", gem_handle)))?;
let mut device = self
.device
.lock()
.map_err(|_| DriverError::Initialization("VirtIO device state poisoned".into()))?;
device.resource_create_blob(resource.resource_id, blob_mem, blob_flags, blob_id, size)?;
Ok((gem_handle, resource.resource_id))
}
@@ -1016,14 +1022,14 @@ impl GpuDriver for VirtioDriver {
return Err(DriverError::NotFound(format!("CRTC {}", crtc_id)));
}
AtomicCheckResult::InvalidMode { crtc_id, reason } => {
return Err(DriverError::InvalidArgument(Box::leak(
format!("CRTC {} invalid mode: {}", crtc_id, reason).into_boxed_str(),
)));
return Err(DriverError::InvalidArgument(
"atomic mode validation failed",
));
}
AtomicCheckResult::ClockTooHigh { crtc_id, .. } => {
return Err(DriverError::InvalidArgument(Box::leak(
format!("CRTC {} pixel clock exceeds hardware limit", crtc_id).into_boxed_str(),
)));
return Err(DriverError::InvalidArgument(
"atomic pixel clock exceeds hardware limit",
));
}
AtomicCheckResult::ConnectorDisconnected { connector_id } => {
return Err(DriverError::Initialization(format!(