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/sda2
originalmente/
/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 test
diretó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,ro
realmente 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/d
to /tmp/test/b
, que será visível /proc/mounts
como:
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_RDONLY
pode 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_BIND
modificar 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 deMS_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_REMOUNT
como sinal para definir apenas os sinalizadores VFS, eles poderiam ter optado por except (e aceitar) MS_RDONLY
junto com o inicial MS_BIND
e 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