I was trying to create a memory buffer in OpenCL with C++ binding. The sentence looks like
cl::Buffer buffer(context,CL_MEM_READ_ONLY,sizeof(float)*(100));
This sentence confuses me because it doesn't specify which device the memory is allocated on. In principle context contains all devices, including cpu and gpu, on the chosen platform. Is it true that the buffer is put in a common region shared by all the devices?
The spec does not define where the memory is. For the API user, it is "in the context".
If you have one device only, probably (99.99%) is going to be in the device. (In rare cases it may be in the host if the device does not have enough memory for the time being)
In case of many different devices, it will be in one of them at the creation. But it may move transparently to another device depending on the kernel launches.
This is the reason why the call clEnqueueMIgrateMemObjects (OpenCL 1.2 only) exists.
It allows the user to tell some hints to the API about where the memory will be needed, and prepare the copy in advance.
Here is the definition of what it does:
clEnqueueMIgrateMemObjects provides a mechanism for assigning which device an OpenCL memory object resides. A user may wish to have more explicit control over the location of their memory objects on creation. This could be used to:
Ensure that an object is allocated on a specific device prior to usage.
Preemptively migrate an object from one device to another.
Typically, memory objects are implicitly migrated to a device for which enqueued commands, using the memory object, are targeted
I'm trying to understand something about HGLOBALs, because I just found out that what I thought is simply wrong.
In app A I GlobalAlloc() data (with GMEM_SHARE|GMEM_MOVABLE) and place the string "Test" in it. Now, what can I give to another application to get to that data?
I though (wrongfully!) that HGLOBALs are valid in all the processes, which is obviously wrong, because HGLOBAL is a HANDLE to the global data, and not a pointer to the global data (that's where I said "OHHHH!").
So how can I pass the HGLOBAL to another application?
Notice: I want to pass just a "pointer" to the data, not the data itself, like in the clipboard.
Thanks a lot! :-)
(This is just a very long comment as others have already explained that Win32 takes different approach to memory sharing.)
I would say that you are reading into books (or tutorials) on Windows programming which are quite old and obsolete as Win16 is virtually dead for quite some time.
16-bit Windows (3.x) didn't have the concept of memory isolation (or virtual /flat/ address space) that 32-bit (and later) Windows versions provide. Memory there used to be divided into local (to the process) and global sections, both living in the same global address space. Descriptors like HGLOBAL were used to allow memory blocks to be moved around in physical memory and still accessed correctly despite their new location in the address space (after proper fixation with LocalLock()/GlobalLock()). Win32 uses pointers instead since physical memory pages can be moved without affecting their location in the virtual address space. It still provides all of the Global* and Local* API functions for compatibility reasons but they should not be used anymore and usual heap management should be used instead (e.g. malloc() in C or the new operator in C++). Also several different kind of pointers existed on Win16 in order to reflect on the several different addressing modes available on x86 - near (same segment), far (segment:offset) and huge (normalised segment:offset). You can still see things like FARPTR in legacy Win16 code that got ported to Win32 but they are defined to be empty strings as in flat mode only near pointers are used.
Read the documentation. With the introduction of 32-bit processing, GlobalAlloc() does not actually allocate global memory anymore.
To share a memory block with another process, you could allocate the block with GlobalAlloc() and put it on the clipboard, then have the other process retreive it. Or you can allocate a block of shared memory using CreateFileMapping() and MapViewOfFile() instead.
Each process "thinks" that it owns the full memory space available on the computer. No process can "see" the memory space of another process. As such, normally, nothing a process stores can be seen by another process.
Because it can be necessary to pass information between processess, certain mechanisms exists to provide this functionality.
One approach is message passing; one process issues a message to another, for example over a pipe, or a socket, or by a Windows message.
Another is shared memory, where a given block of memory is made available to two or more processes, such that whatever one process writes can be seen by the others.
Don't be confused with GMEM_SHARE flag. It does not work the way you possibly supposed. From MSDN:
The following values are obsolete, but are provided for compatibility
with 16-bit Windows. They are ignored.
GMEM_SHARE
GMEM_SHARE flag explained by Raymond Chen:
In 16-bit Windows, the GMEM_SHARE flag controlled whether the memory
should outlive the process that allocated it.
To share memory with another process/application you instead should take a look at File Mappings: Memory-mapped files and how they work.
I SEEM to be having an issue with GlobalLock in my application. I say seem because I haven't been able to witness the issue by stepping through yet but when I let it run it breaks in one of two locations.
The app has multiple threads (say 2) simultaneously reading and writing bitmaps from PDF files. each thread handles a different file.
The first location it breaks I am reading a dib from the pdf to be OCRed. OCR is reading the characters on the bitmap and turning them into string data. The second location is when a new PDF is being created with the string data being added over the bitmap.
GlobalLock is being used on a HANDLE created by the following:
GlobalAlloc(GMEM_MOVEABLE, uBytes);
I either get an AccessViolationError (always in the first instance) or I get GlobalLock returning a NULL pointer. (The second occurance)
It seems like one file is being read and another is having a copy written at the same time. There seems to be no pattern to which files it happens on.
Now I understand that the VC++ runtime has been multithreaded since 2005 (I am using VS2010 with 2008 toolchain). But is GlobalLock part of the runtime? It seems to me more like a platform independent thing.
I want to avoid just putting a CRITICAL_SECTION around globallock and globalunlock to get them to work, or at least not know why I am doing so.
Can anyone inform me better about GlobalLock/Unlock?
-A fish out of water
First, the Global* heap routines are provided for compatibility with 16-bit windows. They still work, but there's no real reason to use them anymore, except for compatibility with routines that still use global heap object handles. Note that GlobalLock/GlobalUnlock are not threading locks - they prevent the memory from moving, but multiple threads can GlobalLock the same object at the same time.
That said, they are otherwise thread-safe; they take a heap lock internally, so there is no need to wrap your own locking around every Global* call. If you are having problems like this, it suggests you may be trying to GlobalLock a freed object, or you may be corrupting the heap (heap overflows, use-after-free, etc). You may also be missing thread synchronization on the contents of the heap object - the Global* API does not prevent multiple threads from accessing or modifying the same object at once.
I have a program running some image treatment with OpenCL, I sometimes have a crash because it's trying to write something into a memory address (with clCreateBuffer) that is null.
Is their any OpenCL call I can use to delay that memory write, or is it possible to check via C++ if a memory address is valid ?
You probably can use OpenCL events.
cl_int clWaitForEvents (cl_uint num_events,
const cl_event *event_list)
You can create an event from the call or operation you want to wait for, then before creating your buffer you wait for that event to complete.
However, could you provide a little bit of information. For example what exactly do you want to do? Maybe there is another way. It would also be better if you have some code showing your operations.
I want to create an allocator which provides memory with the following attributes:
cannot be paged to disk.
is incredibly hard to access through an attached debugger
The idea is that this will contain sensitive information (like licence information) which should be inaccessible to the user. I have done the usual research online and asked a few other people about this, but I cannot find a good place start on this problem.
Updates
Josh mentions using VirtualAlloc to set protection on the memory space. I have created a custom allocator ( shown below ) I have found the using the VirtualLock function it limits the amount of memory I can allocate. This seems to be by design though. Since I am using it for small objects this is not a problem.
//
template<class _Ty>
class LockedVirtualMemAllocator : public std::allocator<_Ty>
{
public:
template<class _Other>
LockedVirtualMemAllocator<_Ty>& operator=(const LockedVirtualMemAllocator<_Other>&)
{ // assign from a related LockedVirtualMemAllocator (do nothing)
return (*this);
}
template<class Other>
struct rebind {
typedef LockedVirtualMemAllocator<Other> other;
};
pointer allocate( size_type _n )
{
SIZE_T allocLen = (_n * sizeof(_Ty));
DWORD allocType = MEM_COMMIT;
DWORD allocProtect = PAGE_READWRITE;
LPVOID pMem = ::VirtualAlloc( NULL, allocLen, allocType, allocProtect );
if ( pMem != NULL ) {
::VirtualLock( pMem, allocLen );
}
return reinterpret_cast<pointer>( pMem );
}
pointer allocate( size_type _n, const void* )
{
return allocate( _n );
}
void deallocate(void* _pPtr, size_type _n )
{
if ( _pPtr != NULL ) {
SIZE_T allocLen = (_n * sizeof(_Ty));
::SecureZeroMemory( _pPtr, allocLen );
::VirtualUnlock( _pPtr, allocLen );
::VirtualFree( _pPtr, 0, MEM_RELEASE );
}
}
};
and is used
//a memory safe std::string
typedef std::basic_string<char, std::char_traits<char>,
LockedVirtualMemAllocato<char> > modulestring_t;
Ted Percival mentions mlock, but I have no implementation of that yet.
I found Practical Cryptography by Neil Furguson and Bruce Schneier quite helpful as well.
You can't really protect against memory access. You can probably prevent paging if you are running as an admin or as the system, but you cannot prevent the admin or system from reading your memory. Even if you could somehow completely block other processes from reading your memory (which you can't), another process could still actually inject a new thread into your process and read the memory that way.
Even if you could somehow completely lock down your process and guarantee that the OS would never allow anyone else to access your process, you still don't have full protection. The entire OS could be running in a virtual machine, which could be paused and inspected at any time.
You cannot protect memory contents from the owner of the system. Hollywood and the music industry have been aching for this for years. If it were possible, they'd already be doing it.
On Unix systems you can use mlock(2) to lock memory pages into RAM, preventing them being paged.
mlock() and mlockall() respectively lock part or all of the calling
process’s virtual address space into RAM, preventing that memory from
being paged to the swap area.
There is a limit to how much memory each process can lock, it can be shown with ulimit -l and is measured in kilobytes. On my system, the default limit is 32 kiB per process.
If you're developing for Windows, there are ways you can restrict access to memory, but absolutely blocking out others is not doable. If you're hoping to keep a secret secret, read Writing Secure Code - which addresses this problem at some length, but be aware that you have no way of knowing if your code is running on a real machine or a virtual machine. There's a bunch of Win32 API stuff to deal with crypto that handles this kind of thing, including safe storage of secrets - the book talks about that. You can look at the online Microsoft CyproAPI for details; the OS designers recognise this very problem and the need to keep the cleartext secure (again, read Writing Secure Code).
The Win32 API function VirtualAlloc is the OS level memory allocator. It allows you to set access protection; what you could do is set access to PAGE_GUARD or PAGE_NOACCESS, and flip the access to something friendlier while your program reads, and reset it afterward, but that's merely a speed hump if someone is trying really hard to peek at your secret.
In summary, look at the crypto APIs on your platform, they'll address the problem better than something you hack up yourself.
Let's take this a bit at a time:
I want to create an allocator which
provides memory with the following
attributes:
That's fair enough.
* cannot be paged to disk.
That's going to be hard. As far as I am aware, you cannot disable Virtual Paging as it is handled by the OS. If there is a way, then you'll be spelunking in the bowels of the OS.
* is incredibly hard to access through an attached debugger
You could run it through PGP and store it encrypted in memory and unencrypt it as needed. Massive performance hit.
The idea is that this will contain
sensitive information (like licence
information) which should be
inaccessible to the user. I have done
the usual research online and asked a
few other people about this, but I
cannot find a good place start on this
problem.
Keep all sensitive information off the machine. Seriously. Don't store sensitive information in memory. Write a custom delete routine that will automatically remove all data from any allocations you perform. Never allow general access to a machine with sensitive material on it. If you perform db access, make sure all access is sanitized before firing. Only people with specific log-ins are allowed to access. No general group access.
On a side note, what other methods are
there of accessing the memory of a
process other than attaching a
debugger?
Taking a dump of the memory.
install Libsodium, use allocation mechanisms by #including <sodium.h>
Guarded heap allocations
Slower than malloc() and friends, they require 3 or 4 extra pages of virtual memory.
void *sodium_malloc(size_t size);
Allocate memory to store sensitive data using sodium_malloc() and sodium_allocarray(). You'll need to first call sodium_init() before using these heap guards.
void *sodium_allocarray(size_t count, size_t size);
The sodium_allocarray() function returns a pointer from which count objects that are size bytes of memory each can be accessed. It provides the same guarantees as sodium_malloc() but also protects against arithmetic overflows when count * size exceeds SIZE_MAX.
These functions add guard pages around the protected data to make it less likely to be accessible in a heartbleed-like scenario.
In addition, the protection for memory regions allocated that way can be changed using the locking memory operations: sodium_mprotect_noaccess(), sodium_mprotect_readonly() and sodium_mprotect_readwrite().
After sodium_malloc you can use sodium_free() to unlock and deallocate memory. At this point in your implementation consider zeroing the memory after use.
zero the memory after use
void sodium_memzero(void * const pnt, const size_t len);
After use, sensitive data should be overwritten, but memset() and hand-written code can be silently stripped out by an optimizing compiler or by the linker.
The sodium_memzero() function tries to effectively zero len bytes starting at pnt, even if optimizations are being applied to the code.
locking the memory allocation
int sodium_mlock(void * const addr, const size_t len);
The sodium_mlock() function locks at least len bytes of memory starting at addr. This can help avoid swapping sensitive data to disk.
int sodium_mprotect_noaccess(void *ptr);
The sodium_mprotect_noaccess() function makes a region allocated using sodium_malloc() or sodium_allocarray() inaccessible. It cannot be read or written, but the data are preserved. This function can be used to make confidential data inaccessible except when actually needed for a specific operation.
int sodium_mprotect_readonly(void *ptr);
The sodium_mprotect_readonly() function marks a region allocated using sodium_malloc() or sodium_allocarray() as read-only. Attempting to modify the data will cause the process to terminate.
int sodium_mprotect_readwrite(void *ptr);
The sodium_mprotect_readwrite() function marks a region allocated using sodium_malloc() or sodium_allocarray() as readable and writable, after having been protected using sodium_mprotect_readonly() or sodium_mprotect_noaccess().
What you are asking for is handled at the OS level. Once the data is in your program, it is liable to be paged out.
For accessing the memory, a motivated individual can attach a hardware debugger.
#graham
You could run it through PGP and store it encrypted in memory and unencrypt it as needed. Massive performance hit.
Then you'd have to hold the key in memory. That would make it a little harder, but definitely not impossible. Anyone motivated will still manage to get the data from memory.
Your best bet is to implement something similar to .NET's SecureString class, and be very careful to zero out any plaintext copies of your data as soon as you are done (don't forget to cleanup even when exceptions are thrown). A good way to do this with std::string and such is to use a custom allocator.
On Windows, if you use CryptProtectMemory (or RtlEncryptMemory for older systems), the encryption password is stored in non-pageable (kernel?) memory. In my testing, these functions are pretty darn fast, esp. taking into account the protection they are giving you.
On other systems, I like to use Blowfish since it's a good mix between speed and strength. In the latter case, you will have to randomly generate your own password (16+ bytes of entropy for Blowfish) at program startup. Unfortunately, there's not a whole lot you can do to protect that password without OS support, although you might use general obfuscation techniques to embed a hard-coded salt value into your executable that you can combine with the password (every little bit helps).
Overall, this strategy is only one part of a broader defense-in-depth approach. Also keep in mind that simple bugs such as buffer overflows and not sanitizing program input remain by far the most common attack vectors.
You cannot protect memory contents from the owner of the system.
Hollywood and the music industry have been aching for this for years.
If it were possible, they'd already be doing it.
Have you had a look at Vista (and above) Protected Processes (direct .doc download). I believe the operating system-enforced protection is courtesy of the entertainment industry.
#Derek: Oh, but with trusted computing, you can use memory curtaining! :-P</devils-advocate>
#roo
I was really hoping that is was possible, and that I just hadn't found it yet. Your example just made me realise that that is exactly what we are trying to do - only allow access to files in the context of our program and so preserve the IP.
I guess I have to accept that there is no truly secure way to store someone’s files on another computer, especially if at some point access is allowed to that file by the owner.
That's definitely the problem. You can store something securely so long as you never grant access, but as soon as you grant access, your control is gone. You can make it a little bit more difficult, but that's all.
#Chris
Oh, but with trusted computing, you can use memory curtaining! :-P
But then you have to actually be willing to pay for a computer someone else owns. :p
#Derek Park
He only said harder, not impossible. PGP would make it harder, not impossible.