よく考えるとやはり chmod(0700) するのは問題がある。 少なくとも chmod(lstat(path).mode & 07770) でないとまずい。
あと、どうにも不安が解消できないのが NTFS なんだよな。 いちおうテストはしてるけど、 これで本当に正しく動作してるのか確信できない。
(16:53)
lchmod と lchown を検出する方法がわかった。
~ % cat t def have_lchmod? return false unless File.respond_to?(:lchmod) begin File.lchmod 0 return true rescue NotImplementedError return false end end def have_lchown? return false unless File.respond_to?(:lchown) begin File.lchown nil, nil return true rescue NotImplementedError return false end end p have_lchown? p have_lchmod? ~ % test-all-ruby t ruby 1.4.6 (2000-08-16) [i686-linux] false false ruby 1.6.0 (2000-09-19) [i686-linux] false false ruby 1.6.1 (2000-09-27) [i686-linux] false false ruby 1.6.2 (2000-12-25) [i686-linux] false false ruby 1.6.3 (2001-03-19) [i686-linux] false false ruby 1.6.4 (2001-06-04) [i686-linux] false false ruby 1.6.5 (2001-09-19) [i686-linux] false false ruby 1.6.6 (2001-12-26) [i686-linux] false false ruby 1.6.7 (2002-03-01) [i686-linux] false false ruby 1.6.8 (2002-12-24) [i686-linux] false false ruby 1.8.0 (2003-08-04) [i686-linux] true false ruby 1.8.1 (2003-12-25) [i686-linux] true false ruby 1.9.0 (2005-05-16) [i686-linux] true false
(17:20)
ちがった。オーナーじゃなきゃ chmod できないんだから chmod できれば常にオーナーだ。だからやっぱ 700 でいいんだ。
とすると、root staff 777 みたいなディレクトリはどうすればいいんだろ。 通常ユーザでも消せるけど、chmod はできないから結局 world writable で、 すりかえは防げないことになるな……。 自分に権限がなきゃ /etc/passwd みたいな重要ファイルは消せないからいいのか? いや、CGI が使ってるデータみたいなものは消せてしまう?
いや違う、world writable ならそんなことしなくても 普通に消せるからこれは問題でないんだ。 今回の問題は権限の大きいユーザが消すときだけ発生する。 問題は「権限が大きい」=「chmod できる (オーナーである)」が成立するかどうかだ。
グループとして所有していて、world writable な場合はどうなるか。 lstat から unlink までの間にディレクトリをシンボリックリンクに すりかえると重要ファイルが消せるな。……え? やっぱりまずい?
あれ? もしかして chdir しても防げないんじゃ……。 chdir しようとしてるディレクトリを シンボリックリンクにすりかえられたらまずいじゃん。 ということは、world writable なディレクトリがあると どうやっても安全には消せない? だから、chdir するかしないかに関係なく chmod 700 する必要がある。 したがって安全に消せるのはオーナーだけだ。 だからオーナー以外が world writable なディレクトリを再帰的に 消す場合はもともとセキュアにはなりえないので、考えるだけ無駄なんだな。
ということで結論は chmod 700 する。 オーナーでない場合は、もともとセキュアじゃないので呼ぶほうが悪い。
(21:58)
と、決心した直後に気付いたけど、 消すディレクトリの上を全部 chmod しないと問題があるのね。 もういい、そんなのあきらめる。
いや、/tmp の場合はやばいのか。 困ったな。root で掃除すると仮定するなら、 まず chown(root) してもらうべきなのかな。
うん、それじゃ、そういうことで。
(22:07)
これまで「a/.」も「a」も同じだろーと思ってたんだけど、 そうじゃないんだな。a がディレクトリを指すシンボリックリンクの場合、 readlink("a") は大丈夫だが readlink("a/.") は EINVAL になる。 まあ、言われてみりゃ確かにそうだけど、って感じ。
(01:03)
http://slashdot.jp/article.pl?sid=05/05/19/088246&topic=16
「複数の Wiki」ってんで慌てて調べたけど、添付ファイルがらみなのね。 明らかに BitChannel は関係ないな (実装してないから)。
あ、なんか BitChannel いじりたくなってきた。
(02:00)
Copyright (c) 2002-2007 青木峰郎 / Minero Aoki. All rights reserved.
errno-*.txt、どっちも404ですだ。
うう、アップロードするの忘れてましたー。