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
This commit is contained in:
Claudiu Belu 2016-10-05 15:55:40 -07:00
parent f52e5cfbca
commit da830016d5
2 changed files with 20 additions and 0 deletions

View File

@ -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:

View File

@ -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',