The somewhat misguided question of whether MapViewOfFile or WriteProcessMemory is faster


A customer asked, "Which is faster for copying data from one process to another; Map­View­Of­File or Write­Process­Memory?"

This is one of those "Huh?"-type questions, where the customer has solved half of a problem and is looking for help with the other half, the half that makes no sense.

First of all, the question is malformed because Map­View­Of­File does not copy any data at all. It takes existing data and maps it into a process. No copy takes place; both processes are seeing the same memory block, and if the memory is modified via one mapping, the change will be visible in other mappings.

It's like asking "Which company has better wireless telephone coverage: FedEx or Sprint?"

Okay, so maybe the question is really "Which is a faster way of transferring data between two processes?" (In the same way the FedEx/Sprint question might really be asking "Which company has a larger service area for me to communicate with my customers?")

But before you choose one or the other based on performance, you need to make the decision be appropriate from a correctness standpoint.

"We want to transfer some data from a client process to a server process. We found that mapping the shared memory causes more virtual memory to be consumed by the server, which is already constrained by the large number of components loaded into the server process. We were hoping we could switch to Write­Process­Memory, assuming the performance characteristics are acceptable."

Okay, now you sort of go "Whoa."

The Write­Process­Memory function requires PROCESS_VM_WRITE permission on the target process. That permission allows you to write to any byte in the process. If you allow a client process full write access to the complete memory space of a server, then the server is pwned!

It doesn't matter how much faster (if any) Write­Process­Memory is compared to Map­View­Of­File, because you can't use it if you want to maintain any shred of security.

"I don't want my packages to get wet, so I taped the key to the front door with instructions to the FedEx delivery person to put the package in the living room."

That key is not a key to the living room. That is a key to the entire house.

If you want to reduce the amount of address space consumed by a Map­View­Of­File, you can pass a nonzero value for dwNumber­Of­Byte­To­Map and map a sliding window into the data rather than mapping it all at once.

And then looking at the question again, it's not clear that the Write­Process­Memory function will help in the first place: If the problem is address space exhaustion, then switching to Write­Process­Memory won't change your address space profile: The memory written by Write­Process­Memory must all be committed in the target process. Whereas Map­View­Of­File lets the server control how much address space is consumed by the view, the Write­Process­Memory function requires it all to be committed up front.

We never did hear back from the customer, so it's not clear whether they understood that their question was confused and misguided, or whether they were just frustrated with us for "not answering their question."

Comments (25)
  1. Mike Caron says:

    Using WriteProcessMemory will certainly help with their memory usage. This way, the client can just poke the appropriate data values directly into the server's data structures. This will be much faster than the hack of using a file as a proxy, and use less memory because it won't have to load or parse it.

    Cleaner, faster, smaller… I cannot see any downsides to this technique!

    (Yes, this is a joke)

  2. Joshua says:

    Hmmm. If loopback TCP/IP proves not fast enough, I'd be using WriteProcessMemory the other way around. The privileged server will call the API (and ReadProcessMemory) targeting the unprivileged client (the control channel would still use TCP/IP). If you have to worry about the server attacking the client then you have bigger problems. I tend to not bother to make my services work without admin privileges (besides the fact they're often given working directories by the customer that only admin has write access to) so anybody who can exploit that already has the machine.

    Address space exhaustion sucks. /3GB to the rescue sometimes. amd64 to the rescue more frequently.

  3. Anonymous Coward says:

    Or maybe client doesn't mean what you think, and refers to architecture alone, not to where it runs or how (un)privileged it is. In that case the customer may have thought ‘these people don't know what they're talking about’ and went on to seek help elsewhere. (They'd be wrong, but they would have no way of knowing.)

  4. I'm amazed by the fact that I replied to an identical question on StackOverflow… stackoverflow.com/…/214671

  5. JM says:

    @Joshua: named pipes are also worth considering if you're only doing message-based local communication (although they also work remotely, they have some quirks and security implications that mean you're probably not better off than with TCP/IP). Locally they're faster than TCP/IP and they free you from having to write a message layer over shared memory yourself.

    If you are going the shared memory route, there is still no excuse for using ReadProcessMemory()/WriteProcessMemory() as opposed to CreateFileMapping()/MapViewOfFile(). WriteProcessMemory() has no restrictions whatsoever — even if you don't care about the security, a simple bug could hose the receiving party in unforeseen and unboundedly subtle ways. At least a file mapping allows you to have a well-defined interface (well, more or less).

  6. I tend to not bother to make my services work without admin privileges

    o_O

  7. Matt says:

    @JM "Locally they're faster than TCP/IP"

    They both run equally fast on the same machine. Connecting to localhost doesn't put packets on the network donchaknow. …

    I think something that is worth mentioning is that shared memory is a BAD choice for IPC unless you REALLY know what you're doing. You have to be really careful about Time-of-check Time-of-use bugs since when you're reading the memory in the server there's nothing to stop a malicious program on the other side writing to that data. You have to manually buffer the content to avoid these TOCTOU bugs.

    If you use a named pipe or a socket, the bytes you've read in aren't subject to those race-conditions, and whilst you're waiting on the pipe or the socket the guy on the other side gets a short scheduler boost, so using those makes your programs more reliable AND faster; and you don't need to allocate funky memory sections which consume lots of Virtual Memory in your process to do it :)

  8. JM says:

    @Matt: last time I measured it, pipes were faster. Obviously local TCP/IP doesn't go over the network, but the overhead characteristics still differ from pipes. Of course, benchmarks always lie, nor do I remember what version of Windows I tested it on — probably Server 2008. Disregarding speed, named pipes don't take up ports.

  9. L. says:

    @JM @Matt:

    Moreover, pipes have an ACL.  TCP/IP on localhost does not, an attacker could race the client for connecting to the server.

  10. sirin says:

    There is also always the possibility to use RFC 1149 to share data. Although not faster and overkill for sharing it on a  single computer

  11. MeaCulpa says:

    @sirin: you are evil! I was curious about the mention of RFC 1149 (not one I have committed to memory, so I looked it up. Humph!

  12. Matt says:

    @L. If your server is running as SYSTEM and does bad things when the wrong client connects in, you're probably Doing It Wrong(TM).

  13. Myria says:

    Additionally, using WriteProcessMemory in a production application is ill-advised because anti-virus programs' heuristics will often assume that your application is malware.  After all, the two primary users of WriteProcessMemory are debuggers and malware, and debuggers are uncommon in the wild.

  14. Neil says:

    @Matteo Do you suppose the age of that question correlates with Raymond's queue length?

  15. I'm upset now.

    I knew what RFC 1149 was. I need to get out more.

  16. @Neil: honestly? At first I thought that it may have been the same guy, but I've actually seen several times people asking about ReadProcessMemory as IPC, so probably it's just a common misunderstanding.

  17. Brian_EE says:

    @Matteo, Raymond has mentioned previously that his queue for blog posts is about 18 months. So it does seem about the correct timeframe.

  18. Myria says:

    @Ken Hagan: Let's say that you want to spawn a child process of your same .exe and only want to give it one of your handles.  One solution, though not the best, is to spawn a copy of yourself with CREATE_SUSPENDED but no handle inheritance, DuplicateHandle the handle into the target process, then WriteProcessMemory the new handle's value into a global variable within the .exe before resuming the new process.  This works, but is extremely hacky.

    Another non-development use is cheating in games. =)

  19. MH says:

    I tend to not bother to make my services work without admin privileges

    Please tell me you're not involved with writing any software I may buy.

  20. Ken Hagan says:

    @Myria: Nicely put! In fact, *are* there non-development uses for WriteProcessMemory? I can't think of any.

  21. Danny says:

    Let's assume that security is not a concern. The client is already in the "inner ring" and trusted. The problem is still valid. Which way is the fastest to copy data from the client to the server? One real-life example would be data analysis done by No Such Agency that receives from spy satellites images (or live video feed) and each satellite is focusing on it's perimeter. To achieve a good analysis for an entire given region (let's say Taliban mountains) you would need that each client to fast upload it's data to the server whom will then start the algorithm that will spit out the response to the question "Do they have an increased activity in the north or the south?" received from White House war room. As you can see in the above illustrated example the clients can do whatever they like, including but not limited to directly inject data into server process. So, in this case, what is the fastest way do achieve it?

    [Okay, well if you're uploading data, then that's your bottleneck, not the performance of intra-computer data transfer. And if you read the question, you'll see that the customer already knew which one was faster. They just wanted to know whether WriteProcessMemory was fast enough for their needs. And there's only one way to know for sure: Measure it and see if it's fast enough for your needs. -Raymond]
  22. Matt says:

    @Danny: I think the No Such Agency streaming Taliban hideouts to the Whitehouse is definitely not a case where "security is not a concern".

  23. Andreas Rejbrand says:

    I really dislike when people don't know when to use (and, in this case, when *not* to use) semicolon.

  24. Danny says:

    @Matt

    The agency will respond to a question received from white house in my scenario, not streaming data to it. Read again my scenario

  25. So, the agency didn't find Bin Laden for 10+ years due to race conditions in their memory sharing code?

Comments are closed.