2023/01/08

root権限のファイルもuserが削除できるのか

かなり初歩的なお話です。

$ sudo touch abc
[sudo] password for xxx:
$ ls -l abc -rw-r--r-- 1 root root 0 Jan  8 11:48 abc $ rm -f abc
$

root のファイルなのに削除できるんだ!
ちなみに xxx はユーザで、この記事では user と表現します。もちろん root のグループには属していない。

 

-f を付けない場合は警告プロンプトが出てきて確認されますが、それでも削除できる。
これはディレクトリも同様だった。

$ sudo mkdir abc
$ ls -l
drwxr-xr-x 2 root root 4096 Jan  8 11:49 abc $ rm -rf abc $

まだ sudo が残っていたのでパスワードの入力無しで mkdir できているが、ともかく sudo 無しで削除できる。所有者はファイルの場合もディレクトリの場合も root.root、アクセス権はファイルが 0644、ディレクトリが 0755。  私は書込権限がなければ削除できないと思い込んでいたのだが、そうではなかった。

書込権限がないので "-f" がないとプロンプトが出て確認が求められるが Permission denied にはならない。

 

ただ、中に root のファイルが入っている root のディレクトリだと Permission denied になる。

$ sudo mkdir abc
$ sudo touch abc/abc
$ rm -rf abc
rm: cannot remove 'abc/abc': Permission denied
$

ではディレクトリが user で中のファイルが root だとどうなるかというと、削除できる。

$ mkdir abc
$ sudo touch abc/abc
$ rm -rf abc
$

逆のパターン、ディレクトリが root で中のファイルが user の場合、これは Permission denied になる。

$ sudo mkdir abc
$ touch abc/abc
touch: cannot touch 'abc/abc': Permission denied
$ sudo touch abc/abc
$ sudo chown xxx.xxx abc/abc
$ rm -rf abc
rm: cannot remove 'abc/abc': Permission denied
$

では中身が空の root のディレクトリで other の権限もない場合だが、これも削除できる。

$ sudo mkdir abc
$ sudo chmod 0700 abc
$ rm -rf abc
$

では自分に対しても権限がない場合はどうなるかというと、削除できる。

$ mkdir abc
$ sudo chmod 0000 abc
$ rm -rf abc
$

Linux でプログラムでディレクトリ削除のプログラムを実装するとわかるが、ディレクトリが空にならないと削除できなかったと思う(思う、と弱気なのはそういうコードを書いたのがかなり昔で覚えていないからだ)。

remove() は、ファイルなら unlink() を、ディレクトリなら rmdir() を呼び出す。

Man page of REMOVE
http://linuxjm.osdn.jp/html/LDP_man-pages/man3/remove.3.html

rmdir() は空でないと ENOTEMPTY エラーになる。
スティッキービットが設定されていたりファイルシステムでディレクトリ削除が許容されていない場合も EPERM エラーになる。
ファイルシステムが読み込み専用だった場合は EROFS エラーになる。
EACCES エラーは、削除したいディレクトリを含んでいるディレクトリが実行する user に対して書込権限がない場合になるのかな? 指定したディレクトリがカレントディレクトリではなくたどっていく場合に途中でたどる権限が無くなった場合も EACCES エラーになりそうだ。
rm コマンドだと全部ひっくるめて「Permission denied」になるのかもしれない。

Man page of RMDIR
http://linuxjm.osdn.jp/html/LDP_man-pages/man2/rmdir.2.html

ではファイルの方はどうか。

Man page of UNLINK
http://linuxjm.osdn.jp/html/LDP_man-pages/man2/unlink.2.html

unlink() と unlinkat() があるそうだ。
unlinkat() なんて昔あったかな? 更新が 2017年だからその頃にはあったことになる。
エラーになる内容は rmdir() と似た感じだ。

 

rm のソースコードを見つけられなかったので推測になるが、カレントディレクトリに書込権限があるならばこうなる。

  • 中身が空であれば user にかかわらず削除できる
  • 中身があるなら、そのディレクトリに書込権限がある user であれば削除できる
    • 中身は unlink() を使って削除するのでディレクトリの書込権限がいる

ファイルに対する書込権限は必要ないのか・・・。
user や group が違うファイルなら削除されないだろうと思ってワイルドカードでがさっと削除させていたのだが認識が甘かったようだ。

 

そうだ、"-f" を付けなければ良いのだ。

$ mkdir abc
$ sudo touch abc/abc
$ rm -r abc
rm: remove write-protected regular empty file 'abc/abc'?

体が勝手に「-r」まで打ち込んだら「-rf」までやってしまうのよね。。。
ということは、rm コマンドって再帰で unlink() する前に stat() とかで権限をチェックしているということだな。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。

注: コメントを投稿できるのは、このブログのメンバーだけです。