RE: More info on dd?

From: Ed Carp (ercat_private)
Date: Fri Oct 18 2002 - 07:30:17 PDT

  • Next message: Gary L. Palmer: "Re: Future trends in computer forensics"

    > >     fn[strlen (fn) - 1] = NULL;
    >
    > Hmm.. so if filename is "foo", then strlen(fn) will be 3, and you just
    > truncated it to "fo".  Is that what you wanted?
    
    fgets() returns a string terminated with "\n\0".  This gets rid of the
    "\n".
    
    > >     chmod (fn, 0622);
    >
    > Bad Juju here - either you're wiping a /dev/hd type entry, in which case
    > you should NOT make it 0622 (because then anybody can bypass permissions
    > on the file system you later make on here), or you're wiping a
    > single file
    > (in which case it's Even Worse).  In any case, the chmod() is
    > totally useless,
    > and I don't understand why you're bothering.  If you insist on doing it,
    > you should check the return codes...
    
    The reason the chmod() call is so that, if the file is read-only, it will
    be set read-write.  It should probably be 0600, but it doesn't matter much.
    This program is designed to overwrite plain files that are listed on stdin,
    such as the output of a find, not whole disks.
    
    > >     n = open (fn, O_RDWR);
    
    This was a typo - it should be O_RDWR|O_SYNC.
    
    > If you're intending to wipe *disks*, you might want to stat() it
    > and check
    > the st_dev, st_ino, st_mode, and st_rdev fields to make sure
    > it's a disk rather
    > than a regular file.  As coded, this will in addition chase
    > symlinks too..
    >
    > Whoops. ;)
    
    As I said before, this is designed to wipe files on stdin, not disks.
    
    > >     for (i = 0; i < 4; i++)
    > >     {
    > >       printf ("\rSecure wipe '%s', pass %d", fn, i + 1);
    > >       fflush (stdout);
    > >       for (j = 0; j < 65535; j++)
    > >         lbuf2[j] = a[i];
    >
    > Well-meaning, but the use of all-nulls (\0) as the first pattern may be
    > very self-defeating (see below)...
    
    I don't think so.
    
    > >       while (1)
    > >       {
    > >         if ((p = read (n, lbuf, 65530)) < 1)
    > >           break;
    > >         lseek (n, -1 * p, SEEK_CUR);
    > >         if (EOF == write (n, lbuf2, p))
    >
    > This goes into the buffer cache...
    
    No, it doesn't.  Note the use of O_SYNC above to guarantee the write is
    done.
    
    > And if you're erasing a *file*, you have the added fun that you are *NOT*
    > guaranteed that the blocks the write() call gets allocated are the blocks
    > that the read() read from.  Several cases:
    >
    > 1) If it's a "sparse" file with holes in it, there may not have
    > been blocks
    > allocated to start with for all-zeros blocks.
    
    From the write(2) manpage: "POSIX  requires that a read() which can be
    proved to occur after a write() has returned returns the new  data."
    
    > 2) There's nothing prohibiting a file system from freeing blocks
    > that have
    > become all zeros (and given the initialization of lbuf2, and the
    > file system
    > block size, it *could* result in 512 bytes written for the first
    > block, and
    > the kernel simply deallocating the all-zeros blocks for the *OTHER* 65020
    > bytes. Particularly nasty if you use zeros as the first pass - the kernel
    > may simply free all the blocks of a file, and then the next pass you get
    > entirely new blocks...
    
    No, sir, this will not happen, because the blocks are allocated to the
    file.  The kernel will *not* deallocate zero-filled blocks just because
    they happen to be zero-filled - they have to be disassociated from the file
    first.
    
    > 3) File systems that support compression (such as AIX's "jfs") will quite
    > likely allocate DIFFERENT blocks than before, if the new data
    > compresses into
    > different number of blocks than the old data.  See (2) above as a special
    > case...
    
    No, this is again not correct.
    
    > 4) 'man fsync()'.  Understand *why* I say that.  If you don't,
    > you'll never
    > understand the issues involved here.. ;)
    
    Not needed, since O_SYNC is used.
    
    > >     close (n);
    > >     unlink (fn);
    >
    > And the data in the file cache may never actually go to disk if
    > the unlink hits
    > before the disk blocks are pushed to disk.  In fact, on most
    > systems, you are
    > almost *guaranteed* that up to <whatever your bufcache size is>
    > will *NOT* be
    > written to disk.
    
    Again, incorrect.  a close() will flush all data to the disk before the
    unlink() call.
    
    > The use of '65530' rather than 2**16 may cause interesting
    > effects performance
    > wise....
    
    No, not at all.  Buffer alignment doesn't matter in this case.
    
    > It's also recommended that you go and read Peter Gutmann's
    > writings on this
    > subject, starting with:
    >
    > http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html
    >
    > It turns out that even if you *DO* manage to actually write to
    > the correct blocks
    > on the disk, that the data may not be as gone as you think....
    
    I have read Peter's stuff, thanks.  Again, your assumptions are not
    correct, unfortunately.
    
    
    -----------------------------------------------------------------
    This list is provided by the SecurityFocus ARIS analyzer service.
    For more information on this free incident handling, management 
    and tracking system please see: http://aris.securityfocus.com
    



    This archive was generated by hypermail 2b30 : Fri Oct 18 2002 - 08:31:09 PDT