]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix possible NULL pointer dereference in GetNamedDSMSegment().
authorNathan Bossart <nathan@postgresql.org>
Tue, 23 Jan 2024 02:44:38 +0000 (20:44 -0600)
committerNathan Bossart <nathan@postgresql.org>
Tue, 23 Jan 2024 02:44:38 +0000 (20:44 -0600)
GetNamedDSMSegment() doesn't check whether dsm_attach() returns
NULL, which creates the possibility of a NULL pointer dereference
soon after.  To fix, emit an ERROR if dsm_attach() returns NULL.
This shouldn't happen, but it would be nice to avoid a segfault if
it does.  In passing, tidy up the surrounding code.

Reported-by: Tom Lane
Reviewed-by: Michael Paquier, Bharath Rupireddy
Discussion: https://postgr.es/m/3348869.1705854106%40sss.pgh.pa.us

src/backend/storage/ipc/dsm_registry.c

index ac11f51375e764a3f601c37233ed2a285ce60584..c17817365325bec99727df9a3b6def1b938cc83f 100644 (file)
@@ -177,19 +177,22 @@ GetNamedDSMSegment(const char *name, size_t size,
                                (errmsg("requested DSM segment size does not match size of "
                                                "existing segment")));
        }
-       else if (!dsm_find_mapping(entry->handle))
+       else
        {
-               /* Attach to existing segment. */
-               dsm_segment *seg = dsm_attach(entry->handle);
+               dsm_segment *seg = dsm_find_mapping(entry->handle);
+
+               /* If the existing segment is not already attached, attach it now. */
+               if (seg == NULL)
+               {
+                       seg = dsm_attach(entry->handle);
+                       if (seg == NULL)
+                               elog(ERROR, "could not map dynamic shared memory segment");
+
+                       dsm_pin_mapping(seg);
+               }
 
-               dsm_pin_mapping(seg);
                ret = dsm_segment_address(seg);
        }
-       else
-       {
-               /* Return address of an already-attached segment. */
-               ret = dsm_segment_address(dsm_find_mapping(entry->handle));
-       }
 
        dshash_release_lock(dsm_registry_table, entry);
        MemoryContextSwitchTo(oldcontext);