Копия Управление процессами - efanov/mephi GitHub Wiki
Изучить свойства процессов и командный интерфейс управления процессами. Изучить механизм привилегий (capabilities).
Команды, изучаемые в лабораторной работе: ps
, top
, pgrep
, pstree
, w
, uptime
, jobs
, fg
, bg
, kill
, killall
, pkill
, trap
, getcap
, setcap
.
-
Выведите информацию обо всех процессах в системе, используя стандартный синтаксис:
$ ps -e $ ps -ef $ ps -eF $ ps -ely
-
Выведите информацию обо всех процессах в системе, используя синтаксис BSD:
$ ps ax $ ps axu
-
Выведите информацию обо всех процессах в системе в виде дерева:
$ ps -ejH $ ps axjf
-
Выведите информацию о легковесных процессах:
$ ps -eLf $ ps axms
-
Выведите атрибуты безопасности процессов:
$ ps -eo euser,ruser,suser,fuser,f,comm,label $ ps axZ $ ps -eM
-
Выведите информацию о процессах, выполняющихся от имени пользователя root (real & effective ID), в пользовательском формате:
$ ps -U root -u root u
-
Выведите информацию о процессах в пользовательском формате:
$ ps -eo pid,tid,class,rtprio,ni,pri,psr,pcpu,stat,wchan:14,comm $ ps axo stat,euid,ruid,tty,tpgid,sess,pgrp,ppid,pid,pcpu,comm $ ps -Ao pid,tt,user,fname,tmout,f,wchan
-
Выведите только идентификаторы процессов с именем systemd:
$ ps -C systemd -o pid=
-
Выведите только имя процесса с идентификатором номер:
$ ps -q номер -o comm=
-
Откройте два окна терминала (левый и правый).
-
В левом окне запустите бесконечный процесс, который с интервалом в одну секунду будет писать строку AAA в файл test.out в домашнем каталоге.
$ ( while true; do printf "AAA %d " $$ >> ~/test.out; sleep 1; done )
-
В правом окне наблюдайте за работой процесса.
$ tail -f ~/test.out
-
В левом окне остановите процесс. BASH вернет номер задания в квадратных скобках. Убедитеь, что процесс перестал писать в файл.
$ Ctrl+z
-
В левом окне выведите список заданий. Знаком + помечено текущее задание. Определите состояние процесса. Запустите задание в фоновом режиме. Убедитеь, что процесс снова продолжил писать в файл. Определите состояние процесса ещё раз.
$ jobs $ ps j $ bg $ jobs $ ps j
-
В левом окне запустите второй бесконечный процесс в фоновом режиме, который с интервалом в одну секунду будет писать строку UUU в файл test.out в домашнем каталоге. Команда должна быть заключена в круглые скобки и заканчиваться знаком &.
$ ( while true; do printf "UUU %d " $$ >> ~/test.out; sleep 1; done ) &
-
В левом окне выведите список заданий. Убедитеь, что теперь два процесса пишут в файл.
$ jobs
-
В левом окне завершите процессы.
$ fg %номер $ Ctrl+c $ fg %номер $ Ctrl+c
-
В правом окне завершите команду tail.
-
Откройте два окна терминала (левый и правый).
-
В левом окне запустите два бесконечных процесса, которые с интервалом в одну секунду будут писать строки в файл test.out в домашнем каталоге. Выведите список заданий (наблюдайте Running). Определите состояние процессов.
$ ( while true; do printf "AAA %d " $$ >> ~/test.out; sleep 1; done ) & $ ( while true; do printf "UUU %d " $$ >> ~/test.out; sleep 1; done ) & $ jobs $ ps j
-
В правом окне наблюдайте за работой процессов.
$ tail -f ~/test.out
-
В левом окне остановите первый процесс (задание "AAA"). Выведите список заданий (наблюдайте Stopped).
$ kill -SIGSTOP %1 $ jobs
-
В левом окне завершите второй процесс (задание "UUU"). Выведите список заданий (наблюдайте Terminated).
$ kill -SIGTERM %2 $ jobs
-
В левом окне завершите процесс.
$ fg $ Ctrl+c
-
В правом окне завершите команду tail.
Команда trap позволяет установить обработчик на сигнал. Опция -l выводит список сигналов. Опция -p выводит установленные обработчики сигналов.
-
Выведите список сигналов.
$ trap -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
-
Запустите дочерний shell и установите обработчик сигнала EXIT (0, который посылается нажатием Ctrl+d).
$ sh sh-4.3$ trap 'echo Завершение работы...; sleep 2' EXIT sh-4.3$ trap -p EXIT trap -- 'echo Завершение работы...; sleep 2' EXIT
-
Завершите shell.
$ Ctrl+d
-
Наблюдайте перехват сигнала и вызов обработчика.
-
Создайте сценарий.
$ cat test-trap.sh #!/bin/bash declare -i i=0 trap 'echo "Аварийное завершение..."; exit 1' SIGINT while [ $i -lt 100 ] do (( i++ )) echo $i sleep 1 done
-
Запустите сценарий.
$ chmod +x test-trap.sh $ ./test-trap.sh
-
Завершите сценарий. Объясните результаты.
$ Ctrl+c
-
Изучите содержимое файла /proc/version и сравните с выводом команды uname -a.
-
Изучите и сравниет содержимое файлов /proc/meminfo и /sys/devices/system/node/node0/meminfo, и вывод команды free.
-
Изучите содержимое файла /proc/cpuinfo. Определите количество ядер.
-
Изучите содержимое файла /proc/uptime и сравните с выводом команды uptime.
-
Изучите специальную символьную ссылку /proc/self, которая указывает на подкаталог текущего процесса. В переменной $ хранится PID текущего процесса. Объясните результаты.
$ echo $$ 3203 $ ls -l /proc/self lrwxrwxrwx. 1 root root 0 Oct 13 21:42 /proc/self -> 12485 $ ls -ld /proc/$$ dr-xr-xr-x. 9 defanov defanov 0 Oct 13 18:58 /proc/3203
-
Изучите содержимое файла /proc/PID_процесса/stat. Формат вывода можно посмотреть в исходном коде ядра Linux в файле /fs/proc/array.c в функции do_task_stat().
$ read pid tcomm state other < /proc/$$/stat $ echo "Процесс $pid $tcomm находится в состоянии $state" Процесс 3203 (bash) находится в состоянии R
-
Изучите различные формы обращения к файловым дескрипторам и потокам stdin, stdout, stderr.
$ ls -l /dev/std* lrwxrwxrwx. 1 root root 15 Oct 13 21:42 /dev/stderr -> /proc/self/fd/2 lrwxrwxrwx. 1 root root 15 Oct 13 21:42 /dev/stdin -> /proc/self/fd/0 lrwxrwxrwx. 1 root root 15 Oct 13 21:42 /dev/stdout -> /proc/self/fd/1 $ ls -l /dev/fd/ total 0 lrwx------. 1 defanov defanov 64 Oct 14 00:31 0 -> /dev/pts/0 lrwx------. 1 defanov defanov 64 Oct 14 00:31 1 -> /dev/pts/0 lrwx------. 1 defanov defanov 64 Oct 14 00:31 2 -> /dev/pts/0 lr-x------. 1 defanov defanov 64 Oct 14 00:31 3 -> /proc/13123/fd
-
Изучите список открытых файлов процесса. Определите потоки stdin, stdout, stderr.
$ ls -l /proc/self/fd total 0 lrwx------. 1 defanov defanov 64 Oct 14 00:07 0 -> /dev/pts/0 lrwx------. 1 defanov defanov 64 Oct 14 00:07 1 -> /dev/pts/0 lrwx------. 1 defanov defanov 64 Oct 14 00:07 2 -> /dev/pts/0 lr-x------. 1 defanov defanov 64 Oct 14 00:07 3 -> /proc/12898/fd
-
Перенаправьте потоки stdout и stderr в файлы. Объясните результаты.
[defanov@dimix /]$ ls -l /proc/self/fd > /tmp/ls.out 2> /tmp/ls.err [defanov@dimix /]$ cat /tmp/ls.out total 0 lrwx------. 1 defanov defanov 64 Oct 14 00:09 0 -> /dev/pts/0 l-wx------. 1 defanov defanov 64 Oct 14 00:09 1 -> /tmp/ls.out l-wx------. 1 defanov defanov 64 Oct 14 00:09 2 -> /tmp/ls.err lr-x------. 1 defanov defanov 64 Oct 14 00:09 3 -> /proc/12915/fd
-
Перенаправьте поток stdin. Объясните права доступа.
-
Откройте два окна терминала (левый и правый).
-
В левом окне запустите конвейер, перенаправьте потоки stdout и stderr в файлы в домашнем каталоге.
$ ( cat | head ) > ~/test.out 2> ~/test.err
-
В правом окне выведите списки открытых файлов процессов bash, cat и head.
$ ps j PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 13700 13704 13704 13704 pts/0 13881 Ss 1000 0:00 bash 13700 13746 13746 13746 pts/1 13884 Ss 1000 0:00 bash 13704 13881 13881 13704 pts/0 13881 S+ 1000 0:00 bash 13881 13882 13881 13704 pts/0 13881 S+ 1000 0:00 cat 13881 13883 13881 13704 pts/0 13881 S+ 1000 0:00 head 13746 13884 13884 13746 pts/1 13884 R+ 1000 0:00 ps j $ ls -l /proc/13881/fd total 0 lrwx------. 1 defanov defanov 64 Oct 14 01:31 0 -> /dev/pts/0 l-wx------. 1 defanov defanov 64 Oct 14 01:31 1 -> /home/defanov/test.out l-wx------. 1 defanov defanov 64 Oct 14 01:30 2 -> /home/defanov/test.err lrwx------. 1 defanov defanov 64 Oct 14 01:31 255 -> /dev/pts/0 $ ls -l /proc/13882/fd total 0 lrwx------. 1 defanov defanov 64 Oct 14 01:30 0 -> /dev/pts/0 l-wx------. 1 defanov defanov 64 Oct 14 01:30 1 -> pipe:[173460] l-wx------. 1 defanov defanov 64 Oct 14 01:30 2 -> /home/defanov/test.err $ ls -l /proc/13883/fd total 0 lr-x------. 1 defanov defanov 64 Oct 14 01:30 0 -> pipe:[173460] l-wx------. 1 defanov defanov 64 Oct 14 01:30 1 -> /home/defanov/test.out l-wx------. 1 defanov defanov 64 Oct 14 01:30 2 -> /home/defanov/test.err
-
Изучите как поток stdout процесса cat связан с потоком stdin процесса head.
-
В левом окне завершите процессы.
-
В левом окне создайте именованный канал и запустите команду cat с перенаправлением вывода в созданный канал.
$ mkfifo ~/fifo1 $ cat > ~/fifo1
-
В правом окне запустите команду cat с перенаправлением ввода из канала.
$ cat < ~/fifo1
-
Откройте новое окно терминала, в котором выведите списки открытых файлов двух процессов cat.
-
В новом (третьем) окне запустите команду cat с перенаправлением ввода из канала.
$ cat < ~/fifo1
-
В левом окне вводите строки текста и наблюдайте вывод в двух других окнах. Объясните результаты.
-
Организуйте чтение из канала в бесконечном цикле while с помощью команды read.
-
Завершите процессы.
Команда exec используется для двух целей: запуск программ и открытие файлов.
-
Запустите дочерний shell и заместите коды порожденного процесса кодами команды ps -l. Обратите внимание на то, что PID процесса sh совпадает с PID процесса ps (13028). Объясните результаты.
$ sh sh-4.3$ ps -l F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 0 S 1000 3203 3197 0 80 0 - 29691 wait pts/0 00:00:00 bash 0 S 1000 13028 3203 0 80 0 - 28960 wait pts/0 00:00:00 sh 0 R 1000 13030 13028 0 80 0 - 34450 - pts/0 00:00:00 ps sh-4.3$ exec ps -l F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 0 S 1000 3203 3197 0 80 0 - 29691 wait pts/0 00:00:00 bash 0 R 1000 13028 3203 0 80 0 - 34450 - pts/0 00:00:00 ps $ ps -l F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 0 S 1000 3203 3197 0 80 0 - 29691 wait pts/0 00:00:00 bash 0 R 1000 13034 3203 0 80 0 - 34450 - pts/0 00:00:00 ps
-
Исследуйте работу процесса с файлами на примере bash. Откройте файл ~/test.out на запись и свяжите его с дескриптором 3.
$ exec 3> ~/test.out $ ls -l /proc/$$/fd total 0 lrwx------. 1 defanov defanov 64 Oct 14 00:31 0 -> /dev/pts/0 lrwx------. 1 defanov defanov 64 Oct 14 00:31 1 -> /dev/pts/0 lrwx------. 1 defanov defanov 64 Oct 14 00:21 2 -> /dev/pts/0 lrwx------. 1 defanov defanov 64 Oct 13 21:30 255 -> /dev/pts/0 l-wx------. 1 defanov defanov 64 Oct 14 00:31 3 -> /home/defanov/test.out $ echo Test Test $ echo Test3 >&3 $ cat ~/test.out Test3 $ echo Test333 >&3 $ cat ~/test.out Test3 Test333
-
Выведите информацию об открытых файлах процесса bash. Объясните позицию указателя чтения/записи (pos: 14).
$ echo $$ 3203 $ ls -l /proc/3203/fdinfo/ total 0 -r--------. 1 defanov defanov 0 Oct 13 21:30 0 -r--------. 1 defanov defanov 0 Oct 13 21:30 1 -r--------. 1 defanov defanov 0 Oct 13 21:30 2 -r--------. 1 defanov defanov 0 Oct 13 21:30 255 -r--------. 1 defanov defanov 0 Oct 14 00:40 3 $ cat /proc/3203/fdinfo/3 pos: 14 flags: 0100001 mnt_id: 82
-
Откройте файл ~/test.out на чтение и свяжите его с дескриптором 4.
$ exec 4< ~/test.out $ ls -l /proc/$$/fd total 0 lrwx------. 1 defanov defanov 64 Oct 14 00:31 0 -> /dev/pts/0 lrwx------. 1 defanov defanov 64 Oct 14 00:31 1 -> /dev/pts/0 lrwx------. 1 defanov defanov 64 Oct 14 00:21 2 -> /dev/pts/0 lrwx------. 1 defanov defanov 64 Oct 13 21:30 255 -> /dev/pts/0 l-wx------. 1 defanov defanov 64 Oct 14 00:31 3 -> /home/defanov/test.out lr-x------. 1 defanov defanov 64 Oct 14 00:54 4 -> /home/defanov/test.out $ cat ~/test.out Test3 Test333 $ cat <&4 Test3 Test333 $ cat ~/test.out Test3 Test333 $ cat <&4 $ $ echo Test4 >&3 $ cat ~/test.out Test3 Test333 Test4 $ cat <&4 Test4 $ cat <&4 $
-
Удалите файл ~/test.out.
$ rm ~/test.out $ ls -l /proc/$$/fd total 0 lrwx------. 1 defanov defanov 64 Oct 14 00:31 0 -> /dev/pts/0 lrwx------. 1 defanov defanov 64 Oct 14 00:31 1 -> /dev/pts/0 lrwx------. 1 defanov defanov 64 Oct 14 00:21 2 -> /dev/pts/0 lrwx------. 1 defanov defanov 64 Oct 13 21:30 255 -> /dev/pts/0 l-wx------. 1 defanov defanov 64 Oct 14 00:31 3 -> /home/defanov/test.out (deleted) lr-x------. 1 defanov defanov 64 Oct 14 00:54 4 -> /home/defanov/test.out (deleted)
-
Попробуйте вывести содержимое файла ~/test.out командой cat, используя два способа обращения к файлу: через дескриптор и через имя. Объясните результат.
Найти в системе все процессы, у которых различаются реальные и эффективные пользовательские идентификаторы. Для обнаруженных процессов вывести имя программы.
Для тестирования можно использовать программу passwd.
- Что происходит при прерывании скрипта
text-trap.sh
? Объясните, почему. - Напишите, по какой причине выводы команды
ls -l /proc/self
иls -l /proc/$$
отличаются? - Напишите, какие дескрипторы в выводе команды
ls -l /proc/self/fd
отвечают заstdin
,stdout
,stderr
. - Что происходит с дескрипторами при перенаправлении потоков
stdout
иstderr
в файлы при выполнении командыls -l /proc/self/fd > /tmp/ls.out 2> /tmp/ls.err
? - Запишите эту же команду, добавив к ней перенаправление потока stdin. Что изменилось?
- Какой эффект наблюдается при выполнении команды
exec ps -l
? - Что означает
pos
при выводе содержимого файла/proc/$$/fdinfo/3
? - Существует ли возможность читать содержимое файла
test.out
даже после его удаления? Почему так происходит?
Механизм привилегий (capabilities) позволяет разделить неограниченные права суперпользователя (у которого EUID == 0
) по администрированию системы на отдельные группы прав, которые могут быть независимо друг от друга предоставлены обычным пользователям (у которых EUID != 0
).
Этим достигается реализация принципа наименьших привилегий, а также уменьшается поверхность атаки: если программа, обладающая одной или более привилегиями скомпрометирована, ее возможности по нанесению ущерба системе будут меньше по сравнению с такой же программой, выполняющейся с EUID == 0
.
Каждый процесс обладает пятью 64-битными векторами привилегий.
Эти векторы хранятся в структуре cred
, на которую ссылается указатель из дескриптора процесса task_struct
.
Рассмотрим фрагмент структуры cred
:
struct cred {
// ...
kernel_cap_t cap_inheritable;
kernel_cap_t cap_permitted;
kernel_cap_t cap_effective;
kernel_cap_t cap_bset;
kernel_cap_t cap_ambient;
// ...
}
- Наследуемый вектор (inheritable) — привилегии, которые сохраняются при выполнении вызова
execve
. Наследуемые привилегии остаются наследуемыми при выполнении любой программы. Наследуемые привилегии добавляются к разрешенному набору при выполнении программы, у которой есть соответствующие биты в наследуемом наборе файла. - Разрешенный вектор (permitted) — максимальный набор привилегий, которые может использовать процесс (является надмножеством эффективного набора).
Это также максимальный набор привилегий, которые могут быть добавлены в наследуемый набор процессом, не имеющим привилегию
CAP_SETPCAP
в своем эффективном наборе. Если процесс удаляет привилегию из своего разрешенного набора, он никогда не сможет повторно получить эту возможность. Исключения составляют случаи запуска в процессе программы с установленным битомSUID
или программы с установленной привилегией на исполняемый файл. - Эффективный вектор (effective) – набор привилегий, используемый ядром при выполнении проверок доступа для процесса (permission checks).
- Ограничивающий вектор (bounding) – механизм, который может использоваться для ограничения привилегий, получаемых во время вызова
execve
. - Внешний вектор (ambient) – привилегии, которые сохраняются при выполнении вызова
execve
привилегированной программой. Привилегия может быть внешней, если она одновременно разрешенная и наследуемая. Внешние привилегии автоматически сбрасываются, если соответствующая разрешенная или наследуемая привилегия сбрасывается.
Посмотреть привилегии процесса можно в файле /proc/<pid>/status
.
Рассмотрим на примере обычного пользователя user1
привилегии процесса cat
:
id
# Вывод:
# uid=1001(user1) gid=1001(user1) groups=1001(user1) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
cat /proc/self/status | grep ^Cap
# Вывод:
# CapInh: 0000000000000000
# CapPrm: 0000000000000000
# CapEff: 0000000000000000
# CapBnd: 000001ffffffffff
# CapAmb: 0000000000000000
capsh --print
# Вывод:
# Current: =
# Bounding set =cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read,38,39,40
# Ambient set =
# Securebits: 00/0x0/1'b0
# secure-noroot: no (unlocked)
# secure-no-suid-fixup: no (unlocked)
# secure-keep-caps: no (unlocked)
# secure-no-ambient-raise: no (unlocked)
# uid=1001(user1)
# gid=1001(user1)
# groups=1001(user1)
capsh --decode=0000000000000001
# Вывод:
# 0x0000000000000001=cap_chown
Для исследования и конструирования наборов привилегий предназначена команда capsh
.
Системные вызовы capget
и capset
позволяют процессу манипулировать собственными векторами привилегий.
Привилегии также можно связать с исполняемым файлом с помощью команды setcap
.
Привилегии файла хранятся в его расширенных атрибутах в пространстве security.capability
.
Запись в этот расширенный атрибут требует наличия привилегии CAP_SETFCAP
.
Суперпозиция привилегий исполняемого файла и привилегий вызывающего процесса определяет привилегии процесса после выполнения системного вызова execve
.
Существует три набора привилегий файла:
- разрешенный набор (permitted) — эти привилегии автоматически разрешаются процессу, независимо от наследуемых привилегий процесса;
- наследуемый набор (inheritable) — логически перемножается с наследуемым набором процесса (операция логического «И»), чтобы определить, какие наследуемые привилегии должны быть включены в разрешенном наборе процесса после вызова
execve
; - эффективный бит (effective).
Если этот бит установлен, то во время выполнения вызова
execve
все новые разрешенные привилегии процесса также поднимаются в векторе эффективных привилегий. Если этот бит не установлен, то послеexecve
никаких новых разрешенных привилегий нет в новом эффективном наборе.
Во время выполнения вызова execve
ядро вычисляет новые привилегии процесса по следующему алгоритму:
P'(ambient) = (файл привилегированный) ? 0 : P(ambient)
P'(permitted) = (P(inheritable) & F(inheritable)) | (F(permitted) & P(bounding)) | P'(ambient)
P'(effective) = F(effective) ? P'(permitted) : P'(ambient)
P'(inheritable) = P(inheritable) [не изменяется]
P'(bounding) = P(bounding) [не изменяется]
где P()
– привилегии процесса до вызова execve
; P'()
– привилегии процесса после вызова execve
; F()
– привилегии исполняемого файла.
Относительно механизма привилегий программы можно разделить на две группы:
- программы, использующие привилегии, которые скомпилированы с библиотекой
libcap
(можно посмотреть с помощью командыldd
); - программы, не использующие механизм привилегий (capability-dumb).
Рассмотрим привилегии исполняемого файла на примере команды cat
.
Пусть обычный пользователь попытается вывести на экран содержимое файла /etc/shadow
, в котором хранятся хэши паролей пользователей, и который доступен только пользователю root
:
whereis -b cat
# Вывод:
# cat: /usr/bin/cat
ldd /usr/bin/cat
# Вывод:
# linux-vdso.so.1 (0x00007ffc48c74000)
# libc.so.6 => /lib64/libc.so.6 (0x00007f5304859000)
# /lib64/ld-linux-x86-64.so.2 (0x00007f5304a4a000)
cat /etc/shadow
# Вывод:
# cat: /etc/shadow: Permission denied
Видно, что в выводе команды ldd
отсутствует библиотека libcap
.
Это означает, что программа cat
не умеет управлять своими привилегиями, т.е. разработчик программы cat
не использовал API библиотеки libcap
для обращения к механизму привилегий.
Создадим копию программы cat и с помощью команды setcap
установим для нее привилегию cap_dac_read_search
.
Так как cat
является capability-dumb-программой, то необходимо установить оба набора привилегий (=pe
) у исполняемого файла: разрешенный (p
) и эффективный (e
).
Если бы программа cat
умела управлять своими привилегиями, то было бы достаточно установить только разрешенный (p
) набор привилегий.
Команда getcap
показывает, что привилегия установлена.
cp /usr/bin/cat .
sudo setcap "cap_dac_read_search=ep" cat
getcap ./cat
# Вывод:
# ./cat = cap_dac_read_search+ep
./cat /etc/shadow | head -n 1
# Вывод:
# root:!::0:99999:7:::
Теперь обычный пользователь может прочитать содержимое любого файла в системе, независимо от установленных для этого файла дискреционных прав доступа, т.е. может обходить механизм DAC по чтению.
- Как запустить программу в фоновом режиме?
- Что такое сигналы и зачем они нужны?
- Какие системные вызовы используются для создания нового процесса?
- Что такое привилегии и для чего они нужны?
- Что такое зомби-процессы?
Для защиты работы необходимо ответить на вопросы по теме работы.