1

4.2BSD の rename() システムコールでこの設計上の決定がなされた理由を理解しようとしています。ここで解決しようとしているものは何もありません。動作自体の理論的根拠を理解するだけです。

4.2BSD では、ファイルのアトミックな名前変更/移動を許可する目的で rename() syscall が導入されました。4.3BSD-Reno/src/sys/ufs/ufs_vnops.c から:

 /*
  * If ".." must be changed (ie the directory gets a new
  * parent) then the source directory must not be in the
  * directory heirarchy above the target, as this would
  * orphan everything below the source directory. Also
  * the user must have write permission in the source so
  * as to be able to change "..". We must repeat the call 
  * to namei, as the parent directory is unlocked by the
  * call to checkpath().
  */

 if (oldparent != dp->i_number)
  newparent = dp->i_number;
 if (doingdirectory && newparent) {
  VOP_LOCK(fndp->ni_vp);
  error = ufs_access(fndp->ni_vp, VWRITE, tndp->ni_cred);
  VOP_UNLOCK(fndp->ni_vp);

したがって、このチェックが意図的に追加されたことは明らかです。私の質問は - なぜですか?この動作は直感的なはずですか?

これの影響は、アトミックに書き込むことができる別のディレクトリに書き込むことができないディレクトリ (書き込み可能なディレクトリにある) を移動できないことです。ただし、新しいディレクトリを作成し、リンクを移動して (ディレクトリへの読み取りアクセス権があると仮定して)、ディレクトリの書き込みビットを削除することはできます。アトミックに行うことはできません。

% cd /tmp
% mkdir stackoverflow-question
% cd stackoverflow-question
% mkdir directory-1
% mkdir directory-2
% mkdir directory-1/directory-i-cant-write
% echo "foo" > directory-1/directory-i-cant-write/contents
% chmod 000 directory-1/directory-i-cant-write/contents
% chmod 000 directory-1/directory-i-cant-write
% mv directory-1/directory-i-cant-write directory-2
mv: rename directory-1/directory-i-cant-write to directory-2/directory-i-cant-write: Permission denied

これで、アトミックに移動できない読み取り不可能なコンテンツを含む書き込み不可能なディレクトリが作成されました。ただし、パーミッションを変更し、新しいディレクトリを作成し、ln を使用して新しいリンクを作成し、パーミッションを変更することで、非アトミックに同じ効果を得ることができます。(読者への演習として残しておきます)

. と .. はすでに特別なケースになっているので、ソースが示唆するように、ディレクトリを書き込むことができない場合は「..」を変更できないという直感的なことを特に購入しません。コードの作成者が認識した正しい動作である以外に、これには何か理由がありますか? 書き込み可能なディレクトリ間で (書き込み不可の) ディレクトリをアトミックに移動できるようにした場合、何か悪いことが起こる可能性はありますか?

4

3 に答える 3

2

AndrewMcGregorが正しい可能性が高いと思います。UFSこのように機能する必要があるとは限りませんが、実装者(Kirk McKusick)は、このケースをカバーするためにファイルシステムのアクセス許可のロジックを拡張しただけです。したがって、ターゲットディレクトリに対する書き込み権限がない場合は、その「..」エントリを変更できないはずです。

しかし、あなたの例を見ると、別の可能性が思い浮かびました。懸念は、あなたが示すように、単一のユーザーが問題のすべてのディレクトリを所有している場合ではなく、ディレクトリが異なるユーザーによって所有されている場合である可能性があります。つまり、このチェックにより、自分が所有するディレクトリを、書き込み権限のある親ディレクトリ間で移動できなくなります。もちろん、あなたが私にあなたのディレクトリへの書き込み権限を与えていないと仮定します。

確かに、これが発生する可能性のあるシナリオは、通常の使用ではほとんどありません。しかし、カーネルは、一般的なユースケースだけでなく、すべての奇妙なユースケースについても心配する必要があります。

明らかな反論は、このシナリオについて心配したい場合は、書き込み権限を持つディレクトリ間で所有していないファイルを移動することを阻止したいということです...

于 2010-04-06T02:17:43.617 に答える
0

Also the user must have write permission in the source so as to be able to change "..".

つまり、移動後にディレクトリを適切な形式にするためには、ディレクトリ内の .. リンクを変更する必要がありますが、これを行う権限はありません。したがって、これは許可スキームの論理的な部分にすぎませんが、それほど明白なものではありません。

于 2010-03-31T15:24:48.283 に答える
0

限定的に定義された特定の条件下で、特権を持たないユーザーが通常は特権を持つ特定の操作を実行できるようにする、多くの特殊なプログラムが存在します。このようなプログラムは、多くの場合、setuid フラグを使用して動作します。プログラムでは、特別な条件が満たされていることを確認し、満たされている場合は特権操作を実行します。

たとえば、ファイル名を引数として取るプログラムを実行する場合など、ファイルを名前で参照する必要がある場合があります。最初にチェックを実行する必要がある場合、権限のないユーザーがチェック時と使用時の間にパス名の任意の部分の名前を変更できる場合、危険な競合状態が発生する可能性があります。これは、指定された各パス コンポーネントを含むディレクトリに権限のないユーザーの書き込み権限を持たないようにすることで解決されることがあります。チェックされました。特権のないユーザーが、そのディレクトリへの書き込み権限がなくても ".." が参照するものを変更できる場合、セキュリティ ホールが作成されます。

さらに、ディレクトリ内の「..」を更新するには、そのディレクトリのデータ ブロックに書き込む必要があり、少なくとも従来の Unix および BSD ファイルシステムでは、ディレクトリの最終更新時刻も更新します (Apple の場合はそうではないことはわかっています)。 HFS+、「..」が合成されます)。他のユーザーの書き込み許可をオフにすると、ディレクトリへの書き込みや最終更新時刻の変更などの操作が禁止されることは直感的にわかります。

于 2010-03-31T23:22:20.837 に答える