Fred Drake | 295da24 | 1998-08-10 19:42:37 +0000 | [diff] [blame] | 1 | \section{\module{rexec} --- |
Fred Drake | ffbe687 | 1999-04-22 21:23:22 +0000 | [diff] [blame] | 2 | Restricted execution framework} |
Fred Drake | b91e934 | 1998-07-23 17:59:49 +0000 | [diff] [blame] | 3 | |
Fred Drake | ffbe687 | 1999-04-22 21:23:22 +0000 | [diff] [blame] | 4 | \declaremodule{standard}{rexec} |
Fred Drake | b91e934 | 1998-07-23 17:59:49 +0000 | [diff] [blame] | 5 | \modulesynopsis{Basic restricted execution framework.} |
| 6 | |
Fred Drake | a891230 | 1998-03-14 07:08:02 +0000 | [diff] [blame] | 7 | |
Fred Drake | 1947991 | 1998-02-13 06:58:54 +0000 | [diff] [blame] | 8 | This module contains the \class{RExec} class, which supports |
Guido van Rossum | 7b0c9d8 | 1998-05-08 13:27:38 +0000 | [diff] [blame] | 9 | \method{r_eval()}, \method{r_execfile()}, \method{r_exec()}, and |
Fred Drake | a891230 | 1998-03-14 07:08:02 +0000 | [diff] [blame] | 10 | \method{r_import()} methods, which are restricted versions of the standard |
Guido van Rossum | 7b0c9d8 | 1998-05-08 13:27:38 +0000 | [diff] [blame] | 11 | Python functions \method{eval()}, \method{execfile()} and |
| 12 | the \keyword{exec} and \keyword{import} statements. |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 13 | Code executed in this restricted environment will |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 14 | only have access to modules and functions that are deemed safe; you |
Fred Drake | 1947991 | 1998-02-13 06:58:54 +0000 | [diff] [blame] | 15 | can subclass \class{RExec} to add or remove capabilities as desired. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 16 | |
Fred Drake | 80a04a4 | 2002-08-27 16:46:06 +0000 | [diff] [blame] | 17 | \begin{notice}[warning] |
| 18 | While the \module{rexec} module is designed to perform as described |
| 19 | below, it does have a few known vulnerabilities which could be |
| 20 | exploited by carefully written code. Thus it should not be relied |
| 21 | upon in situations requiring ``production ready'' security. In such |
| 22 | situations, execution via sub-processes or very careful |
| 23 | ``cleansing'' of both code and data to be processed may be |
| 24 | necessary. Alternatively, help in patching known \module{rexec} |
| 25 | vulnerabilities would be welcomed. |
| 26 | \end{notice} |
| 27 | |
| 28 | \begin{notice} |
| 29 | The \class{RExec} class can prevent code from performing unsafe |
| 30 | operations like reading or writing disk files, or using TCP/IP |
| 31 | sockets. However, it does not protect against code using extremely |
| 32 | large amounts of memory or processor time. |
| 33 | \end{notice} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 34 | |
Fred Drake | a891230 | 1998-03-14 07:08:02 +0000 | [diff] [blame] | 35 | \begin{classdesc}{RExec}{\optional{hooks\optional{, verbose}}} |
Fred Drake | 1947991 | 1998-02-13 06:58:54 +0000 | [diff] [blame] | 36 | Returns an instance of the \class{RExec} class. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 37 | |
Fred Drake | a891230 | 1998-03-14 07:08:02 +0000 | [diff] [blame] | 38 | \var{hooks} is an instance of the \class{RHooks} class or a subclass of it. |
| 39 | If it is omitted or \code{None}, the default \class{RHooks} class is |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 40 | instantiated. |
Fred Drake | ffbe687 | 1999-04-22 21:23:22 +0000 | [diff] [blame] | 41 | Whenever the \module{rexec} module searches for a module (even a |
Fred Drake | 1947991 | 1998-02-13 06:58:54 +0000 | [diff] [blame] | 42 | built-in one) or reads a module's code, it doesn't actually go out to |
| 43 | the file system itself. Rather, it calls methods of an \class{RHooks} |
| 44 | instance that was passed to or created by its constructor. (Actually, |
| 45 | the \class{RExec} object doesn't make these calls --- they are made by |
| 46 | a module loader object that's part of the \class{RExec} object. This |
Fred Drake | 907e76b | 2001-07-06 20:30:11 +0000 | [diff] [blame] | 47 | allows another level of flexibility, which can be useful when changing |
| 48 | the mechanics of \keyword{import} within the restricted environment.) |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 49 | |
Fred Drake | 1947991 | 1998-02-13 06:58:54 +0000 | [diff] [blame] | 50 | By providing an alternate \class{RHooks} object, we can control the |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 51 | file system accesses made to import a module, without changing the |
| 52 | actual algorithm that controls the order in which those accesses are |
Fred Drake | 1947991 | 1998-02-13 06:58:54 +0000 | [diff] [blame] | 53 | made. For instance, we could substitute an \class{RHooks} object that |
| 54 | passes all filesystem requests to a file server elsewhere, via some |
| 55 | RPC mechanism such as ILU. Grail's applet loader uses this to support |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 56 | importing applets from a URL for a directory. |
| 57 | |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 58 | If \var{verbose} is true, additional debugging output may be sent to |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 59 | standard output. |
Fred Drake | a891230 | 1998-03-14 07:08:02 +0000 | [diff] [blame] | 60 | \end{classdesc} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 61 | |
Fred Drake | 307cb05 | 2001-06-22 18:21:53 +0000 | [diff] [blame] | 62 | It is important to be aware that code running in a restricted |
| 63 | environment can still call the \function{sys.exit()} function. To |
| 64 | disallow restricted code from exiting the interpreter, always protect |
| 65 | calls that cause restricted code to run with a |
| 66 | \keyword{try}/\keyword{except} statement that catches the |
| 67 | \exception{SystemExit} exception. Removing the \function{sys.exit()} |
| 68 | function from the restricted environment is not sufficient --- the |
| 69 | restricted code could still use \code{raise SystemExit}. Removing |
| 70 | \exception{SystemExit} is not a reasonable option; some library code |
| 71 | makes use of this and would break were it not available. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 72 | |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 73 | |
Fred Drake | 307cb05 | 2001-06-22 18:21:53 +0000 | [diff] [blame] | 74 | \begin{seealso} |
| 75 | \seetitle[http://grail.sourceforge.net/]{Grail Home Page}{Grail is a |
| 76 | Web browser written entirely in Python. It uses the |
| 77 | \module{rexec} module as a foundation for supporting |
| 78 | Python applets, and can be used as an example usage of |
| 79 | this module.} |
| 80 | \end{seealso} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 81 | |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 82 | |
Fred Drake | 307cb05 | 2001-06-22 18:21:53 +0000 | [diff] [blame] | 83 | \subsection{RExec Objects \label{rexec-objects}} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 84 | |
Fred Drake | 1947991 | 1998-02-13 06:58:54 +0000 | [diff] [blame] | 85 | \class{RExec} instances support the following methods: |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 86 | |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 87 | \begin{methoddesc}{r_eval}{code} |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 88 | \var{code} must either be a string containing a Python expression, or |
| 89 | a compiled code object, which will be evaluated in the restricted |
Fred Drake | a891230 | 1998-03-14 07:08:02 +0000 | [diff] [blame] | 90 | environment's \module{__main__} module. The value of the expression or |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 91 | code object will be returned. |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 92 | \end{methoddesc} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 93 | |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 94 | \begin{methoddesc}{r_exec}{code} |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 95 | \var{code} must either be a string containing one or more lines of |
| 96 | Python code, or a compiled code object, which will be executed in the |
Fred Drake | a891230 | 1998-03-14 07:08:02 +0000 | [diff] [blame] | 97 | restricted environment's \module{__main__} module. |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 98 | \end{methoddesc} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 99 | |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 100 | \begin{methoddesc}{r_execfile}{filename} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 101 | Execute the Python code contained in the file \var{filename} in the |
Fred Drake | a891230 | 1998-03-14 07:08:02 +0000 | [diff] [blame] | 102 | restricted environment's \module{__main__} module. |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 103 | \end{methoddesc} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 104 | |
Fred Drake | a891230 | 1998-03-14 07:08:02 +0000 | [diff] [blame] | 105 | Methods whose names begin with \samp{s_} are similar to the functions |
| 106 | beginning with \samp{r_}, but the code will be granted access to |
Fred Drake | 71f894a | 1998-02-23 14:37:40 +0000 | [diff] [blame] | 107 | restricted versions of the standard I/O streams \code{sys.stdin}, |
Fred Drake | a891230 | 1998-03-14 07:08:02 +0000 | [diff] [blame] | 108 | \code{sys.stderr}, and \code{sys.stdout}. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 109 | |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 110 | \begin{methoddesc}{s_eval}{code} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 111 | \var{code} must be a string containing a Python expression, which will |
| 112 | be evaluated in the restricted environment. |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 113 | \end{methoddesc} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 114 | |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 115 | \begin{methoddesc}{s_exec}{code} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 116 | \var{code} must be a string containing one or more lines of Python code, |
| 117 | which will be executed in the restricted environment. |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 118 | \end{methoddesc} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 119 | |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 120 | \begin{methoddesc}{s_execfile}{code} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 121 | Execute the Python code contained in the file \var{filename} in the |
| 122 | restricted environment. |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 123 | \end{methoddesc} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 124 | |
Fred Drake | 1947991 | 1998-02-13 06:58:54 +0000 | [diff] [blame] | 125 | \class{RExec} objects must also support various methods which will be |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 126 | implicitly called by code executing in the restricted environment. |
| 127 | Overriding these methods in a subclass is used to change the policies |
| 128 | enforced by a restricted environment. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 129 | |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 130 | \begin{methoddesc}{r_import}{modulename\optional{, globals\optional{, |
| 131 | locals\optional{, fromlist}}}} |
Fred Drake | a891230 | 1998-03-14 07:08:02 +0000 | [diff] [blame] | 132 | Import the module \var{modulename}, raising an \exception{ImportError} |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 133 | exception if the module is considered unsafe. |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 134 | \end{methoddesc} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 135 | |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 136 | \begin{methoddesc}{r_open}{filename\optional{, mode\optional{, bufsize}}} |
Fred Drake | a891230 | 1998-03-14 07:08:02 +0000 | [diff] [blame] | 137 | Method called when \function{open()} is called in the restricted |
| 138 | environment. The arguments are identical to those of \function{open()}, |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 139 | and a file object (or a class instance compatible with file objects) |
Fred Drake | 1947991 | 1998-02-13 06:58:54 +0000 | [diff] [blame] | 140 | should be returned. \class{RExec}'s default behaviour is allow opening |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 141 | any file for reading, but forbidding any attempt to write a file. See |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 142 | the example below for an implementation of a less restrictive |
Fred Drake | a891230 | 1998-03-14 07:08:02 +0000 | [diff] [blame] | 143 | \method{r_open()}. |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 144 | \end{methoddesc} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 145 | |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 146 | \begin{methoddesc}{r_reload}{module} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 147 | Reload the module object \var{module}, re-parsing and re-initializing it. |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 148 | \end{methoddesc} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 149 | |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 150 | \begin{methoddesc}{r_unload}{module} |
Fred Drake | 907e76b | 2001-07-06 20:30:11 +0000 | [diff] [blame] | 151 | Unload the module object \var{module} (remove it from the |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 152 | restricted environment's \code{sys.modules} dictionary). |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 153 | \end{methoddesc} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 154 | |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 155 | And their equivalents with access to restricted standard I/O streams: |
| 156 | |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 157 | \begin{methoddesc}{s_import}{modulename\optional{, globals\optional{, |
| 158 | locals\optional{, fromlist}}}} |
Fred Drake | 1947991 | 1998-02-13 06:58:54 +0000 | [diff] [blame] | 159 | Import the module \var{modulename}, raising an \exception{ImportError} |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 160 | exception if the module is considered unsafe. |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 161 | \end{methoddesc} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 162 | |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 163 | \begin{methoddesc}{s_reload}{module} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 164 | Reload the module object \var{module}, re-parsing and re-initializing it. |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 165 | \end{methoddesc} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 166 | |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 167 | \begin{methoddesc}{s_unload}{module} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 168 | Unload the module object \var{module}. |
| 169 | % XXX what are the semantics of this? |
Fred Drake | da70ee1 | 1998-04-02 18:51:30 +0000 | [diff] [blame] | 170 | \end{methoddesc} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 171 | |
Fred Drake | 307cb05 | 2001-06-22 18:21:53 +0000 | [diff] [blame] | 172 | |
| 173 | \subsection{Defining restricted environments \label{rexec-extension}} |
| 174 | |
| 175 | The \class{RExec} class has the following class attributes, which are |
| 176 | used by the \method{__init__()} method. Changing them on an existing |
| 177 | instance won't have any effect; instead, create a subclass of |
| 178 | \class{RExec} and assign them new values in the class definition. |
| 179 | Instances of the new class will then use those new values. All these |
| 180 | attributes are tuples of strings. |
| 181 | |
| 182 | \begin{memberdesc}{nok_builtin_names} |
| 183 | Contains the names of built-in functions which will \emph{not} be |
| 184 | available to programs running in the restricted environment. The |
| 185 | value for \class{RExec} is \code{('open', 'reload', '__import__')}. |
| 186 | (This gives the exceptions, because by far the majority of built-in |
| 187 | functions are harmless. A subclass that wants to override this |
| 188 | variable should probably start with the value from the base class and |
| 189 | concatenate additional forbidden functions --- when new dangerous |
| 190 | built-in functions are added to Python, they will also be added to |
| 191 | this module.) |
| 192 | \end{memberdesc} |
| 193 | |
| 194 | \begin{memberdesc}{ok_builtin_modules} |
| 195 | Contains the names of built-in modules which can be safely imported. |
| 196 | The value for \class{RExec} is \code{('audioop', 'array', 'binascii', |
| 197 | 'cmath', 'errno', 'imageop', 'marshal', 'math', 'md5', 'operator', |
| 198 | 'parser', 'regex', 'rotor', 'select', 'sha', '_sre', 'strop', |
| 199 | 'struct', 'time')}. A similar remark about overriding this variable |
| 200 | applies --- use the value from the base class as a starting point. |
| 201 | \end{memberdesc} |
| 202 | |
| 203 | \begin{memberdesc}{ok_path} |
| 204 | Contains the directories which will be searched when an \keyword{import} |
| 205 | is performed in the restricted environment. |
| 206 | The value for \class{RExec} is the same as \code{sys.path} (at the time |
| 207 | the module is loaded) for unrestricted code. |
| 208 | \end{memberdesc} |
| 209 | |
| 210 | \begin{memberdesc}{ok_posix_names} |
| 211 | % Should this be called ok_os_names? |
| 212 | Contains the names of the functions in the \refmodule{os} module which will be |
| 213 | available to programs running in the restricted environment. The |
| 214 | value for \class{RExec} is \code{('error', 'fstat', 'listdir', |
| 215 | 'lstat', 'readlink', 'stat', 'times', 'uname', 'getpid', 'getppid', |
| 216 | 'getcwd', 'getuid', 'getgid', 'geteuid', 'getegid')}. |
| 217 | \end{memberdesc} |
| 218 | |
| 219 | \begin{memberdesc}{ok_sys_names} |
| 220 | Contains the names of the functions and variables in the \refmodule{sys} |
| 221 | module which will be available to programs running in the restricted |
| 222 | environment. The value for \class{RExec} is \code{('ps1', 'ps2', |
| 223 | 'copyright', 'version', 'platform', 'exit', 'maxint')}. |
| 224 | \end{memberdesc} |
| 225 | |
Guido van Rossum | 59b2a74 | 2002-05-31 21:12:53 +0000 | [diff] [blame] | 226 | \begin{memberdesc}{ok_file_types} |
| 227 | Contains the file types from which modules are allowed to be loaded. |
| 228 | Each file type is an integer constant defined in the \refmodule{imp} module. |
| 229 | The meaningful values are \constant{PY_SOURCE}, \constant{PY_COMPILED}, and |
| 230 | \constant{C_EXTENSION}. The value for \class{RExec} is \code{(C_EXTENSION, |
| 231 | PY_SOURCE)}. Adding \constant{PY_COMPILED} in subclasses is not recommended; |
| 232 | an attacker could exit the restricted execution mode by putting a forged |
| 233 | byte-compiled file (\file{.pyc}) anywhere in your file system, for example |
| 234 | by writing it to \file{/tmp} or uploading it to the \file{/incoming} |
| 235 | directory of your public FTP server. |
| 236 | \end{memberdesc} |
| 237 | |
Fred Drake | 307cb05 | 2001-06-22 18:21:53 +0000 | [diff] [blame] | 238 | |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 239 | \subsection{An example} |
| 240 | |
| 241 | Let us say that we want a slightly more relaxed policy than the |
Fred Drake | 1947991 | 1998-02-13 06:58:54 +0000 | [diff] [blame] | 242 | standard \class{RExec} class. For example, if we're willing to allow |
| 243 | files in \file{/tmp} to be written, we can subclass the \class{RExec} |
| 244 | class: |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 245 | |
Fred Drake | 1947991 | 1998-02-13 06:58:54 +0000 | [diff] [blame] | 246 | \begin{verbatim} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 247 | class TmpWriterRExec(rexec.RExec): |
| 248 | def r_open(self, file, mode='r', buf=-1): |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 249 | if mode in ('r', 'rb'): |
| 250 | pass |
| 251 | elif mode in ('w', 'wb', 'a', 'ab'): |
| 252 | # check filename : must begin with /tmp/ |
| 253 | if file[:5]!='/tmp/': |
| 254 | raise IOError, "can't write outside /tmp" |
| 255 | elif (string.find(file, '/../') >= 0 or |
| 256 | file[:3] == '../' or file[-3:] == '/..'): |
| 257 | raise IOError, "'..' in filename forbidden" |
| 258 | else: raise IOError, "Illegal open() mode" |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 259 | return open(file, mode, buf) |
Fred Drake | 1947991 | 1998-02-13 06:58:54 +0000 | [diff] [blame] | 260 | \end{verbatim} |
Guido van Rossum | e47da0a | 1997-07-17 16:34:52 +0000 | [diff] [blame] | 261 | % |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 262 | Notice that the above code will occasionally forbid a perfectly valid |
| 263 | filename; for example, code in the restricted environment won't be |
| 264 | able to open a file called \file{/tmp/foo/../bar}. To fix this, the |
Fred Drake | a891230 | 1998-03-14 07:08:02 +0000 | [diff] [blame] | 265 | \method{r_open()} method would have to simplify the filename to |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 266 | \file{/tmp/bar}, which would require splitting apart the filename and |
| 267 | performing various operations on it. In cases where security is at |
| 268 | stake, it may be preferable to write simple code which is sometimes |
| 269 | overly restrictive, instead of more general code that is also more |
| 270 | complex and may harbor a subtle security hole. |