Conclusão:

Conclusão:

No meu sistema Arch Linux (Linux Kernel 3.14.2), as montagens de ligação não respeitam a opção somente leitura

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

cria o arquivo /mnt/foo. A entrada relevante /proc/mountsé

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

As opções de montagem não correspondem às opções solicitadas, mas correspondem ao comportamento de leitura/gravação da montagem de ligação e às opções usadas para montar /dev/sda2originalmente/

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

Se, no entanto, eu remontar a montagem, ela respeitará a opção somente leitura

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

e a entrada relevante em/proc/mounts/

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

parece o que eu esperava (embora na verdade eu esperasse ver o caminho completo do testdiretório). A entrada /proc/mounts/para a montagem original de /dev/sda2/on /também permanece inalterada e permanece como leitura/gravação

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

Este comportamento e a solução alternativa são conhecidos desde pelo menos2008e estão documentados na página de manual domount

Observe que as opções de montagem do sistema de arquivos permanecerão as mesmas do ponto de montagem original e não podem ser alteradas passando a opção -o junto com --bind/--rbind. As opções de montagem podem ser alteradas por um comando de remontagem separado

Nem todas as distribuições se comportam da mesma forma. O Arch parece falhar silenciosamente em respeitar as opções enquanto o Debian gera um aviso quando a montagem de ligação não obtém a montagem somente leitura

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

Há relatos de que esse comportamento foi “consertado” no DebianLenny e Squeezeembora não pareça ser umcorreção universalnem ainda funciona no Debian Wheezy. Qual é a dificuldade associada a fazer com que o bind mount respeite a opção somente leitura na montagem inicial?

Responder1

A montagem vinculada é apenas... bem... uma montagem vinculada. Ou seja, não é uma montaria nova. Ele apenas "liga"/"expõe"/"considera" um subdiretório como um novo ponto de montagem. Como tal, não pode alterar os parâmetros de montagem. É por isso que você está recebendo reclamações:

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

Mas como você disse, uma montagem normal funciona:

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

E então uma remontagem ro também funciona:

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

Porém o que acontece é que você está alterando toda a montagem e não apenas essa montagem de ligação. Se você der uma olhada em /proc/mounts você verá que tanto a montagem vinculada quanto a montagem original mudam para somente leitura:

/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

Então o que você está fazendo é como alterar a montagem inicial para uma montagem somente leitura eentãofazendo uma montagem vinculada que, obviamente, será somente leitura.

ATUALIZAÇÃO 20/07/2016:

O seguinte é verdadeiro para kernels 4.5, mas não é verdade para kernels 4.3 (isso está errado. Consulte a atualização nº 2 abaixo):

O kernel possui dois sinalizadores que controlam somente leitura:

  • O MS_READONLY: Indicando se a montagem é somente leitura
  • The MNT_READONLY: Indicando se o "usuário" deseja somente leitura

Em um kernel 4.5, fazer a mount -o bind,rorealmente resolverá o problema. Por exemplo, isto:

# 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

criará uma montagem de ligação somente leitura de /tmp/test/a/dto /tmp/test/b, que será visível /proc/mountscomo:

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

Uma visão mais detalhada é visível em /proc/self/mountinfo, que leva em consideração a visão do usuário (namespace). As linhas relevantes serão estas:

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

Onde na segunda linha, você pode ver que diz ro( MNT_READONLY) e rw( !MS_READONLY).

O resultado final é este:

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

ATUALIZAÇÃO 20/07/2016 # 2:

Um pouco mais de investigação mostra que o comportamento na verdade depende da versão do libmount que faz parte do util-linux. O suporte para isso foi adicionado com estecomprometer-see foi lançado com a versão 2.27:

cometer 9ac77b8a78452eab0612523d27fee52159f5016a
Autor: Karel Zak
Data: segunda-feira, 17 de agosto 11:54:26 2015 +0200

    libmount: adiciona suporte para "bind,ro"

    Agora é necessário usar duas chamadas mount(8) para criar um arquivo somente leitura
    montar:

      montar /foo /bar -o vincular
      montar /bar -o remontar,ro,ligar

    Este patch permite especificar "bind,ro" e a remontagem é feita
    automaticamente por libmount por syscall mount(2) adicional. Não é
    atômico, é claro.

    Assinado por: Karel Zak

que também fornece a solução alternativa. O comportamento pode ser visto usando strace em uma montagem mais antiga e mais recente:

Velho:

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

Novo:

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>

Conclusão:

Para alcançar o resultado desejado é necessário executar dois comandos (como o @Thomas já disse):

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

Versões mais recentes do mount (util-linux >=2.27) fazem isso automaticamente quando alguém executa

mount SRC DST -o bind,ro

Responder2

A solução adequada é montá-lo duas vezes. Na linha de comando:

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

Em /etc/fstab:

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

O manual ( man mount) afirma assim:

   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

Responder3

Você está perguntando da perspectiva da mount(8)linha de comando (que é aceitável neste site). Esse comando foi discutido nas outras respostas e, em alguns casos, abstrai a segunda mount(2)chamada de sistema necessária.

Mas por que a segunda chamada do sistema é necessária? Por que uma única chamada não pode mount(2)criar a montagem de ligação somente leitura?

Omount(2)página de manualexplica que existem, como outros apontaram,dois conjuntosde sinalizadores sendo definidos:

  • Os sinalizadores do sistema de arquivos subjacente
  • Os sinalizadores de ponto de montagem VFS

Diz:

Desde o Linux 2.6.16, MS_RDONLYpode ser definido ou desmarcado por ponto de montagem, bem como no sistema de arquivos subjacente. O sistema de arquivos montado será gravável somente se nem o sistema de arquivos nem o ponto de montagem estiverem sinalizados como somente leitura.

E em relação a MS_REMOUNT:

Desde o Linux 2.6.26, esse sinalizador pode ser usado para MS_BINDmodificar apenas os sinalizadores por ponto de montagem. Isto é particularmente útil para definir ou limpar o sinalizador "somente leitura" em um ponto de montagem sem alterar o sistema de arquivos subjacente. Especificando mountflags como:

      MS_REMOUNT | MS_BIND | MS_RDONLY

tornará o acesso através deste ponto de montagem somente leitura, sem afetar outros pontos de montagem.

Acho que o problema surgiu quando as montagens de ligação foram introduzidas pela primeira vez:

Se mountflags incluir MS_BIND(disponível desde o Linux 2.4), execute uma montagem vinculada. ... Os bits restantes no argumento mountflags também são ignorados, com exceção de MS_REC. (A montagem vinculada tem as mesmas opções de montagem que o ponto de montagem subjacente.)

Parece que, em vez de usar MS_BIND | MS_REMOUNTcomo sinal para definir apenas os sinalizadores VFS, eles poderiam ter optado por except (e aceitar) MS_RDONLYjunto com o inicial MS_BINDe aplicá-lo ao ponto de montagem.

Então, devido à semântica um tanto estranha da mount(2)chamada do sistema:

  • A primeira chamada cria a montagem de ligação e todos os outros sinalizadores são ignorados
  • A segunda chamada (com remontagem) define oponto de montagemsinalizadores para somente leitura

informação relacionada