[Python-checkins] r50487 - python/branches/bcannon-sandboxing/sandboxing_design_doc.txt

brett.cannon python-checkins at python.org
Sat Jul 8 00:43:27 CEST 2006


Author: brett.cannon
Date: Sat Jul  8 00:43:27 2006
New Revision: 50487

Modified:
   python/branches/bcannon-sandboxing/sandboxing_design_doc.txt
Log:
Rewrap to 72 columns.


Modified: python/branches/bcannon-sandboxing/sandboxing_design_doc.txt
==============================================================================
--- python/branches/bcannon-sandboxing/sandboxing_design_doc.txt	(original)
+++ python/branches/bcannon-sandboxing/sandboxing_design_doc.txt	Sat Jul  8 00:43:27 2006
@@ -4,12 +4,12 @@
 About This Document
 =============================
 
-This document is meant to lay out the general design for re-introducing a
-sandboxing model for Python.  This document should provide one with
+This document is meant to lay out the general design for re-introducing
+a sandboxing model for Python.  This document should provide one with
 enough information to understand the goals for sandboxing, what
-considerations were made for the design, and the actual design itself.  Design
-decisions should be clear and explain not only why they were chosen but
-possible drawbacks from taking a specific approach.
+considerations were made for the design, and the actual design itself.
+Design decisions should be clear and explain not only why they were
+chosen but possible drawbacks from taking a specific approach.
 
 If any of the above is found not to be true, please email me at
 brett at python.org and let me know what problems you are having with the
@@ -46,33 +46,35 @@
 Goal
 =============================
 
-A good sandboxing model provides enough protection to prevent
-malicious harm to come to the system, and no more.  Barriers should be
-minimized so as to allow most code that does not do anything that would be
-regarded as harmful to run unmodified.  But the protections need to be thorough
-enough to prevent any unintended changes or information of the system to come
-about.
-
-An important point to take into consideration when reading this document is to
-realize it is part of my (Brett Cannon's) Ph.D. dissertation.  This means it is
-heavily geared toward sandboxing when the interpreter is working
-with Python code embedded in a web page as viewed in Firefox.  While great strides have been taken
-to keep the design general enough so as to allow all previous uses of the
-'rexec' module [#rexec]_ to be able to use the new design, it is not the
-focused goal.  This means if a design decision must be made for the embedded
-use case compared to sandboxing Python code in a pure Python application, the former
-will win out over the latter.
-
-Throughout this document, the term "resource" is used to represent anything that
-deserves possible protection.  This includes things that have a physical
-representation (e.g., memory) to things that are more abstract and specific to
-the interpreter (e.g., sys.path).
-
-When referring to the state of an interpreter, it is either "unprotected" or
-"sandboxed".  A unprotected interpreter has no restrictions imposed upon any
-resource.  A sandboxed interpreter has at least one, possibly more, resource
-with restrictions placed upon it to prevent unsafe code  that is running
-within the interpreter to cause harm to the system.
+A good sandboxing model provides enough protection to prevent malicious
+harm to come to the system, and no more.  Barriers should be minimized
+so as to allow most code that does not do anything that would be
+regarded as harmful to run unmodified.  But the protections need to be
+thorough enough to prevent any unintended changes or information of the
+system to come about.
+
+An important point to take into consideration when reading this
+document is to realize it is part of my (Brett Cannon's) Ph.D.
+dissertation.  This means it is heavily geared toward sandboxing when
+the interpreter is working with Python code embedded in a web page as
+viewed in Firefox.  While great strides have been taken to keep the
+design general enough so as to allow all previous uses of the 'rexec'
+module [#rexec]_ to be able to use the new design, it is not the
+focused goal.  This means if a design decision must be made for the
+embedded use case compared to sandboxing Python code in a pure Python
+application, the former will win out over the latter.
+
+Throughout this document, the term "resource" is used to represent
+anything that deserves possible protection.  This includes things that
+have a physical representation (e.g., memory) to things that are more
+abstract and specific to the interpreter (e.g., sys.path).
+
+When referring to the state of an interpreter, it is either
+"unprotected" or "sandboxed".  A unprotected interpreter has no
+restrictions imposed upon any resource.  A sandboxed interpreter has at
+least one, possibly more, resource with restrictions placed upon it to
+prevent unsafe code  that is running within the interpreter to cause
+harm to the system.
 
 
 .. contents::
@@ -81,11 +83,12 @@
 Use Cases
 /////////////////////////////
 
-All use cases are based on how many sandboxed interpreters are
-running in a single process and whether an unprotected interpreter is also running.  The
-use cases can be broken down into two categories: when the interpreter is
-embedded and only using sandboxed interpreters, and when pure Python code is
-running in an unprotected interpreter and uses sandboxed interpreters.
+All use cases are based on how many sandboxed interpreters are running
+in a single process and whether an unprotected interpreter is also
+running.  The use cases can be broken down into two categories: when
+the interpreter is embedded and only using sandboxed interpreters, and
+when pure Python code is running in an unprotected interpreter and uses
+sandboxed interpreters.
 
 
 When the Interpreter Is Embedded
@@ -94,68 +97,68 @@
 Single Sandboxed Interpreter
 ----------------------------
 
-This use case is when an application embeds the interpreter and never has more
-than one interpreter running which happens to be sandboxed.
+This use case is when an application embeds the interpreter and never
+has more than one interpreter running which happens to be sandboxed.
 
 
 Multiple Sandboxed Interpreters
 -------------------------------
 
-When multiple interpreters, all sandboxed at varying levels, need to be running
-within a single application.  This is the key use case that this proposed
-design is targeted for.
+When multiple interpreters, all sandboxed at varying levels, need to be
+running within a single application.  This is the key use case that
+this proposed design is targeted for.
 
 
 Stand-Alone Python
 =============================
 
-When someone has written a Python program that wants to execute Python code in
-an sandboxed interpreter(s).  This is the use case that 'rexec' attempted to
-fulfill.
+When someone has written a Python program that wants to execute Python
+code in an sandboxed interpreter(s).  This is the use case that 'rexec'
+attempted to fulfill.
 
 
 Issues to Consider
 =============================
 
-Common to all use cases, resources that the interpreter requires to function at a level
-below user code cannot be exposed to a sandboxed
-interpreter.  For instance, the interpreter might need to stat a file to see if
-it is possible to import.  If the ability to stat a file is not allowed to a
-sandboxed interpreter, it should not be allowed to perform that action,
-regardless of whether the interpreter at a level below user code needs that
-ability.
-
-When multiple interpreters are involved (sandboxed or not), not allowing an interpreter
-to gain access to resources available in other interpreters without explicit
-permission must be enforced.
+Common to all use cases, resources that the interpreter requires to
+function at a level below user code cannot be exposed to a sandboxed
+interpreter.  For instance, the interpreter might need to stat a file
+to see if it is possible to import.  If the ability to stat a file is
+not allowed to a sandboxed interpreter, it should not be allowed to
+perform that action, regardless of whether the interpreter at a level
+below user code needs that ability.
+
+When multiple interpreters are involved (sandboxed or not), not
+allowing an interpreter to gain access to resources available in other
+interpreters without explicit permission must be enforced.
 
 
 Resources to Protect
 /////////////////////////////
 
-It is important to make sure that the proper resources are protected from a
-sandboxed interpreter.  If you don't there is no point to sandboxing.
+It is important to make sure that the proper resources are protected
+from a sandboxed interpreter.  If you don't there is no point to sandboxing.
 
 Filesystem
 ===================
 
 All facets of the filesystem must be protected.  This means restricting
-reading and writing to the filesystem (e.g., files, directories, etc.).  It
-should be allowed in controlled situations where allowing access to the
-filesystem is desirable, but that should be an explicit allowance.
-
-There must also be protection to prevent revealing any information about the
-filesystem.  Disclosing information on the filesystem could allow one to infer
-what OS the interpreter is running on, for instance.
+reading and writing to the filesystem (e.g., files, directories, etc.).
+It should be allowed in controlled situations where allowing access to
+the filesystem is desirable, but that should be an explicit allowance.
+
+There must also be protection to prevent revealing any information
+about the filesystem.  Disclosing information on the filesystem could
+allow one to infer what OS the interpreter is running on, for instance.
 
 
 Memory
 ===================
 
-Memory should be protected.  It is a limited resource on the system that can
-have an impact on other running programs if it is exhausted.  Being able to
-restrict the use of memory would help alleviate issues from denial-of-service
-(DoS) attacks on the system.
+Memory should be protected.  It is a limited resource on the system
+that can have an impact on other running programs if it is exhausted.
+Being able to restrict the use of memory would help alleviate issues
+from denial-of-service (DoS) attacks on the system.
 
 
 Networking
@@ -164,273 +167,291 @@
 Networking is somewhat like the filesystem in terms of wanting similar
 protections.  You do not want to let unsafe code make socket
 connections unhindered or accept them to do possibly nefarious things.
-You also want to prevent finding out information about the network you are
-connected to.
+You also want to prevent finding out information about the network your
+are connected to.
 
 
 Interpreter
 ===================
 
-One must make sure that the interpreter is not harmed in any way from sandboxed
-code.  This usually takes the form of crashing the program that the interpreter
-is embedded in or the unprotected interpreter that started the sandbox interpreter.
-Executing hostile bytecode that might lead to undesirable effects is another
-possible issue.
+One must make sure that the interpreter is not harmed in any way from
+sandboxed code.  This usually takes the form of crashing the program
+that the interpreter is embedded in or the unprotected interpreter that
+started the sandbox interpreter.  Executing hostile bytecode that might
+lead to undesirable effects is another possible issue.
 
-There is also the issue of taking it over.  One should not able to gain escalated
-privileges in any way without explicit permission.
+There is also the issue of taking it over.  One should not able to gain
+escalated privileges in any way without explicit permission.
 
 
 Types of Security
 ///////////////////////////////////////
 
-As with most things, there are multiple approaches one can take to tackle a
-problem.  Security is no exception.  In general there seem to be two approaches
-to protecting resources.
+As with most things, there are multiple approaches one can take to
+tackle a problem.  Security is no exception.  In general there seem to
+be two approaches to protecting resources.
 
 
 Resource Hiding
 =============================
 
-By never giving code a chance to access a resource, you prevent it from being
-(ab)used.  This is the idea behind resource hiding; you can't misuse something
-you don't have in the first place.
-
-The most common implementation of resource hiding is capabilities.  In this
-type of system a resource's reference acts as a ticket that represents the right
-to use the resource.  Once code has a reference it is considered to have full
-use of resource that reference represents and no further security checks are
-directly performed (using delegates and other structured ways one can actually
-have a security check for each access of a resource, but this is not a default
-behaviour).
-
-As an example, consider the 'file' type as a resource we want to protect.  That
-would mean that we did not want a reference to the 'file' type to ever be
-accessible without explicit permission.  If one wanted to provide read-only
-access to a temp file, you could have open() perform a check on the permissions
-of the current interpreter, and if it is allowed to, return a proxy object for
-the file that only allows reading from it.  The 'file' instance for the proxy
-would need to be properly hidden so that the reference was not reachable from
+By never giving code a chance to access a resource, you prevent it from
+being (ab)used.  This is the idea behind resource hiding; you can't
+misuse something you don't have in the first place.
+
+The most common implementation of resource hiding is capabilities.  In
+this type of system a resource's reference acts as a ticket that
+represents the right to use the resource.  Once code has a reference it
+is considered to have full use of resource that reference represents
+and no further security checks are directly performed (using delegates
+and other structured ways one can actually have a security check for
+each access of a resource, but this is not a default behaviour).
+
+As an example, consider the 'file' type as a resource we want to
+protect.  That would mean that we did not want a reference to the
+'file' type to ever be accessible without explicit permission.  If one
+wanted to provide read-only access to a temp file, you could have
+open() perform a check on the permissions of the current interpreter,
+and if it is allowed to, return a proxy object for the file that only
+allows reading from it.  The 'file' instance for the proxy would need
+to be properly hidden so that the reference was not reachable from
 outside so that 'file' access could still be controlled.
 
-Python, as it stands now, unfortunately does not work well for a pure capabilities system.
-Capabilities require the prohibition of certain abilities, such as
-"direct access to another's private state" [#paradigm regained]_.  This
-obviously is not possible in Python since, at least at the Python level, there
-is no such thing as private state that is persistent (one could argue that
-local variables that are not cell variables for lexical scopes are private, but
-since they do not survive after a function call they are not usable for keeping
-persistent state).  One can hide references at the C level by storing it in the
-struct for the instance of a type and not providing a function to access that
-attribute.
+Python, as it stands now, unfortunately does not work well for a pure
+capabilities system.  Capabilities require the prohibition of certain
+abilities, such as "direct access to another's private state"
+[#paradigm regained]_.  This obviously is not possible in Python since,
+at least at the Python level, there is no such thing as private state
+that is persistent (one could argue that local variables that are not
+cell variables for lexical scopes are private, but since they do not
+survive after a function call they are not usable for keeping
+persistent state).  One can hide references at the C level by storing
+it in the struct for the instance of a type and not providing a
+function to access that attribute.
 
 Python's introspection abilities also do not help make implementing
-capabilities that much easier.  Consider how one could access 'file' even when it is deleted from
-__builtin__.  You can still get to the reference for 'file' through the sequence returned by
+capabilities that much easier.  Consider how one could access 'file'
+even when it is deleted from __builtin__.  You can still get to the
+reference for 'file' through the sequence returned by
 ``object.__subclasses__()``.
 
 
 Resource Crippling
 =============================
 
-Another approach to security is to not worry about controlling access to the
-reference of a resource.
-One can have a resource perform a
-security check every time someone tries to use a method on that resource.  This
-pushes the security check to a lower level; from a reference level to the
-method level.
-
-By performing the security check every time a resource's method is called the
-worry of a specific resource's reference leaking out to insecure code is alleviated.  This does add extra overhead, though,
-by having to do so many security checks.  It also does not handle the situation
-where an unexpected exposure of a type occurs that has not been properly
-crippled.
-
-FreeBSD's jail system provides a protection scheme similar to this.  Various system calls
-allow for basic usage, but knowing or having access to the system call is not enough to grant
-usage.  Every call to a system call requires checking that the proper rights
-have been granted to the use in order to allow for the system call to perform
+Another approach to security is to not worry about controlling access
+to the reference of a resource.  One can have a resource perform a
+security check every time someone tries to use a method on that
+resource.  This pushes the security check to a lower level; from a
+reference level to the method level.
+
+By performing the security check every time a resource's method is
+called the worry of a specific resource's reference leaking out to
+insecure code is alleviated.  This does add extra overhead, though, by
+having to do so many security checks.  It also does not handle the
+situation where an unexpected exposure of a type occurs that has not
+been properly crippled.
+
+FreeBSD's jail system provides a protection scheme similar to this.
+Various system calls allow for basic usage, but knowing or having
+access to the system call is not enough to grant usage.  Every call to
+a system call requires checking that the proper rights have been
+granted to the use in order to allow for the system call to perform
 its action.
 
-An even better example in FreeBSD's jail system is its protection of sockets.
-One can only bind a single IP address to a jail.  Any attempt to do more or
-perform uses with the one IP address that is granted is prevented.  The check
-is performed at every call involving the one granted IP address.
+An even better example in FreeBSD's jail system is its protection of
+sockets.  One can only bind a single IP address to a jail.  Any attempt
+to do more or perform uses with the one IP address that is granted is
+prevented.  The check is performed at every call involving the one
+granted IP address.
 
 Using 'file' as the example again, one could cripple the type so that
 instantiation is not possible for the type in Python.  One could also
-provide a permission check on each call to a unsafe method call and thus allow
-the type to be used in normal situations (such as type checking), but still
-feel safe that illegal operations are not performed.
-Regardless of which approach you take, you do not need
-to worry about a reference to the type being exposed unexpectedly since the
-reference is not the security check but the actual method calls.
+provide a permission check on each call to a unsafe method call and
+thus allow the type to be used in normal situations (such as type
+checking), but still feel safe that illegal operations are not
+performed.  Regardless of which approach you take, you do not need to
+worry about a reference to the type being exposed unexpectedly since
+the reference is not the security check but the actual method calls.
 
 
 Comparison of the Two Approaches
 ================================
 
-From the perspective of Python, the two approaches differ on what would be the
-most difficult thing to analyze from a security standpoint: all of the ways to
-gain access to various types from a sandboxed interpreter with no imports, or
-finding all of the types that can lead to possibly dangerous actions and thus
-need to be crippled.
-
-Some Python developers, such as Armin Rigo, feel that truly hiding objects in
-Python is "quite hard" [#armin-hiding]_.  This sentiment means that making a
-pure capabilities system in Python that is secure is not possible as people
-would continue to find new ways to get a hold of the reference to a protected
-resource.
-
-Others feel that by not going the capabilities route we will be constantly
-chasing down new types that require crippling.  The thinking is that if we
-cannot control the references for 'file', how are we to know what other types
-might become exposed later on and thus require more crippling?
-
-It essentially comes down to what is harder to do: find all the ways to access
-the types in Python in a sandboxed interpreter with no imported modules, or to
-go through the Python code base and find all types that should be crippled?
+From the perspective of Python, the two approaches differ on what would
+be the most difficult thing to analyze from a security standpoint: all
+of the ways to gain access to various types from a sandboxed
+interpreter with no imports, or finding all of the types that can lead
+to possibly dangerous actions and thus need to be crippled.
+
+Some Python developers, such as Armin Rigo, feel that truly hiding
+objects in Python is "quite hard" [#armin-hiding]_.  This sentiment
+means that making a pure capabilities system in Python that is secure
+is not possible as people would continue to find new ways to get a hold
+of the reference to a protected resource.
+
+Others feel that by not going the capabilities route we will be
+constantly chasing down new types that require crippling.  The thinking
+is that if we cannot control the references for 'file', how are we to
+know what other types might become exposed later on and thus require
+more crippling?
+
+It essentially comes down to what is harder to do: find all the ways to
+access the types in Python in a sandboxed interpreter with no imported
+modules, or to go through the Python code base and find all types that
+should be crippled?
 
 
 The 'rexec' Module
 ///////////////////////////////////////
 
-The 'rexec' module [#rexec]_ was the original attempt at providing a sandbox
-environment for Python code to run in.  It's design was based on Safe-Tcl which
-was essentially a capabilities system
-[#safe-tcl]_.  Safe-Tcl
-allowed you to launch a separate interpreter where its global functions were
-specified at creation time.  This prevented one from having any abilities that
-were not explicitly provided.
-
-For 'rexec', the Safe-Tcl model was tweaked to better match Python's situation.
-An RExec object represented a sandboxed environment.  Imports were checked
-against a whitelist of modules.  You could also restrict the type of modules to
-import based on whether they were Python source, bytecode, or C extensions.
-Built-ins were allowed except for a blacklist of built-ins to not provide.
-One could restrict whether stdin,
-stdout, and stderr were provided or not on a per-RExec basis.
-Several other protections were provided; see documentation for the complete
-list.
-
-The ultimate undoing of the 'rexec' module was how access to objects that in
-normal Python require no imports to reach was handled.  Importing modules
-requires a direct action, and thus can be protected against directly in the
-import machinery.  But for built-ins, they are accessible by default and
-require no direct action to access in normal Python; you just use their name
-since they are provided in all namespaces.
+The 'rexec' module [#rexec]_ was the original attempt at providing a
+sandbox environment for Python code to run in.  It's design was based
+on Safe-Tcl which was essentially a capabilities system [#safe-tcl]_.
+Safe-Tcl allowed you to launch a separate interpreter where its global
+functions were specified at creation time.  This prevented one from
+having any abilities that were not explicitly provided.
+
+For 'rexec', the Safe-Tcl model was tweaked to better match Python's
+situation.  An RExec object represented a sandboxed environment.
+Imports were checked against a whitelist of modules.  You could also
+restrict the type of modules to import based on whether they were
+Python source, bytecode, or C extensions.  Built-ins were allowed
+except for a blacklist of built-ins to not provide.  One could restrict
+whether stdin, stdout, and stderr were provided or not on a per-RExec
+basis.  Several other protections were provided; see documentation for
+the complete list.
+
+The ultimate undoing of the 'rexec' module was how access to objects
+that in normal Python require no imports to reach was handled.
+Importing modules requires a direct action, and thus can be protected
+against directly in the import machinery.  But for built-ins, they are
+accessible by default and require no direct action to access in normal
+Python; you just use their name since they are provided in all
+namespaces.
 
 For instance, in a sandboxed interpreter, one only had to 
-``del __builtins__`` to gain access to the full set of built-ins.  Another way
-is through using the gc module:
-``gc.get_referrers(''.__class__.__bases__[0])[6]['file']``.  While both of
-these could be fixed (the former was a bug in 'rexec' that was fixed and the
-latter could be handled by not allowing
-'gc' to be imported), they are examples of things that do not require proactive
-actions on the part of the programmer in normal Python to gain access to a
-resource.  This was an unfortunate side-effect of having all of that wonderful
-reflection in Python.
-
-There is also the issue that 'rexec' was written in Python which provides its
-own problems based on reflection and the ability to modify the code at
-run-time without security protection.
-
-Much has been learned since 'rexec' was written about how Python tends to be
-used and where security issues tend to appear.  Essentially Python's dynamic
-nature does not lend itself very well to a security implementation that does
-not require a constant checking of permissions.
+``del __builtins__`` to gain access to the full set of built-ins.
+Another way is through using the gc module:
+``gc.get_referrers(''.__class__.__bases__[0])[6]['file']``.  While both
+of these could be fixed (the former was a bug in 'rexec' that was fixed
+and the latter could be handled by not allowing 'gc' to be imported),
+they are examples of things that do not require proactive actions on
+the part of the programmer in normal Python to gain access to a
+resource.  This was an unfortunate side-effect of having all of that
+wonderful reflection in Python.
+
+There is also the issue that 'rexec' was written in Python which
+provides its own problems based on reflection and the ability to modify
+the code at run-time without security protection.
+
+Much has been learned since 'rexec' was written about how Python tends
+to be used and where security issues tend to appear.  Essentially
+Python's dynamic nature does not lend itself very well to a security
+implementation that does not require a constant checking of
+permissions.
 
 
 Threat Model
 ///////////////////////////////////////
 
-Below is a list of what the security implementation assumes, along with what section of this document that addresses
-that part of the security model (if not already true in Python by default).
-The term "bare" when in regards to
-an interpreter means an interpreter that has not performed a single import
-of a module.  Also, all comments refer to a sandboxed interpreter unless
-otherwise explicitly stated.
-
-This list does not address specifics such as how 'file' will be protected or
-whether memory should be protected.  This list is meant to make clear at a more
-basic level what the security model is assuming is true.
+Below is a list of what the security implementation assumes, along with
+what section of this document that addresses that part of the security
+model (if not already true in Python by default).  The term "bare" when
+in regards to an interpreter means an interpreter that has not
+performed a single import of a module.  Also, all comments refer to a
+sandboxed interpreter unless otherwise explicitly stated.
+
+This list does not address specifics such as how 'file' will be
+protected or whether memory should be protected.  This list is meant to
+make clear at a more basic level what the security model is assuming is
+true.
 
 * The Python interpreter itself is always trusted.
-* The Python interpreter cannot be crashed by valid Python source code in a
-  bare interpreter.
+* The Python interpreter cannot be crashed by valid Python source code
+  in a bare interpreter.
 * Python source code is always considered safe.
 * Python bytecode is always considered dangerous [`Hostile Bytecode`_].
 * C extension modules are inherently considered dangerous
   [`Extension Module Importation`_].
     + Explicit trust of a C extension module is possible.
-* Sandboxed interpreters running in the same process inherently cannot communicate with
-  each other.
-    + Communication through C extension modules is possible because of the
-      technical need to share extension module instances between interpreters.
-* Sandboxed interpreters running in the same process inherently cannot share
-  objects.
-    + Sharing objects through C extension modules is possible because of the
-      technical need to share extension module instances between interpreters.
-* When starting a sandboxed interpreter, it starts with a fresh built-in and
-  global namespace that is not shared with the interpreter that started it.
+* Sandboxed interpreters running in the same process inherently cannot
+  communicate with each other.
+    + Communication through C extension modules is possible because of
+      the technical need to share extension module instances between
+      interpreters.
+* Sandboxed interpreters running in the same process inherently cannot
+  share objects.
+    + Sharing objects through C extension modules is possible because
+      of the technical need to share extension module instances between
+      interpreters.
+* When starting a sandboxed interpreter, it starts with a fresh
+  built-in and global namespace that is not shared with the interpreter
+  that started it.
 * Objects in the default built-in namespace should be safe to use
   [`Reading/Writing Files`_, `Stdin, Stdout, and Stderr`_].
-    + Either hide the dangerous ones or cripple them so they can cause no harm.
+    + Either hide the dangerous ones or cripple them so they can cause
+      no harm.
 
 There are also some features that might be desirable, but are not being
 addressed by this security model.
 
-* Communication in any direction between an unprotected interpreter and a sandboxed interpreter
-  it created.
+* Communication in any direction between an unprotected interpreter and
+  a sandboxed interpreter it created.
 
 
 The Proposed Approach
 ///////////////////////////////////////
 
-In light of where 'rexec' succeeded and failed along with what is known about
-the two main approaches to security and how Python tends to operate, the following
-is a proposal on how to secure Python for sandboxing.
+In light of where 'rexec' succeeded and failed along with what is known
+about the two main approaches to security and how Python tends to
+operate, the following is a proposal on how to secure Python for
+sandboxing.
 
 
 Implementation Details
 ===============================
 
-Support for sandboxed interpreters will require a compilation flag.  This allows the
-more common case of people not caring about protections to not take a
-performance hit.  And even when Python is compiled for
+Support for sandboxed interpreters will require a compilation flag.
+This allows the more common case of people not caring about protections
+to not take a performance hit.  And even when Python is compiled for
 sandboxed interpreter restrictions, when the running interpreter *is*
-unprotected,
-there will be no accidental triggers of protections.  This means that
-developers should be liberal with the security protections without worrying
-about there being issues for interpreters that do not need/want the protection.
-
-At the Python level, the __sandboxed__ built-in will be set based on whether
-the interpreter is sandboxed or not.  This will be set for *all* interpreters,
-regardless of whether sandboxed interpreter support was compiled in or not.
+unprotected, there will be no accidental triggers of protections.  This
+means that developers should be liberal with the security protections
+without worrying about there being issues for interpreters that do not
+need/want the protection.
+
+At the Python level, the __sandboxed__ built-in will be set based on
+whether the interpreter is sandboxed or not.  This will be set for
+*all* interpreters, regardless of whether sandboxed interpreter support
+was compiled in or not.
 
 For setting what is to be protected, the PyThreadState for the
-sandboxed interpreter must be passed in.  This makes the protection very
-explicit and helps make sure you set protections for the exact interpreter you
-mean to.  All functions that set protections begin with the prefix
-``PySandbox_Set*()``.  These functions are meant to only work with sandboxed interpreters
-that have not been used yet to execute any Python code.  The calls must be made
-by the code creating and handling the sandboxed interpreter *before* the
-sandboxed interpreter is used to execute any Python code.
-
-The functions for checking for permissions are actually macros that take
-in at least an error return value for the function calling the macro.  This
-allows the macro to return on behalf of the caller if the check fails and cause the
-SandboxError
-exception to be propagated automatically.  This helps eliminate any coding errors from
-incorrectly checking a return value on a rights-checking function call.  For
-the rare case where this functionality is disliked, just make the check in a
-utility function and check that function's return value (but this is strongly
-discouraged!).
-
-Functions that check that an operation is allowed implicitly operate on the currently running interpreter as
-returned by ``PyInterpreter_Get()`` and are to be used by any code (the
-interpreter, extension modules, etc.) that needs to check for permission to
-execute.  They have the common prefix of ``PySandbox_Allowed*()``.
+sandboxed interpreter must be passed in.  This makes the protection
+very explicit and helps make sure you set protections for the exact
+interpreter you mean to.  All functions that set protections begin with
+the prefix ``PySandbox_Set*()``.  These functions are meant to only
+work with sandboxed interpreters that have not been used yet to execute
+any Python code.  The calls must be made by the code creating and
+handling the sandboxed interpreter *before* the sandboxed interpreter
+is used to execute any Python code.
+
+The functions for checking for permissions are actually macros that
+take in at least an error return value for the function calling the
+macro.  This allows the macro to return on behalf of the caller if the
+check fails and cause the SandboxError exception to be propagated
+automatically.  This helps eliminate any coding errors from incorrectly
+checking a return value on a rights-checking function call.  For the
+rare case where this functionality is disliked, just make the check in
+a utility function and check that function's return value (but this is
+strongly discouraged!).
+
+Functions that check that an operation is allowed implicitly operate on
+the currently running interpreter as returned by
+``PyInterpreter_Get()`` and are to be used by any code (the
+interpreter, extension modules, etc.) that needs to check for
+permission to execute.  They have the common prefix of 
+`PySandbox_Allowed*()``.
 
 
 API
@@ -438,12 +459,13 @@
 
 * PyThreadState* PySandbox_NewInterpreter()
     Return a new interpreter that is considered sandboxed.  There is no
-    corresponding ``PySandbox_EndInterpreter()`` as ``Py_EndInterpreter()`` will be taught
-    how to handle sandboxed interpreters.  ``NULL`` is returned on error.
+    corresponding ``PySandbox_EndInterpreter()`` as
+    ``Py_EndInterpreter()`` will be taught how to handle sandboxed
+    interpreters.  ``NULL`` is returned on error.
 
 * PySandbox_Allowed(error_return)
-    Macro that has the caller return with 'error_return' if the interpreter is
-    unprotected, otherwise do nothing.
+    Macro that has the caller return with 'error_return' if the
+    interpreter is unprotected, otherwise do nothing.
 
 
 Memory
@@ -455,18 +477,19 @@
 A memory cap will be allowed.
 
 Modification to pymalloc will be needed to properly keep track of the
-allocation and freeing of memory.  Same goes for the macros around the system
-malloc/free system calls.  This provides a platform-independent system for
-protection of memory instead of relying on the operating system to provide a service for
-capping memory usage of a process.  It also allows the protection to be at the
-interpreter level instead of at the process level.
+allocation and freeing of memory.  Same goes for the macros around the
+system malloc/free system calls.  This provides a platform-independent
+system for protection of memory instead of relying on the operating
+system to provide a service for capping memory usage of a process.  It
+also allows the protection to be at the interpreter level instead of at
+the process level.
 
 
 Why
 --------------
 
-Protecting excessive memory usage allows one to make sure that a DoS attack
-against the system's memory is prevented.
+Protecting excessive memory usage allows one to make sure that a DoS
+attack against the system's memory is prevented.
 
 
 Possible Security Flaws
@@ -474,28 +497,32 @@
 
 If code makes direct calls to malloc/free instead of using the proper
 ``PyMem_*()``
-macros then the security check will be circumvented.  But C code is *supposed*
-to use the proper macros or pymalloc and thus this issue is not with the
-security model but with code not following Python coding standards.
+macros then the security check will be circumvented.  But C code is
+*supposed* to use the proper macros or pymalloc and thus this issue is
+not with the security model but with code not following Python coding
+standards.
 
 
 API
 --------------
 
 * int PySandbox_SetMemoryCap(PyThreadState *, integer)
-    Set the memory cap for an sandboxed interpreter.  If the interpreter is not
-    running an sandboxed interpreter, return a false value.
+    Set the memory cap for an sandboxed interpreter.  If the
+    interpreter is not running an sandboxed interpreter, return a false
+    value.
 
 * PySandbox_AllowedMemoryAlloc(integer, error_return)
-    Macro to increase the amount of memory that is reported that the running
-    sandboxed interpreter is using.  If the increase puts the total count
-    passed the set limit, raise an SandboxError exception and cause the calling function
-    to return with the value of 'error_return', otherwise do nothing.
+    Macro to increase the amount of memory that is reported that the
+    running sandboxed interpreter is using.  If the increase puts the
+    total count passed the set limit, raise an SandboxError exception
+    and cause the calling function to return with the value of
+    'error_return', otherwise do nothing.
 
 * PySandbox_AllowedMemoryFree(integer, error_return)
-    Macro to decrease the current running interpreter's allocated memory.  If this puts
-    the memory used to below 0, raise a SandboxError exception and return
-    'error_return', otherwise do nothing.
+    Macro to decrease the current running interpreter's allocated
+    memory.  If this puts the memory used to below 0, raise a
+    SandboxError exception and return 'error_return', otherwise do
+    nothing.
 
 
 Reading/Writing Files
@@ -506,33 +533,35 @@
 
 XXX
 
-To open a file, one will have to use open().  This will make open() a factory
-function that controls reference access to the 'file' type in terms of creating
-new instances.  When an attempted file opening fails (either because the path
-does not exist or of security reasons), SandboxError will be
-raised.  The same exception must be raised to prevent filesystem information
-being gleaned from the type of exception returned (i.e., returning IOError if a
-path does not exist tells the user something about that file path).
-
-What open() returns may not be an instance of 'file' but a proxy
-that provides the security measures needed.  While this might break code that
-uses type checking to make sure a 'file' object is used, taking a duck typing
-approach would be better.  This is not only more Pythonic but would also allow
-the code to use a StringIO instance.
-
-It has been suggested to allow for a passed-in callback to be called when a
-specific path is to be opened.  While this provides good flexibility in terms
-of allowing custom proxies with more fine-grained security (e.g., capping the
-amount of disk write), this has been deemed unneeded in the initial security
-model and thus is not being considered at this time.
-
+To open a file, one will have to use open().  This will make open() a
+factory function that controls reference access to the 'file' type in
+terms of creating new instances.  When an attempted file opening fails
+(either because the path does not exist or of security reasons),
+SandboxError will be raised.  The same exception must be raised to
+prevent filesystem information being gleaned from the type of exception
+returned (i.e., returning IOError if a path does not exist tells the
+user something about that file path).
+
+What open() returns may not be an instance of 'file' but a proxy that
+provides the security measures needed.  While this might break code
+that uses type checking to make sure a 'file' object is used, taking a
+duck typing approach would be better.  This is not only more Pythonic
+but would also allow the code to use a StringIO instance.
+
+It has been suggested to allow for a passed-in callback to be called
+when a specific path is to be opened.  While this provides good
+flexibility in terms of allowing custom proxies with more fine-grained
+security (e.g., capping the amount of disk write), this has been deemed
+unneeded in the initial security model and thus is not being considered
+at this time.  
 
 Why
 --------------
 
-Allowing anyone to be able to arbitrarily read, write, or learn about the
-layout of your filesystem is extremely dangerous.  It can lead to loss of data
-or data being exposed to people whom should not have access.
+Allowing anyone to be able to arbitrarily read, write, or learn about
+the layout of your filesystem is extremely dangerous.  It can lead to
+loss of data or data being exposed to people whom should not have
+access.
 
 
 Possible Security Flaws
@@ -544,15 +573,16 @@
 API
 --------------
 
-* int PySandbox_SetAllowedFile(PyThreadState *, string path, string mode)
-    Add a file that is allowed to be opened in 'mode' by the 'file' object.  If
-    the interpreter is not sandboxed then return a false value.
+* int PySandbox_SetAllowedFile(PyThreadState *, string path,
+                                string mode)
+    Add a file that is allowed to be opened in 'mode' by the 'file'
+    object.  If the interpreter is not sandboxed then return a false
+    value.
 
 * PySandbox_AllowedPath(string path, string mode, error_return)
-    Macro that causes the caller to return with 'error_return' and raise
-    SandboxError as the
-    exception if the specified path with 'mode' is not allowed, otherwise do
-    nothing.
+    Macro that causes the caller to return with 'error_return' and
+    raise SandboxError as the exception if the specified path with
+    'mode' is not allowed, otherwise do nothing.
 
 
 Extension Module Importation
@@ -561,33 +591,34 @@
 Protection
 --------------
 
-A whitelist of extension modules that may be imported must be provided.  A
-default set is given for stdlib modules known to be safe.
+A whitelist of extension modules that may be imported must be provided.
+A default set is given for stdlib modules known to be safe.
 
-A check in the import machinery will check that a specified module name is
-allowed based on the type of module (Python source, Python bytecode, or
-extension module).  Python bytecode files are never directly imported because
-of the possibility of hostile bytecode being present.  Python source is always
-considered safe based on the assumption that all resource harm is eventually done at
-the C level, thus Python source code directly cannot cause harm without help of
-C extension modules.  Thus only C
-extension modules need to be checked against the whitelist.
-
-The requested extension module name is checked in order to make sure that it
-is on the whitelist if it is a C extension module.  If the name is not correct
-a SandboxError exception is raised.  Otherwise the import is allowed.
+A check in the import machinery will check that a specified module name
+is allowed based on the type of module (Python source, Python bytecode,
+or extension module).  Python bytecode files are never directly
+imported because of the possibility of hostile bytecode being present.
+Python source is always considered safe based on the assumption that
+all resource harm is eventually done at the C level, thus Python source
+code directly cannot cause harm without help of C extension modules.
+Thus only C extension modules need to be checked against the whitelist.
+
+The requested extension module name is checked in order to make sure
+that it is on the whitelist if it is a C extension module.  If the name
+is not correct a SandboxError exception is raised.  Otherwise the
+import is allowed.  
 
 Even if a Python source code module imports a C extension module in an
-unprotected
-interpreter it is not a problem since the Python source code module is reloaded
-in the sandboxed interpreter.  When that Python source module is freshly
-imported the normal import check will be triggered to prevent the C extension
-module from becoming available to the sandboxed interpreter.
-
-For the 'os' module, a special sandboxed version will be used if the proper
-C extension module providing the correct abilities is not allowed.  This will
-default to '/' as the path separator and provide as much reasonable abilities
-as possible from a pure Python module.
+unprotected interpreter it is not a problem since the Python source
+code module is reloaded in the sandboxed interpreter.  When that Python
+source module is freshly imported the normal import check will be
+triggered to prevent the C extension module from becoming available to
+the sandboxed interpreter.
+
+For the 'os' module, a special sandboxed version will be used if the
+proper C extension module providing the correct abilities is not
+allowed.  This will default to '/' as the path separator and provide as
+much reasonable abilities as possible from a pure Python module.
 
 The 'sys' module is specially addressed in
 `Changing the Behaviour of the Interpreter`_.
@@ -600,47 +631,50 @@
 Why
 --------------
 
-Because C code is considered unsafe, its use should be regulated.  By using a
-whitelist it allows one to explicitly decide that a C extension module is considered safe.
+Because C code is considered unsafe, its use should be regulated.  By
+using a whitelist it allows one to explicitly decide that a C extension
+module is considered safe.  
 
 
 Possible Security Flaws
 -----------------------
 
-If a whitelisted C extension module imports a non-whitelisted C extension module and
-makes it an attribute of the whitelisted module there will be a breach in security.
-Luckily this a rarity in extension modules.
+If a whitelisted C extension module imports a non-whitelisted C
+extension module and makes it an attribute of the whitelisted module
+there will be a breach in security.  Luckily this a rarity in
+extension modules.  
 
 There is also the issue of a C extension module calling the C API of a
 non-whitelisted C extension module.
 
-Lastly, if a whitelisted C extension module is loaded in an unprotected interpreter and
-then loaded into a sandboxed interpreter then there is no checks
-during module initialization for possible security issues in the sandboxed
-interpreter that would have occurred had the sandboxed interpreter done the
-initial import.
-
-All of these issues can be handled by never blindly whitelisting a C extension
-module.  Added support for dealing with C extension modules comes in the form
-of `Extension Module Crippling`_.  
+Lastly, if a whitelisted C extension module is loaded in an unprotected
+interpreter and then loaded into a sandboxed interpreter then there is
+no checks during module initialization for possible security issues in
+the sandboxed interpreter that would have occurred had the sandboxed
+interpreter done the initial import.
+
+All of these issues can be handled by never blindly whitelisting a C
+extension module.  Added support for dealing with C extension modules
+comes in the form of `Extension Module Crippling`_.  
+
 
 API
 --------------
 
 * int PySandbox_SetModule(PyThreadState *, string module_name)
     Allow the sandboxed interpreter to import 'module_name'.  If the
-    interpreter is not sandboxed, return a false value.  Absolute import paths must be
-    specified.
+    interpreter is not sandboxed, return a false value.  Absolute
+    import paths must be specified.
 
 * int PySandbox_BlockModule(PyThreadState *, string module_name)
-    Remove the specified module from the whitelist.  Used to remove modules
-    that are allowed by default.  Return a false value if called on an
-    unprotected interpreter.
+    Remove the specified module from the whitelist.  Used to remove
+    modules that are allowed by default.  Return a false value if
+    called on an unprotected interpreter.
 
 * PySandbox_AllowedModule(string module_name, error_return)
-    Macro that causes the caller to return with 'error_return' and sets the
-    exception SandboxError if the specified module cannot be imported,
-    otherwise does nothing.
+    Macro that causes the caller to return with 'error_return' and sets
+    the exception SandboxError if the specified module cannot be
+    imported, otherwise does nothing.
 
 
 Extension Module Crippling
@@ -649,29 +683,29 @@
 Protection
 --------------
 
-By providing a C API for checking for allowed abilities, modules that have some
-useful functionality can do proper security checks for those functions that
-could provide insecure abilities while allowing safe code to be used (and thus
-not fully deny importation).
+By providing a C API for checking for allowed abilities, modules that
+have some useful functionality can do proper security checks for those
+functions that could provide insecure abilities while allowing safe
+code to be used (and thus not fully deny importation).
 
 
 Why
 --------------
 
-Consider a module that provides a string processing ability.  If that module
-provides a single convenience function that reads its input string from a file
-(with a specified path), the whole module should not be blocked from being
-used, just that convenience function.  By whitelisting the module but having a
-security check on the one problem function, the user can still gain access to
-the safe functions.  Even better, the unsafe function can be allowed if the
-security checks pass.
+Consider a module that provides a string processing ability.  If that
+module provides a single convenience function that reads its input
+string from a file (with a specified path), the whole module should not
+be blocked from being used, just that convenience function.  By
+whitelisting the module but having a security check on the one problem
+function, the user can still gain access to the safe functions.  Even
+better, the unsafe function can be allowed if the security checks pass.
 
 
 Possible Security Flaws
 -----------------------
 
-If a C extension module developer incorrectly implements the security checks
-for the unsafe functions it could lead to undesired abilities.
+If a C extension module developer incorrectly implements the security
+checks for the unsafe functions it could lead to undesired abilities.
 
 
 API
@@ -692,9 +726,10 @@
 Why
 --------------
 
-Without implementing a bytecode verification tool, there is no way of making
-sure that bytecode does not jump outside its bounds, thus possibly executing
-malicious code.  It also presents the possibility of crashing the interpreter.
+Without implementing a bytecode verification tool, there is no way of
+making sure that bytecode does not jump outside its bounds, thus
+possibly executing malicious code.  It also presents the possibility of
+crashing the interpreter.
 
 
 Possible Security Flaws
@@ -746,15 +781,15 @@
 --------------
 
 Filesystem information must be removed.  Any settings that could
-possibly lead to a DoS attack (e.g., sys.setrecursionlimit()) or risk crashing
-the interpreter must also be removed.
+possibly lead to a DoS attack (e.g., sys.setrecursionlimit()) or risk
+crashing the interpreter must also be removed.
 
 
 Possible Security Flaws
 -----------------------
 
-Exposing something that could lead to future security problems (e.g., a way to
-crash the interpreter).
+Exposing something that could lead to future security problems (e.g., a
+way to crash the interpreter).
 
 
 API
@@ -769,15 +804,15 @@
 Protection
 --------------
 
-Allow sending and receiving data to/from specific IP addresses on specific
-ports.
+Allow sending and receiving data to/from specific IP addresses on
+specific ports.
 
-open() is to be used as a factory function to open a network connection.  If
-the connection is not possible (either because of an invalid address or
-security reasons), SandboxError is raised.
+open() is to be used as a factory function to open a network
+connection.  If the connection is not possible (either because of an
+invalid address or security reasons), SandboxError is raised.
 
-A socket object may not be returned by the call.  A proxy to handle security
-might be returned instead.
+A socket object may not be returned by the call.  A proxy to handle
+security might be returned instead.
 
 XXX
 
@@ -785,41 +820,43 @@
 Why
 --------------
 
-Allowing arbitrary sending of data over sockets can lead to DoS attacks on the
-network and other machines.  Limiting accepting data prevents your machine from
-being attacked by accepting malicious network connections.  It also allows you
-to know exactly where communication is going to and coming from.
+Allowing arbitrary sending of data over sockets can lead to DoS attacks
+on the network and other machines.  Limiting accepting data prevents
+your machine from being attacked by accepting malicious network
+connections.  It also allows you to know exactly where communication is
+going to and coming from.
 
 
 Possible Security Flaws
 -----------------------
 
-If someone managed to influence the used DNS server to influence what IP
-addresses were used after a DNS lookup.
+If someone managed to influence the used DNS server to influence what
+IP addresses were used after a DNS lookup.
 
 
 API
 --------------
 
 * int PySandbox_SetIPAddress(PyThreadState *, string IP, integer port)
-    Allow the sandboxed interpreter to send/receive to the specified 'IP'
-    address on the specified 'port'.  If the interpreter is not sandboxed,
-    return a false value.
+    Allow the sandboxed interpreter to send/receive to the specified
+    'IP' address on the specified 'port'.  If the interpreter is not
+    sandboxed, return a false value.
 
 * PySandbox_AllowedIPAddress(string IP, integer port, error_return)
-    Macro to verify that the specified 'IP' address on the specified 'port' is
-    allowed to be communicated with.  If not, cause the caller to return with
-    'error_return' and SandboxError exception set, otherwise do nothing.
+    Macro to verify that the specified 'IP' address on the specified
+    'port' is allowed to be communicated with.  If not, cause the
+    caller to return with 'error_return' and SandboxError exception
+    set, otherwise do nothing.
 
 * int PySandbox_SetHost(PyThreadState *, string host, integer port)
-    Allow the sandboxed interpreter to send/receive to the specified 'host' on
-    the specified 'port'.  If the interpreter is not sandboxed, return a false
-    value.
+    Allow the sandboxed interpreter to send/receive to the specified
+    'host' on the specified 'port'.  If the interpreter is not
+    sandboxed, return a false value.
 
 * PySandbox_AllowedHost(string host, integer port, error_return)
-    Check that the specified 'host' on the specified 'port' is allowed to be
-    communicated with.  If not, set a SandboxError exception and cause the caller to
-    return 'error_return', otherwise do nothing.
+    Check that the specified 'host' on the specified 'port' is allowed
+    to be communicated with.  If not, set a SandboxError exception and
+    cause the caller to return 'error_return', otherwise do nothing.
 
 
 Network Information
@@ -828,10 +865,10 @@
 Protection
 --------------
 
-Limit what information can be gleaned about the network the system is running
-on.  This does not include restricting information on IP addresses and hosts
-that are have been explicitly allowed for the sandboxed interpreter to
-communicate with.
+Limit what information can be gleaned about the network the system is
+running on.  This does not include restricting information on IP
+addresses and hosts that are have been explicitly allowed for the
+sandboxed interpreter to communicate with.
 
 XXX
 
@@ -839,31 +876,31 @@
 Why
 --------------
 
-With enough information from the network several things could occur.  One is
-that someone could possibly figure out where your machine is on the Internet.
-Another is that enough information about the network you are connected to could
-be used against it in an attack.
+With enough information from the network several things could occur.
+One is that someone could possibly figure out where your machine is on
+the Internet.  Another is that enough information about the network you
+are connected to could be used against it in an attack.
 
 
 Possible Security Flaws
 -----------------------
 
-As long as usage is restricted to only what is needed to work with allowed
-addresses, there are no security issues to speak of.
+As long as usage is restricted to only what is needed to work with
+allowed addresses, there are no security issues to speak of.
 
 
 API
 --------------
 
 * int PySandbox_SetNetworkInfo(PyThreadState *)
-    Allow the sandboxed interpreter to get network information regardless of
-    whether the IP or host address is explicitly allowed.  If the interpreter
-    is not sandboxed, return a false value.
+    Allow the sandboxed interpreter to get network information
+    regardless of whether the IP or host address is explicitly allowed.
+    If the interpreter is not sandboxed, return a false value.
 
 * PySandbox_AllowedNetworkInfo(error_return)
-    Macro that will return 'error_return' for the caller and set a SandboxError exception
-    if the sandboxed interpreter does not allow checking for arbitrary network
-    information, otherwise do nothing.
+    Macro that will return 'error_return' for the caller and set a
+    SandboxError exception if the sandboxed interpreter does not allow
+    checking for arbitrary network information, otherwise do nothing.
 
 
 Filesystem Information
@@ -872,8 +909,9 @@
 Protection
 --------------
 
-Do not allow information about the filesystem layout from various parts of
-Python to be exposed.  This means blocking exposure at the Python level to:
+Do not allow information about the filesystem layout from various parts
+of Python to be exposed.  This means blocking exposure at the Python
+level to:
 
 * __file__ attribute on modules
 * __path__ attribute on packages
@@ -884,9 +922,9 @@
 Why
 --------------
 
-Exposing information about the filesystem is not allowed.  You can figure out
-what operating system one is on which can lead to vulnerabilities specific to
-that operating system being exploited.
+Exposing information about the filesystem is not allowed.  You can
+figure out what operating system one is on which can lead to
+vulnerabilities specific to that operating system being exploited.
 
 
 Possible Security Flaws
@@ -899,13 +937,13 @@
 --------------
 
 * int PySandbox_SetFilesystemInfo(PyThreadState *)
-    Allow the sandboxed interpreter to expose filesystem information.  If the
-    passed-in interpreter is not sandboxed, return NULL.
+    Allow the sandboxed interpreter to expose filesystem information.
+    If the passed-in interpreter is not sandboxed, return NULL.
 
 * PySandbox_AllowedFilesystemInfo(error_return)
-    Macro that checks if exposing filesystem information is allowed.  If it is
-    not, cause the caller to return with the value of 'error_return' and raise
-    SandboxError, otherwise do nothing.
+    Macro that checks if exposing filesystem information is allowed.
+    If it is not, cause the caller to return with the value of
+    'error_return' and raise SandboxError, otherwise do nothing.
 
 
 Stdin, Stdout, and Stderr
@@ -914,9 +952,9 @@
 Protection
 --------------
 
-By default, sys.__stdin__, sys.__stdout__, and sys.__stderr__ will be set to
-instances of StringIO.  Explicit allowance of the process' stdin, stdout, and
-stderr is possible.
+By default, sys.__stdin__, sys.__stdout__, and sys.__stderr__ will be
+set to instances of StringIO.  Explicit allowance of the process'
+stdin, stdout, and stderr is possible.
 
 This will protect the 'print' statement, and the built-ins input() and
 raw_input().
@@ -941,97 +979,104 @@
 * int PySandbox_SetTrueStdin(PyThreadState *)
   int PySandbox_SetTrueStdout(PyThreadState *)
   int PySandbox_SetTrueStderr(PyThreadState *)
-    Set the specific stream for the interpreter to the true version of the
-    stream and not to the default instance of StringIO.  If the interpreter is
-    not sandboxed, return a false value.
+    Set the specific stream for the interpreter to the true version of
+    the stream and not to the default instance of StringIO.  If the
+    interpreter is not sandboxed, return a false value.
 
 
 Adding New Protections
 =============================
 
-.. note:: This feature has the lowest priority and thus will be the last feature
-          implemented (if ever).
+.. note:: This feature has the lowest priority and thus will be the
+          last feature implemented (if ever).
 
 Protection
 --------------
 
-Allow for extensibility in the security model by being able to add new types of
-checks.  This allows not only for Python to add new security protections in a
-backwards-compatible fashion, but to also have extension modules add their own
-as well.
-
-An extension module can introduce a group for its various values to check, with
-a type being a specific value within a group.  The "Python" group is
-specifically reserved for use by the Python core itself.
+Allow for extensibility in the security model by being able to add new
+types of checks.  This allows not only for Python to add new security
+protections in a backwards-compatible fashion, but to also have
+extension modules add their own as well.
+
+An extension module can introduce a group for its various values to
+check, with a type being a specific value within a group.  The "Python"
+group is specifically reserved for use by the Python core itself.
 
 
 Why
 --------------
 
-We are all human.  There is the possibility that a need for a new type of
-protection for the interpreter will present itself and thus need support.  By
-providing an extensible way to add new protections it helps to future-proof the
-system.
+We are all human.  There is the possibility that a need for a new type
+of protection for the interpreter will present itself and thus need
+support.  By providing an extensible way to add new protections it
+helps to future-proof the system.
 
 It also allows extension modules to present their own set of security
-protections.  That way one extension module can use the protection scheme
-presented by another that it is dependent upon.
+protections.  That way one extension module can use the protection
+scheme presented by another that it is dependent upon.
 
 
 Possible Security Flaws
 ------------------------
 
-Poor definitions by extension module users of how their protections should be
-used would allow for possible exploitation.
+Poor definitions by extension module users of how their protections
+should be used would allow for possible exploitation.
 
 
 API
 --------------
 
 + Bool
-    * int PySandbox_SetExtendedFlag(PyThreadState *, string group, string type)
+    * int PySandbox_SetExtendedFlag(PyThreadState *, string group,
+                                    string type)
         Set a group-type to be true.  Expected use is for when a binary
-        possibility of something is needed and that the default is to not allow
-        use of the resource (e.g., network information).  Returns a false value
-        if used on an unprotected interpreter.
-
-    * PySandbox_AllowedExtendedFlag(string group, string type, error_return)
-        Macro that if the group-type is not set to true, cause the caller to
-        return with 'error_return' with SandboxError exception raised.  For unprotected
-        interpreters the check does nothing.
+        possibility of something is needed and that the default is to
+        not allow use of the resource (e.g., network information).
+        Returns a false value if used on an unprotected interpreter.
+
+    * PySandbox_AllowedExtendedFlag(string group, string type,
+                                    error_return)
+        Macro that if the group-type is not set to true, cause the
+        caller to return with 'error_return' with SandboxError
+        exception raised.  For unprotected interpreters the check does
+        nothing.
 
 + Numeric Range
-    * int PySandbox_SetExtendedCap(PyThreadState *, string group, string type,
-                                    integer cap)
-        Set a group-type to a capped value, 'cap', with the initial allocated value set to 0.
-        Expected use is when a resource has a capped amount of use (e.g.,
-        memory).  Returns a false value if the interpreter is not sandboxed.
+    * int PySandbox_SetExtendedCap(PyThreadState *, string group,
+                                    string type, integer cap)
+        Set a group-type to a capped value, 'cap', with the initial
+        allocated value set to 0.  Expected use is when a resource has
+        a capped amount of use (e.g., memory).  Returns a false value
+        if the interpreter is not sandboxed.
 
     * PySandbox_AllowedExtendedAlloc(integer increase, error_return)
-        Macro to raise the amount of a resource is used by 'increase'.  If the
-        increase pushes the resource allocation past the set cap, then return
-        'error_return' and set SandboxError as the exception, otherwise do
-        nothing.
+        Macro to raise the amount of a resource is used by 'increase'.
+        If the increase pushes the resource allocation past the set
+        cap, then return 'error_return' and set SandboxError as the
+        exception, otherwise do nothing.
 
     * PySandbox_AllowedExtendedFree(integer decrease, error_return)
-        Macro to lower the amount a resource is used by 'decrease'.  If the
-        decrease pushes the allotment to below 0 then have the caller return
-        'error_return' and set SandboxError as the exception, otherwise do
-        nothing.
+        Macro to lower the amount a resource is used by 'decrease'.  If
+        the decrease pushes the allotment to below 0 then have the
+        caller return 'error_return' and set SandboxError as the
+        exception, otherwise do nothing.
 
 
 + Membership
-    * int PySandbox_SetExtendedMembership(PyThreadState *, string group,
-                                            string type, string member)
-        Add a string, 'member',  to be considered a member of a group-type (e.g., allowed
-        file paths).  If the interpreter is not an sandboxed interpreter,
-        return a false value.
+    * int PySandbox_SetExtendedMembership(PyThreadState *,
+                                            string group, string type,
+                                            string member)
+        Add a string, 'member',  to be considered a member of a
+        group-type (e.g., allowed file paths).  If the interpreter is not
+        an sandboxed interpreter, return a false value.
 
     * PySandbox_AllowedExtendedMembership(string group, string type,
-                                            string member, error_return)
-        Macro that checks 'member' is a member of the values set for the
-        group-type.  If it is not, then have the caller return 'error_return'
-        and set an exception for SandboxError, otherwise does nothing.
+                                            string member,
+                                            error_return)
+        Macro that checks 'member' is a member of the values set for
+        the group-type.  If it is not, then have the caller return
+        'error_return' and set an exception for SandboxError, otherwise
+        does nothing.
 
 + Specific Value
     * int PySandbox_SetExtendedValue(PyThreadState *, string group,
@@ -1039,10 +1084,11 @@
         Set a group-type to 'value'.  If the interpreter is not
         sandboxed, return NULL.
 
-    * PySandbox_AllowedExtendedValue(string group, string type, string value, error_return)
-        Macro to check that the group-type is set to 'value'.  If it is not,
-        then have the caller return 'error_return' and set an exception for
-        SandboxError, otherwise do nothing.
+    * PySandbox_AllowedExtendedValue(string group, string type,
+                                        string value, error_return)
+        Macro to check that the group-type is set to 'value'.  If it is
+        not, then have the caller return 'error_return' and set an
+        exception for SandboxError, otherwise do nothing.
 
 
 Python API
@@ -1051,8 +1097,9 @@
 __sandboxed__
 --------------
 
-A built-in that flags whether the interpreter currently running is sandboxed or
-not.  Set to a 'bool' value that is read-only.  To mimic working of __debug__.
+A built-in that flags whether the interpreter currently running is
+sandboxed or not.  Set to a 'bool' value that is read-only.  To mimic
+working of __debug__.
 
 
 sandbox module


More information about the Python-checkins mailing list