SUDO(8) | System Manager's Manual | SUDO(8) |
sudo, sudoedit - コマンドを他のユーザとして実行する
sudo -h | -K | -k | -V
sudo -v [-AknS]
[-g group] [-h host]
[-p prompt] [-u user]
sudo -l [-AknS]
[-g group] [-h host]
[-p prompt] [-U user]
[-u user] [command]
sudo [-AbEHnPS] [-C num]
[-g group] [-h host]
[-p prompt] [-r role]
[-t type] [-u user]
[VAR=value] [-i | -s]
[command]
sudoedit [-AknS] [-C num] [-g group] [-h host] [-p prompt] [-u user] file ...
sudo を使用すると、許可されたユーザが、セキュリティポリシーの設定の範囲内で、 スーパーユーザや他のユーザに変身して、command を実行することが可能になる。 セキュリティポリシーへの問い合わせは、ユーザ名によって行われるが、 そのユーザ名を決めるのは、sudo を実行するユーザの実ユーザ ID であって、 実効ユーザ ID ではない。
sudo はセキュリティポリシーと入出力のロギングについて、プラグイン方式をサポートしている。 従って、サードパーティは、 sudo フロントエンドとシームレスに協働するポリシー・プラグインや入出力ロギング・プラグインを、 独自に開発して配布することができる。 デフォルトのセキュリティポリシーは sudoers であり、その設定は、 /etc/sudoers ファイル、もしくは LDAP を通して行われる。 詳細については、「プラグイン」セクションを参照していただきたい。
セキュリティポリシーは、あるユーザに sudo を使用する権限があるかどうか、 あるとすれば、どんな権限を持っているかを決定する。 セキュリティポリシーは、ユーザにパスワードや他の認証方法を使って、 本人であることを証明するように要求することができる。 認証が必要な場合、ユーザが自分のパスワードを、 設定によって変更可能な制限時間内に入力しないと、sudo は時間切れで終了する (訳注: sudo はデフォルトでは、root や変身対象ユーザのパスワードではなく、 sudo を実行するユーザ本人のパスワードを要求する)。 この制限時間はポリシー次第であり、 sudoers セキュリティポリシーの場合、 パスワード・プロンプトがタイムアウトするまでのデフォルトの時間は、5 分間である。
セキュリティポリシーは、一定時間内ならユーザが認証なしで sudo を何度も実行できるように、認証情報の一時保存 (credential caching) をサポートしてもよい。sudoers ポリシーでは、sudoers(5) で変更されないかぎり、認証情報を 5 分間保持する。 ユーザは sudo に -v を付けて実行することで、 command を実行しないでも、保存された認証情報を更新することができる。
sudoedit というコマンド名で起動するのは、sudo に -e オプション (下記参照) を付けて実行するのと同じである。
セキュリティポリシーは、ユーザが sudo を使おうとして成功した場合も失敗した場合も、それをログに記録することができる。 入出力プラグインが設定されている場合は、 sudo 経由で実行するコマンドの入出力もログに残すことができる。
オプションとして以下のものが使用できる。
# askpass ヘルパー・プログラムのパス Path askpass /usr/X11R6/bin/ssh-askpass
利用できる askpass プログラムがないと、sudo はエラーメッセージを出して、 終了する。
編集する権限のないファイルを編集できないようにするため、 セキュリティポリシーによって明示的に許可されていないかぎり、 以下の制限が行われる。
ユーザがデバイス・スペシャルファイルの編集を許可されることは絶対にない。
指定されたファイルが存在しない場合は作成する。ここで注意すべきは、 sudo によって実行されるコマンドの大部分と違って、 -e でエディタが実行されるときは、sudo を起動したユーザの環境が、 変更を受けずに使われるということだ。 何らかの理由で sudo が編集した内容でファイルを更新できないときは、 ユーザに警告を発し、編集した内容をテンポラリファイルに保存することになる。
コマンドや、パスワードを必要とするような他のオプションと組み合わせて、 このオプションを使用すると、 sudo がユーザの保存された認証情報を無視することになる。 その結果、sudo は (セキュリティポリシーがパスワードを要求するならば)、 プロンプトを出して、パスワードを要求する。 このとき、ユーザの保存された認証情報の更新は行われない。
すべてのセキュリティポリシーが、認証情報の一時保存をサポートしているわけではない。
コマンドを指定した場合は、その実行がセキュリティポリシーによって許可されていれば、 コマンドの絶対パスが表示される。 コマンドラインでコマンドに引き数まで指定すると (訳注: その引き数が許可されていれば)、それも一緒に表示される。 指定したコマンドが許可されていない場合は、 sudo はステータス 1 で終了することになる。
自家特製のプロンプトが、 PAM をサポートしているシステムでシステムのパスワードプロンプトに置き替わるのは、 sudoers で passprompt_override フラグが無効になっていない場合である (訳注: sudoers(5) の passprompt_override の項も参照していただきたい)。
さらに、コマンドのために設定したい環境変数も、VAR=value、たとえば LD_LIBRARY_PATH=/usr/local/pkg/lib といった形でコマンドラインで渡すことができる。コマンドラインで渡す環境変数は、 セキュリティポリシー・プラグインによって課される制限の対象になる。 sudoers ポリシーの場合、コマンドラインで渡される環境変数は、 通常の環境変数と同じ制限の対象になるが、一つだけ重要な相違がある。 sudoers で setenv オプションが設定されているか、実行するコマンドに SETENV タグが付いているか、あるいは、マッチするコマンドが ALL である場合は、 ユーザは他の状況なら禁じられているような環境変数を設定することができるのだ。 詳細については、sudoers(5) のマニュアルを参照していただきたい。
sudo がコマンドを実行するとき、 セキュリティポリシーによってコマンドの実行環境が設定される。たいていの場合、 実ユーザ、実効ユーザ、実グループ、実効グループ、及びその ID 番号が、変身対象ユーザの、 パスワード・データベースに記載されているものと同一になるようにセットされる。 所属グループのリストも、(-P オプションが指定されていないかぎり) グループ・データベースに基づいて、初期化される。
セキュリティポリシーは、以下のパラメータを設定することができる。
sudo は、コマンドを実行するとき、まず fork(2) を呼び、 実行環境を上記のように設定してから、子プロセスで execve システムコールを呼び出す。 メインの sudo プロセスは、コマンドが完了するまで wait し、完了したら、 コマンドの終了ステータスをセキュリティポリシーの close 関数に渡してから、 終了する。入出力ロギング・プラグインが設定されている場合や、 セキュリティポリシーが明示的にそれを要求している場合は、 擬似端末 ("pty") が新規に作成され、二つ目の sudo プロセスが、 既に存在しているユーザの pty と、コマンドがそこで実行されている新しい pty との間で、 ジョブ制御シグナルを中継するために使用される。 この二つ目の sudo プロセスによって、たとえば、 コマンドのサスペンドやレジュームといったことが可能になるのである。 この仕組みがなければ、コマンドは、POSIX で "orphaned process group" と言われる状態に陥り、どんなジョブ制御シグナルも受け取れないことになってしまうだろう。 なお、特殊ケースとして次のことがある。ポリシー・プラグインが close 関数を定義していず、しかも、pty が要求されていない場合は、 sudo は fork(2) を最初に呼ぶことをせず、直接コマンドを実行する。 sudoers ポリシー・プラグインで close 関数が定義されることになるのは、 入出力ロギングが有効か、pty が要求されているか、pam_session または pam_setcred が有効な場合だけである。PAM を使用しているシステムでは、 デフォルトで pam_session と pam_setcred が有効になることに注意していただきたい。 (訳注: 上記の「特殊ケースとして」以下についてだが、最近の sudo では、 sudoers ポリシーにおける pam_session や pam_setcred の有効/無効に関係なく、pty が要求されていない場合は、 fork せずに直接コマンドを実行するようである。)
コマンドが sudo プロセスの子プロセスとして実行されているとき、 sudo は自分が受け取ったシグナルをそのコマンドに中継する。 ただし、SIGINT や SIGQUIT シグナルが中継されるのは、 そのコマンドが新たに開いた pty で実行されているときか、 シグナルがカーネルではなく、ユーザ・プロセスによって送出されたときだけである。 そうなっていることで、ユーザが control-C を入力するたびに、 コマンドが SIGINT シグナルを二重に受け取らないようにしているのだ。 SIGSTOP や SIGKILL のようないくつかのシグナルは、 捕獲できないので、コマンドに中継されることもない。 だから、sudo によって実行されているコマンドをサスペンドしたかったら、 原則として、SIGSTOP ではなく、SIGTSTP コマンドを使用するべきである。
sudo は原則として、自分が受け取ったシグナルを子プロセスに中継するわけだが、 自分が実行しているコマンドから来たシグナルは、中継しないという例外がある。 コマンドが意図に反して自分自身を殺してしまわないようにしているのだ。 システムによっては、reboot(8) コマンドが、システムをリブートする前に、 自分自身を除くすべてのノン・システム・プロセスに SIGTERM を送るものがある。 そうした場合も、中継の抑制があるため、sudo は自分が受け取った SIGTERM シグナルを reboot(8) に送り返さない。もし送り返すようになっていたら、 システムが実際にリブートする前に reboot(8) が終了して、 システムがシングルユーザ・モードによく似た半分死んだ状態 (half-dead state) に陥ってしまうだろう。とは言え、注意していただきたいが、 この中継の抑制が行われるのは、sudo によって直接実行されるコマンドに対してのみであり、 そのコマンドが生成するかもしれない他のどんなプロセスに対しても当てはまらない。 それ故、reboot(8) や shutdown(8) を呼び出すスクリプトを sudo 経由で実行すると、システムがそうしたわけのわからない状態に陥ることがある。 reboot(8) や shutdown(8) の実行に exec() ファミリーの関数ではなく、 system() 関数を使用していると、 (system() は、呼び出しプロセスとコマンドの間にシェルを挟むため) そうしたことが起こりかねないのだ。
入出力ロギング・プラグインがロードされていない場合に、 ポリシー・プラグインが close() 関数を定義してもいず、 コマンドのタイムアウトを設定していることもなく、コマンドを新たに開いた pty で実行することを要求してもいなかったならば、sudo は、 コマンドを子プロセスとしてではなく、直接実行するかもしれない。
プラグインは、sudo.conf(5) ファイルの Plugin 命令 (directive) で指定することができる。プラグインは、(システムがサポートしていれば) 動的な共有オブジェクト (dynamic shared object) としてロードすることもできるし、 また、sudo のバイナリに直接組み込むこともできる。sudo.conf(5) ファイルが存在しない場合や、sudo.conf(5) ファイルに Plugin の行がない場合は、 sudo は従来どおり、sudoers のセキュリティポリシーと入出力ロギングを使用することになる。 /etc/sudo.conf ファイルの詳細については、 sudo.conf(5) のマニュアルを参照していただきたい。 sudo プラグインの設計についての詳しい情報は、 sudo_plugin(5) のマニュアルにある。
コマンドの実行に成功した場合、sudo が返す終了ステータスは、 実行したプログラムの終了ステータスである。 コマンドがシグナルを受け取ることによって終了した場合は、 sudo はコマンドを終了させたシグナルを自分自身に送るようになっている。
それ以外の場合、設定やパーミッションに問題があったり、 sudo が指定されたコマンドを実行できなかったりしたときは、 sudo は終了ステータス 1 で終了する。後者の場合は、 エラーメッセージが標準エラーに表示される。sudo がユーザの PATH にある一つ以上のエントリを stat(2) できなかったときも、 エラーが標準エラーに表示される (ただし、PATH 中のディレクトリが存在しなかったときや、実際にはディレクトリでなかったときは、 そのエントリは無視され、エラーは表示されない)。そういったことは、 通常の状態では起きるはずがないことである。stat(2) が "permission denied" を返す理由で一番よくあるのは、ユーザがオートマウンターを使用していて、 PATH 中のディレクトリの一つが目下到達不可能なマシンにある場合だ。
sudo は、外部のコマンドをできるだけ安全に実行しようとする。
偽コマンドの実行 (command spoofing) を防止するため、sudo はコマンドを捜してユーザの PATH を検索する際に、"." や "" (どちらもカレント・ディレクトリを意味する) を最後に調べる (そのどちらか、 あるいは両方が、PATH 中に存在すればだが)。とは言え、環境変数 PATH そのものは変更されずに、 そのまま sudo が実行するプログラムに渡されることに注意していただきたい。
次のようなファイルを実行する sudo 権限を、絶対にユーザに許可してはいけない。 すなわち、そのユーザに書き込みできるファイルや、 そのユーザに書き込みできるディレクトリにあるファイルを実行する権限である。 もし、ユーザがコマンドを書き換えたり、別のコマンドと置き換えたりできるならば、 そのユーザは自分が実行できるコマンドに何でも追加できるわけで、 それを制限する方法はまったくないのだ。
sudo は通常、自分が明示的に実行するコマンドしかログに記録しないことに注意していただきたい。 ユーザが sudo su や sudo sh といったコマンドを実行した場合、 そのシェルからさらに実行されるコマンドは、 sudo のセキュリティポリシーの対象にはならないのだ。 同じことが、シェル・エスケープを提供するコマンド (たいていのエディターが、 それに含まれる) についても言える。確かに、入出力ロギングが有効になっている場合は、 シェルからさらに実行されるコマンドも、その入力や出力を記録されることになるが、 従来からあるログファイルに記録されるわけではないのである。従って、 ユーザに sudo 経由で、あるコマンドを実行する権限を与えるときは、 そのコマンドが事実上ルート・シェルをユーザにうっかり与えていないことを、 念には念を入れて確認しなければならない。もっと詳しいことをお知りになりたかったら、 sudoers(5) のマニュアルの「シェル・エスケープを防止する」というセクションをご覧になるとよい。
セキュリティ上問題になりかねない情報を漏洩しないように、 sudo はデフォルトでは、自己を実行中のコアダンプを抑止している (指定されたコマンドを実行するときに、コアダンプを有効にし直すのだ)。 この動作は昔からのものであり、たいていのオペレーティングシステムが setuid プロセスにデフォルトではコアダンプを許していた時代からそうなっていた。 sudo 自体のクラッシュをデバッグするためにコアダンプを有効に戻したいならば、 以下のように、sudo.conf(5) ファイルで "disable_coredump" を false にすればよい。
Set disable_coredump false
詳細については、sudo.conf(5) のマニュアルを参照していただきたい。
sudo は以下の環境変数を利用する。 実行するコマンドの環境が実際にどうなるかは、セキュリティポリシー次第である。
注意: 以下の例は、セキュリティポリシーが適切に設定されていることを前提にしている。
読み取り不可のディレクトリのファイル一覧を取得する。
$ sudo ls /usr/local/protected
ユーザ yaz のホームディレクトリのファイル一覧を取得する。 ただし、~yaz を含むファイルシステムが、別のマシンにあって、 root でアクセスできるようにエクスポートされていない場合。
$ sudo -u yaz ls ~yaz
ユーザ www として index.html ファイルを編集する。
$ sudo -u www vi ~www/htdocs/index.html
root と adm グループのユーザだけがアクセスできるシステムログを閲覧する。
$ sudo -g adm view /var/log/syslog
jim に変身してエディタを実行する。プライマリグループには別のグループを指定する。
$ sudo -u jim -g audio vi ~jim/sound.txt
マシンをリブートする。
$ sudo shutdown -r +15 "quick reboot"
/home パーティションに存在するディレクトリのディスク使用量リストを作成する。 cd やファイル・リダイレクションがきちんと動作するように、 コマンドをサブシェルで実行している点に注目していただきたい。
$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"
su(1), stat(2), passwd(5), sudo.conf(5), sudoers(5), sudo_plugin(5), sudoreplay(8), visudo(8)
sudo の簡単な履歴については、sudo の配布に含まれている HISTORY ファイルをご覧いただきたい。 (https://www.sudo.ws/history.html)
多数の人々が長年に渡って sudo の開発に携わってきた。 当バージョンは主として次の者が書いたコードからできている。
sudo の開発に貢献してくださった方々の詳細なリストについては、 配布物中の CONTRIBUTORS ファイルをご覧になっていただきたい。 (https://www.sudo.ws/contributors.html)
もし、ユーザが sudo 経由で任意のコマンドを実行することを許可されているなら、 そのユーザがルート・シェルを手に入れるのを防止する簡単な方法は存在しない。 また、(エディタをはじめとする) 多くのプログラムが、 シェル・エスケープを通してユーザがコマンドを実行できるようにしており、 この方法でユーザは sudo によるチェックをすり抜けることができる。 とは言え、たいていのシステムでは、sudoers(5) プラグインの noexec 機能を使用することでシェルエスケープを抑止することが可能だ。
下記のように sudo 中で直に cd コマンドを実行しても意味がない。
$ sudo cd /usr/local/protected
なぜなら、このコマンドが終了したとき、その親プロセス (すなわち、sudo を実行したシェル) は、sudo を実行する前と同じ状態に戻るからだ。 cd については、「用例」セクションもご覧になっていただきたい。
sudo を介してシェルスクリプトを実行すると、ある種のオペレーティング・システムで setuid シェルスクリプトを危険なものにしているのと同一の、 カーネルのバグが表面化するおそれがある (使用している OS に /dev/fd/ ディレクトリがあれば、setuid シェルスクリプトはたいてい安全である)。
sudo にバグを発見したと思ったら、https://bugzilla.sudo.ws/ にアクセスして、バグレポートを提出していただきたい。
ある程度の無料サポートが sudo-users メーリングリストを通して利用できる。 購読やアーカイブの検索には、次の URL を御覧になるとよい。 https://www.sudo.ws/mailman/listinfo/sudo-users
sudo は「現状のまま」提供される。 明示的な、あるいは黙示的ないかなる保証も、 商品性や特定目的への適合性についての黙示的な保証を含め、 またそれのみに止まらず、これを否認する。詳細な全文については、 sudo と一緒に配布されている LICENSE ファイルや、 次の Web ページをご覧いただきたい。 https://www.sudo.ws/license.html
January 19, 2016 | Sudo 1.8.17 |