This video perfectly captures the elegant "deception" of Copy-on-Write, where Linux trades immediate data copying for a clever system of shared memory. It’s a sharp look at how the most efficient system designs often create the most unexpected security risks.
Deep Dive
Prerequisite Knowledge
- No data available.
Where to go next
- No data available.
Deep Dive
fork() Looks Like Fraud
Added:Imagine a process holding 10 GB of memory. It calls the fork system call which creates a duplicate of that process. A moment later, there are two processes and both of them think that they have their own private 10 GB of memory. But there is no way Linux copied 10 GB that quickly. In fact, it did not copy the data at all, not a single page.
And a lot of the time it couldn't copy it even if it wanted to because the machine may not have enough free memory for another 10 GB. So if the data wasn't copied, what exactly was duplicated? And the trick that makes this possible is genuinely clever. But here's the strange part. One tiny mistake in the same mechanism once allowed almost anyone on an LX machine to become rude. And the bug stayed there for 9 years until it was discovered. And this is not a rare occurrence. You rely on this constantly.
Shells use it, databases use it, and browsers and app runtimes and even servers use it. They create new processes by copying an existing one through system calls like fork, clone, and spawn. In fact, Post SQL can fork a backend when a new connection comes in.
And Android forks a warm process called zygote. Reddis folks when it needs to save something on disk. And on Linux, almost every process running right now begin as a copy of another one. And this is why that can be so cheap. Your laptop does not copy GB of memory every time you press enter. If the child process never changes anything, it costs almost nothing. And that is how Reddis can save a snapshot of a 10 GB database in the background without needing 20 GB of memory. It is how your phone can launch an app in milliseconds while every other app quitly shares the same framework in memory. It is also why asking for a gigabyte of fresh zeroed memory can return instantly. Your machine clearly did not just go and find a whole gigabyte of zeros. All of this uses the same trick. When the kernel duplicates a process, it copies the map that says where everything lives. But both processes still share the actual memory underneath. that continues until one of them tries to change something. So to understand this trick and the mistake hiding inside it, we need to start with what fork is actually supposed to copy.
Fork has one promise to keep. It's that once it returns, the child is a separate process. It can scribble all over its heap, its stat, and its variables. And the parent process must never see any of it. They now have two separate lives.
And the obvious way to keep that promise is using brute force. It's that when fk happens, you physically copy the parents entire address space into the child. It includes every page of the heap, every page of the stack. 10 GB go in and another 10 GB comes out. And if you think about it, that is actually madness. The reason becomes obvious as soon as you look at what a child usually does next. It calls exec.
and that throws away everything the child just inherited and loads a completely different program in its place. So you copy 10 GB only for the child to immediately delete all of it.
So it makes it obvious the naive copy is not just physically slow. But most of the time it's pure waste which leaves the real question. How do you give someone a copy without actually making one? So here's what every process actually has. The addresses used by a program are not really physical locations. They are entries in a map called the page table. And each entry points to a real block of physical memory. You have the map and the territory underneath it. So when the program reads from an address, the CPU follows that map and finds the physical memory behind it. The program only sees the map. It has no idea where that memory actually sits in the machine. So folks uses that indirection to cheat it.
Instead of copying the memory, it copies the map. The child process gets its own page table and its own set of entries, but those entries still point at the same physical memory as a parent. The map is duplicated. The territory is shared. And this is exactly what the manual says. The real cost of fork is duplicating the parents page table and setting up the child cross. The gigabytes of actual data are never touched or copied. You just copy the map which is much smaller than the memory it describes and leave the memory exactly where it is and it matters for a large process. Copying the page table still has a real cost and that comes back to bite us later. But it is nothing compared to copying all the data because that copy never happens. But now we have one problem. Both processes now point to the same physical memory while the child is still supposed to be free to change its own copy. So the kernel does one more thing. It marks all of those shared entries as read only in both page tables. So as long as both processes only read from that memory, this works perfectly fine. Reads do not care who owns the physical page and the parents and child can safely share 10 GB of memory while copying almost none of it.
But the real question is what happens when one of them tries to write. So when the child tries to write to a page but that entry is marked read only. So the write cannot just go through the processor's memory unit catches the violation stops everything cold and raises a page fault. So the control jumps into the kernel into a handler with a very literal name do_wp page which is a right protected page.
And now the colonel understands what is really being asked. Someone who was sharing a tile wants to change it. So the colonel makes the copy it promised at the start. But notice that it only makes it now just in time and only for this one page. It grabs a fresh 4 kilobyte tile and copies the content of the shared page into it. Then it just swings the child map entry over to that private copy and unlocks it for writing.
and then just returns.
The right instruction runs again and this time it lands and the child changed it page but the parents page never moved and that's the entire idea. You do not copy 10 GB. You copied one page and only the page that was actually written. So here's the whole idea in one line. Folk does not copy your memory. It copies the map and lets the first right actually pay the bill. You pay for what you change, not for what you own. Just hold on to that term right because it is doing all the work here where a right turns into a copy is how a single bug handed out root access for the better part of a decade. We'll get there. And sometimes the kernel does not even copy this one page. We'll get there too. Now go back to what a child usually does. it forks and then immediately calls exec to become a completely different program.
The problem here is that exec throws away the entire inherited map and builds a new one. And here's the payoff. In that tiny window between the fork and exec, the child barely writes anything.
So barely anything gets copied. All of those shared tiles that inherited and then abandoned might cost you a page or two in the worst case scenario. And this is why launching a program on Linux is so cheap. The expensive copy the knife version would have made simply never happens. The child does not live long enough to start writing all over the memory it inherited. But there's an honest clarification here. Copying the map is cheap, but it's still not free.
If a process has an enormous address base, duplicating that page table alone can take real time. And that is exactly why Linux also gives you ways to skip even that. The vold lets the child borrow the parents map outright. There's no copy happening, but it's dependent on the promise that it will exec in a heartbeat.
But before the kernel copies anything, do underscorew page asks one more question. How many processes are still pointing at this style? If two processes are still sharing it, that's fine. Make a private copy. But if you're the only one left pointing at this page, then there's nobody left to protect it from.
So the commander does not copy at all in that case. It just simply unlocks the tile that you already have and hands it back. So the last owner of a shared page inherits it for free. A copy only happens when the page is genuinely still being shared. And figuring out whether you really are the last owner turns out to be subtle. Modern kernels track it with an explicit flag that marks a page as exclusively yours. It is the difference between copy on write and copy only if someone else still cares.
And the same trick of waiting until something writes also shows up somewhere that has nothing to do with fork. When you ask for a large fresh block of zeroed memory, the kernel barely does anything at all. It just gives you the address space. The real pages do not exist yet. The first time you read from an address in that block, the kernel points it at a single shared page of zeros that it keeps around and that page is marked read only. So every read somewhere in that block return zero.
They all lead back to the same little page you have gigabyte of zeros. In the same way the child has 10 GB of memory, at least on paper and the instant you write to one of those addresses, you get a page fault. and the colonel gives you a real page for that spot and points the entry at it. So, as you can see, it's all being done very lazily. It's the f trick all over again. The gigabyte existed as address spaces first. The real pages only appear as you touch them. And in this case, the zeros were a promise and writing is what makes the kernel actually pay up. And the kernel is willing to make far more of these promises than it could ever keep. It will happily hand out more memory than a machine physically has betting that most of it will never be written. The colonel is an optimist promise now allocate only on a right. But there was this one time it lost that bet when everyone cashes in at once and the real memory runs out.
It's that moment when you meet the infamous killer, the outer memory killer. But that's the exception. The rule is that both the copy and the allocation wait for the right. So when Reddus saves your database, it folks the parent keeps answering queries while the child gets a frozen readonly view of all 10 GB exactly as they looked at the instant of the fork. Then the child can calmly keep writing that snapshot to disk. The two processes keep sharing the entire data set while that happens. The only extra memory comes from handful of keys that actually change while the save is running. You get a 10 GB snapshot for the price of whatever changed during it.
That's copy and write earning its keep.
And by the way, your phone does this thousands of times a day. Android starts one process called zygot and preloads the entire application framework into it. Then every app you open begins as a fork of that one warm process. So every app starts with the framework already there. It does not have to load its own copy. and all of the apps keeps shredding those same pages until one of them writes. That means faster launches and hundreds of megabytes saved across everything you're running. It's the same trick across a billion phones. So far, this looks like a free lunch, but it isn't. And it's worth being honest about where it bites you later. The whole thing is a bet that you will not write much after you folk. You lose that bet and it turns on you. Let's say Reddus is taking a snapshot while your application is furiously changing keys. Now the parent has to copy page after page after page. Memory starts creeping towards double of what you begin with. And every one of those copies is another fault the kernel has to handle. That's the cost of copying the map coming back to bite us.
On a big data set, the fork alone can stall radius for milliseconds, sometimes for a full second. And if the machine cannot promise enough memory to cover the worst case, the folk can fail outright. That is why the Reddis manual quietly tells you to let the colonel overpromise memory on purpose. And notice who else pays when folk marked all of those pages read only. It did the same thing in the parent. So right after folk, the parents own rights start faulting too. The cost is not only the child's, but the most famous consequence has nothing to do with performance.
Remember the one rule this entire mechanism rests on. When you write, that right must land on your own private copy and never on the shared original copy.
In 2016, someone found a way to break exactly that rule. Race a right against a call that tells the colonel to throw away the private copy. And if you time it just right, the colonel loses track of what is happening. The copy vanishes in that time gap and the rights land on the original page, the readonly page, the one you were never meant to touch.
Now aim that at a file that you are only allowed to read. Mapped read only. The right you were never supposed to make can reach the original file under the right timing of course. And an unprivileged user could force a private readonly file mapping to write back to where it never should have written. They could even modify a file owned by root and from there climb to root themselves.
It was called dirty cow. It has been sitting in the Linux kernel since 2007 unnoticed for about 9 years until it was caught being used in the wild. The bug lived in one scene the entire mechanism depends on and the fix took a weekend and the reuse logic around it was hardened afterwards. But the lesson is not that the trick itself is dangerous.
The stalls, the double memory, even the exploit are all the same thing. Copy on write stops being free the moment the bet gets called. It just moves the build to the exact instant you write and hopes that you really do that. So here is the fork from the very beginning one more time except now you can see the trick.
Two 10 GB processes. The colonel copied the map. It shared the memory and it logged every page and then it waited.
Copies happened one page at a time and only where a right actually happened which for almost everything you fork is almost nowhere. That's the whole idea.
Copy on right is a bet made in hardware that you will change far less than you actually hold. Your shell your database snapshot the apps on your phone a gigabyte of zeros. All of them are running on the same wager. Folk does not copy your memory. It copies the map and lets the first right pay the bill. So that's it for this video. If you enjoyed watching, consider subscribing and I'll see you in the next one.
Related Videos

TOP 15 Data compression Interview Questions and Answers 2019 Part-2 | Data compression | Wisdom jobs
wisdomjobs
281 views•2019-06-28

CTS 158: 802.11w Management Frame Protection
ClearToSend
4K views•2019-02-04

NDSS 2019 Send Hardest Problems My Way: Probabilistic Path Prioritization for Hybrid Fuzzing
NDSSSymposium
496 views•2019-04-02

How realistic is Cities: Skylines?
CityBeautiful
159K views•2019-02-14

GUIs & TUIs: Choosing a User Interface for Your Python Project | Real Python Podcast
realpython
2K views•2025-04-04

The OSI Model - Explained by Example
hnasr
225K views•2019-05-12

Cloud Computing - Introduction
elithecomputerguy
98K views•2019-10-07

From Traveler's Dilemma to Dynamic Routing | Demystifying Networking
IITBombayJuly
5K views•2019-08-04
Trending

Playstation NO DISC/NO BUY Fight Is Over...
DavidJaffeGames
4K views•2026-07-23

Steam and Xbox Just Dropped The Hammer On PlayStation
OhNoItsAlexx
9K views•2026-07-23

Americans Confused in Australia for 17 Minutes Straight
IWrocker
17K views•2026-07-23

SuperBike Factory Has Gone... What's Next for the Motorcycle Industry?
thatbikersimon
11K views•2026-07-22