マウントがバインドマウントの読み取り専用オプションを尊重しないのはなぜですか?


35

私のArch Linuxシステム(Linuxカーネル3.14.2)では、バインドマウントは読み取り専用オプションを尊重しません

# mkdir test
# mount --bind -o ro test/ /mnt
# touch /mnt/foo

ファイルを作成します/mnt/foo。の関連エントリ/proc/mounts

/dev/sda2 /mnt ext4 rw,noatime,data=ordered 0 0

マウントオプションは、要求されたオプションと一致しませんが、バインドマウントの読み取り/書き込み動作と最初にマウント/dev/sda2するために使用されるオプションの両方と一致します/

/dev/sda2 / ext4 rw,noatime,data=ordered 0 0

ただし、マウントを再マウントすると、読み取り専用オプションが尊重されます

# mount --bind -o remount,ro test/ /mnt
# touch /mnt/bar
touch: cannot touch ‘/mnt/bar’: Read-only file system

および関連エントリ /proc/mounts/

/dev/sda2 /mnt ext4 ro,relatime,data=ordered 0 0

私が期待するもののように見えます(実際には、testディレクトリの完全なパスが表示されることを期待しています)。onの元の/proc/mounts/マウントのエントリも変更されず、読み取り/書き込みのままです。/dev/sda2//

/dev/sda2 / ext4 rw,noatime,data=ordered 0 0

この動作と回避策は少なくとも2008年から知られており、次のマニュアルページに記載されています。mount

ファイルシステムのマウントオプションは、元のマウントポイントのオプションと同じままであり、-binオプションと--bind /-rbindを渡すことで変更できないことに注意してください。マウントオプションは、別のremountコマンドで変更できます。

すべての分布が同じように動作するわけではありません。バインドマウントが読み取り専用でマウントされない場合、Debianは警告を生成しますが、Archはオプションを静かに尊重しないようです

mount: warning: /mnt seems to be mounted read-write.

この振る舞いはDebian LennyとSqueezeで「修正」されたという報告がありますが、普遍的な修正ではないようで、Debian Wheezyでもまだ動作しません。バインドマウントが初期マウントの読み取り専用オプションを尊重するようにすることと困難に関連するものは何ですか?


/ etc / mtabはありますか?
eyoung100

参照してくださいthread.gmane.org/gmane.linux.utilities.util-linux-ng/2979と使用してこの問題を回避するmount -t bindとのヘルパースクリプトbugs.launchpad.net/ubuntu/+source/mountall/+bug/519380を
ステファンをシャゼル

@ECarterYoungはい/etc/mtab。最初のマウントの後、エントリはマウントがrwであると言い、再マウントの後はroと言うので、マウントの状態を正しく報告しています。失敗するのはマウントコマンドだけです。
StrongBad

3
私は、2つのDebianのテスト/不安定なマシン上で1 Debianのカーネルを実行し、1でkernel.orgカーネル、どちらの作業を実行するテストmount --bind -o roメッセージを出し、彼らは両方のつばmount: warning: «mountpoint» seems to be mounted read-write.Debianが廃棄されるか、またはいくつかの時点でパッチを失ったようですので...再マウントをしかし、動作します。
デロバート

2
@StrongBad要求どおりにテストしましたが、機能しません。
デロバート

回答:


21

バインドマウントはただ...まあ...バインドマウントです。つまり、新しいマウントではありません。サブディレクトリを新しいマウントポイントとして「リンク」/「エクスポーズ」/「考慮」するだけです。そのため、マウントパラメータを変更することはできません。だからあなたは苦情を受けています:

# mount /mnt/1/lala /mnt/2 -o bind,ro
mount: warning: /mnt/2 seems to be mounted read-write.

しかし、あなたが言ったように、通常のバインドマウントは機能します:

# mount /mnt/1/lala /mnt/2 -o bind

そして、ro remountも機能します:

# mount /mnt/1/lala /mnt/2 -o bind,remount,ro 

ただし、このバインドマウントだけでなく、マウント全体を変更していることになります。/ proc / mountsを見ると、バインドマウントと元のマウントの両方が読み取り専用に変更されていることがわかります。

/dev/loop0 /mnt/1 ext2 ro,relatime,errors=continue,user_xattr,acl 0 0
/dev/loop0 /mnt/2 ext2 ro,relatime,errors=continue,user_xattr,acl 0 0

だから、何をやっていることは、最初は読み取り専用のマウントおよびマウントに変更するようなもので、その後のコース読み取り専用のどの意志をマウントバインドを行います。

更新2016-07-20:

以下は4.5カーネルには当てはまりますが、4.3カーネルには当てはまりません(これは間違っています。以下の更新2を参照してください)。

カーネルには、読み取り専用を制御する2つのフラグがあります。

  • MS_READONLY:マウントは読み取り専用であるかどうかを示します
  • MNT_READONLY:「ユーザー」は、それが読み取り専用望んでいるかどうかを示します

4.5カーネルでmount -o bind,roは、実際に実行するとトリックが実行されます。たとえば、これ:

# mkdir /tmp/test
# mkdir /tmp/test/a /tmp/test/b
# mount -t tmpfs none /tmp/test/a
# mkdir /tmp/test/a/d
# mount -o bind,ro /tmp/test/a/d /tmp/test/b

/tmp/test/a/dtoの読み取り専用バインドマウントを作成し、次の/tmp/test/bように表示さ/proc/mountsれます。

none /tmp/test/a tmpfs rw,relatime 0 0
none /tmp/test/b tmpfs ro,relatime 0 0

より詳細なビューは/proc/self/mountinfo、ユーザービュー(名前空間)を考慮して表示されます。関連する行は次のとおりです。

363 74 0:49 / /tmp/test/a rw,relatime shared:273 - tmpfs none rw
368 74 0:49 /d /tmp/test/b ro,relatime shared:273 - tmpfs none rw

2行目では、roMNT_READONLY)とrw!MS_READONLY)の両方が表示されています。

最終結果は次のとおりです。

# echo a > /tmp/test/a/d/f
# echo a > /tmp/test/b/f
-su: /tmp/test/b/f: Read-only file system

更新2016-07-20#2:

これをもう少し掘り下げると、実際の動作は、util-linuxの一部であるlibmountのバージョンに依存していることがわかります。このサポートはこのコミットで追加され、バージョン2.27でリリースされました。

コミット9ac77b8a78452eab0612523d27fee52159f5016a
著者:カレル・ザック 
日付:月8月17日11:54:26 2015 +0200

    libmount:「bind、ro」のサポートを追加

    これで、2つのmount(8)呼び出しを使用して読み取り専用を作成する必要があります。
    マウント:

      mount / foo / bar -o bind
      マウント/ bar -o remount、ro、bind

    このパッチにより、「bind、ro」を指定でき、再マウントが完了します
    追加のmount(2)syscallによるlibmountによって自動的に。そうではありません
    もちろんアトミック。

    サインオフ:カレルザック 

回避策も提供します。この動作は、古いマウントと新しいマウントでstraceを使用して確認できます。

古い:

mount("/tmp/test/a/d", "/tmp/test/b", 0x222e240, MS_MGC_VAL|MS_RDONLY|MS_BIND, NULL) = 0 <0.000681>

新しい:

mount("/tmp/test/a/d", "/tmp/test/b", 0x1a8ee90, MS_MGC_VAL|MS_RDONLY|MS_BIND, NULL) = 0 <0.011492>
mount("none", "/tmp/test/b", NULL, MS_RDONLY|MS_REMOUNT|MS_BIND, NULL) = 0 <0.006281>

結論:

目的の結果を得るには、2つのコマンドを実行する必要があります(@Thomasが既に述べたように)。

mount SRC DST -o bind
mount DST -o remount,ro,bind

新しいバージョンのマウント(util-linux> = 2.27)は、実行時にこれを自動的に行います

mount SRC DST -o bind,ro

3
はい、しかしありません。IIRCには、異なるオプションを持つ異なるマウントポイント(ファイルシステムではない)のカーネルのサポートがあります。Debian mount -o bind,roは、読み取り/書き込みファイルシステムの読み取り専用ビューを作成するパッチを使用していました(しかし、wheezyには存在しないようです)。
ジル 'SO-悪であるのをやめる'

これが上記とどのように矛盾するかわかりません。ハックは、あまり意味をなさないものを含む、あらゆる種類のものを許可できます。現在、3.14カーネルでの読み取り専用の再マウントは、最終的に次の呼び出しによって処理されます:mnt_make_readonly(real_mount(mnt))。 (読み取り専用)マウントフラグ。少なくともそれは私の理解です。
V13

これは、カーネル3.3で最初に登場した「spread struct mount」パッチ(具体的にはこのcommit)の結果です。このパッチの結果がlkmlまたはlwnで議論されたかどうか知っていますか?
ジル「SO-悪であるのをやめる」

7
mount --bind /tmp/ /mnt/tmp/; mount -o remount,bind,ro /mnt/tmp/...それならtouch /tmp/aOKですが、touch /mnt/tmp/bを与えtouch: cannot touch ‘/mnt/tmp/b’: Read-only file systemます。これはDebian 3.13とkernel.org 3.14.2の両方で機能します。したがって、マウント全体を変更するだけではありません。少なくとも最近のカーネルではそうではありません。
デロバート

1
おそらく、「バインドマウントはただ...まあ...バインドマウント」という文言でしょう。本当に重要ですが、私には何の意味もありません。また、再マウントオプションを使用して2回目に動作する理由もわかりません。
StrongBad

9

適切な解決策は、実際に2回マウントすることです。コマンドラインで:

mount -t none -o bind /source/dir /destination/dir
mount -t none -o bind,remount,ro /source/dir /destination/dir

/etc/fstab

/source/dir            /destination/dir    none  bind            0 0
/source/dir            /destination/dir    none  remount,bind,ro 0 0

マニュアル(man mount)には次のように記載されています。

   The bind mounts.
          Since Linux 2.4.0 it is possible to remount part of the file hierarchy somewhere else. The call is
                 mount --bind olddir newdir
   [...]
          Note that the filesystem mount options will remain the same as those on the original mount point, and cannot be changed  by  passing  the  -o  option
          along with --bind/--rbind. The mount options can be changed by a separate remount command, for example:
          .
                 mount --bind olddir newdir
                 mount -o remount,ro newdir
          .
          Note  that  behavior  of  the remount operation depends on the /etc/mtab file. The first command stores the 'bind' flag to the /etc/mtab file and the
          second command reads the flag from the file.  If you have a system without the /etc/mtab file or if you explicitly define source and target  for  the
          remount command (then mount(8) does not read /etc/mtab), then you have to use bind flag (or option) for the remount command too. For example:
          .
                 mount --bind olddir newdir
                 mount -o remount,ro,bind olddir newdir

これは、少なくともUbuntu 14.04 LTSおよびカーネル3.19.0-51-lowlatencyで動作するようです。いいね!
ミッコランタライネン

0

あなたはmount(8)コマンドラインの観点から尋ねています(このサイトでは受け入れられます)。このコマンドは他の回答で説明されており、場合によっては、必要な2番目のmount(2)システムコールを抽象化します。

しかし、なぜ2番目のシステムコールが必要なのでしょうか?1回のmount(2)呼び出しで読み取り専用バインドマウントを作成できないのはなぜですか?

mount(2)manページには、他の人が指摘したように、そこにあることを説明して二組のフラグが設定されているのは:

  • 基になるファイルシステムフラグ
  • VFSマウントポイントフラグ

それは言います:

Linux 2.6.16以降、MS_RDONLYマウントポイントごと、および基礎となるファイルシステムで設定またはクリアできます。マウントされたファイルシステムは、ファイルシステムもマウントポイントも読み取り専用としてフラグが立てられていない場合にのみ書き込み可能です。

そしてに関してMS_REMOUNT

Linux 2.6.26以降では、このフラグを使用しMS_BINDて、マウントポイントごとのフラグのみを変更できます。これは、基礎となるファイルシステムを変更せずにマウントポイントの「読み取り専用」フラグを設定またはクリアする場合に特に便利です。マウントフラグを次のように指定します。

      MS_REMOUNT | MS_BIND | MS_RDONLY

他のマウントポイントに影響を与えることなく、このマウントポイントを介してアクセスを読み取り専用にします。

この問題は、バインドマウントが最初に導入されたときに発生したと思います。

mountflagsに含まれている場合MS_BIND(Linux 2.4以降で使用可能)、バインドマウントを実行します。... mountflags引数の残りのビットも無視されますが、例外がありMS_RECます。(バインドマウントには、基礎となるマウントポイントと同じマウントオプションがあります。)

MS_BIND | MS_REMOUNTVFSフラグだけを設定するための信号として使用する代わりに、それらMS_RDONLYはinitialとともに除外(および受け入れ)を選択MS_BINDし、マウントポイントに適用することができたようです。

そのため、mount(2)システムコールのやや奇妙なセマンティクスのために:

  • 最初の呼び出しはバインドマウントを作成し、他のすべてのフラグは無視されます
  • 2番目の呼び出し(再マウント)は、マウントポイントフラグを読み取り専用に設定します
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.