SSD Nodes Learn 🎉 VPS dari $5.50/bln
Panduan Matt ConnorOleh Matt Connor · Dikemas kini 2026-08-13

Perubahan sudo-rs pada Ubuntu 26.04 dan fail sudoers

Ubuntu 26.04 menggunakan sudo-rs sebagai lalai. Ketahui sebab peraturan wildcard dalam fail sudoers gagal berfungsi dan cara mengemas kini sintaks arahan anda dengan betul.

Perubahan sudo-rs pada Ubuntu

Ubuntu 26.04 LTS menyertakan sudo-rs sebagai sudo lalai, jadi arahan sudo pada pelayan baharu menjalankan pelaksanaan semula Rust dan bukannya program C asal. Kebanyakan fail sudoers terus berfungsi seperti biasa. Peraturan yang terjejas ialah peraturan yang mengandungi wildcard dalam argumen arahan, kerana sudo-rs tidak memadankan corak glob dengan teks argumen.

Ubuntu 25.10 membuat pertukaran ini terlebih dahulu dan 26.04 LTS mengekalkannya. Ubuntu 24.04 LTS tidak terjejas, kerana ia masih memilih sudo asal melainkan anda memasang sudo-rs secara manual. Perkara ini menjadi penting apabila anda menaik taraf daripada Ubuntu 24.04 ke 26.04, atau apabila anda membina mesin baharu pada keluaran yang lebih baharu. Jika anda juga menjalankan keluaran interim, perbezaan antara keluaran LTS dan interim Ubuntu pada pelayan menjelaskan mesin yang mana akan menerima perubahan seperti ini terlebih dahulu.

Semak sudo yang sebenarnya sedang dijalankan oleh pelayan anda

Jangan tentukan perkara ini berdasarkan nombor keluaran. Tanya mesin tersebut.

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

Percayai sudo --version pada mesin anda sendiri berbanding mana-mana jadual versi di internet, termasuk halaman ini. update-alternatives --config sudo ialah separuh lagi jawapan tersebut: ia menyenaraikan setiap penyedia /usr/bin/sudo yang dipasang dan menandakan yang dipilih. Pakej yang dipasang tidak sama dengan pakej yang dipilih, jadi baca pilihan tersebut, bukan senarai pakej.

Kedua-dua implementasi dipakejkan semasa peralihan. Versi Rust ialah sudo-rs, pada versi 0.2.13 dalam 26.04 setakat Ogos 2026. Versi asal, yang diselenggara oleh Todd C. Miller, dipakejkan sebagai sudo.ws, dan programnya membawa akhiran .ws: sudo.ws dan visudo.ws.

Mengapa Ubuntu beralih kepada sudo-rs

sudo ialah setuid root. Mana-mana pengguna pada pelayan boleh memulakannya, dan ia bermula dengan keistimewaan penuh, jadi pepijat memori di dalamnya merupakan eksploitasi root tempatan. CVE-2021-3156 adalah contoh tepat bagi perkara ini: limpahan penimbal heap yang boleh dicapai oleh mana-mana pengguna tempatan, dan ia wujud dalam kod yang dikeluarkan selama kira-kira sepuluh tahun. Rust menangani kelas pepijat tersebut pada masa kompilasi, yang merupakan hujah utama bagi penulisan semula ini.

Sebab kedua ialah skop, dan ini merupakan perkara yang memberi kesan kepada konfigurasi anda. sudo asal telah mengumpul set ciri yang besar selama tiga dekad, dan setiap ciri bermakna lebih banyak kod yang berjalan sebagai root. sudo-rs melaksanakan subset secara sengaja. Apa-apa sahaja yang dianggap oleh penulisnya sebagai khusus atau berbahaya telah ditinggalkan, jadi binaan sudoers yang berfungsi selama bertahun-tahun mungkin tiada lagi. Peraturan wildcard anda adalah salah satu daripadanya.

Keselamatan memori menghapuskan satu kelas pepijat. Ia tidak menjadikan program bebas daripada pepijat, dan sudo-rs telah mengeluarkan pembetulan keselamatan tersendiri sejak ia menjadi lalai. Lakukan patching seperti perisian lain.

Peraturan sudoers yang masih berfungsi

Fail tersebut adalah fail yang sama. sudo-rs membaca /etc/sudoers dan fail-fail drop-in dalam /etc/sudoers.d/, serta perkara biasa yang ditulis oleh pengendali pelayan disokong:

  • deploy ALL=(ALL:ALL) ALL, dan bentuk kumpulan seperti %sudo ALL=(ALL:ALL) ALL
  • tag NOPASSWD: dan PASSWD:
  • User_Alias, Runas_Alias, Host_Alias dan Cmnd_Alias
  • arahan dengan senarai argumen yang tepat, contohnya /usr/bin/systemctl restart app-api
  • arahan yang diikuti oleh "", yang membenarkan arahan tersebut hanya jika tiada argumen langsung
  • arahan yang diikuti oleh * sebagai argumen terakhirnya, yang membenarkan sebarang argumen tambahan di belakang
  • laluan direktori yang berakhir dengan /, yang membenarkan sebarang arahan dalam direktori tersebut
  • ! untuk menolak arahan daripada senarai
  • subset Defaults yang berguna, termasuk secure_path, env_keep, env_check, timestamp_timeout, passwd_tries, editor, umask, targetpw, rootpw dan use_pty

Dua tetapan lalai berkelakuan berbeza dan sering memeranjatkan pengguna. env_reset tidak boleh dimatikan dalam sudo-rs: ia sentiasa aktif. use_pty diaktifkan secara lalai, jadi arahan tersebut dijalankan dalam pseudo-terminalnya sendiri.

Mengapa peraturan sudoers wildcard anda berhenti sepadan

Wildcard masih dibenarkan di satu tempat: nama fail bagi perintah tersebut. Peraturan %ops ALL = /sbin/fsck* masih membenarkan sudo fsck dan sudo fsck_exfat, kerana * adalah sebahagian daripada laluan yang dipadankan dengan sistem fail.

Di dalam senarai argumen, sudo-rs hanya menerima dua bentuk khas, dan tiada satu pun daripadanya merupakan corak (pattern). "" bermaksud tiada argumen. * di penghujung bermaksud sebarang argumen tambahan di belakang. Setiap argumen lain dibandingkan sebagai teks literal. Jadi %ops ALL = /sbin/service ntp * adalah betul, kerana ntp adalah literal dan * berada di kedudukan terakhir. Walau bagaimanapun, peraturan seperti ini tidak memberikan apa yang anda inginkan:

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

app-* ialah corak di tengah-tengah argumen. sudo-rs tidak mengembangkannya, jadi peraturan tersebut tidak meliputi systemctl restart app-api dan sudo menolak perintah itu. Dua perintah memberitahu anda perkara sebenar tentang sebarang peraturan pada pelayan anda sendiri: sudo -l -U deploy, yang dijalankan sebagai root, mencetak apa yang akaun tersebut sebenarnya boleh jalankan, dan sudo visudo -c memberitahu anda sama ada fail tersebut boleh diurai (parse) atau tidak. Jalankan perintah ini sebelum anda mula menyunting secara rawak.

Peraturan wildcard sentiasa menjadi kelemahan

Di bawah sudo asal, argumen yang anda taip digabungkan menjadi satu rentetan dan dipadankan dengan rentetan argumen peraturan menggunakan glob. Glob memadankan ruang putih (whitespace). Ini adalah bahagian yang hampir semua orang terlepas pandang.

Dokumentasi sudo-rs memberikan demonstrasi yang paling jelas. Peraturan /bin/rm *.txt juga membenarkan sudo rm -rf /home .txt, kerana satu * menelan -rf /home dan rentetan yang digabungkan itu masih berakhir dengan .txt. Peraturan tersebut dibaca sebagai "fail teks sahaja". Ia sebenarnya bermaksud "apa-apa argumen sekalipun, asalkan baris tersebut berakhir dengan .txt".

Perkara yang sama terpakai pada contoh systemctl. Oleh kerana argumen dibandingkan sebagai satu rentetan yang digabungkan, corak yang berada di hujung juga memadankan apa sahaja yang anda tambah selepasnya, jadi restart app-* merangkumi restart app-api serta sebarang argumen tambahan yang dimasukkan oleh pemanggil. Corak di dalam sesuatu argumen mendedahkan argumen di sekelilingnya, dan argumen adalah tempat di mana kuasa sesuatu arahan itu terletak. sudo-rs menolak binaan tersebut daripada cuba menjadikannya selamat, kerana tiada bentuk umum yang selamat untuknya.

Gantikan wildcard dengan senarai arahan yang eksplisit

Kebanyakan peraturan wildcard wujud kerana seseorang tidak mahu menaip empat baris. Taipkan empat baris tersebut.

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

Pastikan path adalah betul. Peraturan yang menamakan /bin/systemctl pada sistem di mana binari berada di /usr/bin/systemctl tidak akan pernah sepadan, dan kegagalan tersebut kelihatan sama seperti masalah keizinan (permissions). Sahkan dengan command -v systemctl dan tampal apa yang dicetaknya.

Letakkan peraturan tersebut dalam fail drop-in sendiri dan bukannya di dalam /etc/sudoers, supaya naik taraf pakej tidak akan bercanggah dengan suntingan anda:

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

Namakan fail tanpa titik dan tanpa tilde di hujungnya. sudo asal mengabaikan fail dalam sudoers.d yang namanya mengandungi titik, jadi 90-deploy.conf adalah contoh klasik no-op senyap, dan mengekalkan konvensyen ini tidak merugikan apa-apa.

Gunakan wrapper milik root apabila senarai menjadi panjang

Apabila set yang dibenarkan terlalu besar untuk disenaraikan, pindahkan keputusan tersebut keluar daripada sudoers dan masukkan ke dalam program kecil yang dimiliki oleh 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

Bahagian sudoers kemudiannya menamakan satu arahan:

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

Penggunaan * di hujung adalah boleh diterima di sini kerana skrip tersebut, bukan sudo, yang menentukan perkara yang dibenarkan. Perkara ini hanya terpakai selagi skrip tersebut dimiliki oleh root dan tidak boleh ditulis oleh orang lain. Jika deploy boleh menulis pada fail tersebut, deploy boleh menggantikan kandungannya dan menjalankan apa sahaja sebagai root, yang mana lebih buruk daripada peraturan wildcard yang anda buang. Semak mod dengan ls -l, dan jika outputnya tidak jelas kepada anda, membaca rentetan kebenaran drwxr-xr-x hanya mengambil masa lima minit untuk dipelajari. Peraturan yang sama meliputi direktori: /usr/local/sbin juga tidak boleh boleh ditulis oleh akaun tersebut, kerana direktori yang boleh ditulis bermakna fail tersebut boleh digantikan sepenuhnya.

Berikan tugasan akaunnya sendiri dan bukannya peraturan sudo

Soalan yang lebih tepat selalunya adalah mengapa arahan tersebut memerlukan root sama sekali. Servis yang berjalan sebagai pengguna sendiri boleh diuruskan oleh pengguna tersebut, dan tiada baris sudoers yang terlibat. Bagi unit sistem, systemd sudah menyerahkan keputusan itu kepada polkit, jadi satu peraturan boleh menamakan satu unit dan satu pengendali:

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

Simpan fail tersebut sebagai /etc/polkit-1/rules.d/50-app-api.rules dan deploy boleh menjalankan systemctl restart app-api tanpa sebarang sudo. Uji peraturan tersebut daripada konteks tepat yang akan menggunakannya, kerana peraturan yang berfungsi dalam sesi SSH anda perlu disahkan daripada cron sebelum anda bergantung kepadanya. Walau apa pun, akaun yang melakukan kerja tersebut harus wujud untuk kerja itu sahaja, yang merupakan hujah yang sama di sebalik akaun pengguna dengan keistimewaan paling rendah pada VPS.

Perkara lain yang tidak disertakan dalam sudo-rs

sudo -E tidak dilaksanakan. Namakan pemboleh ubah yang anda perlukan dengan Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY" sebagai ganti, dan ingat bahawa env_reset sentiasa aktif, jadi apa-apa yang tidak disimpan akan dibersihkan.

Storan sudoers berpusat dalam LDAP telah dibuang. sudoers.ldap dan cvtsudoers tidak dilaksanakan, dan pakej sudo-ldap telah dikeluarkan dalam versi 26.04. Pengesahan LDAP melalui PAM atau SSSD masih berfungsi. Bahagian dasar-dalam-direktori adalah di luar skop.

INTERCEPT, yang cuba menghalang shell escape daripada arahan yang dibenarkan, tidak dilaksanakan. Ia tidak pernah berkesan terhadap pengguna yang berazam. Jika sesuatu peraturan membenarkan seseorang menjalankan editor atau penterjemah sebagai root, mereka mempunyai akses root, dan tiada pilihan sudo yang boleh mengubah perkara itu.

Rakaman sesi tidak dilaksanakan, jadi tiada log I/O dan tiada sudoreplay. Pembalakan hanya dihantar ke syslog, dan tiada pilihan logfile untuk mengubah halanya ke tempat lain, jadi mesej sudo akan mendarat di mana sahaja sistem anda menghantar syslog pada masa ini.

Patutkah anda kembali kepada sudo.ws?

Anda boleh berbuat demikian, dan sepanjang kitaran 26.04, versi asal kekal dipakejkan atas sebab ini.

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

Salin laluan tepat daripada output --config dan bukannya daripada halaman ini, kerana itulah senarai yang akan diterima oleh sistem anda sendiri. Kembali kepada sudo-rs kemudian bermakna menetapkan alternatif kepada laluan binari sudo-rs daripada senarai yang sama.

Pastikan sesi SSH kedua dibuka, dilog masuk dan melahu, sebelum anda menyentuh apa-apa yang menjejaskan sudo. Fail sudoers yang gagal dihuraikan, atau alternatif yang menghala kepada binari yang tidak dipasang, boleh menyebabkan anda tiada cara untuk menjadi root pada kotak jauh. Tabiat itu perlu diamalkan bersama semua perkara lain yang anda lakukan dalam sepuluh minit pertama pada VPS baharu.

Anggap pertukaran kembali itu sebagai tarikh akhir dan bukannya penyelesaian. Ia memberi anda masa seminggu untuk menulis semula peraturan dengan betul, dan penulisan semula itu berbaloi dilakukan atas meritnya sendiri, kerana setiap peraturan wildcard yang anda padamkan telah memberikan lebih banyak akses daripada yang difahami oleh penulisnya.

FAQ

Mengapa peraturan wildcard sudoers saya tidak lagi berfungsi pada Ubuntu 26.04?

Ini kerana Ubuntu 26.04 LTS memilih sudo-rs sebagai sudo lalai, dan sudo-rs tidak memadankan corak wildcard di dalam argumen sesuatu arahan. Ia membenarkan wildcard pada nama fail arahan, "" untuk bermaksud tiada argumen, dan satu * sebagai argumen terakhir. Peraturan seperti /usr/bin/systemctl restart app-* meletakkan corak di tengah-tengah argumen, jadi ia tidak memberikan sebarang kebenaran dan arahan tersebut ditolak. Jalankan sudo -l -U deploy sebagai root untuk melihat apa yang sebenarnya dimiliki oleh akaun tersebut, kemudian gantikan peraturan itu dengan arahan yang tepat atau dengan skrip pembungkus (wrapper script) milik root.

Bagaimanakah cara untuk kembali kepada sudo asal pada Ubuntu 26.04?

Versi asal dibungkus sebagai sudo.ws. Pasang ia dengan sudo apt install sudo.ws, kemudian halakan alternatif kepadanya dengan sudo update-alternatives --set sudo /usr/bin/sudo.ws. Jalankan update-alternatives --config sudo terlebih dahulu untuk membaca laluan tepat yang ditawarkan oleh sistem anda, dan pastikan sesi SSH kedua dibuka semasa anda melakukan perubahan. Ini tidak akan mengembalikan sudo-ldap, yang telah dibuang daripada 26.04 tanpa mengira pelaksanaan yang anda pilih.

Adakah sudo-rs membaca fail /etc/sudoers yang sama?

Ya. sudo-rs membaca /etc/sudoers dan fail-fail drop-in di bawah /etc/sudoers.d/, dengan sintaks yang sama untuk pengguna, kumpulan, alias, spesifikasi run-as dan tag NOPASSWD. Ia melaksanakan subset bahasa sudoers, jadi perbezaannya muncul sebagai binaan yang tiada dan bukannya binaan yang berkelakuan berbeza. Sunting dengan sudo visudo, kemudian sahkan dengan sudo visudo -c sebelum anda menutup sesi anda.

Apakah yang menggantikan sudo -E dalam sudo-rs?

sudo -E tidak dilaksanakan, dan ia sudah pun tidak digalakkan dalam sudo asal, kerana memberikan proses root satu persekitaran yang dikawal oleh pemanggil adalah cara yang diketahui umum untuk mengubah kelakuan proses tersebut. Namakan pemboleh ubah yang anda perlukan dalam sudoers sebaliknya, dengan baris seperti Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY". env_reset sentiasa aktif dalam sudo-rs dan tidak boleh dinyahdayakan, jadi setiap pemboleh ubah yang tidak anda simpan akan dibersihkan.

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