Shared memory is a powerful and efficient method of IPC, but there are ways to make it more secure.
- Traditionally, the way to gain access to a shared memory object is to open it via a publicly known path, by calling
the POSIX
shm_open()
function.
Sharing a path is difficult because of the variable length of pathnames, and it's hard to do securely
because the shared memory object resides in the global path space and could be interfered with by processes
that aren't meant to access it.
- Processes other than the creator of the shared memory object might be able to use
shm_ctl()
to modify the size, backing memory, or flags associated with the object.
- Traditionally, once a process was given the right to map a shared memory object, there was nothing that
the object's creator could do to force the other process to unmap it or stop accessing it.
For example, there could be a protocol between a client and a resource manager where the client would tell the
resource manager that it's done with the object, but nothing ensures that it actually unmaps the object.
- If a process wants to grant access to its shared memory objects to another process, it might have to use
mmap_peer(),
which requires coordination between the processes to avoid unexpected changes to the processes' address spaces.
In order to address these issues, QNX Neutrino supports the following:
- a way to create
an anonymous shared memory object
that doesn't appear in the pathname space
- shared memory handles
that let you share buffers among processes without using public pathnames
- a way for the creator of a shared memory object to
seal a shared memory object
to prevent other processes
from changing the physical layout of the object, even if these processes are allowed to change the object's contents
- a way for the creator of a shared memory object to
revoke access to the object
such that it can be safely destroyed or reused for other purposes.
Without the revocable flag, a shared memory object is cleaned up only when the last process removes a mapping
to it, which means that the creator has no control over destruction and reuse.
- an enhanced
mmap()
protocol between the memory manager and a resource manager
that allows the resource manager to respond to a mmap()
call by specifying a shared memory object and an offset that the client should be mapping.
This protocol should eliminate many of the use cases for mmap_peer(),
especially with direct physical addresses.
For more information, see
Handling mmap() messages
in the Handling Other Messages chapter of Writing a Resource Manager.
We'll describe these features in the sections that follow, and then demonstrate
how to use these features together
to get the most security.