|
7 | 7 | Simplistic RPC implementation.
|
8 | 8 | Exposes all functions of a Server object.
|
9 | 9 |
|
10 |
| -Uses pickle for serialization and the socket interface. |
| 10 | +This code is for demonstration purposes only, and does not include certain |
| 11 | +security protections. It is not meant to be run on an untrusted network or |
| 12 | +in a production environment. |
11 | 13 | """
|
12 | 14 |
|
| 15 | +import importlib |
13 | 16 | import os
|
14 | 17 | import pickle
|
15 | 18 | import sys
|
|
23 | 26 | # default
|
24 | 27 | PORT = 12032
|
25 | 28 |
|
| 29 | +safe_modules = { |
| 30 | + 'numpy', |
| 31 | + 'numpy.core.multiarray', |
| 32 | +} |
26 | 33 |
|
27 |
| -######################################################################### |
28 |
| -# simple I/O functions |
29 | 34 |
|
| 35 | +class RestrictedUnpickler(pickle.Unpickler): |
30 | 36 |
|
31 |
| -def inline_send_handle(f, conn): |
32 |
| - st = os.fstat(f.fileno()) |
33 |
| - size = st.st_size |
34 |
| - pickle.dump(size, conn) |
35 |
| - conn.write(f.read(size)) |
36 |
| - |
37 |
| - |
38 |
| -def inline_send_string(s, conn): |
39 |
| - size = len(s) |
40 |
| - pickle.dump(size, conn) |
41 |
| - conn.write(s) |
| 37 | + def find_class(self, module, name): |
| 38 | + # Only allow safe modules. |
| 39 | + if module in safe_modules: |
| 40 | + return getattr(importlib.import_module(module), name) |
| 41 | + # Forbid everything else. |
| 42 | + raise pickle.UnpicklingError("global '%s.%s' is forbidden" % |
| 43 | + (module, name)) |
42 | 44 |
|
43 | 45 |
|
44 | 46 | class FileSock:
|
@@ -123,7 +125,7 @@ def one_function(self):
|
123 | 125 | """
|
124 | 126 |
|
125 | 127 | try:
|
126 |
| - (fname,args)=pickle.load(self.fs) |
| 128 | + (fname, args) = RestrictedUnpickler(self.fs).load() |
127 | 129 | except EOFError:
|
128 | 130 | raise ClientExit("read args")
|
129 | 131 | self.log("executing method %s"%(fname))
|
@@ -214,7 +216,7 @@ def generic_fun(self, fname, args):
|
214 | 216 | return self.get_result()
|
215 | 217 |
|
216 | 218 | def get_result(self):
|
217 |
| - (st, ret) = pickle.load(self.fs) |
| 219 | + (st, ret) = RestrictedUnpickler(self.fs).load() |
218 | 220 | if st!=None:
|
219 | 221 | raise ServerException(st)
|
220 | 222 | else:
|
|
0 commit comments