SSD Nodes Learn Hosting plans →
Przewodniki Matt ConnorAutor: Matt Connor · Zaktualizowano 2026-09-08

sudo-rs w Ubuntu 26.04: zmiany w pliku sudoers

W Ubuntu 26.04 implementacja sudo-rs zastępuje tradycyjne sudo. Dowiedz się, dlaczego reguły z wieloznacznikami przestają działać i jak poprawnie skonfigurować plik sudoers.

Zmiany wprowadzone przez sudo-rs w Ubuntu

Ubuntu 26.04 LTS dostarcza sudo-rs jako domyślne sudo, więc polecenie sudo na świeżo zainstalowanym serwerze uruchamia implementację w języku Rust zamiast oryginalnego programu w języku C. Większość plików sudoers działa bez zmian. Regułą, która przestaje działać, jest ta zawierająca wieloznaczniki (wildcards) w argumentach polecenia, ponieważ sudo-rs nie dopasowuje wzorców glob do tekstu argumentów.

Ubuntu 25.10 jako pierwsze wprowadziło tę zmianę, a Ubuntu 26.04 LTS ją utrzymało. Ubuntu 24.04 LTS nie podlega tej zmianie, ponieważ nadal korzysta z oryginalnego sudo, chyba że sudo-rs zostanie zainstalowane ręcznie. Kwestia ta staje się istotna w momencie aktualizacji z Ubuntu 24.04 do 26.04 lub podczas tworzenia nowego serwera w nowszym wydaniu. W przypadku korzystania z wydań pośrednich, artykuł różnice między wydaniami LTS a pośrednimi Ubuntu na serwerze wyjaśnia, które maszyny otrzymują tego typu zmiany w pierwszej kolejności.

Sprawdzenie, która wersja sudo jest faktycznie uruchomiona na serwerze

Nie należy opierać się na numerze wydania systemu. Należy zapytać o to samą maszynę.

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

Należy ufać sudo --version na własnym serwerze bardziej niż jakiejkolwiek tabeli wersji w Internecie, w tym tej stronie. update-alternatives --config sudo stanowi drugą część odpowiedzi: wyświetla listę wszystkich zainstalowanych dostawców /usr/bin/sudo i oznacza tego wybranego. Sam fakt zainstalowania pakietu nie oznacza, że jest on wybrany, dlatego należy sprawdzić wybór, a nie listę pakietów.

Obie implementacje są pakowane w okresie przejściowym. Wersja napisana w Rust to sudo-rs, w wersji 0.2.13 w wydaniu 26.04 na sierpień 2026 roku. Oryginalna wersja, utrzymywana przez Todda C. Millera, to nadal pakiet sudo; zmianie uległo to, że jej programy posiadają przyrostek .ws, dzięki czemu oba pakiety mogą być zainstalowane jednocześnie: /usr/bin/sudo.ws oraz /usr/bin/visudo.ws, obok cvtsudoers.ws i sudoreplay.ws. Zweryfikowano w archiwum 26.04 we wrześniu 2026 roku: dpkg -L sudo wyświetla pliki binarne z przyrostkiem, a sudo-rs dostarcza /usr/bin/sudo-rs obok nich.

Dlaczego Ubuntu przeszło na sudo-rs

sudo posiada uprawnienia setuid root. Każdy użytkownik w systemie może je uruchomić, a proces startuje z pełnymi uprawnieniami, więc błąd pamięci wewnątrz tego narzędzia stanowi lokalny exploit typu root. CVE-2021-3156 było dokładnie takim przypadkiem: przepełnienie bufora sterty, dostępne dla każdego lokalnego użytkownika, które znajdowało się w wydanym kodzie przez około dziesięć lat. Rust eliminuje tę klasę błędów na etapie kompilacji, co stanowi główny argument za przepisaniem tego narzędzia.

Drugim powodem jest zakres funkcjonalny i to on wpływa na konfigurację użytkownika. Oryginalne sudo zgromadziło przez trzy dekady obszerny zestaw funkcji, a każda z nich oznacza więcej kodu uruchamianego z uprawnieniami roota. sudo-rs celowo implementuje tylko podzbiór tych możliwości. Wszystko, co autorzy uznali za niszowe lub szkodliwe, zostało pominięte, dlatego konstrukcja w pliku sudoers, która działała przez lata, może po prostu nie być obsługiwana. Reguła z użyciem symboli wieloznacznych jest jedną z nich.

Bezpieczeństwo pamięci eliminuje jedną klasę błędów. Nie czyni to jednak programu wolnym od błędów, a sudo-rs od momentu stania się domyślnym rozwiązaniem również otrzymywało poprawki bezpieczeństwa. Należy je aktualizować tak samo, jak każde inne oprogramowanie.

Które reguły sudoers nadal działają

Plik pozostaje ten sam. sudo-rs odczytuje /etc/sudoers oraz pliki konfiguracyjne z katalogu /etc/sudoers.d/, a typowe wpisy tworzone przez administratorów serwerów są obsługiwane:

  • deploy ALL=(ALL:ALL) ALL oraz formy grupowe, takie jak %sudo ALL=(ALL:ALL) ALL
  • znaczniki NOPASSWD: oraz PASSWD:
  • User_Alias, Runas_Alias, Host_Alias oraz Cmnd_Alias
  • polecenie z dokładną listą argumentów, na przykład /usr/bin/systemctl restart app-api
  • polecenie z dopiskiem "", co zezwala na wykonanie polecenia wyłącznie bez żadnych argumentów
  • polecenie z dopiskiem * jako ostatnim argumentem, co zezwala na dowolne argumenty końcowe
  • ścieżka do katalogu kończąca się na /, co zezwala na każde polecenie w tym katalogu
  • ! w celu wykluczenia polecenia z listy
  • użyteczny podzbiór Defaults, w tym secure_path, env_keep, env_check, timestamp_timeout, passwd_tries, editor, umask, targetpw, rootpw oraz use_pty

Dwa ustawienia domyślne działają inaczej i często zaskakują użytkowników. Opcji env_reset nie można wyłączyć w sudo-rs: jest ona zawsze aktywna. Opcja use_pty jest domyślnie włączona, więc polecenie uruchamia się we własnym pseudo-terminalu.

Dlaczego reguła wildcard w sudoers przestała działać

Symbole wieloznaczne są nadal dozwolone w jednym miejscu: w nazwie pliku polecenia. Reguła %ops ALL = /sbin/fsck* nadal zezwala na sudo fsck oraz sudo fsck_exfat, ponieważ * jest częścią ścieżki porównywanej z systemem plików.

Wewnątrz listy argumentów sudo-rs akceptuje tylko dwie specjalne formy i żadna z nich nie jest wzorcem. "" oznacza brak argumentów. Końcowe * oznacza dowolne argumenty końcowe. Każdy inny argument jest porównywany jako tekst dosłowny. Zatem %ops ALL = /sbin/service ntp * jest poprawne, ponieważ ntp jest dosłowne, a * znajduje się na końcu. Reguła taka jak ta poniżej nie przyznaje jednak żadnych uprawnień, które były zamierzone:

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

app-* jest wzorcem w środku argumentu. sudo-rs nie rozwija go, więc reguła nie obejmuje systemctl restart app-api, a sudo odmawia wykonania polecenia. Dwa polecenia informują o rzeczywistym działaniu każdej reguły na własnym serwerze: sudo -l -U deploy, uruchomione jako root, wyświetla to, co dane konto może faktycznie wykonać, a sudo visudo -c informuje, czy plik w ogóle poprawnie się parsuje. Należy je uruchomić przed rozpoczęciem przypadkowej edycji.

Reguła wieloznaczna zawsze stanowiła lukę

W oryginalnym sudo wpisywane argumenty są łączone w jeden ciąg znaków i porównywane z ciągiem argumentów reguły za pomocą wzorca glob. Wzorzec glob dopasowuje również spacje. Jest to szczegół, który większość osób pomija.

Dokumentacja sudo-rs przedstawia to w najbardziej przejrzysty sposób. Reguła /bin/rm *.txt zezwala również na sudo rm -rf /home .txt, ponieważ pojedyncza spacja * pochłania -rf /home , a połączony ciąg nadal kończy się na .txt. Reguła ta jest interpretowana jako "tylko pliki tekstowe". W rzeczywistości oznacza ona "dowolne argumenty, pod warunkiem, że linia kończy się na .txt".

To samo dotyczy przykładu z systemctl. Ponieważ argumenty są porównywane jako jeden połączony ciąg, wzorzec końcowy dopasowuje również wszystko, co zostanie do niego dodane, więc restart app-* obejmuje restart app-api oraz wszelkie dodatkowe argumenty przekazane przez wywołującego. Wzorzec wewnątrz argumentu ujawnia argumenty znajdujące się wokół niego, a to właśnie w argumentach kryje się moc polecenia. sudo-rs odrzuca taką konstrukcję zamiast próbować czynić ją bezpieczną, ponieważ nie istnieje jej bezpieczna, ogólna forma.

Zastąpienie symbolu wieloznacznego jawną listą poleceń

Większość reguł z użyciem symboli wieloznacznych istnieje, ponieważ użytkownik chciał uniknąć wpisywania czterech linii. Należy wpisać te cztery linie.

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

Należy poprawnie wskazać ścieżkę. Reguła wskazująca /bin/systemctl w systemie, w którym plik binarny znajduje się w /usr/bin/systemctl, nigdy nie zadziała, a błąd będzie wyglądał identycznie jak problem z uprawnieniami. Należy potwierdzić lokalizację za pomocą command -v systemctl i wkleić wynik działania tego polecenia.

Regułę należy umieścić w osobnym pliku konfiguracyjnym typu drop-in, zamiast w /etc/sudoers, aby aktualizacja pakietu nie powodowała konfliktów z wprowadzonymi zmianami:

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

Plik należy nazwać bez użycia kropki oraz bez znaku tyldy na końcu. Oryginalny sudo ignoruje pliki w sudoers.d, których nazwy zawierają kropkę, dlatego 90-deploy.conf jest klasycznym przykładem cichego niepowodzenia, a przestrzeganie tej konwencji nie wiąże się z żadnym kosztem.

Użycie wrappera należącego do root, gdy lista staje się długa

Gdy dozwolony zestaw jest zbyt duży, aby go wypisać, należy przenieść decyzję poza plik sudoers do małego programu, którego właścicielem jest 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

W pliku sudoers należy wówczas wskazać tylko jedno polecenie:

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

Końcowe * jest tutaj dopuszczalne, ponieważ to skrypt, a nie sudo, decyduje o tym, co jest dozwolone. Zasada ta obowiązuje tylko wtedy, gdy właścicielem skryptu jest root, a nikt inny nie ma uprawnień do zapisu. Jeśli deploy może zapisywać do pliku, deploy może zastąpić jego zawartość i uruchomić dowolny proces z uprawnieniami roota, co jest gorsze niż usunięta reguła z symbolem wieloznacznym. Sprawdź tryb dostępu za pomocą ls -l, a jeśli wynik nie jest dla Ciebie oczywisty, zrozumienie ciągu uprawnień drwxr-xr-x zajmuje pięć minut nauki. Ta sama zasada dotyczy katalogu: /usr/local/sbin również nie może być zapisywalny przez to konto, ponieważ zapisywalny katalog oznacza, że plik może zostać całkowicie podmieniony.

Nadanie zadaniu własnego konta zamiast reguły sudo

Często lepszym pytaniem jest, dlaczego polecenie w ogóle wymaga uprawnień root. Usługa działająca na własnym koncie użytkownika może być zarządzana przez tego użytkownika, co eliminuje potrzebę edycji pliku sudoers. W przypadku jednostek systemd decyzja ta jest delegowana do polkit, dzięki czemu reguła może wskazywać konkretną jednostkę oraz operatora:

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;
    }
});

Zapisz to jako /etc/polkit-1/rules.d/50-app-api.rules, a deploy będzie mogło uruchomić systemctl restart app-api bez użycia sudo. Przetestuj rozwiązanie w kontekście, w którym będzie ono faktycznie używane. Reguła działająca w sesji SSH powinna zostać zweryfikowana z poziomu cron przed wdrożeniem produkcyjnym. W każdym przypadku konto wykonujące zadanie powinno służyć wyłącznie do tego celu, co jest zgodne z zasadą kont użytkowników o minimalnych uprawnieniach na serwerze VPS.

Czego jeszcze brakuje w sudo-rs

sudo -E nie jest zaimplementowane. Należy zdefiniować wymagane zmienne za pomocą Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY" i pamiętać, że env_reset jest zawsze włączone, więc wszystkie niezachowane zmienne są usuwane.

Centralne przechowywanie plików sudoers w LDAP zostało usunięte. sudoers.ldap oraz cvtsudoers nie są zaimplementowane, a pakiet sudo-ldap został usunięty w wersji 26.04. Uwierzytelnianie LDAP przez PAM lub SSSD nadal działa. Poza zakresem pozostaje jedynie polityka oparta na katalogu.

INTERCEPT, które miało zapobiegać ucieczkom do powłoki z dozwolonego polecenia, nie jest zaimplementowane. Mechanizm ten i tak nie stanowił zabezpieczenia przed zdeterminowanym użytkownikiem. Jeśli reguła pozwala komuś na uruchomienie edytora lub interpretera z uprawnieniami root, użytkownik ten uzyskuje dostęp root, a żadna opcja sudo tego nie zmieni.

Rejestrowanie sesji nie jest zaimplementowane, więc nie ma dziennika I/O ani sudoreplay. Logowanie odbywa się wyłącznie do syslog i nie ma opcji logfile, która pozwalałaby na przekierowanie go w inne miejsce, zatem komunikaty sudo trafiają tam, gdzie system domyślnie wysyła dane syslog.

Czy należy powrócić do sudo.ws?

Jest to możliwe, a w cyklu wydawniczym 26.04 oryginalne rozwiązanie pozostaje w pakietach właśnie z tego powodu.

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

Należy kopiować dokładne ścieżki z wyniku polecenia --config, a nie z tej strony, ponieważ jest to lista akceptowana przez dany system. Powrót do sudo-rs w późniejszym czasie oznacza ustawienie alternatywy na ścieżkę do pliku binarnego sudo-rs z tej samej listy.

Przed wykonaniem jakichkolwiek operacji wpływających na sudo należy pozostawić otwartą drugą sesję SSH, zalogowaną i bezczynną. Błąd parsowania pliku sudoers lub wskazanie alternatywy na niezainstalowany plik binarny może uniemożliwić uzyskanie uprawnień root na zdalnej maszynie. Ten nawyk należy stosować przy wszystkich działaniach opisanych w pierwszych dziesięciu minutach na nowym VPS.

Powrót do poprzedniego rozwiązania należy traktować jako rozwiązanie tymczasowe, a nie docelowe. Daje to tydzień na poprawne przepisanie reguł, co jest wartościowe samo w sobie, ponieważ każda usunięta reguła z użyciem symboli wieloznacznych przyznawała szersze uprawnienia, niż zakładał jej autor.

FAQ

Dlaczego moja reguła sudoers z użyciem symboli wieloznacznych przestała działać w Ubuntu 26.04?

Ponieważ Ubuntu 26.04 LTS domyślnie wybiera sudo-rs, a sudo-rs nie obsługuje dopasowywania wzorców z symbolami wieloznacznymi wewnątrz argumentów polecenia. Obsługuje ono symbole wieloznaczne w nazwie pliku polecenia, "" w znaczeniu braku argumentów oraz pojedynczy * jako ostatni argument. Reguła taka jak /usr/bin/systemctl restart app-* umieszcza wzorzec w środku argumentu, więc nie nadaje żadnych uprawnień, a polecenie jest odrzucane. Uruchom sudo -l -U deploy jako root, aby sprawdzić rzeczywiste uprawnienia konta, a następnie zastąp regułę dokładnymi poleceniami lub skryptem opakowującym (wrapper script) należącym do roota.

Jak przywrócić oryginalne sudo w Ubuntu 26.04?

Oryginalne oprogramowanie jest dostarczane w pakiecie sudo, którego pliki binarne mają przyrostek .ws. Zainstaluj je za pomocą sudo apt install sudo, a następnie wskaż je za pomocą mechanizmu alternatyw sudo update-alternatives --set sudo /usr/bin/sudo.ws. Uruchom najpierw update-alternatives --config sudo, aby odczytać dokładne ścieżki oferowane przez system i utrzymuj otwartą drugą sesję SSH podczas wprowadzania zmian. Nie przywraca to sudo-ldap, które zostało usunięte z wersji 26.04 niezależnie od wybranej implementacji.

Czy sudo-rs odczytuje ten sam plik /etc/sudoers?

Tak. sudo-rs odczytuje /etc/sudoers oraz pliki w katalogu /etc/sudoers.d/, stosując tę samą składnię dla użytkowników, grup, aliasów, specyfikacji run-as oraz znacznika NOPASSWD. Implementuje ono podzbiór języka sudoers, więc różnice objawiają się brakiem obsługi niektórych konstrukcji, a nie ich odmiennym działaniem. Edytuj plik za pomocą sudo visudo, a następnie zweryfikuj go poleceniem sudo visudo -c przed zamknięciem sesji.

Co zastępuje sudo -E w sudo-rs?

sudo -E nie jest zaimplementowane i było już odradzane w oryginalnym sudo, ponieważ przekazywanie procesowi z uprawnieniami roota środowiska kontrolowanego przez wywołującego jest znanym sposobem na zmianę zachowania tego procesu. Zamiast tego należy wymienić zmienne, które są faktycznie potrzebne w sudoers, używając linii takiej jak Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY". env_reset jest zawsze włączone w sudo-rs i nie można go wyłączyć, więc każda zmienna, która nie została zachowana, jest usuwana.

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