Overlayfs root

  • How to use
  • How to disable

I can’t tell if OverlayFS is an actual filesystem I need to create on
the disk images with mkfs -t xxx /path/to/raw/disk/image, or is a
special mounting method and the raw disk images are actually using
something like ext4, but they are mounted in a special way with mount
-t OverlayFS?

One does not need to run any mkfs command for overlayFS, it is just a way of mounting.

Once mounted I believe that I should still be able to see my already
existing files and any files I now create will actually be stored
inside the filesystem1.img file that I could possibly move to another
system?

Yes, for a more detailed explanation of how OverlayFS works, you may wish to refer to «Docker and OverlayFS in practice».

When I run the live image (Ubuntu 18.04), it shows the root filesystem being an overlay with the squashfs image (/cdrom/casper/filesystem.squashfs, containing the main data) as lower layer, and /cow/upper as upper layer. But /cow is not visible anymore as it is hidden by the overlay mounted on root.

Where (on what device) does the upper layer live? Is it accessible somewhere or is it a memory-only device?

asked Dec 21, 2018 at 12:33

JanKanis's user avatar

9 silver badges13 bronze badges

COW stands for copy-on-write, In the case of live media it refers to the changes that are made to the live environment. It is accessible if you boot live iso in persistence mode, in that case it is written to the drive, folder or casper-rw container file you specify. But if persistence mode is not enabled it is just a memory only device.

There are many articles available on askubuntu regarding persistence.

answered Dec 21, 2018 at 13:51

harshit's user avatar

root@rasp:/home/pi # mount
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,relatime)
udev on /dev type devtmpfs (rw,nosuid,relatime,size=243284k,nr_inodes=60821,mode=755)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
tmpfs on /run type tmpfs (rw,nosuid,noexec,relatime,size=76332k,mode=755)
overlay on / type overlay (rw,noatime,lowerdir=/lower,upperdir=/upper/data,workdir=/upper/work)
securityfs on /sys/kernel/security type securityfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
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)
cgroup2 on /sys/fs/cgroup/unified type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,name=systemd)
none on /sys/fs/bpf type bpf (rw,nosuid,nodev,noexec,relatime,mode=700)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
systemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=32,pgrp=1,timeout=0,minproto=5,maxproto=5,direct)
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
mqueue on /dev/mqueue type mqueue (rw,relatime)
configfs on /sys/kernel/config type configfs (rw,relatime)
/dev/mmcblk0p1 on /boot type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro)
tmpfs on /run/user/1000 type tmpfs (rw,nosuid,nodev,relatime,size=76328k,mode=700,uid=1000,gid=1000)
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)
tracefs on /sys/kernel/debug/tracing type tracefs (rw,relatime)

можно видеть, что / (root) монтирован в overlay, где в скобочках видно lowerdir=/lower,upperdir=/upper/data,workdir=/upper/work
но если сделать так:

root@rasp:/ # ls -la /
total 36
drwxr-xr-x   1 root root   160 Jan  1  1970 .
drwxr-xr-x   1 root root   160 Jan  1  1970 ..
lrwxrwxrwx   1 root root     7 Jan 11 18:50 bin -> usr/bin
drwxr-xr-x   4 root root  4096 Jan  1  1970 boot
drwxr-xr-x  17 root root  3720 Jul  6 12:49 dev
drwxr-xr-x   1 root root   120 Jul  6 16:15 etc
drwxr-xr-x   1 root root    60 Jan 11 18:52 home
lrwxrwxrwx   1 root root     7 Jan 11 18:50 lib -> usr/lib
drwx------   2 root root 16384 Jan 11 19:08 lost+found
drwxr-xr-x   2 root root  4096 Jan 11 18:50 media
drwxr-xr-x   2 root root  4096 Jan 11 18:50 mnt
drwxr-xr-x   3 root root  4096 Jan 11 18:52 opt
dr-xr-xr-x 194 root root     0 Jan  1  1970 proc
drwx------   1 root root   120 Jul  6 16:19 root
drwxr-xr-x  20 root root   700 Jul  6 17:38 run
lrwxrwxrwx   1 root root     8 Jan 11 18:50 sbin -> usr/sbin
drwxr-xr-x   2 root root  4096 Jan 11 18:50 srv
dr-xr-xr-x  12 root root     0 Jan  1  1970 sys
drwxrwxrwt   1 root root   340 Jul  6 17:17 tmp
drwxr-xr-x   1 root root   100 Jan 11 18:50 usr
drwxr-xr-x   1 root root   140 Feb 12 21:19 var

то папки /lower или /upper тут нет. А где они?! А как это?

Псевдо-файловая система OverlayFS была впервые включена в релиз 3.18 ядра Linux: она позволяет объединять два дерева каталогов или файловых систем (“верхнее” и “нижнее”) совершенно прозрачно для пользователя, который может обращаться к файлам и каталогам на “объединенном” уровне точно так же, как и на стандартной файловой системе.

В этом руководстве мы изучим основные концепции OverlayFS и увидим демонстрацию ее использования.

В этом руководстве вы узнаете:

  • Основные концепции OverlayFS
  • Как объединить две файловые системы с помощью OverlayFS

Введение

Все мы должны быть знакомы со стандартным поведением ядра Linux при монтировании файловой системы: файлы и каталоги, существующие в каталоге, используемом в качестве точки монтирования, маскируются и становятся недоступными для пользователя, в то время как файлы, существующие в смонтированной файловой системе, отображаются.

Доступ к исходным файлам можно получить только после размонтирования файловой системы.

Это также происходит тогда, когда мы монтируем несколько файловых систем в одном каталоге.

Когда используется псевдо-файловая система OverlayFS, вместо этого файлы, существующие на разных слоях, объединяются, и результирующая файловая система может быть смонтирована самостоятельно.

OverlayFS обычно используется в системах, работающих на встроенных устройствах, таких как OpenWRT, где полезно сохранять базовый набор конфигураций и в то же время позволять пользователю выполнять модификации.

OverlayFS также лежит в основе драйверов хранения “overlay” и “overlay2” Docker.

Что происходит при удалении файла или каталога?

Если удаляемый файл принадлежит верхнему слою, то он удаляется на месте; если же он принадлежит нижнему слою, то удаление имитируется с помощью файла whiteout (или непрозрачного каталога – каталога с расширенным атрибутом trusted.overlay.opaque), который создается в слое с возможностью записи и заслоняет исходный элемент.

OverlayFS является основой драйверов Docker overlay и overlay2.

В такой реализации нижний, доступный только для чтения, слой представлен образами; верхний, доступный для записи, представлен контейнерами на их основе.

Образы неизменяемы: все изменения происходят внутри контейнеров и теряются при их удалении (именно поэтому для сохранения данных используются тома).

Дополнительно:  Root explorer на андроид для чего

Использование OverlayFS

Давайте посмотрим, как использовать OverlayFS.

Для данного примера я предположу, что мы хотим объединить две файловые системы: нижнюю, существующую на разделе /dev/sda1, и ту, которая будет использоваться в режиме чтения-записи, на разделе /dev/sda2.

Первое, что мы хотим сделать, это создать каталоги, которые мы будем использовать в качестве точек монтирования:

$ sudo mkdir /lower /overlay

Теперь смонтируем файловую систему /dev/sda1 в каталоге /lower в режиме только для чтения:

$ sudo mount -o ro /dev/sda1 /lower

Команда ls показывает, что файловая система содержит только один файл:

$ ls -l /lower
total 20
-rw-r--r--. 1 root root 23 Sep 1 10:43 file1.txt
drwx------. 2 root root 16384 Sep 1 10:40 lost+foun

Файлы содержат всего одну строку:

$ cat /lower/file1.txt 
this is the first line

Теперь давайте продолжим.

В качестве следующего шага мы смонтируем файловую систему /dev/sda2 в каталог /overlay:

$ sudo mount /dev/sda2 /overlay

Когда файловая система смонтирована, мы создаем на ней две директории: upper и work.

В первой будут храниться файлы, являющиеся частью верхнего слоя, вторая будет использоваться для подготовки файлов при переходе с одного слоя на другой: она должна быть пустой и находиться в той же файловой системе, что и верхняя:

$ sudo mkdir /overlay/{upper,work}

Теперь мы можем “собрать” и смонтировать оверлей.

Для выполнения этой задачи мы используем следующую команду:

$ sudo mount overlay -t overlay -o lowerdir=/lower,upperdir=/overlay/upper,workdir=/overlay/work  /media

Мы вызвали mount, передав “overlay” в качестве аргумента опции -t (сокращение от –types), тем самым указав тип файловой системы, которую мы хотим смонтировать (в данном случае псевдо-файловую систему), затем мы использовали флаг -o для перечисления опций монтирования: в данном случае “lowerdir”, “upperdir” и “workdir”, чтобы указать: каталог, в который монтируется файловая система только для чтения, каталог, содержащий файлы верхнего, записываемого слоя, и расположение “рабочего” каталога, соответственно. Наконец, мы указали точку монтирования для “объединенной” файловой системы: /media, в данном случае.

С помощью команды mount мы можем просмотреть сводную информацию о настройке оверлея:

$ mount | grep -i overlay
overlay on /media type overlay (rw,relatime,seclabel,lowerdir=/lower,upperdir=/overlay/upper,workdir=/overlay/work)

Если мы перечислим файлы в каталоге /media, то увидим, что существует только файл file1.txt, который, как мы знаем, принадлежит нижнему уровню:

$ ls -l /media
total 20
-rw-r--r--. 1 root root 23 Sep 1 10:43 file1.txt
drwx------. 2 root root 16384 Sep 1 10:40 lost+found

Теперь давайте попробуем добавить строку в файл и посмотрим, что произойдет:

$ echo "this is the second line" | sudo tee -a /media/file1.txt

Если мы проверим содержимое файла, то увидим, что строка была добавлена успешно:

$ cat /media/file1.txt
this is the first line
this is the second line

Однако оригинальный файл file1.txt не был изменен:

$ cat /lower/file1.txt
this is the first line

IВместо этого в верхний слой был добавлен файл с тем же именем:

$ ls -l /overlay/upper
-rw-r--r--. 1 root root 47 Sep 1 14:36 file1.txt

Теперь, если мы удалим файл /media/file1.txt, /overlay/upper/file1.txt станет таким файлом whiteout :

$ sudo rm /media/file1.txt
$ ls -l /overlay/upper
c---------. 2 root root 0, 0 Sep 1 14:45 file1.txt

Как указано в официальной документации, файл whiteout является символьным устройством (это отражено в выводе ls – см. выделенную ведущую “c”) с номером устройства 0/0.

Заключение

В этом руководстве мы поговорили о OverlayFS: мы узнали основные концепции ее использования, увидели, как она может быть использована для объединения двух файловых систем или деревьев каталогов, и каковы некоторые из возможных случаев ее использования.

Наконец, мы увидели, как на самом деле создать установку OverlayFS на Linux.

Время на прочтение

Я Алексей, исследователь‑аналитик киберугроз в компании R‑Vision. Сегодня я продолжу выявление вредоносных активностей в Linux-системах и рассмотрю новую критичную уязвимость, получившую идентификатор CVE-2023-0386. Уязвимость, обнаруженная в ядре Linux, затронула версии ядра до 6.2 и связана с файловой системой OverlayFS. Она опасна тем, что позволяет непривилегированному пользователю создавать исполняемые файлы с SUID-битом и с их помощью получать привилегии root.

На просторах сети уже можно найти несколько доступных вариаций эксплуатации CVE-2023-0386 (PoC’ов), некоторые из них представлены под спойлером ниже:

Варианты эксплуатации

В этой статье я хочу разобрать с вами принципы работы данной узвимости и рассмотреть, каким образом мы можем обнаружить ее в системе.

Как работает уязвимость

Для понимая работы CVE-2023-0386, давайте посмотрим, как она была исправлена в ядре Linux с помощью недавно вышедшего патча:

diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 140f2742074d4..c14e90764e356 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -1011,6 +1011,10 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
 	if (err)
 		return err;
 
+	if (!kuid_has_mapping(current_user_ns(), ctx.stat.uid) ||
+	    !kgid_has_mapping(current_user_ns(), ctx.stat.gid))
+		return -EOVERFLOW;
+
 	ctx.metacopy = ovl_need_meta_copy_up(dentry, ctx.stat.mode, flags);
 
 	if (parent) {

В нем мы видим дополнительное условие, добавленное в ovl_copy_up_on — функцию из библиотеки ядра Linux.

Данная функция относится к файловой системе OverlayFS, позволяющей объеднять несколько файловых систем в единую иерархию, и используется для копирования файла или каталога из нижнего слоя (lower layer) в верхний слой (upper layer) OverlayFS. Эта операция дает возможность создать или обновить файлы и каталоги в верхней файловой системе, не затрагивая исходные файлы в нижней.

Но вернемся к условию, оно состоит из двух частей кода:

При этом если хотя бы одно из условий возвращает истину (true), то возвращается и значение -EOVERFLOW (оно обычно используется для обозначения переполнения или некорректных значений), и тогда функция не будет выполнена.

Способ эксплуатации уязвимости

А теперь посмотрим какие шаги необходимо предпринять для эксплуатация уязвимости. Для этого нам понадобится:

unshare -Urm
  1. В новом пространстве имен мы получаем возможность монтирования, для которого обычно требуются права root.Теперь можно смонтировать OverlayFS, запустив команду ниже. В ней для нижней директории (lowerdir) будет использоваться созданная ранее FUSE с исполняемым файлом, а для верхней (upperdir) любая директория, доступная для записи:

mount -t overlay overlay -o lowerdir=fuse_dir,upperdir=upperdir,workdir=workdir overlay_mount_point
  1. Далее нужно «переместить» наш файл с SUID-битом из нижней директории в верхнюю. Для этого достаточно выполнить команду touch для файла в OverlayFS. Это не изменит сам файл, но изменит метку времени последнего доступа к файлу. Данного изменения будет достаточно для запуска процесса записи OverlayFS в верхнюю директорию. И поскольку в непропатченном ядре нет условия, описанного выше, файл будет записан в верхнюю директорию со всеми правами. Ну а дальше достаточно выйти из нашего пользовательского пространства и запустить полученный файл из «верхней» директории.

Дополнительно:  Come here i root

Для более наглядного понимая процесса эксплуатации, представлю описанные мною шаги в виде схемы ниже:

Рисунок 1 - Эксплуатация уязвимости CVE-2023-0386
Рисунок 1 — Эксплуатация уязвимости CVE-2023-0386

Разобравшись с принципом работы уязвимости, давайте выясним как можно мониторить подобную активность.

Обнаружение CVE-2023-0386

Повышение привилегий через исполняемые файлы с SUID-битом до сих пор является одним из наиболее популярных способов у злоумышленников, согласно отчету компании red-canary. В данной уязвимости также применяется эта техника, поэтому детектирование повышения привилегий через SUID-бит в данном случае будет также актуально. Но CVE-2023-0386 позволяет создать любой файл с SUID-битом, поэтому мы будем рассматривать именно обнаружение процесса эксплуатации самой уязвимости.

Для этого нам будет достаточно мониторить системный вызов mount. Так как он вызывается только привилегированным пользователем, то вызов с UID не равным 0 может свидетельствовать о вызове из пространства имен (namespace).

Также mount хранит информацию о типе вызываемой файловой системы. Ниже показано, как данный системный вызов будет выглядеть в ядре:

mount("overlay", "/home/sea-admin/cveOver/overlay_mount_point", "overlay", 0, "lowerdir=hello_mount_point,upper"...) = 0

А для мониторинга в реальном времени посмотрим, как mount представлен в логе auditd. С этой целью добавим правило, которое позволит отследить нужный нам системный вызов:

-a always,exit -F arch=b64 -S mount -F key=mount

И увидим, как mount()выглядит в auditd:

type=SYSCALL msg=audit(1685308769.215:832): arch=c000003e syscall=165 success=yes exit=0 a0=5615b38dbb70 a1=5615b286c7d4 a2=5615b38dbbb0 a3=6 items=5 ppid=73263 pid=73264 auid=1000 uid=1001 gid=1001 euid=0 suid=0 fsuid=0 egid=1001 sgid=1001 fsgid=1001 tty=pts1 ses=1 comm="fusermount" exe="/usr/bin/fusermount3" subj=unconfined key="mount" ARCH=x86_64 SYSCALL=mount AUID="sea-admin" UID="sea-admin" GID="sea-admin" EUID="sea-admin" SUID="sea-admin" FSUID="sea-admin" EGID="sea-admin" SGID="sea-admin" FSGID="sea-admin"

Но как можно заметить, в этом событии мы не обнаружили значений аргументов a0-a2, а только ссылки на их адресное пространство. Так как данные аргументы хранят информацию о типе файловой системы и точках монтирования, они также важны для детектирования.

Поэтому мы попробуем получить их с помощью eBPF, а для этого напишем следующий С-код:

BPF_PERF_OUTPUT(args);

#include <linux/ptrace.h>
// структура данных для передачи в пользовательское пространство
struct args {
    char task[TASK_COMM_LEN];
    u32 m_uid;
    char m_source[32];
    char m_target[32];
    char m_filesystem[32];
    char m_data[64];
    long m_flags;
};
// основная функция для перехвата системных вызовов mount()
int syscall__mount(struct pt_regs *ctx, const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data){

       struct args arg_data = {};
       //вызывающая команда
       bpf_get_current_comm(&arg_data.task, sizeof(&arg_data.task));
       //uid пользователя
       arg_data.m_uid = bpf_get_current_uid_gid();
       //аргументы системного вызова
       bpf_probe_read(&arg_data.m_source, sizeof(arg_data.m_source), &*source);
       bpf_probe_read(&arg_data.m_target, sizeof(arg_data.m_target), &*target);
       bpf_probe_read(&arg_data.m_filesystem, sizeof(arg_data.m_filesystem), &*filesystemtype);
       bpf_probe_read(&arg_data.m_flags, sizeof(arg_data.m_flags), &mountflags);
       bpf_probe_read(&arg_data.m_data, sizeof(arg_data.m_data), &*data);
       
       args.perf_submit(ctx, &arg_data, sizeof(arg_data));

       return 0;
}

Данный код мониторит все системные вызовы mount() и передает их аргументы в пользовательское пространство через perf ring buffer. Для загрузки в пользовательское пространство данного BPF и вывода результата воспользуемся Python «оберткой», пример которой представлен ниже под спойлером:

Пример обертки
from bcc import BPF

# Читаем ebpf код из файла
with open("bpf.c") as file:
    bpf_txt = file.read()
    
def handle_event(cpu, data, size):
    output = bpf_ctx["args"].event(data)
    print("{:15} {:<5} {:<10} {:<15} {:<10} {:<10} {:<30}".format(output.task.decode("utf-8") , output.m_uid,
        output.m_source.decode("utf-8"), output.m_target.decode("utf-8"), output.m_filesystem.decode("utf-8"), output.m_flags, output.m_data.decode("utf-8")))

bpf_ctx = BPF(text=bpf_txt)
syscall_fnname = bpf_ctx.get_syscall_fnname("mount")
# Присоединяем наш ebpf к системному вызову bpf
bpf_ctx.attach_kprobe(event=syscall_fnname, fn_name="syscall__mount")
bpf_ctx["args"].open_perf_buffer(handle_event)

# Настраиваем вывод в консоль
print("{:<15} {:<5} {:<10} {:<15} {:<10} {:<10} {:<30}".format('exe_task',"uid",
    'source', 'target', 'fs type','flags', 'data'))
while 1:
    try:
        bpf_ctx.perf_buffer_poll()
    except KeyboardInterrupt:
        print()
        exit()

После загрузки нашего BPF и эксплуатации уязвимости, нам станет доступен следующий вывод:

exe_task        uid   source     target          fs type    flags      data
fuse            1000  /dev/fuse  ./ovlcap/lower  fuse       6          fd=3,rootmode=40000,user_id=1000,group_id=1000
fusermo         1000  /dev/fuse  .               fuse       6          fd=4,rootmode=40000,user_id=1000,group_id=1000
exp             1000  overlay    ./ovlcap/merge  overlay    0          lowerdir=./ovlcap/lower,upperdir=./ovlcap/upper,workdir=./ovlcap

И здесь мы увидим, что изначально была создана файловая система fuse из-под пользователя с UID 1000 с точкой монтирования в ./ovlcap/lower.

В то же время в конце вывода показано создание файловой системы Overlay из-под того же пользователя в «нижний уровень», которой передается та же директория ./ovlcap/lower. Логическое правило будет выглядеть так:

event1.uid = event2.uid != 0 &
event1.fs_type = fuse &
event2.fs_type = overlay &
event1.target = event2.data.lowerdir

Данная логика полностью соответствует принципу работы уязвимости и маловероятно встретить ее в легитимной работе приложений. Реализовать подобное правило можно в SIEM-системе, передав ей данные логи, или непосредственно в самом модуле eBPF.

Вывод

Уязвимости ядра Linux могут создавать большие возможности для атакующего, как например уязвимость OverlayFS (CVE-2023-0386), которая сегодня была рассмотрена этой в статье. Как мы могли заметить, стандартных механизмов auditd явно недостаточно, чтобы обеспечить корректное детектирование эксплуатации данной уязвимости. Поэтому мною было предложено решение, основанное на механизме eBPF. Оно позволило увидеть все аргументы системного вызова mount() и сформировать корреляционное правило.

Чтобы защититься от подобных уязвимостей, помимо обнаружения их эксплуатации, я также рекомендую вам регулярно обновлять свои информационные системы.

Спасибо за внимание! Если у вас остались вопросы — пишите в комментариях 🙂

Note

noauto,x-systemd.automount

This will have effect, that overlay filesystem will be simply not mounted at boot time (noauto option), avoiding possible failure if previous mounts are not ready. On first access to overlay directory, the filesystem will be mounted (x-systemd.automount option). This approach has two weaknesses:

  1. If needed lower/upper directories are not ready this mount will fail.
  2. Mount will succeed even if lower/upper directories are not populated (ISO is not mounted f.e.)

We can avoid later, by adding x-systemd.require to the options list.

Examples

Creating an overlay mount can be done purely with directories if desired as demonstrated here:

cd /tmp
mkdir lower upper workdir overlay
sudo mount -t overlay -o \
lowerdir=/tmp/lower,\
upperdir=/tmp/upper,\
workdir=/tmp/workdir \
none /tmp/overlay
cd /tmp

# Create the necessary directories.
mkdir lower upper overlay

# Lets create a fake block device to hold our "lower" filesystem
dd if=/dev/zero of=lower-fs.img bs=4096 count=102400
dd if=/dev/zero of=upper-fs.img bs=4096 count=102400

# Give this block device an ext4 filesystem.
mkfs -t ext4 lower-fs.img
mkfs -t ext4 upper-fs.img

# Mount the filesystem we just created and give it a file
sudo mount lower-fs.img /tmp/lower
sudo chown $USER:$USER /tmp/lower
echo "hello world" >> /tmp/lower/lower-file.txt

# Remount the lower filesystem as read only just for giggles
sudo mount -o remount,ro lower-fs.img /tmp/lower

# Mount the upper filesystem
sudo mount upper-fs.img /tmp/upper
sudo chown $USER:$USER /tmp/upper

# Create the workdir in the upper filesystem and the 
# directory in the upper filesystem that will act as the upper
# directory (they both have to be in the same filesystem)
mkdir /tmp/upper/upper
mkdir /tmp/upper/workdir

# Create our overlayfs mount
sudo mount -t overlay -o \
lowerdir=/tmp/lower,\
upperdir=/tmp/upper/upper,\
workdir=/tmp/upper/workdir \
none /tmp/overlay

The examples above are taken from my blog post on using overlayfs.

Nesting OverlayFS

You can nest overlayFS. For example, you can nest the example above as the lowerdir to another overlayFS system by running:

mkdir -p /tmp/upperdir2/upper /tmp/upperdir2/workdir /tmp/overlay2
sudo mount -t overlay -o \
lowerdir=/tmp/overlay,\
upperdir=/tmp/upperdir2/upper,\
workdir=/tmp/upperdir2/workdir \
none /tmp/overlay2

When Ubuntu gets kernel 4.0+, we should be able to combine multiple lower directories in a single command by using the colon character as a separator like so:

sudo mount -t overlay -o \
lowerdir=/tmp/lower:/tmp/lowest,\
upperdir=/tmp/upper,\
workdir=/tmp/workdir \
none /tmp/overlay

In this case, you do not have two workdirs but one, and you keep the same merged path of /tmp/overlay. The lower directories will be stacked from right to left. You can also omit upperdir= entirely, which results in a readonly mount.

Дополнительно:  Пароль для root в altlinux

Mounting OverlayFS in fstab

Above answers have explained how to mount overlay filesystem from cmd line and/or script. It is also possible to mount OverlayFS from fstab.

Mounting directory which is not present, will fail, while mounting not yet «populated» directory will not fail, since OverlayFS has no way to know, if directory is ready.

When mounting filesystems from fstab, that is particularly a problem, since all mounting is done in parallel, thus we can not ensure that everything is prepared for OverlayFS.

However, if Linux distribution uses systemd, than mounting of filesystems is handled by it. Systemd reads fstab file, and creates mount units on the fly. After that all mounting is processed by systemd. Systemd unit files have options: require, after, before, which can be used to control the order and dependency of mounts defined in fstab, thus ensuring that mounting of OverlayFS will not fail (at least not, because of wrong order).

To set order/dependency of mounts in fstab file, we will declare systemd option «require» using syntax: x-systemd.require. Argument for this option is mount point of the mount which should be successfully mounted before given mount (defined in fstab).

How to disable

When you change some file under OverlayFS, and after the reboot, the file will keep the same.

But sometimes you do want to change the original file, how to disable this feature?

We have these methods:

  • Remount the disk with rw, and change the file under lowerdir
  • Use overlayroot-chroot tool provided by the package
  • Disable OverlayFS when booting
  • Disable by overlayroot.conf

Use overlayroot-chroot

If we want to install some package and keep the package after reboot, we can’t use the first method, since the package may change many files under different directories.

We still have a simple way, you run overlayroot-chroot with root, make changes, and the changes will be saved after reboot.

$ sudo overlayroot-chroot

The change may not take effect immediately after exit the command, you can mount again like this:

$ sudo mount -o remount /

Disable by overlayroot. conf

We can disable OverlayFS during the boot time, but if we want to keep it disabled after several reboots, we have a simple way.

You can change the overlayroot.conf config file using the remount method, and comment all the lines, and then reboot again.

If we want to enable, we can remount and un-comment the config lines, and after reboot, the OverlayFS will be enabled agian.

$ cat /media/root-ro/etc/overlayroot.conf
# overlayroot="tmpfs:swap=1,recurse=0"

Example

To show an example (and syntax of fstab entries), we will show case, where we will overlay directory on which iso image is mounted, while this particular image file will be stored on separate hdd, which will have to be mounted before we access image file. Thus forming required ordered of events:

mount hdd -> mount iso image -> mount OverlayFS

For given case fstab entries would look like:

# 1. mount hdd partition
# 2. mount iso image from hdd partition, but only if/after hdd is mounted
# 3. overlay iso image, but only if/after iso image is mounted
#
/dev/hdb1            /mnt/hdd      ext4     errors=remount-ro                 0  2  
/mnt/hdd/linux.iso   /mnt/iso      auto     x-systemd.requires=/mnt/hdd,ro    0  0
overlay              /mnt/merged   overlay  x-systemd.requires=/mnt/iso,lowerdir=/mnt/iso,upperdir=/overlay/lower,workdir=/overlay/working  0 0
                                                                            

If any mounts in chain fail, dependent one(s) will not be executed.

Disable OverlayFS when booting

The overlayroot-chroot method may solve 90% of the problem, but it do has some limitation.

The overlayroot-chroot just like chroot into the lower filesystem, and remount with writable.

If you have some scripts-say postinstall in some package, checks the chroot mode, it may refuse to execute under this case.

To fix this problem, we can disable OverlayFS during the booting phase.

We can edit the boot command line, append overlayroot=disabled and boot again.

Under this case, the OverlayFS will be disabled completely.

Remount

# remount with read-write
$ sudo mount -o remount,rw /dev/sda3

# say we want to change overlayroot.conf
# note: we must change under the file under the lowerdir: /media/root-ro
$ sudo vim /media/root-ro/etc/overlayroot.conf

# remount with read-only
$ sudo mount -o remount,ro /dev/sda3

Access Casper-rw file

You can mount casper-rw file and access contents within using:

sudo mkdir /media/casper

sudo mount -o loop casper-rw /media/casper/

answered Dec 1, 2021 at 3:15

C.S.Cameron's user avatar

10 gold badges63 silver badges103 bronze badges

How to use

We have a device running Ubuntu and will be powered off directly without shutdown gracefully.

In order to keep the file system from damage, we use the OverlayFS provided in Linux kernel since 3.18.

# first install overlayroot package
$ sudo apt-get install overlayroot

# second, change the config file /etc/overlayroot.conf
# the simple config is as following
# we enable swap, and disable recurse overlay
$ cat /etc/overlayroot.conf
overlayroot="tmpfs:swap=1,recurse=0"

After rebooting, we should see something like this:

$ df -h
Filesystem              Size  Used Avail Use% Mounted on
udev                     16G  8.0K   16G   1% /dev
tmpfs                   3.1G   74M  3.1G   3% /run
/dev/sda3                96G   16G   76G  17% /media/root-ro
tmpfs-root               16G   60M   16G   1% /media/root-rw
overlayroot              16G   60M   16G   1% /
tmpfs                    16G   24K   16G   1% /dev/shm
tmpfs                   5.0M  4.0K  5.0M   1% /run/lock
tmpfs                    16G     0   16G   0% /sys/fs/cgroup

$ mount
[...]
configfs on /sys/kernel/config type configfs (rw,relatime)
overlayroot on /var/cache/apt/archives type overlay (rw,relatime,lowerdir=/media/root-ro,upperdir=/media/root-rw/overlay,workdir=/media/root-rw/overlay-workdir/_)
overlayroot on /opt/var/cache/apt/archives type overlay (rw,relatime,lowerdir=/media/root-ro,upperdir=/media/root-rw/overlay,workdir=/media/root-rw/overlay-workdir/_)
overlayroot on /var/lib/apt/lists type overlay (rw,relatime,lowerdir=/media/root-ro,upperdir=/media/root-rw/overlay,workdir=/media/root-rw/overlay-workdir/_)
overlayroot on /opt/var/lib/apt/lists type overlay (rw,relatime,lowerdir=/media/root-ro,upperdir=/media/root-rw/overlay,workdir=/media/root-rw/overlay-workdir/_)

Оцените статью
Master Hi-technology
Добавить комментарий