mktemp(1) もどきを作ってみた - 拡張 POSIX シェルスクリプト Advent Calendar 2013 - ダメ出し Blog

2013-12-07(Sat) [sh][shell][security] [更新履歴]

拡張 POSIX シェルスクリプト Advent Calendar 2013、7日目の記事です。

昨日のネタの続きで mktemp(1) もどきをシェルスクリプトで実装してみました。

mktemp コマンドの仕様

mktemp の主な仕様をおさらいしましょう。

  1. /tmp/tmp.<ランダム文字列> という名前のファイルを作成する。
  2. 必ず新規のファイルとなる。既存のファイルを絶対に上書きしない。
    • 競合の回避。
    • シンボリックリンク攻撃の回避。
  3. ファイルのモードは必ず 0700 になる。
    • ファイル内容漏洩の回避。

まずは、これらをシェルスクリプトで実現する方法を紹介します。

/tmp/tmp.<ランダム文字列> という名前のファイルを作成

bash, ksh, zsh なら $RANDOM で乱数が得られるので、 この仕様に即したファイル名を作るのは簡単です。

$ bash -c 'seeds=(0 1 2 3 4 5 6 7 8 9); echo "${seeds[$RANDOM % ${#seeds[@]}]}"'
…seeds内の一文字がランダムに表示される…

既存ファイルの上書きを避けた新規ファイルの作成

ファイルの作成は : >ファイル名 が定番ですね。

既存ファイルの上書きを避けるには、 リダイレクト時のファイル上書きを拒否するシェルオプション noclobber が利用できます。

$ bash -c 'set -o noclobber; ls -l file; : >file; ls -l file; : >file'
file: ファイルもディレクトリもありません。
-rw-rw-r--   1 fumiyas  users              0 12月  6日  20:28 file
bash: file: cannot overwrite existing file

noclobber を有効にした後、リダイレクトでファイルの作成を試みて、 失敗したら別の名前で再試行…を成功するまで繰り返す実装にすればよいです。

ちなみに noclobber を利用せずに「(1)ファイルの作成前にファイルの存在を検査し、 (2)存在しなかったらファイルを作成する」という実装にした場合、 (1) と (2) の間に別プロセスがファイルを作成する余地があるため、 安全ではありません。

noclobber がどのように既存ファイルの上書きを回避しているか興味のある方は、 open(2) システムコールのマニュアル記載の O_EXCL フラグを参照してください。 O_EXCL によりファイルの存在有無とファイル作成がカーネル内部で不可分で行なわれるため、 ほかのプロセスと競合することはありません。

新規ファイルのモードを 0700 にする

これは簡単ですね。ファイル作成時の umask 値を 0077 に設定するだけです。

$ bash -c 'umask; : >file1; ls -l file1; umask 0077; umask; : >file2; ls -l file2'
0002
-rw-rw-r-- 1 fumiyas users   0 12月  6 20:32 file1
0077
-rw------- 1 fumiyas users   0 12月  6 20:32 file2

「(1) umask 値を気にせずにファイルを作成した後に (2) モードを 0700 に変更する」 という実装にした場合、(1) と (2) の間に別プロセスがファイルを開く余地があるため、 安全ではありません。 ファイルのモードをいくら制限しても、オープン済みのプロセスに対しては何ら抑止効果はありません。

mktemp.bash の実装例

以上を元に mktemp.bash を実装しました。

スクリプト名は *.bash ですが、いつものように ksh, zsh でも動きます。 zsh はある条件で妙なエラーメッセージが出ますが、面倒なので放置しています (基本的な動作は問題ありません)。

mktemp.bash


ところで、12月25日はクリスマスな上に、 OSS 界隈で地味に活躍されているふみやすさんの誕生日ですね!
http://www.amazon.co.jp/registry/wishlist/27M7TV8CEEF6G?sort=priority

逆に、あなたの書いた OSS や Blog や Advent Calendar が気に入ったら何か送りたく なってしまうかもしれないので、プロフィールや Web サイトに あなたの Amazon 欲しいものリストの URL を貼っておいてくださいね!


私が勤める OSSTech っていう某弊社で社員募集しているようです。 人材紹介会社を介さなければ、入社後に 20万円のボーナス! 「ふみやすっていう人に紹介された」と言ってもらえると私にもボーナス!! → https://www.osstech.co.jp/recruit/


よろしければ、これまで参加した/参加予定のほかの Advent Calendar もどうぞ。