diff --git a/src/firecracker/src/api_server/request/snapshot.rs b/src/firecracker/src/api_server/request/snapshot.rs
index 4a96292d1..df6600603 100644
--- a/src/firecracker/src/api_server/request/snapshot.rs
+++ b/src/firecracker/src/api_server/request/snapshot.rs
@@ -96,6 +96,7 @@ fn parse_put_snapshot_load(body: &Body) -> Result<ParsedRequest, RequestError> {
                 // either `mem_file_path` or `mem_backend` field is always specified.
                 backend_path: snapshot_config.mem_file_path.unwrap(),
                 backend_type: MemBackendType::File,
+                shared: false,
             }
         }
     };
@@ -179,6 +180,7 @@ mod tests {
             mem_backend: MemBackendConfig {
                 backend_path: PathBuf::from("bar"),
                 backend_type: MemBackendType::File,
+                shared: false,
             },
             enable_diff_snapshots: false,
             resume_vm: false,
@@ -209,6 +211,7 @@ mod tests {
             mem_backend: MemBackendConfig {
                 backend_path: PathBuf::from("bar"),
                 backend_type: MemBackendType::File,
+                shared: false,
             },
             enable_diff_snapshots: true,
             resume_vm: false,
@@ -239,6 +242,7 @@ mod tests {
             mem_backend: MemBackendConfig {
                 backend_path: PathBuf::from("bar"),
                 backend_type: MemBackendType::Uffd,
+                shared: false,
             },
             enable_diff_snapshots: false,
             resume_vm: true,
@@ -275,6 +279,7 @@ mod tests {
             mem_backend: MemBackendConfig {
                 backend_path: PathBuf::from("bar"),
                 backend_type: MemBackendType::Uffd,
+                shared: false,
             },
             enable_diff_snapshots: false,
             resume_vm: true,
@@ -305,6 +310,7 @@ mod tests {
             mem_backend: MemBackendConfig {
                 backend_path: PathBuf::from("bar"),
                 backend_type: MemBackendType::File,
+                shared: false,
             },
             enable_diff_snapshots: false,
             resume_vm: true,
diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs
index aeacadeb6..5ddcc1dc4 100644
--- a/src/vmm/src/persist.rs
+++ b/src/vmm/src/persist.rs
@@ -384,8 +384,13 @@ pub fn restore_from_snapshot(
                 .into());
             }
             (
-                guest_memory_from_file(mem_backend_path, mem_state, track_dirty_pages)
-                    .map_err(RestoreFromSnapshotGuestMemoryError::File)?,
+                guest_memory_from_file(
+                    mem_backend_path,
+                    mem_state,
+                    track_dirty_pages,
+                    params.mem_backend.shared,
+                )
+                .map_err(RestoreFromSnapshotGuestMemoryError::File)?,
                 None,
             )
         }
@@ -451,9 +456,15 @@ fn guest_memory_from_file(
     mem_file_path: &Path,
     mem_state: &GuestMemoryState,
     track_dirty_pages: bool,
+    shared: bool,
 ) -> Result<Vec<GuestRegionMmap>, GuestMemoryFromFileError> {
-    let mem_file = File::open(mem_file_path)?;
-    let guest_mem = memory::snapshot_file(mem_file, mem_state.regions(), track_dirty_pages)?;
+    let mem_file = if shared {
+        OpenOptions::new().read(true).write(true).open(mem_file_path)?
+    } else {
+        File::open(mem_file_path)?
+    };
+    let guest_mem =
+        memory::snapshot_file(mem_file, mem_state.regions(), track_dirty_pages, shared)?;
     Ok(guest_mem)
 }
 
diff --git a/src/vmm/src/vmm_config/snapshot.rs b/src/vmm/src/vmm_config/snapshot.rs
index 27a7841d5..9796daaf9 100644
--- a/src/vmm/src/vmm_config/snapshot.rs
+++ b/src/vmm/src/vmm_config/snapshot.rs
@@ -107,6 +107,16 @@ pub struct MemBackendConfig {
     pub backend_path: PathBuf,
     /// Specifies the guest memory backend type.
     pub backend_type: MemBackendType,
+    /// If `true` and `backend_type == File`, mmap the backing file with
+    /// `MAP_SHARED` instead of the default `MAP_PRIVATE`. Enables
+    /// cooperative-snapshot tooling: an external process that holds
+    /// the backing memfd open via `/proc/<pid>/fd/<N>` can observe
+    /// guest writes through its own mmap of the same fd.
+    ///
+    /// Defaults to `false` (unchanged behavior). Ignored for the
+    /// `Uffd` backend.
+    #[serde(default)]
+    pub shared: bool,
 }
 
 /// The microVM state options.
diff --git a/src/vmm/src/vstate/memory.rs b/src/vmm/src/vstate/memory.rs
index 19367f7f9..390f1d7e3 100644
--- a/src/vmm/src/vstate/memory.rs
+++ b/src/vmm/src/vstate/memory.rs
@@ -124,12 +124,24 @@ pub fn anonymous(
 
 /// Creates a GuestMemoryMmap given a `file` containing the data
 /// and a `state` containing mapping information.
+///
+/// When `shared` is `true`, the file is mapped with `MAP_SHARED`
+/// instead of the default `MAP_PRIVATE`. This is opt-in for
+/// cooperative-snapshot tooling that needs an external process
+/// (holding the same backing fd open) to observe guest writes.
+/// Existing callers pass `shared=false` and get unchanged behavior.
 pub fn snapshot_file(
     file: File,
     regions: impl Iterator<Item = (GuestAddress, usize)>,
     track_dirty_pages: bool,
+    shared: bool,
 ) -> Result<Vec<GuestRegionMmap>, MemoryError> {
-    create(regions, libc::MAP_PRIVATE, Some(file), track_dirty_pages)
+    let mmap_flags = if shared {
+        libc::MAP_SHARED
+    } else {
+        libc::MAP_PRIVATE
+    };
+    create(regions, mmap_flags, Some(file), track_dirty_pages)
 }
 
 /// Defines the interface for snapshotting memory.
