SSD Nodes Learn Hosting plans →
Посібники Matt ConnorВід Matt Connor · Оновлено 2026-09-08

sudo-rs в Ubuntu: що змінюється у sudoers

Ubuntu 26.04 використовує sudo-rs за замовчуванням: wildcard у правилах аргументів більше не зіставляються. Дізнайтеся, що записати натомість.

Що змінює sudo-rs в Ubuntu

Ubuntu 26.04 LTS постачається із sudo-rs як стандартною реалізацією sudo, тому команда sudo на новому сервері запускає реалізацію на Rust замість оригінальної програми на C. Більшість файлів sudoers продовжує працювати без змін. Проблеми виникають із правилами, у яких у аргументах команди використано wildcard, оскільки sudo-rs не зіставляє glob-шаблони з текстом аргументів.

Ubuntu 25.10 першою перейшла на sudo-rs, а в Ubuntu 26.04 LTS цей варіант залишився. Ubuntu 24.04 LTS це не стосується, оскільки в ній за замовчуванням використовується оригінальний sudo, якщо не встановити sudo-rs вручну. Це стає важливим під час оновлення з Ubuntu 24.04 до 26.04 або під час розгортання нового сервера на новішому випуску. Якщо ви також використовуєте проміжні випуски, у матеріалі як відрізняються LTS і проміжні випуски Ubuntu на сервері пояснено, на якому сервері така зміна з’явиться першою.

Перевірте, який sudo фактично запущено на сервері

Не визначайте це за номером випуску. Запитайте безпосередньо систему.

sudo --version
update-alternatives --config sudo
dpkg -l 'sudo*'

Довіряйте sudo --version на власному сервері більше, ніж будь-якій таблиці версій в Інтернеті, зокрема на цій сторінці. update-alternatives --config sudo — це друга частина відповіді: вона перелічує всіх установлених постачальників /usr/bin/sudo і позначає вибраного постачальника. Установлений пакет не обов’язково вибраний, тому перевіряйте вибір, а не список пакетів.

Під час переходу пакуються обидві реалізації. Реалізація на Rust — це sudo-rs, версія 0.2.13 у 26.04 станом на серпень 2026 року. Оригінальна реалізація, яку підтримує Todd C. Miller, і далі постачається як пакет sudo. Змінилося лише те, що її програми мають суфікс .ws, щоб обидві реалізації можна було встановити одночасно: /usr/bin/sudo.ws і /usr/bin/visudo.ws, а також cvtsudoers.ws і sudoreplay.ws. Перевірено за архівом 26.04 у вересні 2026 року: dpkg -L sudo перелічує двійкові файли із суфіксом, а sudo-rs постачає /usr/bin/sudo-rs разом із ними.

Чому Ubuntu перейшла на sudo-rs

sudo має біт setuid і запускається з правами root. Будь-який користувач системи може його запустити, а процес одразу отримує повні привілеї. Тому помилка роботи з пам’яттю всередині sudo може дати локальному користувачу права root. Саме такою була CVE-2021-3156: переповнення буфера в купі, доступне будь-якому локальному користувачу. Ця вразливість залишалася у випущеному коді приблизно десять років. Rust виявляє такий клас помилок під час компіляції. Саме це є головним аргументом на користь переписування.

Друга причина — обсяг функціональності. Саме вона безпосередньо впливає на конфігурацію. Оригінальний sudo накопичував великий набір функцій протягом трьох десятиліть. Кожна функція означає більше коду, який працює з правами root. sudo-rs навмисно реалізує лише частину цих функцій. Розробники не додали можливості, які вважали маловживаними або потенційно шкідливими. Тому конструкція sudoers, яка роками працювала, може бути просто відсутньою. Ваше правило з wildcard — один із таких випадків.

Безпека роботи з пам’яттю усуває один клас помилок. Вона не робить програму повністю захищеною від помилок. Після того як sudo-rs став версією за замовчуванням, для нього також випускали виправлення безпеки. Оновлюйте його, як і будь-яке інше програмне забезпечення.

Які правила sudoers і далі працюють

Файл залишається тим самим. sudo-rs читає /etc/sudoers і додаткові файли в /etc/sudoers.d/, а звичайні правила, які пише адміністратор сервера, підтримуються:

  • deploy ALL=(ALL:ALL) ALL і форми для груп, наприклад %sudo ALL=(ALL:ALL) ALL
  • теги NOPASSWD: і PASSWD:
  • User_Alias, Runas_Alias, Host_Alias і Cmnd_Alias
  • команду з точним списком аргументів, наприклад /usr/bin/systemctl restart app-api
  • команду з "" після неї. У такому разі команду дозволено виконувати лише без аргументів
  • команду з * як останнім аргументом. У такому разі дозволено будь-які наступні аргументи
  • шлях до каталогу, що закінчується на /. У такому разі дозволено будь-яку команду в цьому каталозі
  • ! для вилучення команди зі списку
  • корисну підмножину Defaults, зокрема secure_path, env_keep, env_check, timestamp_timeout, passwd_tries, editor, umask, targetpw, rootpw і use_pty

Два параметри за замовчуванням працюють інакше, що часто спричиняє помилки. env_reset не можна вимкнути в sudo-rs: він завжди увімкнений. use_pty увімкнений за замовчуванням, тому команда виконується у власному псевдотерміналі.

Чому правило wildcard у sudoers перестало збігатися

Wildcards і далі дозволені в одному місці: в імені файлу команди. Правило `%ops ALL = /sbin/fsck* усе ще дозволяє sudo fsck і sudo fsck_exfat, оскільки *` є частиною шляху, який порівнюється з файловою системою.

У списку аргументів sudo-rs приймає лише дві спеціальні форми, і жодна з них не є шаблоном. `"" означає відсутність аргументів. Кінцевий * означає будь-які наступні аргументи. Усі інші аргументи порівнюються як літералний текст. Тому %ops ALL = /sbin/service ntp * працює, оскільки ntp є літералом, а *` розташований останнім. Однак таке правило не надає жодних потрібних вам дозволів:

deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart app-*

`app-* є шаблоном усередині аргументу. sudo-rs не розгортає його, тому правило не охоплює systemctl restart app-api, і sudo відхиляє команду. Дві команди покажуть фактичний результат для будь-якого правила на вашому сервері: sudo -l -U deploy, виконана від імені root, виводить, які команди цей обліковий запис справді може запускати, а sudo visudo -c` повідомляє, чи файл узагалі має правильний синтаксис. Виконайте їх, перш ніж починати навмання редагувати конфігурацію.

Правило з wildcard завжди було вразливістю

У початковій реалізації sudo аргументи, які ви вводите, об’єднуються в один рядок і зіставляються з рядком аргументів правила за допомогою glob. Glob зіставляється також із пробілами. Саме цю особливість майже всі пропускають.

У документації sudo-rs наведено найчіткішу демонстрацію. Правило /bin/rm *.txt також дозволяє sudo rm -rf /home .txt, оскільки один * поглинає -rf /home , а об’єднаний рядок усе одно закінчується на .txt. Правило читається як «лише текстові файли». Фактично воно означає «будь-які аргументи, якщо рядок закінчується на .txt».

Те саме стосується прикладу із systemctl. Оскільки аргументи порівнюються як один об’єднаний рядок, шаблон у кінці також відповідає всьому, що додається після нього. Тому restart app-* охоплює restart app-api і будь-які наступні аргументи, додані користувачем. Шаблон усередині аргументу відкриває доступ до аргументів навколо нього, а саме в аргументах визначаються повноваження команди. sudo-rs відхиляє таку конструкцію, а не намагається зробити її безпечною, оскільки безпечної універсальної форми для неї не існує.

Замініть шаблон явним списком команд

Більшість правил із шаблонами з’являється тому, що хтось не захотів вводити чотири рядки. Введіть ці чотири рядки.

Cmnd_Alias APP_RESTART = /usr/bin/systemctl restart app-api, /usr/bin/systemctl restart app-worker
Cmnd_Alias APP_STATUS = /usr/bin/systemctl status app-api, /usr/bin/systemctl status app-worker
deploy ALL=(root) NOPASSWD: APP_RESTART, APP_STATUS

Укажіть правильний шлях. Правило, у якому зазначено /bin/systemctl, не спрацює в системі, де двійковий файл розташований за шляхом /usr/bin/systemctl. Така помилка виглядає так само, як проблема з правами доступу. Перевірте це за допомогою command -v systemctl і вставте отриманий результат.

Помістіть правило в окремий drop-in-файл, а не в /etc/sudoers, щоб оновлення пакета не конфліктувало з вашими змінами:

sudo visudo -f /etc/sudoers.d/90-deploy
sudo visudo -c
sudo -l -U deploy

Назвіть файл без крапки та без кінцевої тильди. Оригінальний sudo ігнорує файли в sudoers.d, якщо їхні імена містять крапку, тому 90-deploy.conf — типовий випадок непомітного ігнорування. Дотримуватися цього правила нічого не коштує.

Використовуйте wrapper, власником якого є root, якщо список стає довгим

Якщо дозволений набір стає надто великим для явного переліку, перенесіть перевірку з sudoers у невелику програму, власником якої є root.

sudo tee /usr/local/sbin/app-restart >/dev/null <<'EOF'
#!/bin/sh
set -eu
case "${1:-}" in
  app-api|app-worker) ;;
  *) echo "app-restart: not allowed: ${1:-}" >&2; exit 1 ;;
esac
exec /usr/bin/systemctl restart "$1"
EOF
sudo chown root:root /usr/local/sbin/app-restart
sudo chmod 0755 /usr/local/sbin/app-restart
ls -l /usr/local/sbin/app-restart

У sudoers тоді вказують лише одну команду:

deploy ALL=(root) NOPASSWD: /usr/local/sbin/app-restart *

Кінцевий * тут допустимий, оскільки дозволені дії визначає скрипт, а не sudo. Це справедливо лише доти, доки власником скрипту є root і ніхто інший не має права його змінювати. Якщо deploy може записувати у файл, deploy може замінити його вміст і виконати будь-яку команду від імені root. Це небезпечніше за правило з wildcard, яке ви видалили. Перевірте режим доступу за допомогою ls -l. Якщо результат вам незрозумілий, прочитати рядок прав drwxr-xr-x можна навчитися за п’ять хвилин. Це саме правило поширюється і на каталог: /usr/local/sbin також не повинен бути доступним для запису цьому обліковому запису, оскільки доступний для запису каталог дає змогу повністю замінити файл.

Надайте завданню окремий обліковий запис замість правила sudo

Часто краще спочатку з’ясувати, навіщо команді взагалі потрібні права root. Сервіс, який працює від імені власного користувача, може керуватися цим користувачем, і рядок у sudoers не потрібен. Для system units systemd уже делегує це рішення polkit, тому правило може вказувати один unit і одного оператора:

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units" &&
        action.lookup("unit") == "app-api.service" &&
        subject.user == "deploy") {
        return polkit.Result.YES;
    }
});

Збережіть це як /etc/polkit-1/rules.d/50-app-api.rules, і deploy зможе виконувати systemctl restart app-api без sudo. Перевірте правило з того самого контексту, у якому воно використовуватиметься. Правило, яке працює у вашій SSH-сесії, слід додатково перевірити з cron, перш ніж покладатися на нього. У будь-якому разі обліковий запис, який виконує роботу, має бути призначений лише для цієї роботи. Це той самий принцип, що й у облікових записах користувачів із мінімальними привілеями на VPS.

Що ще відсутнє в sudo-rs

sudo -E не реалізовано. Замість цього називайте потрібні змінні за допомогою Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY". Пам’ятайте, що env_reset завжди увімкнено, тому все, що не зберігається, очищується.

Централізоване зберігання sudoers у LDAP відсутнє. sudoers.ldap і cvtsudoers не реалізовано, а пакет sudo-ldap видалено у 26.04. Автентифікація LDAP через PAM або SSSD все ще працює. Поза межами реалізації залишається лише зберігання політик у каталозі.

INTERCEPT, який мав блокувати вихід із shell у дозволеній команді, не реалізовано. Утім, він усе одно не захищав від користувача, який діє цілеспрямовано. Якщо правило дозволяє запускати редактор або інтерпретатор від імені root, користувач отримує root-доступ. Жодна опція sudo цього не змінює.

Запис сеансів не реалізовано, тому немає журналу введення-виведення і sudoreplay. Журнали надсилаються лише до syslog. Опції logfile для перенаправлення журналів в інше місце немає, тому повідомлення sudo потрапляють туди, куди ваша система вже надсилає syslog.

Чи варто повернутися до sudo.ws?

Можна. У циклі 26.04 оригінальний пакет і далі доступний саме з цієї причини.

sudo apt install sudo
update-alternatives --config sudo
sudo update-alternatives --set sudo /usr/bin/sudo.ws

Копіюйте точні шляхи з виводу --config, а не з цієї сторінки, оскільки саме цей список прийматиме ваша система. Щоб пізніше повернутися до sudo-rs, встановіть alternative на шлях до бінарного файла sudo-rs із цього самого списку.

Перш ніж змінювати щось, що впливає на sudo, відкрийте другий SSH-сеанс, увійдіть у систему й залиште його бездіяльним. Файл sudoers із помилкою синтаксичного аналізу або alternative, що вказує на неінстальований бінарний файл, може позбавити вас можливості отримати root на віддаленому сервері. Ця звичка має бути такою самою стандартною процедурою, як і все інше, що ви робите в перші десять хвилин на новому VPS.

Сприймайте повернення як тимчасовий захід із кінцевим строком, а не як виправлення. Це дає вам тиждень, щоб належно переписати правила. Саме переписування варте виконання незалежно від цього, оскільки кожне видалене правило з wildcard надавало більше доступу, ніж передбачав його автор.

FAQ

Чому моє правило wildcard у sudoers перестало працювати в Ubuntu 26.04?

Тому що Ubuntu 26.04 LTS використовує sudo-rs як sudo за замовчуванням, а sudo-rs не зіставляє wildcard-шаблони всередині аргументів команди. Wildcard можна використовувати в імені файлу команди, "" означає відсутність аргументів, а один * можна вказати як останній аргумент. Правило на кшталт /usr/bin/systemctl restart app-* містить шаблон посередині аргументу, тому воно нічого не дозволяє, і виконання команди відхиляється. Виконайте sudo -l -U deploy від імені root, щоб перевірити фактичні дозволи облікового запису, а потім замініть правило точними командами або wrapper script, власником якого є root.

Як повернути оригінальний sudo в Ubuntu 26.04?

Оригінальний sudo входить до пакета sudo, а його бінарні файли мають суфікс .ws. Установіть його за допомогою sudo apt install sudo, а потім виберіть його для alternative командою sudo update-alternatives --set sudo /usr/bin/sudo.ws. Спочатку виконайте update-alternatives --config sudo, щоб переглянути точні шляхи, доступні у вашій системі, і залиште відкритим другий SSH-сеанс, поки змінюєте налаштування. Це не повертає sudo-ldap: його видалено з 26.04 незалежно від вибраної реалізації.

Чи читає sudo-rs той самий файл /etc/sudoers?

Так. sudo-rs читає /etc/sudoers і drop-in-файли в /etc/sudoers.d/, використовуючи той самий синтаксис для користувачів, груп, alias, специфікацій run-as і тега NOPASSWD. Він реалізує підмножину мови sudoers, тому відмінності полягають у відсутніх конструкціях, а не в іншій поведінці наявних конструкцій. Відредагуйте файл за допомогою sudo visudo, а потім перевірте його командою sudo visudo -c, перш ніж завершити сеанс.

Що замінює sudo -E у sudo-rs?

sudo -E не реалізовано. В оригінальному sudo його також уже не рекомендували, оскільки передавання root-процесу середовища, яким керує користувач, є відомим способом змінити поведінку цього процесу. У sudoers явно вкажіть потрібні змінні, наприклад рядком Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY". env_reset у sudo-rs завжди увімкнено й не може бути вимкнено, тому всі змінні, які ви не залишили, буде очищено.

#sudo#sudo-rs#ubuntu#sudoers#permissions