LINUX.ORG.RU

Функция в bash для обработки выполнения внешних команд

 , , ,


0

4

Есть ли в bash какая-нибудь функция или переменная, с помощью которой можно детерминировать имя вызываемой внешней программы?

Т.е. нужно прописать что-то в ~/.bashrc, чтобы в интерактивном режиме при выполнении ЛЮБОЙ внешней программы выполнялась определённая функция-обработчик, что-то типо хука, знающая имя вызываемой внешней программы.

например при вызове

$ command arguments
ЗАМЕСТО выполнения 'command arguments' должна выполнятся моя функция, которая получает аргументы 'command arguments' и выполняет определённые действмя.

★★★★★
Ответ на: комментарий от Bfgeshka

я хочу сделать обработчик набранных команд, чтобы при вызове любых внешних программ выполнялся запуск этих команд от другого пользователя (кроме чёрного списка).

я всю жизнь, что пользуюсь линуксом, сижу под рутом. уже сделал функцию, чтобы от рута при вызове определённых команд, таких как vp (скрипт для mpv для видео), ap (скрипт для mpv для аудио), ly (скрипт для lynx), rtorrent (скрипт для rtorrent), y (скрипт для yt-dlp), ff (скрипт для ffmpeg), fir (скрипт для firefox), wg (скрипт для wget), выполнялись одноимённые функции, делающие 'su user ...'

Пришла мысль, что хорошо бы заместо белого списка сделать чёрный, т.е. сделать чтобы под рутом вообще всё запускалось от другого пользователя, кроме определённых команд (mount, ls, chmod, chown, ...).

Т.е. нужно перехватывать запускаемые в интерактивном шелле внешние программы и заместо них выполнять определённую функцию.

teod0r ★★★★★
() автор топика
Ответ на: комментарий от teod0r

сижу под рутом.

хорошо бы заместо белого списка сделать чёрный, т.е. сделать чтобы под рутом вообще всё запускалось от другого пользователя, кроме определённых команд (mount, ls, chmod, chown, …).

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

Вот как у меня:

$ cat /etc/sudoers.d/util-linux
%users ALL=NOPASSWD: /bin/mount *, /bin/umount *

$ cat /etc/bash/bashrc.d/util-linux_aliases.sh
if [[ ${EUID} == 0 ]] ; then
        true
else
        alias mount="sudo /bin/mount"
        alias umount="sudo /bin/umount"
fi

# Result

$ alias
alias mount='sudo /bin/mount'
alias umount='sudo /bin/umount'
alias poweroff='sudo /sbin/poweroff'
alias reboot='sudo /sbin/reboot'
alias shutdown='sudo /sbin/shutdown'
...
Kroz ★★★★★
()

Напиши свой маленький REPL и запускай его как оболочку, без всех фичей шелла конечно, но задачу решать именно эту будет на ура.

В ином случае патчить sh/bash/dash/няш/мяш/etc

Как альтернатива, можно найти всё исполняемое в системе и всё встраиваемое и вписать в .bashrc всё это в виде функций.

ls()
{
  echo "Пользователь запустил 'ls' с аргументами $@"
  command ls $@
}

alias ls='ls --color=auto'
dron@gnu:~$ ls
Пользователь запустил 'ls' с аргументами --color=auto
 backup-info.log   move.diff         Видео         Музыка
 car-demo          req.lua           Документы     Общедоступные
 cc.lua            SOMAModLauncher   Загрузки      Рабочий-стол

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от Kroz

Тебе нужно наоборот: сидеть под пользователем, и сделать белый список для рутовых команд.
sudo

нет. в моей системе нет такого говна как sudo, systemd, polkit, consolekit, PAM.
в моей системе ни один пользователь вообще не может поднять привелегии впринципе. у рута пароля вообще нет, просто не нужен.

teod0r ★★★★★
() автор топика
Ответ на: комментарий от teod0r
shopt -s extdebug
trap 'preexec' DEBUG

preexec(){
  [ -n "$COMP_LINE" ] && return
  [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return
  local this_command=$(HISTTIMEFORMAT= history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//");

if [ "shopt -u extdebug" == "$this_command" ]; then
  return 0
fi

# Твой код тут
echo "$this_command"

return 1 # Чтоб не выполнялась оригинальная команда
}
BACR
()
Последнее исправление: BACR (всего исправлений: 1)
Ответ на: комментарий от BACR

похоже на то что нужно.

[ -n «$COMP_LINE» ] && return

что такое $COMP_LINE ?

if [ «shopt -u extdebug» == «$this_command» ]; then

а здесь что проверяется?

есть пару проблем:

не работают аргументы команды с пробелами. наверное, нужно как-то через массив.

если у меня в profile задана PROMPT_COMMAND, то echo «$this_command» выполняется 3 раза.

teod0r ★★★★★
() автор топика
Ответ на: комментарий от teod0r

$COMP_LINE это чтоб не срабатывало на автодополнениях

if [ «shopt -u extdebug» == «$this_command» ]; then чтоб не получилась форк-бомба

есть пару проблем:

давай дальше сам

BACR
()
Ответ на: комментарий от teod0r

в моей системе нет такого говна как sudo, systemd, polkit, consolekit, PAM.

Остальное, конечно, переусложнено, но вот чем тебе sudo не угодил, я не понимаю. Точнее, наверное стоит начать с того, чем тебе не угодило наличие обычного пользователя в добавление к руту.

Kroz ★★★★★
()
Ответ на: комментарий от Kroz

чем тебе sudo не угодил

потенциальная дыра. не раз уже в нём уязвимости находили. тем более зачем оно мне, если я настроил систему без него, и моя система без него безопаснее, чем с ним?

чем тебе не угодило наличие обычного пользователя в добавление к руту

у меня есть обычный пользователь. иксы запускаются от обычного пользователя. под рутом я только в консоли.

teod0r ★★★★★
() автор топика
Ответ на: комментарий от sr11

В иксах эмулятор терминала запретил кто-то? Запускай в нём что надо от пользователя.

в иксах эмулятор терминала и запущен. в нём под рутом всегда сижу. открывать новый экземпляр/вкладку лишнее действме. зачем, если уже есть вклатка с рутом? тем более у меня в st, который стартует при загрузке системы сделано, что при открытии новой вкладки в screen автологин рута. хотел сначала сделать suid-bit на программы, которые нужно запускать от непривилегированного пользователя, но к великому сожалению, на рута suid-bit не действует. патчить ядро?

teod0r ★★★★★
() автор топика
Ответ на: комментарий от anonymous

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

я не запускаю от рута иксы, браузер, yt-dlp, rtorrent, медиаплеер. рут нужен для управления системой (запуск системы инициализации, mount, редактирование системных файлов, запуск демонов, установка/удаление программ). в идеале вообще все демоны должны работать не от рута, а от отдельных пользователей (ntpd, dhcpd, wpa_supplicant, udevd, все). когда-нибудь так сделаю у себя.

а под рутом в терминале сижу просто потому что удобно, нет никаких ограничений. всё-равно всегда нужно править системные файлы, обновлять ПО, монтировать и т.д., зачем ограничивать себя какими-то костылями вроде sudo? это потенциальная дыра, плюс постоянно писать в консоли лишнее слово, не говоря уже про пароль. в основном эмуляторе терминала у меня автологин рута для удобства. когда надо делаю su - user. все пользователи кроме рута не могут менять пользователя, эскалация прав доступа невозможна.

вообще, может, есть смысл сидеть не под рутом, а под каким-нибудь привилегированным пользователем, которому разрешено обновлять ПО, монтировать, запускать демоны, редактировать системные файлы, но будет ли такой пользователь отличаться от рута?

teod0r ★★★★★
() автор топика
Ответ на: комментарий от teod0r

у рута пароля вообще нет, просто не нужен.

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

teod0r ★★★★★
() автор топика
Ответ на: комментарий от teod0r

в моей системе нет такого говна как sudo, systemd, polkit, consolekit ни один пользователь вообще не может поднять привелегии впринципе

Привилегии поднимаются с помощью suid флага. Если у тебя работает su, значит диски не примонтированы с опцией nosuid, и привилегии в принципе поднимаются. Ты можешь и руками расставить suid для нужного набора команд, они всегда от рута будут стрелять, какой бы пользователь их не запустил.

su и sudo работают с помощью этого же suid флага, запускаются сразу как рут, только первый спрашивает пароль рута и запускает что сказали (что угодно), а второй ходит в конфиг, и если эту конкретную команду согласно конфигу можно запустить этому пользователю, спрашивает его личный пароль, или не спрашивает если конфиг разрешил.

Иными словами su + беспарольный рут это полное отсутствие защиты. Любой процесс от любого пользователя может запустить от рута что угодно. Использование sudo на три головы выше и правильнее для твоего конкретного случая, это более умный su с настройками.

neumond
()
Ответ на: комментарий от neumond

Если у тебя работает su, значит диски не примонтированы с опцией nosuid, и привилегии в принципе поднимаются.
Иными словами su + беспарольный рут это полное отсутствие защиты. Любой процесс от любого пользователя может запустить от рута что угодно. Использование sudo на три головы выше и правильнее для твоего конкретного случая

нет. у меня нет suid-bit на su. я вообще поубирал suid-bitы на программы из системы.

teod0r ★★★★★
() автор топика
Ответ на: комментарий от anonymous

$ id

uid=102(user) gid=102(user) groups=102(user),16(audio),17(video),22(input),100(users)

$ stat $(which su)

which: no su in (/bin/:/usr/bin:/S)
stat: missing operand
Try 'stat --help' for more information.
$ stat /sbin/su
  File: /sbin/su
  Size: 57144           Blocks: 112        IO Block: 4096   regular file
Device: 8,1     Inode: 1835121     Links: 1
Access: (0755/-rwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2024-08-16 09:07:20.000000000 +0300
Modify: 2024-08-16 09:07:17.000000000 +0300
Change: 2024-10-14 21:51:50.456673046 +0300
 Birth: 2024-10-14 21:51:50.453339713 +0300

$ su root

-su: su: command not found
$ /sbin/su root
You are not authorized to su root
teod0r ★★★★★
() автор топика
Ответ на: комментарий от MirandaUser2

это задокументированное поведение?

походу да. гопатыч сказал, что при запуске suid-программ осуществляется проверка, авляется ли пользователь рутом, если да - то не срабатывает.

в файле fs/open.c (или аналогичных в зависимости от версии ядра) можно найти обработку прав доступа к файлам. В частности, проверка на то, что функция suid_try_set была выполнена для операций, связанных с suid-программами.

Еще одна важная часть кода находится в fs/exec.c, где происходит выполнение новых программ (например, функция do_execve). Эта функция отвечает за то, как программа запускается и какие права ей выдаются, в том числе учитывая различные биты прав доступа.
ещё писал, что дополнительные проверки осущесталяются в директории security для всяких SELinux...
Буду патчить.

teod0r ★★★★★
() автор топика
Последнее исправление: teod0r (всего исправлений: 1)
Ответ на: комментарий от anonymous

То есть, у тебя где-то постоянно работает интерактивный рутовый шелл, или ты постоянно сидишь под рутом?!

да, я же об этом писал выше. и как это следует из

You are not authorized to su root

?

teod0r ★★★★★
() автор топика
Ответ на: комментарий от teod0r

Иначе ты бы не мог выполнять привилегированные операции. То есть, ты наврал выводом команды id.

У тебя работает в привилегированном режиме сложный (Тьюринг-полный) интерактивный шелл. Но ты воюешь с простой утилитой su.

anonymous
()
Ответ на: комментарий от anonymous

что за херню я сейчас прочитал?

Иначе ты бы не мог выполнять привилегированные операции.

какие привилегированные операции?

То есть, ты наврал выводом команды id.

всмысле наврал? я скопировал как есть.

У тебя работает в привилегированном режиме сложный (Тьюринг-полный) интерактивный шелл.

что это значит? с чего ты взял, что он привилегированный?

вывод

You are not authorized to su root

показывается, если в /etc/login.defs есть 'SU_WHEEL_ONLY yes'.
если это убрать, при запуске su от обычного пользователя запрашивает пароль, после ввода выдаёт su: Authentication failure

teod0r ★★★★★
() автор топика