トップ «前の日記(2014-06-03) 最新 次の日記(2014-06-05)» 編集

ヨタの日々

2001|08|09|10|11|12|
2002|01|02|03|04|05|06|07|08|09|10|11|12|
2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|12|
2024|01|02|03|04|

2014-06-04 :-(

_ 午前

0530 起床

0700 食堂

0830 出勤 && lint祭り

_ 午後

1300 lint祭り

_

1700 退勤

1800 ぐったり

1900 読書

2230 飯

_ [NetBSD][/bin/rm][rm][ランダム][RC4][コードリーディング]NetBSD /bin/rm を読む

ソース src/bin/rm/rm.c

マニュアル rm - NetBSD Manual Pages

使用例

rm ファイル
rm -r ディレクトリ

流れはこうなる。-r があると rm_tree にいく。

main
rm_file または rm_tree

面白いのは -P されたとき。

rm -P ファイル

マニュアルより

     -P    Overwrite regular files before deleting them.  Files are overwrit-
           ten three times, first with the byte pattern 0xff, then 0x00, and
           then with random data, before they are deleted.  Some care is taken
           to ensure that the data are actually written to disk, but this can-
           not be guaranteed, even on traditional filesystems; on log-struc-
           tured filesystems or if any block-journaling scheme is in use, this
           option is completely useless.  If the file cannot be overwritten,
           it will not be removed.
  1. ファイルに 0xff を書く
  2. ファイルに 0x00 を書く
  3. ファイルにランダム値を書く

ファイルを削除する前にデタラメな値を書き込んで、それから削除する。

これを rm_overwrite() で処理している。

コメントがあるので読むとよい。

/*
 * rm_overwrite --
 *	Overwrite the file 3 times with varying bit patterns.
 *
 * This is an expensive way to keep people from recovering files from your
 * non-snapshotted FFS filesystems using fsdb(8).  Really.  No more.  Only
 * regular files are deleted, directories (and therefore names) will remain.
 * Also, this assumes a fixed-block file system (like FFS, or a V7 or a
 * System V file system).  In a logging file system, you'll have to have
 * kernel support.
 *
 * A note on standards:  U.S. DoD 5220.22-M "National Industrial Security
 * Program Operating Manual" ("NISPOM") is often cited as a reference
 * for clearing and sanitizing magnetic media.  In fact, a matrix of
 * "clearing" and "sanitization" methods for various media was given in
 * Chapter 8 of the original 1995 version of NISPOM.  However, that
 * matrix was *removed from the document* when Chapter 8 was rewritten
 * in Change 2 to the document in 2001.  Recently, the Defense Security
 * Service has made a revised clearing and sanitization matrix available
 * in Microsoft Word format on the DSS web site.  The standardization
 * status of this matrix is unclear.  Furthermore, one must be very
 * careful when referring to this matrix: it is intended for the "clearing"
 * prior to reuse or "sanitization" prior to disposal of *entire media*,
 * not individual files and the only non-physically-destructive method of
 * "sanitization" that is permitted for magnetic disks of any kind is
 * specifically noted to be prohibited for media that have contained
 * Top Secret data.
 *
 * It is impossible to actually conform to the exact procedure given in
 * the matrix if one is overwriting a file, not an entire disk, because
 * the procedure requires examination and comparison of the disk's defect
 * lists.  Any program that claims to securely erase *files* while 
 * conforming to the standard, then, is not correct.  We do as much of
 * what the standard requires as can actually be done when erasing a
 * file, rather than an entire disk; but that does not make us conformant.
 *
 * Furthermore, the presence of track caches, disk and controller write
 * caches, and so forth make it extremely difficult to ensure that data
 * have actually been written to the disk, particularly when one tries
 * to repeatedly overwrite the same sectors in quick succession.  We call
 * fsync(), but controllers with nonvolatile cache, as well as IDE disks
 * that just plain lie about the stable storage of data, will defeat this.
 *
 * Finally, widely respected research suggests that the given procedure
 * is nowhere near sufficient to prevent the recovery of data using special
 * forensic equipment and techniques that are well-known.  This is 
 * presumably one reason that the matrix requires physical media destruction,
 * rather than any technique of the sort attempted here, for secret data.
 *
 * Caveat Emptor.
 *
 * rm_overwrite will return 0 on success.
 */

ここで言ってる「U.S. DoD 5220.22-M "National Industrial Security Program Operating Manual"」とやらはこれらしい。

DoD 5220.22-M(PDF)

「8-301. Clearing and Sanitization.」に項目があるけど、具体的な手法については書いてない。

rm_overwrite() を読む。

書き込み処理は define されている。なぜマクロ....

do{}while で囲むのは定石。カッコ付きで呼び出されたりしたときなどの対策。

#define RAND_BYTES  1
#define THIS_BYTE  0

#define  WRITE_PASS(mode, byte) do {          \
  off_t len;              \
  size_t wlen, i;              \
  char buf[8 * 1024];            \
                  \
  // ファイル先頭へ移動。fd は rm_overwrite() 冒頭で open() されたファイルディスクリプタ
  if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET))      \
    goto err;            \
                  \
  // 0x00 を書くときは buf (1024*8バイト) を 0x00 で埋める。
  // ランダム値を設定するときは↓で設定するので、ここではようするにデフォルト値を設定してる
  if (mode == THIS_BYTE)            \
    memset(buf, byte, sizeof(buf));        \

  // ファイルサイズぶんを 8 * 1024 ずつ処理していく
  // ファイル末尾のほうで 8 * 1024 から余ったら余ったぶんだけ書く
  for (len = sbp->st_size; len > 0; len -= wlen) {    \
    // ランダム値を書く場合は
    // 8 * 1024 バイトの buf をランダム値で埋める
    if (mode == RAND_BYTES) {        \
      for (i = 0; i < sizeof(buf);       \
          i+= sizeof(u_int32_t))      \
        *(int *)(buf + i) = arc4random();  \
    }              \
    wlen = len < (off_t)sizeof(buf) ? (size_t)len : sizeof(buf); \
    // write します
    if ((size_t)write(fd, buf, wlen) != wlen)    \
      goto err;          \
  }                \
  sync();    /* another poke at hidden caches */    \
} while (/* CONSTCOND */ 0)

読み込む処理もマクロ。

#define READ_PASS(byte) do {            \
  off_t len;              \
  size_t rlen;              \
  char pattern[8 * 1024];            \
  char buf[8 * 1024];            \
                  \
  if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET))      \
    goto err;            \
                  \
  // pattern が比較元。埋める
  memset(pattern, byte, sizeof(pattern));        \
  
  // ファイルをすべて読み込む。WRITE_PASS と同じ
  for(len = sbp->st_size; len > 0; len -= rlen) {      \
    rlen = len < (off_t)sizeof(buf) ? (size_t)len : sizeof(buf); \
    if((size_t)read(fd, buf, rlen) != rlen)      \
      goto err;          \

    // 読んだ値 buf と pattern を比較
    if(memcmp(buf, pattern, rlen))        \
      goto err;          \
  }                \
  sync();    /* another poke at hidden caches */    \
} while (/* CONSTCOND */ 0)

つまり WRITE_PASS でファイルにちゃんと書かれているかを確認している。

これらを呼び出す処理。

  /*
   * DSS sanitization matrix "clear" for magnetic disks: 
   * option 'c' "Overwrite all addressable locations with a single 
   * character."
   */
  randint = arc4random();
  randchar = *(char *)&randint;
  WRITE_PASS(THIS_BYTE, randchar);

  /*
   * DSS sanitization matrix "sanitize" for magnetic disks: 
   * option 'd', sub 2 "Overwrite all addressable locations with a
   * character, then its complement.  Verify "complement" character
   * was written successfully to all addressable locations, then
   * overwrite all addressable locations with random characters; or
   * verify third overwrite of random characters."  The rest of the
   * text in d-sub-2 specifies requirements for overwriting spared
   * sectors; we cannot conform to it when erasing only a file, thus
   * we do not conform to the standard.
   */

  /* 1. "a character" */
  WRITE_PASS(THIS_BYTE, 0xff);

  /* 2. "its complement" */
  WRITE_PASS(THIS_BYTE, 0x00);

  /* 3. "Verify 'complement' character" */
  READ_PASS(0x00);

  /* 4. "overwrite all addressable locations with random characters" */

  WRITE_PASS(RAND_BYTES, 0x00);

arc4random() はランダム生成器 arc4random - NetBSD Manual Pages

RC4 でランダム値を生成するよ。

でもちょっとヤバいかもしれず という噂 RC4の脆弱性とSSL/TLSへの攻撃