Làm cách nào để sử dụng OverlayFS để bảo vệ hệ thống tập tin gốc?


8

Làm cách nào để sử dụng chính xác OverlayFS để bảo vệ hệ thống tập tin gốc của tôi?

Tôi có một hệ thống nhúng khởi động và chạy từ thẻ SD. Vì nó sẽ bị mất điện đột ngột, tôi muốn bảo vệ hệ thống tập tin gốc. OverlayFS có vẻ như là giải pháp đơn giản nhất, nhưng các ví dụ tôi thấy thường không liên quan đến hệ thống tệp gốc và / hoặc sử dụng một tmpfs không tốt cho tôi vì tôi có rất ít bộ nhớ.

Tôi đang sử dụng Linux Kernel 4.4.0 CONFIG_OVERLAY_FS=yđược kích hoạt. Hệ thống tập tin của tôi là xenial-base-armhf.tar.gzvà tôi đã làm apt install -y overlayroot.

Thẻ SD của tôi trông như:

# fdisk -l /dev/mmcblk1
Disk /dev/mmcblk1: 29 GiB, 31104958464 bytes, 60751872 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x7f56a0ab

Device         Boot    Start      End  Sectors  Size Id Type
/dev/mmcblk1p1 *        2048  1050623  1048576  512M  c W95 FAT32 (LBA)
/dev/mmcblk1p2       1050624  1052671     2048    1M da Non-FS data
/dev/mmcblk1p3       1052672  7344127  6291456    3G 83 Linux
/dev/mmcblk1p4       7344128 60751871 53407744 25.5G  5 Extended
/dev/mmcblk1p5       7346176 13637631  6291456    3G 83 Linux
/dev/mmcblk1p6      13639680 60751871 47112192 22.5G 83 Linux

Trước khi tạo OverlayFS, mọi thứ được gắn kết là:

# mount
/dev/mmcblk1p3 on / type ext4 (rw,noatime,data=ordered)
devtmpfs on /dev type devtmpfs (rw,relatime,size=170440k,nr_inodes=42610,mode=755)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/lib/systemd/systemd-    cgroups-agent,name=systemd)
configfs on /sys/kernel/config type configfs (rw,relatime)
tmpfs on /run/user/0 type tmpfs (rw,nosuid,nodev,relatime,size=35752k,mode=700)
/dev/mmcblk1p6 on /opt type ext4 (rw,noatime,data=ordered)
/dev/mmcblk1p5 on /overlay type ext4 (rw,noatime,data=ordered)

Kế hoạch của tôi là sử dụng /dev/mmcblk1p5như hệ thống tập tin lớp phủ được gắn tại /overlay.

# tree /overlay
/overlay
├── lost+found
├── root-fs
└── work

Hoặc là tôi đang làm sai, hoặc tôi có một số vấn đề về cấu hình, bởi vì:

# mount -t overlay overlay -o lowerdir=/,upperdir=/overlay/root-fs,workdir=/overlay/work /
# mount
/dev/mmcblk1p3 on / type ext4 (rw,noatime,data=ordered)
devtmpfs on /dev type devtmpfs (rw,relatime,size=170440k,nr_inodes=42610,mode=755)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd)
configfs on /sys/kernel/config type configfs (rw,relatime)
tmpfs on /run/user/0 type tmpfs (rw,nosuid,nodev,relatime,size=35752k,mode=700)
/dev/mmcblk1p6 on /opt type ext4 (rw,noatime,data=ordered)
/dev/mmcblk1p5 on /overlay type ext4 (rw,noatime,data=ordered)
overlay on / type overlay (rw,relatime,lowerdir=/,upperdir=/overlay/root-fs,workdir=/overlay/work)

Có vẻ như nó đã hoạt động, nhưng nếu tôi tạo một tệp như:

# touch /root/test_file_write

Sau đó, tắt nguồn và nhìn vào thẻ SD trong máy tính để bàn của tôi, tôi thấy /dev/mmcblk1p3/root/test_file_writekhông như tôi mong đợi /dev/mmcblk1p5/root-fs/root/test_file_write.

Có nên làm việc này?


Thật không may, việc gắn / dev / mmcblk1p3 chỉ đọc không dễ dàng. mount -o remount,ro /trả về mount: / is busyvà cố gắng khởi động hệ thống với nó chỉ đọc được rất nhiều lỗi. Tôi chưa thành công nhưng tôi sẽ tiếp tục cố gắng.
đúng

Tôi đã giết tất cả mọi thứ đang giữ / và thành công chỉ đọc lại. Bây giờ, touch /root/test_file_writetrả về touch: cannot touch '/root/test_file_write': Read-only file system, rõ ràng lớp phủ không hoạt động ... nhưng tại sao?
đúng

Nó có hoạt động trên một thư mục không / khác, như thế này:mkdir /tmp/{root,overlay,work}; touch /tmp/root/lowerfile; mount -t overlay overlay -o lowerdir=/tmp/root,upperdir=/tmp/overlay,workdir=/tmp/work /tmp/root/; touch /tmp/root/upperfile; umount /tmp/root
rudimeier

Vâng, nó hoạt động. Tôi kết thúc với /tmp/overlay/upperfile/tmp/overlay/root/lowerfile.
đúng

1
Thật không may, tôi vẫn chưa tìm thấy một giải pháp. Có vẻ như cách tiếp cận dự kiến ​​là xử lý vấn đề này trong initramfs (về cơ bản đó là những gì gói apt overlayrootfs làm). Tôi không sử dụng initramfs và không muốn bắt đầu. Hiện tại tôi đang sử dụng cách tiếp cận cũ, sử dụng các thư mục gốc (aka /), / var và / opt riêng biệt với việc giới hạn rw mình.
đúng vào

Câu trả lời:



3

Câu trả lời này dựa trên kinh nghiệm của riêng tôi, nhưng không phải với các thiết bị nhúng. Có lẽ nó hữu ích cho những người khác vấp ngã trong thiết lập này - bạn nên điều chỉnh nó phù hợp với hoàn cảnh cụ thể của mình, hoặc ít nhất là hy vọng học được một hoặc hai điều từ nó.

Một phương pháp đơn giản là chiếm quyền điều khiển khi hệ thống tập tin gốc được gắn kết (trong initramfs, nếu không thì chiếm quyền điều khiển init) và gắn lớp phủ ở đó, sau đó tiếp tục như bình thường. Nếu bạn gắn kết nó mà không có initramfs, đừng quên di chuyển tất cả các hệ thống tệp ảo (ví dụ /proc/sys) trong tập lệnh của bạn trước khi chuyển điều khiển sang bình thường init.

Nếu bạn không muốn có một initramfs, thì giải pháp được liên kết của Mathieu Maret về cách nó được thực hiện trong quả mâm xôi sẽ hoạt động. Về cơ bản, bạn ghi đè inittiến trình / tập lệnh của riêng bạn thông qua một dòng lệnh đến kernel. Giả sử bạn tạo tập lệnh vào hệ thống tập tin gốc tại /sbin/init-overlay, sau đó bạn cần thêm các init=/sbin/init-overlaytham số khởi động kernel của cấu hình bộ nạp khởi động.

Các init-overlaykịch bản có thể làm bất cứ điều gì trước khi nó chuyển điều khiển đến init, trong trường hợp này nó gắn kết các lớp phủ vào thư mục khác và sau đó chrootvào nó.


Một cách có thể để làm điều đó với initramfs là chỉ cần chiếm quyền điều khiển /inittập lệnh bên trong initramfs sau khi nó gắn kết hệ thống tập tin gốc. Ví dụ: giả sử bạn muốn có một lớp phủ gốc, nhưng cũng có quyền truy cập vào các điểm gắn kết ban đầu, tại /run/rootfs/ro/run/rootfs/rw(trước đây là gốc chỉ đọc, sau là sửa đổi được thực hiện, upperdir) sau khi hệ thống hoạt động và chạy . Tôi cũng sẽ cho rằng ổ đĩa khởi động hệ thống của bạn có một root.squashfstệp chứa hệ thống tệp gốc chỉ đọc và bạn muốn gắn kết nó. Giả sử bạn cũng muốn truy cập vào ổ đĩa này, để thuận tiện, tại /media/drivehoặc tương tự, một lần nữa, sau khi hệ thống hoạt động.

Lý do chúng tôi chiếm quyền điều khiển tập lệnh initramfs là vì điều này cho phép chúng tôi linh hoạt hơn trong quy trình hơn là sử dụng một số tham số tiền xử lý cuối cùng chạy các lệnh tập lệnh mặc định. Vì vậy, bạn cần chỉnh sửa cấu hình khởi động để truyền cho kernel thông tin rằng hệ thống tập tin "root" thực sự là nơi root.squashfsđược tìm thấy, vì chúng ta sẽ gắn kết nó sau.

Một lệnh thông thường với syslinux.cfgtrên phân vùng VFAT sẽ là (thay đổi UUID nếu cần):

label linux
    linux vmlinuz
    append root=UUID=ABCD-1234 rootfstype=vfat rootflags=ro,umask=022,quiet ro quiet splash
    initrd initrd.img

Giả định này bạn sẽ đặt root.squashfsphân vùng VFAT, có thể không lý tưởng (thứ bạn cần chỉ định là root = ở trên là phân vùng hoặc hệ thống tệp có chứa root.squashfshoặc tương tự, chẳng hạn như hệ thống tệp gốc thực sự nếu bạn không muốn nó nén). Tuy nhiên, tôi đang giải thích rằng giả sử bạn đặt nó trên phân vùng khởi động. Tôi không biết loại hệ thống nhúng nào bạn chạy để bạn sẽ phải sử dụng phán đoán của riêng mình ở đây.

Trước tiên, bạn sẽ phải trích xuất initramfs ở đâu đó trong / tmp để bạn có thể sửa đổi /inittập lệnh của nó . Đừng quên làm điều đó như root(siêu người dùng) để giữ quyền sở hữu đúng cách trước khi chúng tôi đóng gói lại. Bạn có thể có thể viết kịch bản toàn bộ sau khi bạn hiểu làm thế nào nó có thể được thực hiện. Ví dụ: giải nén nó để /tmp/initramfschỉnh sửa:

mkdir /tmp/initramfs 2>/dev/null; (cd /tmp/initramfs && zcat /initrd.img | sudo cpio -idmv)

Bây giờ chúng ta cần tìm nơi tập lệnh mặc định gắn kết root. Tìm kiếm một cái gì đó như thế này trong /tmp/initramfs/init(chỉnh sửa nó như root):

maybe_break mount
log_begin_msg "Mounting root file system"
. /scripts/${BOOT}
parse_numeric ${ROOT}
maybe_break mountroot
mountroot
log_end_msg

Bạn không cần phải hiểu cách thức hoạt động của nó. Tất cả những gì bạn cần hiểu là cái này gắn kết hệ thống tập tin bình thường chứa của bạn root.squashfstới một điểm gắn kết rõ ràng được đưa ra thông qua ${rootmnt}biến shell.

Nói cách khác, những gì chúng ta có tại ${rootmnt}thời điểm này là phân vùng VFAT của chúng ta (hoặc bất cứ điều gì chúng ta đã chỉ định thông qua root=tham số dòng lệnh). Kịch bản lệnh này bây giờ sẽ làm những việc khác như di chuyển tất cả các hệ thống tệp ảo đến ${rootmnt}điểm gắn kết, vì vậy chúng tôi cần chắc chắn thực hiện tất cả các công cụ tùy chỉnh của mình sau đoạn mã trên.

Tất cả bạn phải làm là chỉ cần chèn một cái gì đó như thế này sau đoạn mã trên trong initramfs's /init:

# create some temporary directories under the initramfs's /run
# they will be our mountpoints and such, which will get moved
# by the default script to the actual root filesystem...
mkdir -m 755 /run/rootfs
mount -t tmpfs -o size=90%,mode=755,suid,exec tmpfs /run/rootfs
mkdir -m 755 /run/rootfs/drive /run/rootfs/ro /run/rootfs/rw /run/rootfs/.workdir

# move the original root that was mounted, temporarily
mount -n -o move "${rootmnt}" /run/rootfs/drive

# mount the squashfs and then the overlay to our designated locations
mount -t squashfs -o defaults,ro /run/rootfs/drive/root.squashfs /run/rootfs/ro
mount -t overlay -o lowerdir=/run/rootfs/ro,upperdir=/run/rootfs/rw,workdir=/run/rootfs/.workdir root "${rootmnt}"

# at this point we have our overlay root at ${rootmnt}!
# however, move the drive's filesystem mount to the new root
# this allows it to be accessed afterwards from /media/drive
# NOTE: this assumes you have the /media/drive dir in the root squashfs
mount -n -o move /run/rootfs/drive "${rootmnt}/media/drive"
rm -d /run/rootfs/drive

Đó là nó. Tập lệnh sẽ tiếp tục như bình thường nhưng với hệ thống tập tin gốc là lớp phủ và tất cả các phần của nó có thể truy cập dễ dàng sau đó. Lưu ý rằng nó không kiểm tra lỗi , tùy theo ý của bạn để thêm các lệnh ở trên hoặc để đảm bảo overlaymô-đun được tải.

Bây giờ chỉ cần đóng gói initramfs:

sudo sh -c 'cd /tmp/initramfs && find . -print0 | cpio --null -ov --format=newc' | gzip -9 > /tmp/initrd.img

Và sao chép /tmp/initrd.img vào thẻ SD của bạn hoặc bất cứ nơi nào. Đừng quên đặt root.squashfstại thư mục gốc của phân vùng VFAT, mặc dù điều đó rõ ràng dễ dàng tùy chỉnh và bạn không phải làm theo cách này. Đây chỉ là cách "dễ nhất" với syslinux (và thậm chí cả UEFI boot), không có nghĩa là tốt nhất.

Và xin lỗi, tôi biết bạn đã yêu cầu thiết bị nhúng nhưng tôi không biết quy trình khởi động hoạt động ở đó như thế nào, tôi chỉ sử dụng một ví dụ cho x86, nhưng phần đó ít quan trọng hơn (chỉ syslinux.cfgphần).

Xin lưu ý rằng điều này sẽ làm cho phần có thể ghi của overlayfsas tmpfs, đó không phải là điều bạn muốn. Tuy nhiên, nó có thể dễ dàng thay đổi , nếu bạn nhìn ở trên, chỉ cần gắn một cái gì đó khác /run/rootfsthay vì tmpfs, bất cứ nơi nào bạn muốn viết.

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.