400の権限を持つファイルがrootからは書き込み可能であるのに、ユーザーからは読み取り専用であるのはなぜですか?


10

非特権ユーザーとしてファイルを作成し、アクセス許可モードをに変更すると400、そのユーザーには正しく読み取り専用として表示されます。

$ touch somefile
$ chmod 400 somefile
$ [ -w somefile ] && echo rw || echo ro
ro

すべては順調です。

しかし、その後ルートがやって来ます:

# [ -w somefile ] && echo rw || echo ro
rw

一体何ですか?確かに、rootは読み取り専用ファイルに書き込むことができますが、それを習慣にするべきではありません。ベストプラクティスでは、書き込み許可ビットをテストできるように指示する傾向があり、そうでない場合は設定されています。理由のためにその方法。

私は両方を理解したいと思い、なぜこれが起こっている、そしてどのように私は得ることができます偽の書き込みビットがセットされていないファイルをテストするときにリターンコードを?


ところで、RHEL6(4.1.2(1)-release)とRHEL7(4.2.46(2)-release)の両方を使用しています。
リッチ

16
「ベストプラクティスでは、書き込み許可ビットをテストできるはずであると規定する傾向があります。そうでない場合は、理由によりそのように設定されています。」-実際、ベストプラクティスは「rootとして実行しない」です。rootとして実行している場合は、すでに権限チェックをバイパスすることを決定しています。ユーザー空間でこれらの権限チェックを手動で再実装することは、災害のレシピです。
ケビン

@Kevin権限のないものを実行できる場合に適しています。これは/etc/dhcp/dhcpd.confrootが所有するを操作するためのものです。ベンダー提供のを使用していdhcpdます。完全な災害ですよね?ファイルがRCSにチェックインされて、私はの使用を自動化していますrcsdiffcico私たちは持っているので、オペレータが必要には...動作します。許可ビットのチェック(-w、詳細はtest(1))はci -u、ファイルを読み取り専用のままにすることに基づいて機能する最初の行のエラーになります。私はそれを捨てて、まっすぐ行っrcsdiff -qてチェックしてい$?ます。悲惨なdhcpd?それはによって所有されdhcpdます。
リッチ

1
権限チェックの実装が2つあります。1つはカーネル内、もう1つはユーザー空間内にあるため、これは潜在的な災害です。さらに悪いことに、これらの実装は同一の結果を生成することさえ意図されていないため、お互いに対してファズテストを実行することはできません。これで、2つのパスにアクセスできるようになりました。これらのパスは、互いに独立してロックおよび保護する必要があります。
ケビン

@Kevin確かに、それらは同じ結果を生成することはなく、(マンページの詳細が少ないにもかかわらず)意図されていませんでしたが、書き込み許可ビットを明示的に確認したいと思います。マンページはbashtestそれが何の[ -wためにあるのかを私に信じさせました。
リッチ

回答:


26

test -w別名[ -wはファイルモードをチェックしません。書き込み可能かどうかをチェックします。ルートについては、そうです。

$ help test | grep '\-w'
  -w FILE        True if the file is writable by you.

私がテストする方法は、stat(1)( " %a 8進数のアクセス権")の出力に対してビットごとの比較を行うことです。

(( 0$(stat -c %a somefile) & 0200 )) && echo rw || echo ro

の出力がによって8進数として解釈されるように、サブシェル$(...)には0接頭辞が必要であることに注意してください。stat(( ... ))


簡潔にしていただきありがとうございます。の活用(( ... & ... ))。1つの誤植を修正:-)
リッチ

3にしてください... if必要ありません。8進数のアクセス許可の出力はで%aなく%d、の出力を8進数として解釈(( ... ))するには接頭辞が必要です。0stat
リッチ

@Patrick私man statは「10進数の%dデバイス番号」と言いますが、私たちが望むのは「アクセス権」です、いいえ?0接頭辞が必要であるというあなたの主張はよくできていますが、私はそれをそこに詰め込む必要があるだけだと思います:)
sourcejedi

2
stat -c 0%a...
sourcejedi

@sourcejedi ack、あなたは正しい。何らかの理由で、%dは10進数のアクセス権であると考えていました。編集を復元しました。おかげで:-)
Patrick

30

何を-wしているのか誤解されていると思います。ファイルが「書き込み許可」を持っているかどうかを確認するのではなく、呼び出し元のユーザーがファイルに書き込み可能かどうかを確認します。

より具体的には、それは呼び出しaccess(2)または類似しています。

たとえば、スクリプトがある場合、そのスクリプトでif [ -w /etc/shadow ]実行するstraceと、次のような行が表示されることがあります。

faccessat(AT_FDCWD, "/etc/shadow", W_OK)

rootファイルに書き込むことができるので、0を返します。

たとえば、通常のユーザーとして:

faccessat(AT_FDCWD, "/etc/shadow", W_OK) = -1 EACCES (Permission denied)

ルートとして

faccessat(AT_FDCWD, "/etc/shadow", W_OK) = 0

これは、私のマシンで/etc/shadow許可を得ているにもかかわらず000です。

---------- 1 root root 4599 Jan 29 20:08 /etc/shadow

これで、やりたいことが面白くなり、それほど単純ではありません。

単純な権限を確認する場合は、ls出力を確認するか、電話statなどで確認します。ただし、ACLはこれらの権限を上書きできることを理解してください。ファイルが権限400であるという理由だけで、ファイルが書き込み可能であることを停止しません...


いいえ、「誤解」はマンページを間違って読み取ることになります-wtest(1)は明示的です:「ファイルが存在し、書き込み権限が付与されています」ではなく、「現在のユーザーがファイルを書き込んでいる可能性があります」。許可のオーバーライドやACL については何もありません。bash(1)は注意:「ファイルが存在し、書き込み可能である場合は、真です。」ksh(1)shenanigansに対する微妙なヒントを作成します:「-w file // True、ファイルが存在し、現在のプロセスによって書き込み可能である場合。」zsh(1)はに延期されtest(1)zshmisc(1)と表現されksh(1)zshexpn(1)いくつかの興味深いアクセス許可ベースのグロビングを詳しく説明します。csh(1)陽気に簡潔です:「書き込みアクセス」。

btw:私はPatrickの回答を受け入れました。1。先の質問に適切に回答しなかったため:書き込みビットが設定されていないファイルをテストするときに、偽の戻りコードをどのように取得できますか?および2.マンページを誤解していると思われる引き締まった導入のため。
リッチ

3
@リッチ私がこれを読んだ方法では、あなたのコメントも少しぎこちないようになっていると思います。あなたが書いたことが間違っていたと言っているのではありません。
デビッドZ

3
「あなたは誤解されていると思います...」は卑劣ではありません。しかし、あなたの反応は100%ぎくしゃくしています。
バーベキュー

manページは、クリスタルクリアされていないかもしれないが@Richまた、スティーブンは、あなたが「誤解持っていることを述べている-wが何をどのようなない」、およびマニュアルページは、したがって、質問、かつてのルックスはケースのようにどこ、と言う
SEBI

1

rootユーザーは好きなように実行できますが、「通常の」ファイル権限は制限されません。これは、足のターゲットの練習に対する少しの保険のために、eXecute権限なしでプレーンファイルを直接実行しません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.