From: Martin Pitt <martin.pitt@ubuntu.com>
Date: Mon, 11 May 2015 16:00:10 +0200
Subject: SECURITY FIX: Prevent code execution through crafted pyc files

When loading a template from an arbitrary file through the AddTemplate() D-Bus
method call or DBusTestCase.spawn_server_template() Python method, don't create
or use Python's *.pyc cached files.By tricking a user into loading a template
from a world-writable directory like /tmp, an attacker could run arbitrary code
with the user's privileges by putting a crafted .pyc file into that directory.

Note that this is highly unlikely to actually appear in practice as custom
dbusmock templates are usually shipped in project directories, not directly in
world-writable directories.

Thanks to Simon McVittie for discovering this!

LP: #1453815
CVE-2015-1326
---
 dbusmock/mockobject.py | 13 +++++--------
 tests/test_api.py      | 10 ++++++++++
 2 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/dbusmock/mockobject.py b/dbusmock/mockobject.py
index 0228070..6d35608 100644
--- a/dbusmock/mockobject.py
+++ b/dbusmock/mockobject.py
@@ -17,6 +17,7 @@ import time
 import sys
 import types
 import importlib
+import imp
 from xml.etree import ElementTree
 
 # we do not use this ourselves, but mock methods often want to use this
@@ -40,14 +41,10 @@ if sys.version_info[0] >= 3:
 
 def load_module(name):
     if os.path.exists(name) and os.path.splitext(name)[1] == '.py':
-        sys.path.insert(0, os.path.dirname(os.path.abspath(name)))
-        try:
-            m = os.path.splitext(os.path.basename(name))[0]
-            module = importlib.import_module(m)
-        finally:
-            sys.path.pop(0)
-
-        return module
+        mod = imp.new_module(os.path.splitext(os.path.basename(name))[0])
+        with open(name) as f:
+            exec(f.read(), mod.__dict__, mod.__dict__)
+        return mod
 
     return importlib.import_module('dbusmock.templates.' + name)
 
diff --git a/tests/test_api.py b/tests/test_api.py
index 57f0a62..7b8c126 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -582,6 +582,16 @@ def load(mock, parameters):
             self.addCleanup(p_mock.terminate)
             self.addCleanup(p_mock.stdout.close)
 
+            # ensure that we don't use/write any .pyc files, they are dangerous
+            # in a world-writable directory like /tmp
+            self.assertFalse(os.path.exists(my_template.name + 'c'))
+            try:
+                from importlib.util import cache_from_source
+                self.assertFalse(os.path.exists(cache_from_source(my_template.name)))
+            except ImportError:
+                # python < 3.4
+                pass
+
         self.assertEqual(dbus_ultimate.Answer(), 42)
 
         # should appear in introspection
