Mac OS Xで削除がとても難しいファイルを作成する方法
2013年の記事だが、Mac OS XとそのHFS+はこの上なくクソなので何があっても驚きはしないが、Mac OS Xで削除しにくいシンボリックリンクファイルを作成する方法があるらしい
OS X and the Unremovable File - galvanist
HFS+上で、削除しにくいシンボリックリンクを作成できる。
# be root, for example with: sudo -i str1=$(python -c "print '1' * 255") str2=$(python -c "print '2' * 255") str3=$(python -c "print '3' * 255") str4=$(python -c "print '4' * 253") mkdir -p $str1/$str2/$str3/$str4 ln -s ftw $str1/$str2/$str3/$str4/L
さて、このように作った以上、OS X v10.9では以下のコマンドでは削除できない。
# still as root... unlink 1*/2*/3*/4*/L unlink $str1/$str2/$str3/$str4/L rm -rf 1* rm -rf $str1 rm -rf $str1/$str2/$str3/$str4 rm -rf $str1/$str2/$str3/$str4/L (cd $str1/$str2/$str3/$str4; unlink L) (cd $str1/$str2/$str3/$str4; rm -rf L)
すべて、以下のようなエラーとなる。(読みやすさのために[...]で省略)
root# pwd /private/tmp/111[ ... ]111/222[ ... ]222/333[ ... ]333/444[ ... ]444 root# ls L root# rm -f L rm: L: No space left on device root# df -H Filesystem Size Used Avail Capacity iused ifree %iused Mounted on /dev/disk1 250G 108G 142G 44% 26385563 34601956 43% / [...]
念の為、システムコールを直接呼び出すコードを書いてみる。/tmp/fixit.cにおいてあるとする。
#include <unistd.h> #include <stdio.h> #include <errno.h> int main(int argc, char* argv[]) { printf("Unlink returned %i\n", unlink("L")); perror("Error was"); return 0; }
実行してみるが、
root# pwd /private/tmp/111[ ... ]111/222[ ... ]222/333[ ... ]333/444[ ... ]444 root# gcc -o /tmp/fixit /tmp/fixit.c root# /tmp/fixit Unlink returned -1 Error was: No space left on device
ENOSPCだと。unlink(2) Mac OS X Developer Tools Manual Pageに返すとは書かれていないエラーだぞ。
状況は複雑だ。
- 一般ユーザーが作ったのならば、一般ユーザーは、rm -rfで消すことができる
- 一般ユーザーが作ったのならば、rootは消すことができない。おかしい
- rootが作ったのならば、rootは消すことができない
- rootが作ったのならば、通常通りの権限により、一般ユーザーは削除が行えない
- rootが作ったものであっても、chmod -hとchown -hで権限を変えれば、一般ユーザーにも消せるはずである
- rootが作ったものを、chmod -hとchown -hしようとすると、ENOSPCが返る。
- rootが作ったものに対し、"mkdir -p some/containing/paths; mv 1111* some/containing/paths/"は動くが、その後、"rm -rf some"しても動かない。
Workaround
なぜか、パスはシンボリックリンクを作るには短いが、削除するには長すぎるようだ。パスを短縮すれば消せる。
root# pwd /private/tmp/111[ ... ]111/222[ ... ]222/333[ ... ]333/444[ ... ]444 root# ls L root# mv /private/tmp/1* /private/tmp/one root# pwd /private/tmp/one/222[ ... ]222/333[ ... ]333/444[ ... ]444 root# rm L root# ls root# rm -rf /tmp/one root#
workaroundは十分なのか。
そういうわけで、一応workaroundはあるのだが、しかし疑問がある。
- アンチウイルスソフトウェアはマルウェアがこのような方法で保存されていた場合、ちゃんと消せるよう作られているのか? アンチウイルスソフトウェアはすでにchflags(2)の問題に対処しなければならないが、こういうパスと複数のchflagsで構成されていた場合はどうか
- マルウェアや悪意ある人物がディスクをこのようなもので埋め尽くした時に、rm -rfの代替品となるツールは存在するのか?
ちなみに、これは2013年の記事だが、Yosemiteまでは同じ問題があるそうだ。El Capitainだと、ファイルパスが長すぎて作成できないエラーが返るらしい。そもそも、Mac OS XのカーネルであるXNUのファイルパスの上限が2024文字なのに2025文字のファイルパスを作成できてしまうのがおかしいようだ。