From da830016d52cffd7f7cf2850ad98841729144c06 Mon Sep 17 00:00:00 2001 From: Claudiu Belu Date: Wed, 5 Oct 2016 15:55:40 -0700 Subject: [PATCH] Properly deserializes built-in exceptions If the remote target and the caller have different python versions, then built-in exceptions raised by the remote target will not be properly deserialized on the caller. Because of this, oslo.messaging will simply raise a RemoteError, instead of any expected exceptions the caller might expect. This patch addresses this issue. Closes-Bug: #1630795 Change-Id: I6d9eaf5497e746be9766731172406ec624ef9ba7 --- oslo_messaging/_drivers/common.py | 8 ++++++++ oslo_messaging/tests/test_exception_serialization.py | 12 ++++++++++++ 2 files changed, 20 insertions(+) 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',