shm_create_handle()

Updated: April 19, 2023

Create a handle so a specific process can access a shared memory object

Synopsis:

#include <fcntl.h>
#include <sys/mman.h>

int shm_create_handle( int fd, 
                       pid_t pid, 
                       int flags,
                       shm_handle_t* handlep,
                       unsigned options );

Arguments:

fd
The file descriptor for the shared object. This file descriptor can be created first by open(), shm_open(), or shm_open_handle().
pid
The ID of the process that you want to access the shared object.
flags
You must specify exactly one of the following file access modes (defined in <fcntl.h>) in the value of flags:
  • O_RDONLY — open for read access only.
  • O_RDWR — open for read and write access.
  • O_WRONLY — open for write access only.
Note:

For the function call to succeed, the flags must specify an access mode that's as privileged as or less privileged than the mode specified when the file descriptor in fd was created; for details, see the shm_open() description.

Setting a more privileged access mode or any flags other than the ones listed above causes the function call to fail.

handlep
A pointer to a location for storing the handle to the shared object.
options
A bitmask configuring options for the shared object. Currently, the only supported flag is:
  • SHM_CREATE_HANDLE_OPT_NOFD — prevent the shared memory object handle from being converted to a file descriptor using shm_open_handle(). This improves security because the creator can share an object with a recipient process in such a way that prevents the recipient from accessing the object after the creator revokes its access to it. This flag is meant to be used after setting the SHMCTL_REVOCABLE flag on the object via shm_ctl(), and before giving the handle to the recipient so it can use the object until the creator calls shm_revoke() to revoke its access.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

The shm_create_handle() function takes a file descriptor (fd) for a shared memory object and returns a unique single-use handle for it. The handle can be used only once, and only by the process specified by pid to access the object in a mode that's as privileged as or less privileged than what's indicated in flags. For example, if flags is set to O_RDWR when creating the handle, the recipient process can open the object (using shm_open_handle()) with O_RDWR, O_RDONLY, or O_WRONLY access. But if flags is set to O_RDONLY, the recipient can open the object with O_RDONLY access but not O_RDWR or O_WRONLY access.

Alert: If a handle created with O_WRONLY permissions is subsequently mapped by a recipient process (using PROT_WRITE, since the handle was created with O_WRONLY), that process may be able to read the shared memory object. That's because, on some architectures, PROT_WRITE also implies PROT_READ.

The shm_create_handle() function provides a means for one process to provide another with access to a shared memory object without having to share a path. Sharing a path is difficult because of the variable length of pathnames, and is 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.

For the steps to follow when using shm_revoke() and handles for shared memory objects, see Secure buffer management in the “Shared Memory” chapter of the QNX Neutrino Programmer's Guide.

For an example of how a server can create a shared memory object handle and provide it to a client so it can access the object from its own process, see below.

Returns:

0 on success, or -1 if an error occurred (errno is set).

Errors:

EACCES
Permission to create the handle is denied because the access modes specified by flags are denied.
EBADF
The specified file descriptor does not exist.
EINVAL
An illegal flag, meaning a flag other than one indicating the access mode, was given in flags (see the parameter description).
ENOMEM
There's insufficient memory to create a shared object handle.
ESRCH
The process ID in pid is invalid.

Example:

int shm_fd;
int chid, rcvid;
// Your application will likely have its own data structure for representing messages
// received from clients.
mymsg_t msg;
shm_handle_t handle = 0;
struct _msg_info info;
void* ptr;
	
// Create a shared memory object and truncate its size.
shm_fd = shm_open(SHM_ANON, O_RDWR | O_CREAT | O_TRUNC, 0600); 
ftruncate(shm_fd, __PAGESIZE);

// Map the memory object into our own address space.
ptr = mmap(0, __PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
// Populate the shared memory.
snprintf(ptr, __PAGESIZE, "Hello from %d", getpid());

// Create a channel to receive client messages.
chid = ChannelCreate(0);

// Wait for a message from the client.
rcvid = MsgReceive(chid, &msg, sizeof(msg), &info);

// Create a client-specific, read-only handle for the object.
shm_create_handle(shm_fd, info.pid, O_RDONLY, &handle, 0);

// Tell the client about the handle.
MsgReply(rcvid, 0, &handle, sizeof(handle));

Classification:

QNX Neutrino

Safety:  
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes