Почему непривилегированные пользователи не могут гнездить крепления FUSE, но они могут монтировать FUSE внутри NFS с помощью root_squash?

Какую команду вы используете для установки значения по умолчанию? Вы можете установить его через команду systemctl:

systemctl set-default multi-user.target

Или с помощью ссылки default.target:

ln -s '/usr/lib/systemd/system/multi-user.target' '/etc/systemd/system/default.target'
0
17.08.2018, 00:29
1 ответ

Сначала рассмотрим реализацию FUSE no_allow_others.

Требуется, чтобы действующие, реальные и сохраненные UID (идентификаторы пользователя )совпадали. (И то же самое для GID ). Это преднамеренно предотвращает доступ установленной -UID-программы к монтированию.

https://github.com/torvalds/linux/blob/v4.18/fs/fuse/dir.c#L1024

Calling into a user-controlled filesystem gives the filesystem
daemon ptrace-like capabilities over the current process. This
means, that the filesystem daemon is able to record the exact
filesystem operations performed, and can also control the behavior
of the requester process in otherwise impossible ways. For example
it can delay the operation for arbitrary length of time allowing
DoS against the requester.

Теперь давайте проследим, что делает fusermount. Мы можем попробовать посмотреть на

strace -f bindfs...

и

sudo perf trace -o trace.txt -a sleep 2; sleep 1; bindfs...

Первый выдает фатальную ошибку «Отказано в доступе», потому что установленный -UID root не работает при работе под strace. Второй преуспевает, но не может отображать строковые параметры, такие как пути. Я думаю, что две трассировки показывают один и тот же общий путь кода до фатальной ошибки. Это означает, что мы можем использовать результаты straceдля заполнения отсутствующих строковых параметров.

Последний вызов в результатах strace—:

[pid 30609] mount("/home/alan-sysop/mnt", ".", "fuse", MS_NOSUID|MS_NODEV, "default_permissions,fd=5,rootmod"...) = -1 EPERM (Operation not permitted)

Интересно! "."означает текущий каталог. Так что fusermountдолжно быть уже работало в точке монтирования... каким-то образом. Этот трюк иногда можно использовать для доступа к каталогу, к которому вы в настоящее время не можете получить доступ, используя его абсолютный путь.

Если мы прокрутим вверх, то увидим, что fusermountдействительно перешел в этот каталог. И это также было связано с некоторыми системными вызовами, связанными с UID -(и связанными с GID -).

[pid 30609] getuid()                    = 1000
[pid 30609] setfsuid(1000)              = 1000
[pid 30609] getgid()                    = 1000
[pid 30609] setfsgid(1000)              = 1000
[pid 30609] openat(AT_FDCWD, "/etc/fuse.conf", O_RDONLY) = 6
...
[pid 30609] lstat("/home/alan-sysop/mnt", {st_mode=S_IFDIR|0775, st_size=4096,...}) = 0
[pid 30609] getuid()                    = 1000
[pid 30609] chdir("/home/alan-sysop/mnt") = 0
[pid 30609] lstat(".", {st_mode=S_IFDIR|0775, st_size=4096,...}) = 0
[pid 30609] access(".", W_OK)           = 0
[pid 30609] getuid()                    = 1000
[pid 30609] setfsuid(1000)              = 1000
[pid 30609] setfsgid(1000)              = 1000

Результаты UID "неправильные" в сеансе strace. Мы можем лучше увидеть танцевальную часть UID в сеансе perf trace. (Я удалил левые -большинство столбцов для удобочитаемости ).

getuid(                                                               ) = 1000
setfsuid(uid: 1000                                                    ) = 0
getgid(                                                               ) = 1000
setfsgid(gid: 1000                                                    ) = 1000
openat(dfd: CWD, filename: 0xa428e2bc                                 ) = 6
   ...
close(fd: 6                                                           ) = 0
lstat(filename: 0xa63882a0, statbuf: 0x7ffe7bd4f6d0                   ) = 0
getuid(                                                               ) = 1000
chdir(filename: 0xa63882a0                                            ) = 0
lstat(filename: 0xa428eca5, statbuf: 0x7ffe7bd4f6d0                   ) = 0
access(filename: 0xa428eca5, mode: W                                  ) = 0
getuid(                                                               ) = 1000
setfsuid(                                                             ) = 1000
setfsgid(gid: 1000                                                    ) = 1000
getuid(                                                               ) = 1000

Вызовы setfsuid()находятся в функциях drop_privs()и restore_privs()в fusermount.c .

Вызов chdir()незаметно скрыт в функции с именем check_perm().

Заключение

Почему это работает в NFS? Ответьте :, потому что NFS просматриваетfsuidfsgid), для которых задан корневой UID, отличный от -.

Почему это не работает на FUSE, если у вас нет allow_others? Ответьте :, потому что FUSE проверяет «настоящий» UID, а не fsuid.

0
28.01.2020, 04:13

Теги

Похожие вопросы