Tại sao mount không tôn trọng tùy chọn chỉ đọc cho mount mount?


35

Trên hệ thống Arch Linux của tôi (Linux Kernel 3.14.2), các liên kết gắn kết không tôn trọng tùy chọn chỉ đọc

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

tạo ra các tập tin /mnt/foo. Các mục có liên quan trong /proc/mounts

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

Các tùy chọn gắn kết không phù hợp với lựa chọn của tôi yêu cầu, nhưng làm phù hợp với cả đọc / ghi hành vi của các ràng buộc gắn kết và các tùy chọn để sử dụng ban đầu gắn /dev/sda2trên/

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

Tuy nhiên, nếu tôi nhắc lại mount thì nó tôn trọng tùy chọn chỉ đọc

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

và các mục có liên quan trong /proc/mounts/

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

trông giống như những gì tôi có thể mong đợi (mặc dù trong thực tế tôi sẽ mong đợi để xem đường dẫn đầy đủ của testthư mục). Mục nhập /proc/mounts/cho gắn kết gốc của /dev/sda2/on /cũng không thay đổi và vẫn đọc / ghi

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

Hành vi này và công việc xung quanh đã được biết đến từ ít nhất là năm 2008 và được ghi lại trong trang củamount

Lưu ý rằng các tùy chọn gắn kết hệ thống tệp sẽ giữ nguyên như các tùy chọn trên điểm gắn kết ban đầu và không thể thay đổi bằng cách chuyển tùy chọn -o cùng với --bind / - rbind. Các tùy chọn gắn kết có thể được thay đổi bằng lệnh remount riêng

Không phải tất cả các bản phân phối hành xử giống nhau. Arch dường như không thể tôn trọng các tùy chọn trong khi Debian tạo cảnh báo khi gắn kết liên kết không chỉ có giá trị gắn kết

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

Có nhiều báo cáo cho rằng hành vi này đã được "sửa" trong Debian Lenny và Squeeze mặc dù nó dường như không phải là một bản sửa lỗi chung và nó vẫn không hoạt động trong Debian Wheezy. Khó khăn gì liên quan đến việc tạo liên kết gắn kết tôn trọng tùy chọn chỉ đọc trên giá trị gắn kết ban đầu?


Bạn có / etc / mtab không?
Eyoung100

Xem thêm thread.gmane.org/gmane.linux.utilities.util-linux-ng/2979 và một workaround bằng cách sử dụng mount -t bindvà một kịch bản helper tại bugs.launchpad.net/ubuntu/+source/mountall/+bug/519380
Stéphane Chazelas

@ECarterYoung vâng tôi có một /etc/mtab. Sau khi gắn kết ban đầu, mục nhập cho biết giá trị gắn kết là rw và sau khi kết thúc, nó báo ro, do đó, nó báo cáo chính xác trạng thái của giá treo. Nó chỉ là lệnh mount thất bại.
StrongBad

3
Tôi đã thử nghiệm trên hai máy kiểm tra Debian / máy không ổn định, một máy chạy kernel Debian và một chạy kernel kernel.org, không hoạt động mount --bind -o ro, cả hai đều phát ra một thông báo mount: warning: «mountpoint» seems to be mounted read-write.Vì vậy, có vẻ như Debian đã đánh rơi hoặc mất bản vá tại một số điểm ... công trình, mặc dù.
derobert

2
@StrongBad Đã kiểm tra theo yêu cầu và nó cũng không hoạt động.
derobert

Câu trả lời:


21

Gắn kết ràng buộc chỉ là ... à ... một liên kết gắn kết. Tức là nó không phải là một thú cưỡi mới. Nó chỉ "liên kết" / "lộ" / "coi" thư mục con là điểm gắn kết mới. Vì vậy, nó không thể thay đổi các tham số gắn kết. Đó là lý do tại sao bạn nhận được khiếu nại:

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

Nhưng như bạn đã nói, một mount mount thông thường hoạt động:

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

Và sau đó một ro remount cũng hoạt động:

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

Tuy nhiên, điều xảy ra là bạn đang thay đổi toàn bộ giá treo và không chỉ giá treo này. Nếu bạn xem / Proc / mounts, bạn sẽ thấy cả mount mount và mount gốc thay đổi thành chỉ đọc:

/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

Vì vậy, những gì bạn đang làm giống như thay đổi giá trị ban đầu thành giá treo chỉ đọc và sau đó thực hiện gắn kết liên kết, tất nhiên sẽ chỉ đọc.

CẬP NHẬT 2016-07-20:

Điều sau đây đúng với hạt nhân 4,5, nhưng không đúng với hạt nhân 4,3 (Điều này sai. Xem cập nhật # 2 bên dưới):

Nhân có hai cờ điều khiển chỉ đọc:

  • The MS_READONLY: Cho biết giá treo có ở chế độ chỉ đọc không
  • The MNT_READONLY: Cho biết "người dùng" có muốn nó chỉ đọc không

Trên một hạt nhân 4.5, thực hiện một mount -o bind,roý chí thực sự làm thủ thuật. Ví dụ: cái này:

# 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

sẽ tạo ra một chỉ đọc ràng buộc gắn kết của /tmp/test/a/dđể /tmp/test/b, mà sẽ được hiển thị trong /proc/mountsnhư:

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

Một chế độ xem chi tiết hơn có thể nhìn thấy trong /proc/self/mountinfođó xem xét chế độ xem người dùng (không gian tên). Các dòng liên quan sẽ là:

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

Ở đâu trên dòng thứ hai, bạn có thể thấy nó nói cả ro( MNT_READONLY) và rw( !MS_READONLY).

Kết quả cuối cùng là đây:

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

CẬP NHẬT 2016-07-20 # 2:

Đi sâu hơn một chút vào điều này cho thấy rằng hành vi trên thực tế phụ thuộc vào phiên bản libmount là một phần của linux-linux. Hỗ trợ cho điều này đã được thêm vào với cam kết này và được phát hành với phiên bản 2.27:

cam kết 9ac77b8a78452ables0612523d27fee52159f5016a
Tác giả: Karel Zak 
Ngày: Thứ Hai 17 tháng 8 11:54:26 2015 +0200

    libmount: thêm hỗ trợ cho "bind, ro"

    Bây giờ không cần thiết phải sử dụng hai lệnh gọi (8) để tạo chỉ đọc
    gắn kết:

      gắn kết / foo / bar -o liên kết
      gắn kết / thanh -o remount, ro, ràng buộc

    Bản vá này cho phép chỉ định "liên kết, ro" và việc hoàn thành được thực hiện
    tự động bằng libmount bằng tòa nhà gắn kết (2) bổ sung. Không phải
    nguyên tử tất nhiên.

    Đã ký: Karel Zak 

cũng cung cấp cách giải quyết. Hành vi có thể được nhìn thấy bằng cách sử dụng strace trên một mount cũ hơn và mới hơn:

Cũ:

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

Mới:

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>

Phần kết luận:

Để đạt được kết quả mong muốn, người ta cần chạy hai lệnh (như @Thomas đã nói):

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

Các phiên bản mới hơn của mount (produc-linux> = 2.27) tự động thực hiện việc này khi chạy

mount SRC DST -o bind,ro

3
Đúng nhưng không phải thế. IIRC có một số hỗ trợ trong kernel cho các điểm gắn kết khác nhau (không phải hệ thống tập tin) để có các tùy chọn khác nhau. Debian đã từng có một bản vá mount -o bind,rotạo ra chế độ xem chỉ đọc của hệ thống tệp đọc ghi (nhưng dường như nó không còn ở đó trong trạng thái khò khè).
Gilles 'SO- ngừng trở nên xấu xa'

Tôi không thấy làm thế nào điều này mâu thuẫn ở trên. Hacks có thể cho phép tất cả các loại công cụ, bao gồm cả những thứ không có ý nghĩa nhiều. Hiện tại, phần giới thiệu chỉ đọc trên kernel 3.14 cuối cùng được xử lý bởi lệnh gọi này: mnt_make_readonly (real_mount (mnt)), như bạn có thể thấy sử dụng real_mount (), do đó, nó thực sự ảnh hưởng đến mount thực sự và điều đó gây ra sự gắn kết liên kết (chỉ đọc) gắn cờ. Ít nhất đó là sự hiểu biết của tôi.
V13

Vì vậy, đây sẽ là hậu quả của bản vá lỗi mount mount struct struct (cụ thể là cam kết này ), lần đầu tiên xuất hiện trong kernel 3.3. Bạn có biết nếu hậu quả của bản vá này đã được thảo luận trên lkml hoặc lwn?
Gilles 'SO- ngừng trở nên xấu xa'

7
mount --bind /tmp/ /mnt/tmp/; mount -o remount,bind,ro /mnt/tmp/... Sau đó touch /tmp/alà OK, nhưng touch /mnt/tmp/bcho touch: cannot touch ‘/mnt/tmp/b’: Read-only file system. Nó hoạt động trên cả Debian 3.13 và kernel.org 3.14.2. Vì vậy, nó không chỉ thay đổi toàn bộ gắn kết. Ít nhất là không với hạt nhân gần đây.
derobert

1
Có lẽ tuyên bố rằng "Bind mount chỉ là ... à ... một mount mount." là thực sự quan trọng nhưng có nghĩa là không có gì với tôi. Tôi cũng không hiểu tại sao sau đó nó hoạt động lần thứ hai với tùy chọn remount.
StrongBad

9

Giải pháp thích hợp là thực sự gắn kết hai lần. Trên dòng lệnh:

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

Trong /etc/fstab:

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

Hướng dẫn ( man mount) nói theo cách đó:

   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

Điều này dường như hoạt động với ít nhất Ubuntu 14.04 LTS và kernel 3.19.0-51-lowlatency. Tốt đẹp!
Mikko Rantalainen

0

Bạn đang hỏi từ góc độ của mount(8)dòng lệnh (có thể chấp nhận được trên trang web này). Lệnh đó đã được thảo luận trong các câu trả lời khác và trong một số trường hợp, tóm tắt mount(2)cuộc gọi hệ thống thứ hai cần thiết .

Nhưng tại sao cuộc gọi hệ thống thứ hai lại cần thiết? Tại sao một mount(2)cuộc gọi không thể tạo ra liên kết gắn kết chỉ đọc?

Các mount(2)trang người đàn ông giải thích rằng có, như những người khác đã chỉ ra, hai bộ cờ là thiết lập:

  • Các cờ hệ thống tập tin cơ bản
  • Các cờ gắn điểm VFS

Nó nói rằng:

Kể từ Linux 2.6.16, MS_RDONLYcó thể được đặt hoặc xóa trên cơ sở mỗi điểm gắn kết cũng như trên hệ thống tệp cơ bản. Hệ thống tập tin được gắn kết sẽ chỉ có thể ghi nếu cả hệ thống tập tin và điểm gắn kết không được gắn cờ là chỉ đọc.

Và liên quan đến MS_REMOUNT:

Kể từ Linux 2.6.26, cờ này có thể được sử dụng MS_BINDđể chỉ sửa đổi các cờ trên mỗi điểm gắn kết. Điều này đặc biệt hữu ích để cài đặt hoặc xóa cờ "chỉ đọc" trên điểm gắn kết mà không thay đổi hệ thống tệp cơ bản. Chỉ định mountflags như:

      MS_REMOUNT | MS_BIND | MS_RDONLY

sẽ truy cập thông qua điểm gắn kết này chỉ đọc, mà không ảnh hưởng đến các điểm gắn kết khác.

Tôi nghĩ rằng vấn đề đã xảy ra khi các liên kết gắn kết được giới thiệu lần đầu tiên:

Nếu mountflags bao gồm MS_BIND(có sẵn từ Linux 2.4), thì thực hiện gắn kết liên kết. ... Các bit còn lại trong đối số mountflags cũng bị bỏ qua, ngoại trừ MS_REC. (Gắn kết liên kết có các tùy chọn gắn kết tương tự như điểm gắn kết cơ bản.)

Có vẻ như, thay vì sử dụng MS_BIND | MS_REMOUNTlàm tín hiệu để chỉ đặt các cờ VFS, họ có thể đã chọn ngoại trừ (và chấp nhận) MS_RDONLYcùng với ban đầu MS_BINDvà áp dụng nó vào điểm gắn kết.

Vì vậy, do ngữ nghĩa hơi kỳ lạ của mount(2)cuộc gọi hệ thống:

  • Cuộc gọi đầu tiên tạo ra liên kết gắn kết và tất cả các cờ khác được bỏ qua
  • Cuộc gọi thứ hai (có kết nối lại) đặt các cờ điểm gắn kết thành chỉ đọc
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.