diff --git a/oslo_messaging/_drivers/common.py b/oslo_messaging/_drivers/common.py index 539998bc9..a28e37c02 100644 --- a/oslo_messaging/_drivers/common.py +++ b/oslo_messaging/_drivers/common.py @@ -33,6 +33,7 @@ from oslo_messaging import _utils as utils LOG = logging.getLogger(__name__) _EXCEPTIONS_MODULE = 'exceptions' if six.PY2 else 'builtins' +_EXCEPTIONS_MODULES = ['exceptions', 'builtins'] '''RPC Envelope Version. @@ -208,6 +209,13 @@ def deserialize_remote_exception(data, allowed_remote_exmods): name = failure.get('class') module = failure.get('module') + # the remote service which raised the given exception might have a + # different python version than the caller. For example, the caller might + # run python 2.7, while the remote service might run python 3.4. Thus, + # the exception module will be "builtins" instead of "exceptions". + if module in _EXCEPTIONS_MODULES: + module = _EXCEPTIONS_MODULE + # NOTE(ameade): We DO NOT want to allow just any module to be imported, in # order to prevent arbitrary code execution. if module != _EXCEPTIONS_MODULE and module not in allowed_remote_exmods: diff --git a/oslo_messaging/tests/test_exception_serialization.py b/oslo_messaging/tests/test_exception_serialization.py index ca4f92b02..a6922828f 100644 --- a/oslo_messaging/tests/test_exception_serialization.py +++ b/oslo_messaging/tests/test_exception_serialization.py @@ -26,6 +26,7 @@ from oslo_messaging.tests import utils as test_utils load_tests = testscenarios.load_tests_apply_scenarios EXCEPTIONS_MODULE = 'exceptions' if six.PY2 else 'builtins' +OTHER_EXCEPTIONS_MODULE = 'builtins' if six.PY2 else 'exceptions' class NovaStyleException(Exception): @@ -149,6 +150,17 @@ class DeserializeRemoteExceptionTestCase(test_utils.BaseTestCase): remote_name='Exception', remote_args=('test\ntraceback\ntraceback\n', ), remote_kwargs={})), + ('different_python_versions', + dict(allowed=_standard_allowed, + clsname='Exception', + modname=OTHER_EXCEPTIONS_MODULE, + cls=Exception, + args=['test'], + kwargs={}, + str='test\ntraceback\ntraceback\n', + remote_name='Exception', + remote_args=('test\ntraceback\ntraceback\n', ), + remote_kwargs={})), ('nova_style', dict(allowed=_standard_allowed, clsname='NovaStyleException',