Perché mount non rispetta l'opzione di sola lettura per i mount bind?


35

Sul mio sistema Arch Linux (Linux Kernel 3.14.2) i bind mount non rispettano l'opzione di sola lettura

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

crea il file /mnt/foo. La voce pertinente /proc/mountsè

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

Le opzioni di montaggio non corrispondono le mie opzioni richieste, ma fanno corrispondere sia il comportamento di lettura / scrittura del bind montare e le opzioni utilizzate per originariamente montare /dev/sda2su/

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

Se, tuttavia, rimonto il supporto, rispetta l'opzione di sola lettura

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

e la relativa voce in /proc/mounts/

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

sembra quello che potrei aspettarmi (anche se in verità mi aspetterei di vedere il percorso completo della testdirectory). Anche la voce /proc/mounts/per il montaggio originale di /dev/sda2/on /rimane invariata e rimane in lettura / scrittura

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

Questo comportamento e la soluzione sono noti almeno dal 2008 e sono documentati nella pagina man dimount

Notare che le opzioni di mount del filesystem rimarranno le stesse di quelle sul punto di mount originale e non possono essere cambiate passando l'opzione -o insieme a --bind / - rbind. Le opzioni di montaggio possono essere modificate da un comando di rimontaggio separato

Non tutte le distribuzioni si comportano allo stesso modo. Arch sembra non riuscire a rispettare silenziosamente le opzioni mentre Debian genera un avviso quando il mount di bind non ottiene mount di sola lettura

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

Ci sono rapporti secondo cui questo comportamento è stato "risolto" in Debian Lenny e Squeeze sebbene non sembri essere una correzione universale né funziona ancora in Debian Wheezy. Qual è la difficoltà associata a far sì che mount bind rispetti l'opzione di sola lettura sul mount iniziale?


Hai un / etc / mtab?
eyoung100,

Vedi anche thread.gmane.org/gmane.linux.utilities.util-linux-ng/2979 e una soluzione alternativa utilizzando mount -t binde uno script di supporto su bugs.launchpad.net/ubuntu/+source/mountall/+bug/519380
Stéphane Chazelas,

@ECarterYoung yes I have an /etc/mtab. Dopo il mount iniziale la voce dice che il mount è rw e dopo il rimontaggio dice ro, quindi riporta lo stato del mount correttamente. È solo il comando mount che fallisce.
StrongBad

3
Ho testato su due macchine di prova / instabili Debian, una con un kernel Debian e una con un kernel kernel.org, nessuna delle quali funziona mount --bind -o ro, entrambi hanno sputato un messaggio mount: warning: «mountpoint» seems to be mounted read-write.Quindi sembra che Debian abbia abbandonato o perso la patch ad un certo punto ... Rimonta funziona, però.
derobert,

2
@StrongBad Testato come richiesto e non funziona neanche.
derobert,

Risposte:


21

Bind mount è solo ... beh ... un mount bind. Cioè non è una nuova cavalcatura. "Collega" / "espone" / "considera" una sottodirectory come un nuovo punto di montaggio. Pertanto, non può modificare i parametri di montaggio. Ecco perché stai ricevendo lamentele:

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

Ma come hai detto, funziona un normale attacco bind:

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

E poi un ro remount funziona anche:

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

Tuttavia, ciò che accade è che stai cambiando l'intero innesto e non solo questo innesto. Se dai un'occhiata a / proc / mounts vedrai che sia il bind mount che il mount originale cambiano in sola lettura:

/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

Quindi, quello che stai facendo è come cambiare il mount iniziale in un mount di sola lettura e poi fare un mount di binding che ovviamente sarà di sola lettura.

AGGIORNAMENTO 2016-07-20:

Quanto segue è vero per i kernel 4.5, ma non per i kernel 4.3 (Questo è sbagliato. Vedi l'aggiornamento n. 2 di seguito):

Il kernel ha due flag che controllano la sola lettura:

  • Il MS_READONLY : Indica se il mount è di sola lettura
  • Il MNT_READONLY : Indica se "l'utente" lo desidera in sola lettura

Su un kernel 4.5, fare una mount -o bind,rovolontà farà davvero il trucco. Ad esempio, questo:

# 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

creerà un mount bind di sola lettura di /tmp/test/a/dto /tmp/test/b, che sarà visibile /proc/mountscome:

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

Una vista più dettagliata è visibile in /proc/self/mountinfo, che prende in considerazione la vista utente (spazio dei nomi). Le linee pertinenti saranno queste:

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

Dove sulla seconda riga, puoi vedere che dice sia ro( MNT_READONLY) che rw(!MS_READONLY ).

Il risultato finale è questo:

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

AGGIORNAMENTO 2016-07-20 # 2:

Un po 'più di approfondimento mostra che il comportamento in effetti dipende dalla versione di libmount che fa parte di util-linux. Il supporto per questo è stato aggiunto con questo commit ed è stato rilasciato con la versione 2.27:

commit 9ac77b8a78452eab0612523d27fee52159f5016a
Autore: Karel Zak 
Data: lun 17 ago 11:54:26 2015 +0200

    libmount: aggiungi il supporto per "bind, ro"

    Ora è necessario utilizzare due chiamate mount (8) per creare una sola lettura
    montare:

      mount / foo / bar -o bind
      mount / bar -o rimontaggio, ro, bind

    Questa patch consente di specificare "bind, ro" e il rimontaggio è fatto
    automaticamente da libmount da mount (2) syscall aggiuntivo. Non è
    atomico ovviamente.

    Firmato-fuori-da: Karel Zak 

che fornisce anche la soluzione alternativa. Il comportamento può essere visto usando strace su un mount più vecchio e più recente:

Vecchio:

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

Nuovo:

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>

Conclusione:

Per ottenere il risultato desiderato è necessario eseguire due comandi (come già detto da @Thomas):

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

Le versioni più recenti di mount (util-linux> = 2.27) lo fanno automaticamente quando si esegue

mount SRC DST -o bind,ro

3
Sì, ma no. In IIRC esiste un supporto nel kernel per diversi punti di mount (non filesystem) per avere diverse opzioni. Debian aveva una patch che faceva mount -o bind,rocreare una vista di sola lettura di un filesystem di lettura / scrittura (ma non sembra più essere lì in wheezy).
Gilles 'SO- smetti di essere malvagio'

Non vedo come questo contraddica quanto sopra. Gli hack possono consentire tutti i tipi di cose, comprese le cose che non hanno molto senso. Attualmente il remaunt di sola lettura sul kernel 3.14 viene infine gestito da questa chiamata: mnt_make_readonly (real_mount (mnt)), che come puoi vedere usa real_mount (), quindi influenza praticamente il vero mount e fa sì che i mount di bind riflettano il nuovo (sola lettura) mount flag. Almeno questa è la mia comprensione.
V13,

Quindi questa sarebbe una conseguenza della patch "spread struct mount" (in particolare questo commit ), che appare per la prima volta nel kernel 3.3. Sai se le conseguenze di questa patch sono state discusse su lkml o lwn?
Gilles 'SO- smetti di essere malvagio'

7
mount --bind /tmp/ /mnt/tmp/; mount -o remount,bind,ro /mnt/tmp/... allora touch /tmp/ava bene, ma touch /mnt/tmp/btouch: cannot touch ‘/mnt/tmp/b’: Read-only file system. Funziona su Debian 3.13 e kernel.org 3.14.2. Quindi non cambia solo l'intera montatura. Almeno non con kernel recenti.
derobert

1
Presumibilmente l'affermazione che un "attacco Bind è solo ... beh ... un attacco Bind." è davvero importante ma non significa nulla per me. Inoltre non capisco perché funzioni la seconda volta con l'opzione di rimontaggio.
StrongBad

9

La soluzione corretta è davvero montarla due volte. Sulla riga di comando:

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

In /etc/fstab:

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

Il manuale ( man mount) lo afferma in questo modo:

   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

Questo sembra funzionare almeno con Ubuntu 14.04 LTS e kernel 3.19.0-51-lowlatency. Bello!
Mikko Rantalainen,

0

Stai chiedendo dal punto di vista della mount(8)riga di comando (che è accettabile su questo sito). Tale comando è stato discusso nelle altre risposte e, in alcuni casi, estrae la seconda mount(2)chiamata di sistema necessaria .

Ma perché è necessaria la seconda chiamata di sistema? Perché una singola mount(2)chiamata non può creare il mount del binding di sola lettura?

La mount(2)pagina man spiega che ci sono, come altri hanno sottolineato, due set di flag impostati:

  • I flag del file system sottostante
  • I flag del punto di montaggio VFS

Dice:

A partire da Linux 2.6.16, MS_RDONLYpuò essere impostato o cancellato in base al punto di montaggio e sul file system sottostante. Il filesystem montato sarà scrivibile solo se né il filesystem né il mountpoint sono contrassegnati come di sola lettura.

E riguardo a MS_REMOUNT:

A partire da Linux 2.6.26, questo flag può essere usato con MS_BINDper modificare solo i flag per punto di mount. Ciò è particolarmente utile per impostare o cancellare il flag "sola lettura" su un punto di montaggio senza modificare il file system sottostante. Specificare mountflags come:

      MS_REMOUNT | MS_BIND | MS_RDONLY

accederà a questo mountpoint in sola lettura, senza influire su altri mount point.

Penso che il problema si sia verificato quando sono stati introdotti per la prima volta i bind mount:

Se mountflags include MS_BIND(disponibile da Linux 2.4), quindi eseguire un mount bind. ... Anche i bit rimanenti nell'argomento mountflags vengono ignorati, ad eccezione di MS_REC. (Il bind mount ha le stesse opzioni di mount del punto di mount sottostante.)

Sembra che, invece di utilizzare MS_BIND | MS_REMOUNTcome segnale per impostare solo i flag VFS, avrebbero potuto scegliere di tranne (e accettare) MS_RDONLYinsieme all'iniziale MS_BINDe applicarlo al punto di montaggio.

Quindi a causa della semantica un po 'strana della mount(2)chiamata di sistema:

  • La prima chiamata crea il bind mount e tutti gli altri flag vengono ignorati
  • La seconda chiamata (con rimontaggio) imposta i flag del punto di montaggio su sola lettura
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.