@@ -56,6 +56,13 @@ struct oo_dshm_buffer {
5656};
5757
5858
59+ /* Linked list node for tracking users of a dshm segment */
60+ struct oo_dshm_list {
61+ struct oo_dshm_buffer * buffer ;
62+ struct oo_dshm_list * next ;
63+ };
64+ 65+ 5966static inline int /* bool */
6067validate_shm_class (ci_int32 shm_class )
6168{
@@ -248,11 +255,26 @@ oo_dshm_free_handle_list(ci_dllist* list)
248255}
249256
250257
258+ int oo_dshm_free_used (struct oo_dshm_list * head )
259+ {
260+ /* We don't need to hold the oo_dshm_state.lock here as this list is local to
261+ * this file and if we are shutting down, then we shouldn't be in a context
262+ * that allows new memory maps to be created. */
263+ while ( head ) {
264+ struct oo_dshm_list * next = head -> next ;
265+ dshm_release (head -> buffer );
266+ vfree (head );
267+ head = next ;
268+ }
269+ 270+ return 0 ;
271+ }
272+ 251273
252274#ifdef OO_MMAP_TYPE_DSHM
253275/* Maps a dshm segment into a process's address space. */
254276int
255- oo_dshm_mmap_impl (struct vm_area_struct * vma )
277+ oo_dshm_mmap_impl (struct vm_area_struct * vma , struct oo_dshm_list * * used_head )
256278{
257279 ci_uint64 map_id = OO_MMAP_OFFSET_TO_MAP_ID (VMA_OFFSET (vma ));
258280 ci_int32 buffer_id = OO_MMAP_DSHM_BUFFER_ID (map_id );
@@ -293,8 +315,27 @@ oo_dshm_mmap_impl(struct vm_area_struct* vma)
293315 */
294316 ci_uint32 num_pages = CI_MIN ((unsigned long )buffer -> num_pages ,
295317 map_length >> PAGE_SHIFT );
318+ struct oo_dshm_list * dshm_node ;
296319 ci_uint32 i ;
297- for ( i = 0 , rc = 0 ; i < num_pages && rc == 0 ; ++ i ) {
320+ 321+ /* Reset rc, to allow the remapping loop to start unless we encounter
322+ * another error before we reach that point. */
323+ rc = 0 ;
324+ 325+ dshm_node = vmalloc (sizeof (* dshm_node ));
326+ if ( dshm_node == NULL ) {
327+ OO_DEBUG_SHM (ci_log ("%s: unable to allocate memory to track dshm" ,
328+ __FUNCTION__ ));
329+ /* Setting rc != 0 here will skip the remapping loop below */
330+ rc = - ENOMEM ;
331+ dshm_release (buffer );
332+ } else {
333+ dshm_node -> buffer = buffer ;
334+ dshm_node -> next = * used_head ;
335+ * used_head = dshm_node ;
336+ }
337+ 338+ for ( i = 0 ; i < num_pages && rc == 0 ; ++ i ) {
298339 /* vm_insert_page() would have been simpler (and allow core dumps to
299340 * capture these pages), but it fails with anonymous pages */
300341 rc = remap_pfn_range (vma ,
@@ -307,8 +348,8 @@ oo_dshm_mmap_impl(struct vm_area_struct* vma)
307348 OO_DEBUG_SHM (ci_log ("%s: can't map buffer owned by %u" , __FUNCTION__ ,
308349 buffer -> owner_euid ));
309350 rc = - EACCES ;
351+ dshm_release (buffer );
310352 }
311- dshm_release (buffer );
312353 }
313354
314355 return rc ;
0 commit comments