Guido van Rossum | be0a8a6 | 1996-09-10 17:37:05 +0000 | [diff] [blame] | 1 | \section{Standard Module \sectcode{rexec}} |
Guido van Rossum | e47da0a | 1997-07-17 16:34:52 +0000 | [diff] [blame] | 2 | \label{module-rexec} |
Guido van Rossum | be0a8a6 | 1996-09-10 17:37:05 +0000 | [diff] [blame] | 3 | \stmodindex{rexec} |
| 4 | \renewcommand{\indexsubitem}{(in module rexec)} |
| 5 | |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 6 | This module contains the \code{RExec} class, which supports |
| 7 | \code{r_exec()}, \code{r_eval()}, \code{r_execfile()}, and |
| 8 | \code{r_import()} methods, which are restricted versions of the standard |
| 9 | Python functions \code{exec()}, \code{eval()}, \code{execfile()}, and |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 10 | the \code{import} statement. |
| 11 | Code executed in this restricted environment will |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 12 | only have access to modules and functions that are deemed safe; you |
| 13 | can subclass \code{RExec} to add or remove capabilities as desired. |
| 14 | |
| 15 | \emph{Note:} The \code{RExec} class can prevent code from performing |
| 16 | unsafe operations like reading or writing disk files, or using TCP/IP |
| 17 | sockets. However, it does not protect against code using extremely |
| 18 | large amounts of memory or CPU time. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 19 | |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 20 | \begin{funcdesc}{RExec}{\optional{hooks\optional{\, verbose}}} |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 21 | Returns an instance of the \code{RExec} class. |
| 22 | |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 23 | \var{hooks} is an instance of the \code{RHooks} class or a subclass of it. |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 24 | If it is omitted or \code{None}, the default \code{RHooks} class is |
| 25 | instantiated. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 26 | Whenever the RExec module searches for a module (even a built-in one) |
| 27 | or reads a module's code, it doesn't actually go out to the file |
| 28 | system itself. Rather, it calls methods of an RHooks instance that |
| 29 | was passed to or created by its constructor. (Actually, the RExec |
| 30 | object doesn't make these calls---they are made by a module loader |
| 31 | object that's part of the RExec object. This allows another level of |
| 32 | flexibility, e.g. using packages.) |
| 33 | |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 34 | By providing an alternate RHooks object, we can control the |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 35 | file system accesses made to import a module, without changing the |
| 36 | actual algorithm that controls the order in which those accesses are |
| 37 | made. For instance, we could substitute an RHooks object that passes |
| 38 | all filesystem requests to a file server elsewhere, via some RPC |
| 39 | mechanism such as ILU. Grail's applet loader uses this to support |
| 40 | importing applets from a URL for a directory. |
| 41 | |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 42 | 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] | 43 | standard output. |
| 44 | \end{funcdesc} |
| 45 | |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 46 | The RExec class has the following class attributes, which are used by the |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 47 | \code{__init__} method. Changing them on an existing instance won't |
| 48 | have any effect; instead, create a subclass of \code{RExec} and assign |
| 49 | them new values in the class definition. Instances of the new class |
| 50 | will then use those new values. All these attributes are tuples of |
| 51 | strings. |
| 52 | |
| 53 | \renewcommand{\indexsubitem}{(RExec object attribute)} |
| 54 | \begin{datadesc}{nok_builtin_names} |
| 55 | Contains the names of built-in functions which will \emph{not} be |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 56 | available to programs running in the restricted environment. The |
| 57 | value for \code{RExec} is \code{('open',} \code{'reload',} |
| 58 | \code{'__import__')}. (This gives the exceptions, because by far the |
| 59 | majority of built-in functions are harmless. A subclass that wants to |
| 60 | override this variable should probably start with the value from the |
| 61 | base class and concatenate additional forbidden functions --- when new |
| 62 | dangerous built-in functions are added to Python, they will also be |
| 63 | added to this module.) |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 64 | \end{datadesc} |
| 65 | |
| 66 | \begin{datadesc}{ok_builtin_modules} |
| 67 | Contains the names of built-in modules which can be safely imported. |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 68 | The value for \code{RExec} is \code{('audioop',} \code{'array',} |
| 69 | \code{'binascii',} \code{'cmath',} \code{'errno',} \code{'imageop',} |
| 70 | \code{'marshal',} \code{'math',} \code{'md5',} \code{'operator',} |
| 71 | \code{'parser',} \code{'regex',} \code{'rotor',} \code{'select',} |
| 72 | \code{'strop',} \code{'struct',} \code{'time')}. A similar remark |
| 73 | about overriding this variable applies --- use the value from the base |
| 74 | class as a starting point. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 75 | \end{datadesc} |
| 76 | |
| 77 | \begin{datadesc}{ok_path} |
| 78 | Contains the directories which will be searched when an \code{import} |
| 79 | is performed in the restricted environment. |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 80 | The value for \code{RExec} is the same as \code{sys.path} (at the time |
| 81 | the module is loaded) for unrestricted code. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 82 | \end{datadesc} |
| 83 | |
| 84 | \begin{datadesc}{ok_posix_names} |
| 85 | % Should this be called ok_os_names? |
| 86 | Contains the names of the functions in the \code{os} module which will be |
| 87 | available to programs running in the restricted environment. The |
| 88 | value for \code{RExec} is \code{('error',} \code{'fstat',} |
| 89 | \code{'listdir',} \code{'lstat',} \code{'readlink',} \code{'stat',} |
| 90 | \code{'times',} \code{'uname',} \code{'getpid',} \code{'getppid',} |
| 91 | \code{'getcwd',} \code{'getuid',} \code{'getgid',} \code{'geteuid',} |
| 92 | \code{'getegid')}. |
| 93 | \end{datadesc} |
| 94 | |
| 95 | \begin{datadesc}{ok_sys_names} |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 96 | Contains the names of the functions and variables in the \code{sys} |
| 97 | module which will be available to programs running in the restricted |
| 98 | environment. The value for \code{RExec} is \code{('ps1',} |
| 99 | \code{'ps2',} \code{'copyright',} \code{'version',} \code{'platform',} |
| 100 | \code{'exit',} \code{'maxint')}. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 101 | \end{datadesc} |
| 102 | |
| 103 | RExec instances support the following methods: |
| 104 | \renewcommand{\indexsubitem}{(RExec object method)} |
| 105 | |
| 106 | \begin{funcdesc}{r_eval}{code} |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 107 | \var{code} must either be a string containing a Python expression, or |
| 108 | a compiled code object, which will be evaluated in the restricted |
| 109 | environment's \code{__main__} module. The value of the expression or |
| 110 | code object will be returned. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 111 | \end{funcdesc} |
| 112 | |
| 113 | \begin{funcdesc}{r_exec}{code} |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 114 | \var{code} must either be a string containing one or more lines of |
| 115 | Python code, or a compiled code object, which will be executed in the |
| 116 | restricted environment's \code{__main__} module. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 117 | \end{funcdesc} |
| 118 | |
| 119 | \begin{funcdesc}{r_execfile}{filename} |
| 120 | Execute the Python code contained in the file \var{filename} in the |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 121 | restricted environment's \code{__main__} module. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 122 | \end{funcdesc} |
| 123 | |
| 124 | Methods whose names begin with \code{s_} are similar to the functions |
| 125 | beginning with \code{r_}, but the code will be granted access to |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 126 | restricted versions of the standard I/O streans \code{sys.stdin}, |
| 127 | \code{sys.stderr}, and \code{sys.stdout}. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 128 | |
| 129 | \begin{funcdesc}{s_eval}{code} |
| 130 | \var{code} must be a string containing a Python expression, which will |
| 131 | be evaluated in the restricted environment. |
| 132 | \end{funcdesc} |
| 133 | |
| 134 | \begin{funcdesc}{s_exec}{code} |
| 135 | \var{code} must be a string containing one or more lines of Python code, |
| 136 | which will be executed in the restricted environment. |
| 137 | \end{funcdesc} |
| 138 | |
| 139 | \begin{funcdesc}{s_execfile}{code} |
| 140 | Execute the Python code contained in the file \var{filename} in the |
| 141 | restricted environment. |
| 142 | \end{funcdesc} |
| 143 | |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 144 | \code{RExec} objects must also support various methods which will be |
| 145 | implicitly called by code executing in the restricted environment. |
| 146 | Overriding these methods in a subclass is used to change the policies |
| 147 | enforced by a restricted environment. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 148 | |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 149 | \begin{funcdesc}{r_import}{modulename\optional{\, globals\, locals\, fromlist}} |
| 150 | Import the module \var{modulename}, raising an \code{ImportError} |
| 151 | exception if the module is considered unsafe. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 152 | \end{funcdesc} |
| 153 | |
| 154 | \begin{funcdesc}{r_open}{filename\optional{\, mode\optional{\, bufsize}}} |
| 155 | Method called when \code{open()} is called in the restricted |
| 156 | environment. The arguments are identical to those of \code{open()}, |
| 157 | and a file object (or a class instance compatible with file objects) |
| 158 | should be returned. \code{RExec}'s default behaviour is allow opening |
| 159 | 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] | 160 | the example below for an implementation of a less restrictive |
| 161 | \code{r_open()}. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 162 | \end{funcdesc} |
| 163 | |
| 164 | \begin{funcdesc}{r_reload}{module} |
| 165 | Reload the module object \var{module}, re-parsing and re-initializing it. |
| 166 | \end{funcdesc} |
| 167 | |
| 168 | \begin{funcdesc}{r_unload}{module} |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 169 | Unload the module object \var{module} (i.e., remove it from the |
| 170 | restricted environment's \code{sys.modules} dictionary). |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 171 | \end{funcdesc} |
| 172 | |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 173 | And their equivalents with access to restricted standard I/O streams: |
| 174 | |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 175 | \begin{funcdesc}{s_import}{modulename\optional{\, globals, locals, fromlist}} |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 176 | Import the module \var{modulename}, raising an \code{ImportError} |
| 177 | exception if the module is considered unsafe. |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 178 | \end{funcdesc} |
| 179 | |
| 180 | \begin{funcdesc}{s_reload}{module} |
| 181 | Reload the module object \var{module}, re-parsing and re-initializing it. |
| 182 | \end{funcdesc} |
| 183 | |
| 184 | \begin{funcdesc}{s_unload}{module} |
| 185 | Unload the module object \var{module}. |
| 186 | % XXX what are the semantics of this? |
| 187 | \end{funcdesc} |
| 188 | |
| 189 | \subsection{An example} |
| 190 | |
| 191 | Let us say that we want a slightly more relaxed policy than the |
| 192 | standard RExec class. For example, if we're willing to allow files in |
| 193 | \file{/tmp} to be written, we can subclass the \code{RExec} class: |
| 194 | |
| 195 | \bcode\begin{verbatim} |
| 196 | class TmpWriterRExec(rexec.RExec): |
| 197 | def r_open(self, file, mode='r', buf=-1): |
Guido van Rossum | f73f79b | 1996-10-24 22:14:06 +0000 | [diff] [blame] | 198 | if mode in ('r', 'rb'): |
| 199 | pass |
| 200 | elif mode in ('w', 'wb', 'a', 'ab'): |
| 201 | # check filename : must begin with /tmp/ |
| 202 | if file[:5]!='/tmp/': |
| 203 | raise IOError, "can't write outside /tmp" |
| 204 | elif (string.find(file, '/../') >= 0 or |
| 205 | file[:3] == '../' or file[-3:] == '/..'): |
| 206 | raise IOError, "'..' in filename forbidden" |
| 207 | else: raise IOError, "Illegal open() mode" |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 208 | return open(file, mode, buf) |
| 209 | \end{verbatim}\ecode |
Guido van Rossum | e47da0a | 1997-07-17 16:34:52 +0000 | [diff] [blame] | 210 | % |
Guido van Rossum | 095538d | 1996-10-22 01:11:19 +0000 | [diff] [blame] | 211 | Notice that the above code will occasionally forbid a perfectly valid |
| 212 | filename; for example, code in the restricted environment won't be |
| 213 | able to open a file called \file{/tmp/foo/../bar}. To fix this, the |
| 214 | \code{r_open} method would have to simplify the filename to |
| 215 | \file{/tmp/bar}, which would require splitting apart the filename and |
| 216 | performing various operations on it. In cases where security is at |
| 217 | stake, it may be preferable to write simple code which is sometimes |
| 218 | overly restrictive, instead of more general code that is also more |
| 219 | complex and may harbor a subtle security hole. |