You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@qpid.apache.org by "Ken Giusti (Jira)" <ji...@apache.org> on 2021/05/10 19:50:00 UTC

[jira] [Assigned] (DISPATCH-1821) Double-free in qd_entity_configure_policy on error

     [ https://issues.apache.org/jira/browse/DISPATCH-1821?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Ken Giusti reassigned DISPATCH-1821:
------------------------------------

    Assignee: Charles E. Rolke

> Double-free in qd_entity_configure_policy on error
> --------------------------------------------------
>
>                 Key: DISPATCH-1821
>                 URL: https://issues.apache.org/jira/browse/DISPATCH-1821
>             Project: Qpid Dispatch
>          Issue Type: Bug
>          Components: Policy Engine
>    Affects Versions: 1.14.0
>            Reporter: Jiri Daněk
>            Assignee: Charles E. Rolke
>            Priority: Trivial
>              Labels: clang-analyzer
>
> As far as I can tell, this double-free is near impossible in normal operation of the router. Below, it is reproduced using a test, which passes in a value for that cannot be converted to a Python bool. There is no way for a legitimate user to make this happen.
> Regarding a fix, I am not sure what the router should do when it detect invalid configuration. Freeing qd->policy is IMO not the right response, because that is normally freed in qd_dispatch_free. Printing an error and carying on (that now happens for {{maxConnections < 0}}) does not seem right to me either (but it's probably needed in case the config is changed through remote management interface),
> {noformat}
> 2020-11-02 09:48:51.887312 +0100 ROUTER_CORE (info) In-process subscription L/$management
> 2020-11-02 09:48:51.939210 +0100 ERROR (error) Python: NotImplementedError: 
> 2020-11-02 09:48:51.941666 +0100 ERROR (error) Traceback (most recent call last):
>   File "test_module", line 3, in __bool__
> NotImplementedError
> =================================================================
> ==27615==ERROR: AddressSanitizer: attempting double-free on 0x602000001810 in thread T0:
>     #0 0x7f876d5191d7 in __interceptor_free (/nix/store/zhbhxp4jgalycwffildy2bwcgmrsmayk-gcc-9.2.0-lib/lib/libasan.so.5+0x10a1d7)
>     #1 0x7f876cd33b95 in qd_policy_free ../src/policy.c:136
>     #2 0x7f876cd347cf in qd_entity_configure_policy ../src/policy.c:178
>     #3 0x4ef6a6 in _DOCTEST_ANON_FUNC_6 ../tests/c_unittests/test_policy.cpp:75
>     #4 0x493edd in doctest::Context::run() ../tests/c_unittests/doctest.h:5849
>     #5 0x4974e9 in main ../tests/c_unittests/doctest.h:5933
>     #6 0x7f876b610d8a in __libc_start_main (/nix/store/xg6ilb9g9zhi2zg1dpi4zcp288rhnvns-glibc-2.30/lib/libc.so.6+0x23d8a)
>     #7 0x43cd99 in _start (/home/jdanek/repos/qpid/qpid-dispatch/cmake-build-debug/tests/c_unittests/c_unittests+0x43cd99)
> 0x602000001810 is located 0 bytes inside of 5-byte region [0x602000001810,0x602000001815)
> freed by thread T0 here:
>     #0 0x7f876d5191d7 in __interceptor_free (/nix/store/zhbhxp4jgalycwffildy2bwcgmrsmayk-gcc-9.2.0-lib/lib/libasan.so.5+0x10a1d7)
>     #1 0x7f876cd347c3 in qd_entity_configure_policy ../src/policy.c:177
>     #2 0x4ef6a6 in _DOCTEST_ANON_FUNC_6 ../tests/c_unittests/test_policy.cpp:75
>     #3 0x493edd in doctest::Context::run() ../tests/c_unittests/doctest.h:5849
>     #4 0x4974e9 in main ../tests/c_unittests/doctest.h:5933
>     #5 0x7f876b610d8a in __libc_start_main (/nix/store/xg6ilb9g9zhi2zg1dpi4zcp288rhnvns-glibc-2.30/lib/libc.so.6+0x23d8a)
> previously allocated by thread T0 here:
>     #0 0x7f876d4a40b5 in strdup (/nix/store/zhbhxp4jgalycwffildy2bwcgmrsmayk-gcc-9.2.0-lib/lib/libasan.so.5+0x950b5)
>     #1 0x7f876cec8c99 in py_string_2_c ../src/python_utils.c:35
>     #2 0x7f876cce21e2 in qd_entity_get_string ../src/entity.c:49
>     #3 0x7f876cce2b5f in qd_entity_opt_string ../src/entity.c:84
>     #4 0x7f876cd341b0 in qd_entity_configure_policy ../src/policy.c:161
>     #5 0x4ef6a6 in _DOCTEST_ANON_FUNC_6 ../tests/c_unittests/test_policy.cpp:75
>     #6 0x493edd in doctest::Context::run() ../tests/c_unittests/doctest.h:5849
>     #7 0x4974e9 in main ../tests/c_unittests/doctest.h:5933
>     #8 0x7f876b610d8a in __libc_start_main (/nix/store/xg6ilb9g9zhi2zg1dpi4zcp288rhnvns-glibc-2.30/lib/libc.so.6+0x23d8a)
> SUMMARY: AddressSanitizer: double-free (/nix/store/zhbhxp4jgalycwffildy2bwcgmrsmayk-gcc-9.2.0-lib/lib/libasan.so.5+0x10a1d7) in __interceptor_free
> ==27615==ABORTING
> Process finished with exit code 1
> {noformat}
> The test which follows is currently missing PY decrefs. 
> {noformat}
> #include <Python.h>
> #include <thread>
> #include "helpers.hpp"
> #include "qdr_doctest.h"
> extern "C" {
> #include <qpid/dispatch/python_embedded.h>
> #include <qpid/dispatch/router_core.h>
> #include <router_core/router_core_private.h>
> #include <terminus_private.h>
> #include <inttypes.h>
> #include <stdint.h>
> #include <stdio.h>
> }
> TEST_CASE("policy") {
>     std::thread([]() {
>         WithNoMemoryLeaks leaks{};
>         QDR               qdr;
>         qdr.start();
>         qdr.wait();
>         {
>             auto qd = qdr.qd;
>             PyObject *module = Py_CompileString(
>                 // language: Python
>                 R"EOT(
> class NotBool:
>     def __bool__(self):
>         raise NotImplementedError()
> fake_policy = {
>       "maxConnections": 4,
>       "policyDir": "/tmp",
>       "enableVhostPolicy": 4,
>       "enableVhostNamePatterns": NotBool(),
> })EOT",
>                 "test_module", Py_file_input);
>             REQUIRE(module != nullptr);
>             PyObject *pModuleObj = PyImport_ExecCodeModule("test_module", module);
>             CHECK(pModuleObj != nullptr);
>             PyErr_Print();
>             PyObject *pAttrObj = PyObject_GetAttrString(pModuleObj, "fake_policy");
>             REQUIRE(pAttrObj != nullptr);
>             auto *entity = reinterpret_cast<qd_entity_t *>(pAttrObj);
>             REQUIRE(qd_entity_has(entity, "enableVhostNamePatterns"));  // sanity check for the test input
>             // TODO Py Decrefs probably needed somewhere
>             const qd_python_lock_state_t lock_state = qd_python_lock();
>             qd_error_t                   err = qd_dispatch_configure_policy(qd, entity);
>             CHECK(err == QD_ERROR_PYTHON);
>             qd_python_unlock(lock_state);
>         }
>         qdr.stop();
>     }).join();
> }
> {noformat}



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
For additional commands, e-mail: dev-help@qpid.apache.org