# 30. 制限実行 (restricted execution)

警告

Python 2.3 で、既知の容易に修正できないセキュリティーホールのために、これらのモジュールは無効にされています。 `rexec` や `Bastion` モジュールを使った古いコードを読むときに助けになるよう、モジュールのドキュメントだけは残されています。

制限実行 (restricted execution) とは、信頼できるコードと信頼できないコードを区別できるようにするための Python における基本的なフレームワークです。このフレームワークは、信頼できる Python コード (スーパバイザ (supervisor)) が、パーミッションに制限のかけられた "拘束セル (padded cell)" を生成し、このセル中で信頼のおけないコードを実行するという概念に基づいています。信頼のおけないコードはこの拘束セルを破ることができず、信頼されたコードで提供され、管理されたインタフェースを介してのみ、傷つきやすいシステムリソースとやりとりすることができます。 "制限実行" という用語は、"安全な Python (safe-Python)" を裏から支えるものです。というのは、真の安全を定義することは難しく、制限された環境を生成する方法によって決められるからです。制限された環境は入れ子にすることができ、このとき内側のセルはより縮小されることはあるが決して拡大されることのない特権を持ったサブセルを生成します。

Python の制限実行モデルの興味深い側面は、信頼されないコードに提供されるインタフェースが、信頼されるコードに提供されるそれらと同じ名前を持つということです。このため、制限された環境で動作するよう設計されたコードを書く上で特殊なインタフェースを学ぶ必要がありません。また、拘束セルの厳密な性質はスーパバイザによって決められるため、アプリケーションによって異なる制限を課すことができます。例えば、信頼されないコードが指定したディレクトリ内の何らかのファイルを読み出すが決して書き込まないということが "安全" と考えられるかもしれません。この場合、スーパバイザは組み込みの `open()` 関数について、 mode パラメタが `'w'` の時に例外を送出するように再定義できます。また例えば、"安全" とは、 filename パラメタに対して `chroot()` に似た操作を施して、ルートパスがファイルシステム上の何らかの安全な "砂場 (sandbox)" 領域に対する相対パスになるようにすることかもしれません。この場合でも、信頼されないコードは依然として、もとの呼び出しインタフェースを持ったままの組み込みの `open()` 関数を制限環境中に見出します。ここでは、関数に対する意味付け (semantics) は同じですが、許可されないパラメタが使われようとしているとスーパバイザが判断した場合には `IOError` が送出されます。

Python のランタイムシステムは、特定のコードブロックが制限実行モードかどうかを、グローバル変数の中の `__builtins__` オブジェクトの一意性をもとに判断します: オブジェクトが標準の `__builtin__` モジュール (の辞書) の場合、コードは非制限下にあるとみなされます。それ以外は制限下にあるとみなされます。

制限実行モードで動作する Python コードは、拘束セルから侵出しないように設計された数多くの制限に直面します。例えば、関数オブジェクト属性 `func_globals` や、クラスおよびインスタンスオブジェクトの属性 `__dict__` は利用できません。

二つのモジュールが、制限実行環境を立ち上げるためのフレームワークを提供しています:

- 30.1. `rexec` --- 制限実行のフレームワーク
  - 30.1.1. RExec オブジェクト
  - 30.1.2. 制限された環境を定義する
  - 30.1.3. 例
- 30.2. `Bastion` --- オブジェクトに対するアクセスの制限

参考

Grail Home Page
  Python で書かれたインターネットブラウザ Grail です。Python で書かれたアプレットをサポートするために、上記のモジュールを使っています。 Grail における Python 制限実行モードの利用に関する詳しい情報は、Web サイトで入手することができます。