自分が所有していないファイルを移動できるにもかかわらず、ハードリンクできないのはなぜですか?

自分が所有していないファイルを移動できるにもかかわらず、ハードリンクできないのはなぜですか?

スクリプト例:

#!/bin/sh -e 
sudo useradd -m user_a
sudo useradd -m user_b -g user_a
sudo chmod g+w /home/user_a

set +e
sudo su user_a <<EOF
cd
umask 027
>> file_a 
>> file_b
>> file_c
ls -l file_*
EOF

sudo su user_b <<EOF
cd
umask 000
rm -f file_*
ls -l ~user_a/
set -x
mv ~user_a/file_a .
cp ~user_a/file_b .
ln ~user_a/file_c .
set +x
ls -l ~/
EOF
sudo userdel  -r user_b
sudo userdel  -r user_a

出力:

-rw-r----- 1 user_a user_a 0 Jul 11 12:26 file_a
-rw-r----- 1 user_a user_a 0 Jul 11 12:26 file_b
-rw-r----- 1 user_a user_a 0 Jul 11 12:26 file_c
total 0
-rw-r----- 1 user_a user_a 0 Jul 11 12:26 file_a
-rw-r----- 1 user_a user_a 0 Jul 11 12:26 file_b
-rw-r----- 1 user_a user_a 0 Jul 11 12:26 file_c
+ mv /home/user_a/file_a .
+ cp /home/user_a/file_b .
+ ln /home/user_a/file_c .
ln: failed to create hard link ‘./file_c’ => ‘/home/user_a/file_c’: Operation not permitted
+ set +x
total 0
-rw-r----- 1 user_a user_a 0 Jul 11 12:26 file_a
-rw-r----- 1 user_b user_a 0 Jul 11 12:26 file_b
userdel: user_b mail spool (/var/mail/user_b) not found
userdel: user_a mail spool (/var/mail/user_a) not found

答え1

どのシステムを実行していますか? Linuxでは、この動作は/proc/sys/fs/protected_hardlinks(またはsysctl fs.protected_hardlinks)を介して設定できます。

この動作については後述する。proc(5):

/proc/sys/fs/protected_hardlinks(Linux 3.6以降)
このファイルの値が0の場合、ハードリンクの作成に制限はありません(つまり、これはLinux 3.6より前の歴史的な動作です)。このファイルの値が1の場合、次のいずれかの条件が満たされている場合にのみ、ターゲットファイルへのハードリンクを作成できます。

  • 呼び出しプロセスにはCAP_FOWNER機能があります。
  • リンクを作成したプロセスのファイルシステムUIDは、ターゲットファイルの所有者(UID)と一致します。
  • 次の条件はすべて真です。
    • ターゲットは通常のファイルです。
    • 宛先ファイルには設定されたユーザIDモードビットは有効になっていません。
    • ターゲットファイルには、設定されたグループIDとグループ実行モードビットの両方が有効になっていません。
    • 呼び出し側には、ターゲットファイルを読み書きする権限があります(ファイルの権限マスクまたは適切な機能があるため)。

その理由は次のように明確でなければなりません。

このファイルのデフォルト値は 0 です。この値を1に設定すると、/ tmpなど、誰でも書き込むことができるディレクトリで最も一般的なハードリンクベースのチェック時間、および使用時間の競合によって引き起こされる長いセキュリティ問題を回避できます。

Debian システムprotected_hardlinksと同様のprotected_symlinks基本システムでは、ファイルへの書き込み権限なしでリンクを設定すると機能しません。

$ ls -ld . ./foo
drwxrwxr-x 2 root itvirta 4096 Jul 11 16:43 ./
-rw-r--r-- 1 root root       4 Jul 11 16:43 ./foo
$ mv foo bar
$ ln bar bar2
ln: failed to create hard link 'bar2' => 'bar': Operation not permitted

0 に設定すると、protected_hardlinks制限が削除されます。

# echo 0 >  /proc/sys/fs/protected_hardlinks 
$ ln bar bar2
$ ls -l bar bar2
-rw-r--r-- 2 root root 4 Jul 11 16:43 bar
-rw-r--r-- 2 root root 4 Jul 11 16:43 bar2

答え2

通常、各ファイルにはディレクトリエントリがあります(例外がありますが、詳しく説明する必要はありません)。

ディレクトリエントリはデフォルトで名前+番号ペアはファイル名とi番号の数字です。 「というプロジェクトです。私のリスト、各ファイルのすべての実際の詳細を含む構造は次のとおりです。アイノード

iノードには、ファイル所有者などに関する詳細が含まれています。実際には、ファイル所有者が「所有」します。フィールドの一つは使用回数、通常は1に設定されます。

ハードリンクが作成されると、これは最初のリンクと変わらない別の名前と番号のペアにすぎません。この時、使用回数は1ずつ増加します。ハードリンク(または状態が同じであるため、元のディレクトリエントリ)が削除されると、使用回数は1ずつ減少します。 0に達するとファイルは消えます。ここに示すように、ハードリンクを作成することは、iノードの所有者でなくてもiノードを変更できる必要があることを意味します。

これはUNIXとのシンボリックリンク(またはシンボリックリンク、時には呼び出されるソフトリンク)をご紹介します。これは名前+名前はい、デフォルトでは元のファイルにエイリアスを割り当てます。 iノードでは何も変更されません。ただリダイレクトです。欠点は、シンボリックリンクが消えたり、存在しないファイルを指すことなく元のファイルを削除できることです。

答え3

~からman 2 link:「...両方の名前は同じファイルを参照します(したがって同じ権限と所有権を持ちます)。」

ファイルの読み取り/コピー/移動権限がある場合でも、同じファイルに対して異なる権限で2つのリンクを作成することはできません。または所有権モデルUIDそしてジドディレクトリエントリ自体ではなく、2つの異なるディレクトリからリンクを生成するinodeに格納されます。

考慮する:

$ touch file_a
$ touch file_b
$ ln file_a file_A
$ ls -iln
total 0
1310731 -rw-rw-r-- 2 1000 1000 0 Jul 11 08:45 file_a
1310731 -rw-rw-r-- 2 1000 1000 0 Jul 11 08:45 file_A
1320710 -rw-rw-r-- 1 1000 1000 0 Jul 11 08:45 file_b

======= ===================================== ======
^       ^                                     ^
|       |                                     \-- names, stored in directory
|       \-- file metadata, stored in inode
\-- inode number, stored in directory and pointing to inode

この例では同じ inode 番号を持つfile_aのでfile_A〜しなければならないすべての同じ属性をinodeに保存します。

関連情報