Заключение:

Заключение:

В моей системе Arch Linux (Linux Kernel 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). Запись /proc/mounts/для исходного монтирования /dev/sda2/on /также не изменилась и остается доступной для чтения/записи

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

Такое поведение и способы его обхода известны по крайней мере с тех пор, как2008и задокументированы на странице руководстваmount

Обратите внимание, что параметры монтирования файловой системы останутся такими же, как и в исходной точке монтирования, и не могут быть изменены путем передачи параметра -o вместе с --bind/--rbind. Параметры монтирования можно изменить с помощью отдельной команды перемонтирования

Не все дистрибутивы ведут себя одинаково. Arch, похоже, молча не учитывает параметры, в то время как Debian выдает предупреждение, когда привязка монтирования не получает монтирование только для чтения

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

Есть сообщения, что это поведение было «исправлено» в Debian.Ленни и Сжимайхотя это, кажется, неуниверсальное решениеи это все еще не работает в Debian Wheezy. В чем сложность, связанная с тем, чтобы заставить bind mount уважать опцию только для чтения при первоначальном монтировании?

решение1

Bind mount — это просто... ну... bind mount. То есть это не новое монтирование. Оно просто "связывает"/"открывает"/"рассматривает" подкаталог как новую точку монтирования. Таким образом, оно не может изменить параметры монтирования. Вот почему вы получаете жалобы:

# 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 

Однако происходит то, что вы меняете все монтирование, а не только это монтирование bind. Если вы посмотрите на /proc/mounts, вы увидите, что и монтирование bind, и исходное монтирование меняются на read-only:

/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 ниже):

Ядро имеет два флага, которые управляют режимом «только чтение»:

  • : Указывает MS_READONLY, доступно ли монтирование только для чтения.
  • : Указывает MNT_READONLY, хочет ли «пользователь» иметь доступ только для чтения.

На ядре 4.5 выполнение a 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/dк /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

Где во второй строке вы можете видеть, что написано и ro( MNT_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:

Немного покопавшись в этом, мы видим, что поведение на самом деле зависит от версии libmount, которая является частью util-linux. Поддержка этого была добавлена ​​с помощью этогосовершитьи был выпущен с версией 2.27:

совершить 9ac77b8a78452eab0612523d27fee52159f5016a
Автор: Карел Зак
Дата: Пн 17 авг 11:54:26 2015 +0200

    libmount: добавлена ​​поддержка "bind,ro"

    Теперь необходимо использовать два вызова mount(8) для создания файла, доступного только для чтения.
    устанавливать:

      монтировать /foo /bar -o привязать
      mount /bar -o перемонтировать,ro,bind

    Этот патч позволяет указать «bind,ro» и перемонтирование будет выполнено.
    автоматически с помощью libmount с помощью дополнительного системного вызова mount(2). Это не
    атомный конечно.

    Подписано: Карел Зак

что также обеспечивает обходной путь. Поведение можно увидеть, используя 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>

Заключение:

Для достижения желаемого результата необходимо выполнить две команды (как уже сказал @Thomas):

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

Более новые версии mount (util-linux >=2.27) делают это автоматически при запуске

mount SRC DST -o bind,ro

решение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

решение3

Вы спрашиваете с точки зрения mount(8)командной строки (что приемлемо на этом сайте). Эта команда обсуждалась в других ответах и ​​в некоторых случаях абстрагируется от необходимого второго mount(2)системного вызова.

Но зачем нужен второй системный вызов? Почему один mount(2)вызов не может создать read-only bind mount?

Themount(2)страница руководстваобъясняет, что, как уже отмечали другие, существуютдва набораиз устанавливаемых флагов:

  • Базовые флаги файловой системы
  • Флаги точки монтирования VFS

Там говорится:

Начиная с Linux 2.6.16, MS_RDONLYможет быть установлен или очищен на основе точки монтирования, а также на основе базовой файловой системы. Смонтированная файловая система будет доступна для записи только в том случае, если ни файловая система, ни точка монтирования не помечены как доступные только для чтения.

И относительно MS_REMOUNT:

Начиная с Linux 2.6.26, этот флаг можно использовать MS_BINDдля изменения только флагов per-mount-point. Это особенно полезно для установки или снятия флага "только для чтения" на точке монтирования без изменения базовой файловой системы. Указание mountflags как:

      MS_REMOUNT | MS_BIND | MS_RDONLY

сделает доступ через эту точку монтирования только для чтения, не затрагивая другие точки монтирования.

Я думаю, что проблема возникла, когда впервые были введены привязные крепления:

Если mountflags включает MS_BIND(доступно с Linux 2.4), то выполнить монтирование привязки. ... Остальные биты в аргументе mountflags также игнорируются, за исключением MS_REC. (Монтирование привязки имеет те же параметры монтирования, что и базовая точка монтирования.)

Похоже, что вместо использования MS_BIND | MS_REMOUNTв качестве сигнала для установки только флагов VFS, они могли бы выбрать исключение (и принятие) MS_RDONLYвместе с начальным MS_BINDи применить его к точке монтирования.

Итак, из-за несколько странной семантики системного mount(2)вызова:

  • Первый вызов создает привязку монтирования, а все остальные флаги игнорируются.
  • Второй вызов (с повторным монтированием) устанавливаетТочка монтированияфлаги только для чтения

Связанный контент