Ubuntu 26.04のsudo-rsでsudoersはどう変わる?
Ubuntu 26.04ではsudo-rsがsudoの標準になります。sudoersの引数内ワイルドカードは照合されないため、該当するルールの書き換え方を確認できます。
Ubuntu で sudo-rs が変更する点
Ubuntu 26.04 LTS では sudo-rs がデフォルトの sudo として提供されるため、新規サーバーで sudo コマンドを実行すると、従来の C プログラムではなく Rust による再実装が実行されます。ほとんどの sudoers ファイルは、これまでどおりそのまま動作します。動作しなくなるのは、コマンドの引数内にワイルドカードを含むルールです。sudo-rs は引数のテキストに対して glob パターンを照合しないためです。
Ubuntu 25.10 で先に切り替えられ、Ubuntu 26.04 LTS でもその構成が維持されました。Ubuntu 24.04 LTS は、手動で sudo-rs をインストールしない限り従来の sudo を選択するため、影響を受けません。この変更が問題になるのは、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 で、2026年8月時点の 26.04 ではバージョン 0.2.13 です。Todd C. Miller が開発し、現在も保守している従来版は、引き続き sudo パッケージです。変更点は、そのプログラムに .ws サフィックスが付くことです。これにより、両方を同時にインストールできます。つまり、/usr/bin/sudo.ws と /usr/bin/visudo.ws に加えて、cvtsudoers.ws と sudoreplay.ws も利用できます。2026年9月に 26.04 のアーカイブで確認したところ、dpkg -L sudo にはサフィックス付きのバイナリが一覧表示され、sudo-rs にはそれらとともに /usr/bin/sudo-rs が含まれています。
Ubuntu が sudo-rs に切り替えた理由
sudo は setuid root です。システム上のすべてのユーザーが起動でき、起動時には完全な権限を持つため、内部のメモリバグはローカル root 権限昇格につながります。CVE-2021-3156 はまさにその例でした。すべてのローカルユーザーから到達可能なヒープバッファオーバーフローであり、リリース済みのコードに約 10 年間存在していました。Rust はこの種のバグをコンパイル時に検出します。これが書き換えの主な理由です。
2 つ目の理由はスコープです。こちらは設定に直接影響します。元の sudo には 30 年以上にわたって多数の機能が追加されてきました。機能が増えるほど、root として実行されるコードも増えます。sudo-rs は意図的に機能の一部だけを実装しています。開発者が特殊用途向け、または有害と判断した機能は含まれていません。そのため、何年も動作していた sudoers の構文が単純に存在しない場合があります。ワイルドカード規則はその一例です。
メモリ安全性によって、バグの一種は排除されます。しかし、プログラムからすべてのバグがなくなるわけではありません。sudo-rs も、デフォルトになって以降、独自のセキュリティ修正をリリースしています。他のソフトウェアと同様に、パッチを適用してください。
sudoers ルールのうち、引き続き機能するもの
ファイル自体は同じです。sudo-rs は /etc/sudoers と /etc/sudoers.d/ 内の drop-in ファイルを読み込みます。サーバー運用者が通常記述する要素はサポートされています。
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などの有用な一部
2 つのデフォルト設定は動作が異なるため、注意が必要です。sudo-rs では env_reset を無効にできません。常に有効です。use_pty はデフォルトで有効なため、コマンドは独自の pseudo-terminal で実行されます。
ワイルドカードを含む sudoers ルールが一致しなくなった理由
ワイルドカードが引き続き許可される場所は 1 つだけです。対象コマンドのファイル名です。%ops ALL = /sbin/fsck* のルールでは、sudo fsck と sudo fsck_exfat も引き続き許可されます。これは * がファイルシステムと照合されるパスの一部だからです。
引数リスト内で sudo-rs が受け付ける特殊な形式は 2 つだけで、どちらもパターンではありません。"" は引数なしを意味します。最後にある * は、後続する任意の引数を意味します。それ以外の引数はすべて、リテラル文字列として比較されます。そのため %ops ALL = /sbin/service ntp * は使用できます。ntp はリテラルであり、* が最後にあるためです。ただし、次のようなルールでは意図した権限が何も付与されません。
deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart app-*app-* は引数の途中にあるパターンです。sudo-rs はこれを展開しないため、このルールは systemctl restart app-api を許可せず、sudo はコマンドを拒否します。自分のサーバー上のルールを確認するには、2 つのコマンドで実際の状態を確認できます。sudo -l -U deploy を root として実行すると、そのアカウントが実際に実行できるコマンドが表示されます。sudo visudo -c では、ファイルを解析できるかどうかを確認できます。手当たり次第に編集を始める前に、これらを実行してください。
ワイルドカード規則には常に抜け穴がありました
元の sudo では、入力した引数を 1 つの文字列に結合し、glob を使って規則の引数文字列と照合します。glob は空白にも一致します。ここを見落とす人がほとんどです。
sudo-rs のドキュメントには、最も分かりやすい例があります。/bin/rm *.txtという規則はsudo rm -rf /home .txtも許可します。1 つの*が-rf /home を取り込み、結合後の文字列が.txtで終わるためです。この規則は「テキストファイルのみ」と読めます。しかし実際には、「行末が .txt である限り、引数は何でもよい」という意味になります。
systemctl の例でも同じです。引数は 1 つの結合後の文字列として比較されるため、末尾のパターンは、その後に追加された内容にも一致します。したがって、restart app-*はrestart app-apiと、呼び出し元が追加するそれ以降の任意の引数を許可します。引数内にパターンを置くと、その前後にある引数まで意図せず許可されます。コマンドの権限は引数によって決まります。sudo-rs は安全にする方法を試すのではなく、この構文自体を拒否します。安全な一般形が存在しないためです。
ワイルドカードを明示的なコマンド一覧に置き換える
ワイルドカードルールの多くは、4 行を入力したくなかったために存在します。4 行を入力してください。
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パスを正しく指定してください。バイナリが /usr/bin/systemctl にあるシステムで /bin/systemctl を指定するルールは一致しません。この場合、失敗の状況が権限の問題と同じに見えます。command -v systemctl で確認し、表示された内容を貼り付けてください。
ルールは /etc/sudoers に直接記述せず、専用の drop-in ファイルに記述してください。これにより、パッケージのアップグレードによって編集内容が上書きされることを防げます。
sudo visudo -f /etc/sudoers.d/90-deploy
sudo visudo -c
sudo -l -U deployファイル名にはドットを含めず、末尾にチルダを付けないでください。元の sudo は、sudoers.d にある名前にドットを含むファイルを無視します。そのため、90-deploy.conf は典型的な、エラーが表示されない無効な設定になります。この慣例に従っても手間はかかりません。
許可リストが長くなった場合は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-restartsudoers側では、1つのコマンドだけを指定します。
deploy ALL=(root) NOPASSWD: /usr/local/sbin/app-restart *末尾の*がここで許容されるのは、許可する内容をsudoではなくスクリプトが判定するためです。ただし、スクリプトをrootが所有し、他のユーザーが書き込めない場合に限ります。deployがファイルに書き込める場合、deployで内容を置き換えて、rootとして任意の処理を実行できます。これは、削除したワイルドカード規則よりも危険です。ls -lでモードを確認してください。出力の意味がすぐに分からない場合でも、drwxr-xr-xの権限文字列を読む方法は5分で習得できます。同じ規則はディレクトリにも適用されます。/usr/local/sbinもアカウントから書き込み可能であってはなりません。ディレクトリが書き込み可能だと、ファイル全体を置き換えられるためです。
sudo ルールではなく、ジョブ専用のアカウントを割り当てる
多くの場合、先に考えるべきなのは、そのコマンドが本当に root を必要とするのかという点です。専用ユーザーで実行するサービスは、そのユーザーで管理できるため、sudoers の行は必要ありません。systemd の system unit では、すでに polkit にその判断を委譲できます。そのため、1 つの unit と 1 人の操作担当者を指定するルールを作成できます。
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 は sudo をまったく使わずに systemctl restart app-api を実行できます。実際に使用するのと同じコンテキストからテストしてください。SSH セッションで動作するルールでも、運用で依存する前に cron から確認する必要があります。いずれの場合も、処理を実行するアカウントは、その処理専用に用意してください。これは VPS の最小権限ユーザーアカウント を推奨する理由と同じです。
sudo-rs で省略されているその他の機能
sudo -E は実装されていません。必要な変数は代わりに Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY" で指定してください。また、env_reset は常に有効であるため、保持されないものはすべてクリアされます。
LDAP による sudoers の集中管理は廃止されています。sudoers.ldap と cvtsudoers は実装されておらず、sudo-ldap パッケージは 26.04 で削除されました。PAM または SSSD を介した LDAP 認証は引き続き機能します。対象外なのは、ディレクトリにポリシーを保存する機能です。
許可されたコマンドからのシェルエスケープを阻止しようとした INTERCEPT は実装されていません。そもそも、意志の強いユーザーには効果がありません。ルールによってエディターやインタープリターを root として実行できるなら、そのユーザーは root 権限を取得できます。sudo のオプションでこれを変えることはできません。
セッション記録は実装されていないため、I/O ログも 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 に戻す場合は、同じ一覧にある sudo-rs のバイナリパスを alternative に設定します。
sudo に影響する操作を行う前に、ログインしたまま待機している SSH セッションをもう 1 つ開いておいてください。構文解析に失敗する sudoers ファイルや、インストールされていないバイナリを指す alternative によって、リモートホストで root になる手段を失うことがあります。この習慣は、新しい VPS で最初の 10 分間に行う作業の一部として身につけてください。
この切り替えは修正ではなく、期限を延ばす措置と考えてください。ルールを書き直すための 1 週間が得られます。書き直しは、それ自体に価値があります。削除するワイルドカードルールはすべて、作成者が意図した以上の権限を付与していたからです。
FAQ
Ubuntu 26.04 で sudoers のワイルドカード規則が機能しなくなったのはなぜですか?
Ubuntu 26.04 LTS ではデフォルトの sudo として sudo-rs が選択され、sudo-rs はコマンドの引数内にあるワイルドカードパターンを照合しないためです。コマンドのファイル名にはワイルドカードを使用でき、"" は引数なしを意味し、最後の引数には単一の * を使用できます。/usr/bin/systemctl restart app-* のような規則では引数の途中にパターンを指定するため、何も許可されず、コマンドは拒否されます。root として sudo -l -U deploy を実行し、そのアカウントに実際に許可されている内容を確認してください。その後、規則を正確なコマンド、または root 所有のラッパースクリプトに置き換えます。
Ubuntu 26.04 で元の sudo に戻すにはどうすればよいですか?
元の sudo は sudo パッケージに含まれており、バイナリには .ws サフィックスが付いています。sudo apt install sudo でインストールし、sudo update-alternatives --set sudo /usr/bin/sudo.ws で alternative の参照先を切り替えます。最初に update-alternatives --config sudo を実行して、システムで選択できる正確なパスを確認してください。切り替え中は、2 つ目の SSH セッションを開いたままにします。これは sudo-ldap を復元するものではありません。選択する実装に関係なく、sudo-ldap は 26.04 で削除されています。
sudo-rs は同じ /etc/sudoers ファイルを読み取りますか?
はい。sudo-rs は /etc/sudoers と /etc/sudoers.d/ 配下の drop-in ファイルを読み取ります。ユーザー、グループ、alias、run-as 指定、NOPASSWD タグには同じ構文を使用します。ただし、sudoers 言語のサブセットだけを実装しているため、違いは動作が変わる構文ではなく、利用できない構文として現れます。sudo visudo で編集し、セッションを終了する前に sudo visudo -c で検証してください。
sudo-rs では sudo -E の代わりに何を使いますか?
sudo -E は実装されていません。元の sudo でもすでに非推奨でした。呼び出し元が制御する環境を root プロセスに渡すと、そのプロセスの動作を変更される既知の方法になるためです。実際に必要な変数を sudoers で指定してください。たとえば、Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY" のように記述します。env_reset は sudo-rs では常に有効で、無効化できません。そのため、保持しない変数はすべてクリアされます。