Bug 38225 - AltHa позволяет запустить интерпретатор через ld-linux
Summary: AltHa позволяет запустить интерпретатор через ld-linux
Status: CLOSED NOTABUG
Alias: None
Product: Sisyphus
Classification: Development
Component: kernel-image-un-def (show other bugs)
Version: unstable
Hardware: x86_64 Linux
: P5 major
Assignee: Vitaly Chikunov
QA Contact: qa-sisyphus
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-03-16 22:18 MSK by mikhailnov
Modified: 2022-07-20 15:54 MSK (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description mikhailnov 2020-03-16 22:18:22 MSK
На 5.5.6-un-def-alt1 в соответствии с https://www.altlinux.org/AltHa и Documentation/admin-guide/LSM/AltHa.rst настроил блокировку интерпретатор, но в дефолтной рекомендуемой конфигурации нет проблем запустить заблокированный интерпретатор:

[root@alt-xfce ~]# sysctl -w kernel.altha.rstrscript.enabled=1
[root@alt-xfce ~]# sysctl -w kernel.altha.rstrscript.interpreters=/usr/bin/python:/usr/bin/python3:/usr/bin/perl:/usr/bin/tclsh
[root@alt-xfce ~]# python3
-bash: /usr/bin/python3: Операция не позволена
[root@alt-xfce ~]# dmesg | tail -n 1
[  162.090737] AltHa/RestrScript: /usr/bin/python3 is blocked to run directly by 0
[root@alt-xfce ~]# /lib64/ld-linux-x86-64.so.2 /usr/bin/python3
Python 3.7.4 (default, Oct 18 2019, 08:46:11) 
[GCC 8.3.1 20190507 (ALT Sisyphus 8.3.1-alt5)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 

Но при этом:

[root@alt-xfce ~]# setarch --addr-no-randomize /usr/bin/python3
setarch: невозможно выполнить /usr/bin/python3: Операция не позволена
[root@alt-xfce ~]# dmesg | tail -n 1
[  597.621353] AltHa/RestrScript: /usr/bin/python3 is blocked to run directly by 0
[root@alt-xfce ~]# 

В коде вижу, что производится сравнение путей:
> if (path_equal(&bprm->file->f_path, &node->path)) {
http://git.altlinux.org/gears/k/kernel-image-un-def.git?p=kernel-image-un-def.git;a=blob;f=security/altha/altha_lsm.c;h=7d1cc8f8a1a7ada31975473935a620e8ff2f772d;hb=HEAD#l260

Как это красиво решить, я пока не придумал.
Comment 1 Anton V. Boyarshinov 2020-03-17 11:12:35 MSK
Спасибо, будем думать
Comment 2 Anton V. Boyarshinov 2020-03-17 11:35:02 MSK
На мой взгляд, самое простое и разумное -- добавить /lib64/ld-linux-x86-64.so.2 и /lib/ld-linux.so.2 (ну и на других платформах соответственно)  в списки ограничений altha.

Обычно они не запускаются напрямую.

Что-то, скорее всего, сломается (как и при блокировке прямого запуска интерпретаторов вообще), но быстрый тест на рабочей станции 9 не показал регрессий.

Спасибо за сообщение, эту информацию обязательно надо будет внести в документацию
Comment 3 mikhailnov 2020-03-17 13:45:16 MSK
Я тоже не придумал, чем на типовой рабочей станции может помешать запрет запуска ld-linux*. Но здесь хочется выяснить, почему при запуске через ld-linux не происходит блокировки, через strace видны одинаковые системные вызовы:
[root@alt-xfce ~]# strace /lib64/ld-linux-x86-64.so.2 /usr/bin/python3 2>&1 | grep /usr/bin/python3
execve("/lib64/ld-linux-x86-64.so.2", ["/lib64/ld-linux-x86-64.so.2", "/usr/bin/python3"], 0x7fff7c00c658 /* 45 vars */) = 0
openat(AT_FDCWD, "/usr/bin/python3", O_RDONLY|O_CLOEXEC) = 3
<...>
[root@alt-xfce ~]# strace /bin/sh /usr/bin/python3 2>&1 | grep /usr/bin/python3
execve("/bin/sh", ["/bin/sh", "/usr/bin/python3"], 0x7ffe002e9148 /* 45 vars */) = 0
openat(AT_FDCWD, "/usr/bin/python3", O_RDONLY) = 3
<...>
[root@alt-xfce ~]# 
В первом случае блокировка не срабатывает, во втором срабатывает.
Надеюсь, через user mode linux получится проследить, как так получается. Сборки uml с altha у меня уже есть, пока не запускал и не уверен, что под uml LSM будут работать.
Comment 4 Anton V. Boyarshinov 2020-03-17 14:16:12 MSK
(Ответ для Михаил Новоселов на комментарий #3)
> Я тоже не придумал, чем на типовой рабочей станции может помешать запрет
> запуска ld-linux*. Но здесь хочется выяснить, почему при запуске через
> ld-linux не происходит блокировки, через strace видны одинаковые системные
> вызовы:
> [root@alt-xfce ~]# strace /lib64/ld-linux-x86-64.so.2 /usr/bin/python3 2>&1
> | grep /usr/bin/python3
> execve("/lib64/ld-linux-x86-64.so.2", ["/lib64/ld-linux-x86-64.so.2",
> "/usr/bin/python3"], 0x7fff7c00c658 /* 45 vars */) = 0
> openat(AT_FDCWD, "/usr/bin/python3", O_RDONLY|O_CLOEXEC) = 3
> <...>
> [root@alt-xfce ~]# strace /bin/sh /usr/bin/python3 2>&1 | grep

тут должно быть strace /bin/sh -с /usr/bin/python3

Что даёт
execve("/bin/sh", ["/bin/sh", "-c", "/usr/bin/python"], 0x7ffd0d05fa60 /* 64 vars */) = 0
execve("/usr/bin/python", ["/usr/bin/python"], 0x775700 /* 64 vars */) = 0


А в случае запуска через ld-linux, второго exec нет
Comment 5 mikhailnov 2020-11-05 15:35:31 MSK
AltHa привязывается к LSM-хукам bprm_set_creds и inode_unlink. А вот в политиках IMA обычно отслеживают bprm_check и mmap_file:
https://en.opensuse.org/SDB:Ima_evm#Configuration_of_the_IMA_Policy_and_dracut_Early_Init

<...>
appraise func=BPRM_CHECK fowner=0 appraise_type=imasig
appraise func=BPRM_CHECK euid=0 appraise_type=imasig
appraise func=FILE_MMAP fowner=0 mask=MAY_EXEC appraise_type=imasig
appraise func=FILE_MMAP euid=0 mask=MAY_EXEC appraise_type=imasig
<...>
Require all files that are directly executed or memory mapped with execute permission to carry a digital signature

При запуске через rtld выполняется mmap с PROT_EXEC 2 раза:

$ strace /lib64/ld-linux-x86-64.so.2 /bin/true 2>&1 | grep mmap | grep PROT_EXEC
mmap(0x7f72dd6ca000, 16384, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7f72dd6ca000
mmap(0x7f72dd4a5000, 1540096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x25000) = 0x7f72dd4a5000

Без rtld - один раз:
$ strace /bin/true 2>&1 | grep mmap | grep PROT_EXEC
mmap(0x7f96b4d5f000, 1540096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x25000) = 0x7f96b4d5f000

Может быть, в АльтХе стоит ловить mmap с PROT_EXEC, как это делает IMA?
Comment 6 mikhailnov 2020-11-05 15:41:02 MSK
Может ли быть блокировка mmap() с PROT_EXEC полезна еще чем-то, кроме отсутствия необходимости блокировать rtld как интерпретатор?
Comment 7 Dmitry V. Levin 2020-11-06 02:34:28 MSK
(In reply to Михаил Новоселов from comment #5)
> $ strace /bin/true 2>&1 | grep mmap | grep PROT_EXEC
> mmap(0x7f96b4d5f000, 1540096, PROT_READ|PROT_EXEC,
> MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x25000) = 0x7f96b4d5f000

Меня насторожил этот пример, потому что альтовый /bin/true не использует rtld, и mmap ему делать совершенно незачем.  Но я на всякий случай проверил:
$ env -i strace -v /bin/true
execve("/bin/true", ["/bin/true"], [])  = 0
exit_group(0)                           = ?
+++ exited with 0 +++

Наверное, /bin/true не очень подходит в качестве иллюстрации, лучше /bin/cat </dev/null
Comment 8 Anton V. Boyarshinov 2020-11-06 10:36:24 MSK
> Может быть, в АльтХе стоит ловить mmap с PROT_EXEC, как это делает IMA?

Я сомневаюсь, что в хуке на mmap удастся отличить запуск бинарника как интерпертатор и прямой запуск.

> необходимости блокировать rtld как интерпретатор?
Вообще говоря, запрет прямого запуска rtld, запуска не в качестве интерпретатора выглядит неплохой идеей для систем, в которых это предполагается использовать.
Comment 9 mikhailnov 2020-11-06 11:17:48 MSK
(Ответ для Dmitry V. Levin на комментарий #7)
> Меня насторожил этот пример, потому что альтовый /bin/true не использует
> rtld, и mmap ему делать совершенно незачем.  Но я на всякий случай проверил:
> $ env -i strace -v /bin/true
> execve("/bin/true", ["/bin/true"], [])  = 0
> exit_group(0)                           = ?
> +++ exited with 0 +++
> 
> Наверное, /bin/true не очень подходит в качестве иллюстрации, лучше /bin/cat
> </dev/null

Да, пример был не с Альта, спасибо за уточнение.

(Ответ для Anton V. Boyarshinov на комментарий #8)
> > Может быть, в АльтХе стоит ловить mmap с PROT_EXEC, как это делает IMA?
> 
> Я сомневаюсь, что в хуке на mmap удастся отличить запуск бинарника как
> интерпертатор и прямой запуск.

Разумно. Надо сказать, звучит как повод в rpm автоматически заменять #!/usr/bin/env foo на реальный путь в шебангах.
Comment 10 mikhailnov 2022-07-20 15:54:02 MSK
Смотрю, в исходниках ядра теперь упомянут ld-linux, но на вики не был. Добавил про него в статью https://www.altlinux.org/AltHa

P.S. В исходниках
https://git.altlinux.org/gears/k/kernel-image-un-def.git?p=kernel-image-un-def.git;a=blob;f=Documentation/admin-guide/LSM/AltHa.rst;h=beda40601c9e72fb1b9ed17e5492a3223a707452;hb=HEAD#l35
кавычки стоят на одно слово правее, чем нужно, мне кажется:
"Adding ld-linux into blocking list prevents running interpreters via ``ld-linux interpreter``"