Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ disclosure policy. Please visit our [Product Security Incident Response Team
(PSIRT)](https://www.nvidia.com/en-us/security/psirt-policies/) policies page for more
information.

## CUDA IPC and Python serialization

`cuda.core.Buffer` objects allocated from IPC-enabled memory resources can be
pickled for transfer between same-host processes. Unpickling performs an IPC
memory import using the embedded `IPCBufferDescriptor`. Only unpickle buffers
(and call `Buffer.from_ipc_descriptor`) with descriptors from trusted peers;
malicious descriptors can trigger invalid memory operations.

When sharing CUDA objects across processes, use `multiprocessing` with the
`spawn` start method.

## NVIDIA Product Security

For all security-related concerns, please visit NVIDIA's Product Security portal at
Expand Down
13 changes: 13 additions & 0 deletions cuda_core/cuda/core/_memory/_buffer.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ class Buffer:
allocations.

Support for data interchange mechanisms are provided by DLPack.

Note
----
Pickling an IPC-enabled :class:`Buffer` embeds an
:class:`~_memory.IPCBufferDescriptor`. Unpickling reconstructs the buffer
by calling :meth:`from_ipc_descriptor` and therefore performs an IPC
import. Do not unpickle buffers from untrusted sources.
"""

def __cinit__(self) -> None:
Expand Down Expand Up @@ -85,6 +92,12 @@ class Buffer:
stream : :obj:`~_stream.Stream`
Keyword-only. The stream used for asynchronous deallocation when
the buffer is closed or garbage collected.

Note
----
The descriptor payload and ``size`` are supplied by the exporting peer
and must be treated as untrusted input unless the peer is known to be
cooperating.
"""

@property
Expand Down
15 changes: 15 additions & 0 deletions cuda_core/cuda/core/_memory/_buffer.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ cdef class Buffer:
allocations.

Support for data interchange mechanisms are provided by DLPack.

Note
----
Pickling an IPC-enabled :class:`Buffer` embeds an
:class:`~_memory.IPCBufferDescriptor`. Unpickling reconstructs the buffer
by calling :meth:`from_ipc_descriptor` and therefore performs an IPC
import. Do not unpickle buffers from untrusted sources.
"""
def __cinit__(self) -> None:
self._clear()
Expand Down Expand Up @@ -138,6 +145,8 @@ cdef class Buffer:
return Buffer.from_ipc_descriptor(mr, ipc_descriptor, stream=default_stream())

def __reduce__(self) -> tuple[object, ...]:
# Unpickling performs a live CUDA IPC import from descriptor bytes in the
# pickle stream. Only deserialize Buffers from a trusted principal.
# Must not serialize the parent's stream!
return Buffer._reduce_helper, (self.memory_resource, self.ipc_descriptor)

Expand Down Expand Up @@ -187,6 +196,12 @@ cdef class Buffer:
stream : :obj:`~_stream.Stream`
Keyword-only. The stream used for asynchronous deallocation when
the buffer is closed or garbage collected.

Note
----
The descriptor payload and ``size`` are supplied by the exporting peer
and must be treated as untrusted input unless the peer is known to be
cooperating.
"""
return _ipc.Buffer_from_ipc_descriptor(cls, mr, ipc_descriptor, stream)

Expand Down
11 changes: 10 additions & 1 deletion cuda_core/cuda/core/_memory/_device_memory_resource.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,16 @@ class DeviceMemoryResource(_MemPool):
an MMR is created and registered in the receiving process. Subsequently,
buffers may be serialized and transferred using ordinary :mod:`pickle`
methods. The reconstruction procedure uses the registry to find the
associated MMR.
associated MMR. Unpickling a :class:`Buffer` performs an IPC import from
the embedded descriptor; only unpickle buffers received from trusted peers.

Warning
-------
IPC descriptors and pickled buffers cross a trust boundary between
cooperating same-host processes. A malicious peer can supply crafted
descriptor fields. Use :meth:`Buffer.from_ipc_descriptor` only with
descriptors from trusted peers, and do not unpickle buffers from
untrusted sources.
"""

def __cinit__(self, *args, **kwargs) -> None:
Expand Down
11 changes: 10 additions & 1 deletion cuda_core/cuda/core/_memory/_device_memory_resource.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,16 @@ cdef class DeviceMemoryResource(_MemPool):
an MMR is created and registered in the receiving process. Subsequently,
buffers may be serialized and transferred using ordinary :mod:`pickle`
methods. The reconstruction procedure uses the registry to find the
associated MMR.
associated MMR. Unpickling a :class:`Buffer` performs an IPC import from
the embedded descriptor; only unpickle buffers received from trusted peers.

Warning
-------
IPC descriptors and pickled buffers cross a trust boundary between
cooperating same-host processes. A malicious peer can supply crafted
descriptor fields. Use :meth:`Buffer.from_ipc_descriptor` only with
descriptors from trusted peers, and do not unpickle buffers from
untrusted sources.
"""

def __cinit__(self, *args, **kwargs) -> None:
Expand Down
9 changes: 8 additions & 1 deletion cuda_core/cuda/core/_memory/_ipc.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,14 @@ class IPCDataForMR:
...

class IPCBufferDescriptor:
"""Serializable object describing a buffer that can be shared between processes."""
"""Serializable object describing a buffer that can be shared between processes.

Note
----
The payload and ``size`` fields are controlled by the exporting peer.
Receivers must treat them as untrusted and import only through
:meth:`Buffer.from_ipc_descriptor`.
"""

def __init__(self, *arg, **kwargs) -> None:
...
Expand Down
9 changes: 8 additions & 1 deletion cuda_core/cuda/core/_memory/_ipc.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,14 @@ cdef class IPCDataForMR:


cdef class IPCBufferDescriptor:
"""Serializable object describing a buffer that can be shared between processes."""
"""Serializable object describing a buffer that can be shared between processes.

Note
----
The payload and ``size`` fields are controlled by the exporting peer.
Receivers must treat them as untrusted and import only through
:meth:`Buffer.from_ipc_descriptor`.
"""

def __init__(self, *arg, **kwargs) -> None:
raise RuntimeError("IPCBufferDescriptor objects cannot be instantiated directly. Please use MemoryResource APIs.")
Expand Down