@@ -110,11 +110,21 @@ impl VsockVq {
110110 /// Returns `Some(RxPermit)` if a descriptor chain is available,
111111 /// `None` if the rx queue is full.
112112 pub fn try_rx_permit ( & mut self ) -> Option < RxPermit < ' _ > > {
113+ let vq = self . queues . get ( VSOCK_RX_QUEUE as usize ) ?;
114+ // See propolis#1110 & propolis#1115
115+ // If propolis-server has started the vsock device but a different
116+ // device has encountered an error at startup there's a good chance
117+ // we attempt to access guest memory and panic. A way of preventing
118+ // us from doing that is to first check if the virtqueue is alive. A
119+ // virtqueue only becomes alive once a guest vCPU has ran.
120+ if !vq. is_alive ( ) {
121+ return None ;
122+ }
123+
113124 // Reuse cached chain or pop a new one
114125 if self . rx_chain . is_none ( ) {
115126 // TODO: cannot access memory?
116127 let mem = self . acc_mem . access ( ) . expect ( "mem access for write" ) ;
117- let vq = self . queues . get ( VSOCK_RX_QUEUE as usize ) ?;
118128 let mut chain = Chain :: with_capacity ( 10 ) ;
119129 if let Some ( _) = vq. pop_avail ( & mut chain, & mem) {
120130 self . rx_chain = Some ( chain) ;
@@ -201,7 +211,7 @@ impl PciVirtioSock {
201211 ) ;
202212 let port_mappings = port_mappings. into_iter ( ) . collect ( ) ;
203213
204- let backend = VsockProxy :: new ( cid , vvq , log , port_mappings) ;
214+ let backend = VsockProxy :: new ( log , cid , vvq , port_mappings) ;
205215
206216 Arc :: new ( Self { cid, backend, virtio_state, pci_state } )
207217 }
@@ -262,6 +272,10 @@ impl Lifecycle for PciVirtioSock {
262272 fn type_name ( & self ) -> & ' static str {
263273 "pci-virtio-socket"
264274 }
275+ fn start ( & self ) -> Result < ( ) , anyhow:: Error > {
276+ self . backend . start ( ) ;
277+ Ok ( ( ) )
278+ }
265279 fn pause ( & self ) {
266280 let _ = self . backend . pause ( ) ;
267281 self . backend . wait_stopped ( ) ;
0 commit comments