I was trying to write a program as a proof of concept in order to delete the GPT partition table from my HDD. To cut it short after opening the disk, I do something like the following:
//Removes the first partition table in the beginning of the disk
::lseek(fd, 0, SEEK_SET);
::write(fd, '\0', GPT_PARTITION_TABLE_SIZE);
//Removes the backup partition in the end of the disk
::lseek(fd, -GPT_PARTITION_TABLE_SIZE, SEEK_END);
::write(fd, '\0', GPT_PARTITION_TABLE_SIZE);
Even though that seemed to work well, I got a word from a friend that this way is not correct and I should use a local buffer for writing and that my code tries to use NULL as a pointer into write() which is not the right way.
I spend quite a few hours to understand what he meant, but I am still not sure I get it. Has anyone have ever tried something similar?
In this line of code:
::write(fd, '\0', GPT_PARTITION_TABLE_SIZE);
the second argument to write
is a const void *
. What is happening is the char
NUL ('\0'
) value is a constant 0
and thus equivalent to NULL
, or converted to the nullptr
value. the write
call then tries to read GPT_PARTITION_TABLE_SIZE
bytes starting at that address. On typical systems the address for NULL is literally 0 and usually tehre is no page mapped there and it causes an exception. Inside an operating system kernel or in some embedded systems, there may be memory mapped readable at address 0 and this might write whatever is mapped there.
Compare to the code example:
char buffer[GPT_PARTITION_TABLE_SIZE];
memset(buffer, '\0', sizeof(buffer));
write(fd, buffer, sizeof(buffer));