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:

  1. 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.
  2. 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.
  3. 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.

Screenshot of the Ubuntu VM after wiping the disk


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.