From 23b7021c00b0a52cd7837c9d51cfa7fa52dc9776 Mon Sep 17 00:00:00 2001 From: Vernon Mauery Date: Wed, 8 May 2019 15:19:05 -0700 Subject: Legacy D-Bus interface must set yield_context The legacy D-Bus interface was not setting the yield_context pointer in the ipmi::Context struct. This means that a command coming in from a legacy D-Bus interface that called a new-provider that uses the yield_method_call function would segfault on a NULL pointer. This change makes the legacy interface behave the same as the new D-Bus interface by creating a new boost::coroutine for each command. Tested-by: running a legacy ipmitool to ensure that the rewritten set chassis power restore policy command worked without a segfault. Change-Id: Ie45fff1fc222b9b949a9d3976bf9d1b2c29bd8f5 Signed-off-by: Vernon Mauery --- ipmid-new.cpp | 59 ++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/ipmid-new.cpp b/ipmid-new.cpp index 5eec4d1..7e77b12 100644 --- a/ipmid-new.cpp +++ b/ipmid-new.cpp @@ -739,29 +739,42 @@ Router* mutableRouter() /* legacy alternative to executionEntry */ void handleLegacyIpmiCommand(sdbusplus::message::message& m) { - unsigned char seq, netFn, lun, cmd; - std::vector data; - - m.read(seq, netFn, lun, cmd, data); - - auto ctx = std::make_shared(netFn, cmd, 0, 0, - ipmi::Privilege::Admin); - auto request = std::make_shared( - ctx, std::forward>(data)); - ipmi::message::Response::ptr response = ipmi::executeIpmiCommand(request); - - // Responses in IPMI require a bit set. So there ya go... - netFn |= 0x01; - - const char *dest, *path; - constexpr const char* DBUS_INTF = "org.openbmc.HostIpmi"; - - dest = m.get_sender(); - path = m.get_path(); - getSdBus()->async_method_call([](boost::system::error_code ec) {}, dest, - path, DBUS_INTF, "sendMessage", seq, netFn, - lun, cmd, response->cc, - response->payload.raw); + // make a copy so the next two moves don't wreak havoc on the stack + sdbusplus::message::message b{m}; + boost::asio::spawn(*getIoContext(), [b = std::move(b)]( + boost::asio::yield_context yield) { + sdbusplus::message::message m{std::move(b)}; + unsigned char seq, netFn, lun, cmd; + std::vector data; + + m.read(seq, netFn, lun, cmd, data); + auto ctx = std::make_shared( + netFn, cmd, 0, 0, ipmi::Privilege::Admin, 0, &yield); + auto request = std::make_shared( + ctx, std::forward>(data)); + ipmi::message::Response::ptr response = + ipmi::executeIpmiCommand(request); + + // Responses in IPMI require a bit set. So there ya go... + netFn |= 0x01; + + const char *dest, *path; + constexpr const char* DBUS_INTF = "org.openbmc.HostIpmi"; + + dest = m.get_sender(); + path = m.get_path(); + boost::system::error_code ec; + getSdBus()->yield_method_call(yield, ec, dest, path, DBUS_INTF, + "sendMessage", seq, netFn, lun, cmd, + response->cc, response->payload.raw); + if (ec) + { + log("Failed to send response to requestor", + entry("ERROR=%s", ec.message().c_str()), + entry("SENDER=%s", dest), + entry("NETFN=0x%X", netFn), entry("CMD=0x%X", cmd)); + } + }); } #endif /* ALLOW_DEPRECATED_API */ -- cgit v1.2.1