What happens if I dd zeros to the drive where dd resides?
Will this command: dd if=/dev/zero of=/dev/sda bs=1M
succeed if the dd command was originally on /dev/sda? Will this complete because dd is in memory at that time?
There are three things which can happen:
- The command starts, runs till completion and you get dropped back to a prompt. Since the disk is effectively wiped at you can't do much after that, though you might get lucky with some shell build-in commands.
- The command starts. At some point it gets paged out due to memory pressure. Normally this is not a problem because parts of it can just be reloaded from disk (unchanged data) of from swap. However if you just wiped these then the dd command will fail partially though filling the disk.
- The third option is something from BSDs. The MBR on a mounted disk is protected from overwriting. Even if you run the command as root. There are dozens of Linux distributions, all being just slightly different. It is quite possible that some of them emulate this.
So far for the theory. Now for a practical test.
I installed a fresh Ubuntu 12.10 on a VM. (VMware workstation on win7-x64, using default options and a 10 GB virtual disk).
The dd command completed successfully and I got dropped back at what seemed a working prompt. I could enter new commands, though they would fail for obvious reasons.
A quick experiment in a virtual machine using Damn Small Linux indicates the dd command indeed completes, as expected; the program is initially loaded into memory to run and it makes very little sense to load the executable again and again during the process. Eventually, dd will exit and report 'no space left on device'.
Afterwards, the operating system seems to function normally at first sight, but hangs after the first command it can no longer execute for obvious reasons and becomes unresponsive. A brief inspection of the hard drive contents shows the partition has indeed been zeroed.
From the mmap
page on Linux:
MAP_SHARED Share this mapping. Updates to the mapping are visible to other processes that map this file,
and are carried through to the underlying file. The file may not actually be updated until
msync(2) or munmap() is called.
MAP_PRIVATE
Create a private copy-on-write mapping. Updates to the mapping are not visible to other pro‐
cesses mapping the same file, and are not carried through to the underlying file. It is
unspecified whether changes made to the file after the mmap() call are visible in mapped
region.
Executables are mapped to memory by the kernel via an internal call to the mmap
function. A MAP_PRIVATE
type mapping is requested (look in fs/binfmt_elf.c
of the kernel source tree).
So it boils down to the behavior of mmap
: whether changes in the file, or the underlying block device to which that file is referenced, are propagated back to the pages of the mapping which have already been paged in and are present.
That page is based on API standards, rather than kernel behavior, hence the "unspecified". The actual behavior is that changes to the file are not propagated back to already present pages. Of course, if the program suddenly jumps to a page of code which has not been paged in, and the erasure has already taken place, then it will get a page of all zeros.
But, quite probably, by the time dd
erases itself, it has paged in all the pages of code it needs to continue the erasure loop. There is the possibility that once the loop terminates, it may hit some code that is in a not present page: like, say a function spans across a page boundary, so to reach the return instruction, a page has to be fetched.
But that page may be cached from a previous dd
invocation, too.