fw-update: reject mismatched EID in ItemUpdateManager dispatch ItemUpdateManager::handleRequest declared its eid parameter as mctp_eid_t /*eid*/ and dispatched purely on command. Combined with AggregateUpdateManager iterating updateManagers in SoftwareIdentifier (i.e. eid-then-component) order, whichever active ItemUpdateManager came first claimed every FW-update response regardless of the inbound EID. Two concurrent target updates on different EIDs would have all responses funneled to the lower-EID manager. Concretely: with an update on EID 12 in flight, starting an update on EID 10 created ItemUpdateManager(10). EID 12's apply_complete was then consumed by deviceUpdater10 and logged as if it belonged to EID 10 (device_updater.cpp:858 uses the deviceUpdater's own eid member). EID 10 timed out on ActivateFirmware while EID 12's deviceUpdater state was corrupted by the misrouted messages. The per-ItemUpdateManager state (deviceUpdater, packageMap, dupFd, inProgressActivation, ...) is already independent, and the shared Handler<Request>/InstanceIdDb demux BMC->FD responses by (eid, instanceId), so concurrent multi-EID target updates work correctly once the responder path stops the cross-EID misrouting. Add an explicit eid != this->eid early-return that yields PLDM_FWUP_COMMAND_NOT_EXPECTED, letting AggregateUpdateManager fall through to the next manager. Fold the !deviceUpdater branch into the same early-return since it returns the same encoded response, and convert the placement-new calls to std::start_lifetime_as<> to match the rest of the codebase. Tested on nvl32-obmc: - Full bundle multipart update. - Single target update. - Back to back single-target updates. - Full bundle update followed by a target update (previously flooded the journal with "invalid state when updating progress" and served data from the stale bundle DeviceUpdater; now routed correctly). - Target update on a second PLDM device while an update on another device is in progress: both complete successfully. - Target update on the same device while its update is in progress: rejected as expected. Signed-off-by: Dhruv Rathi <rathidhruv04@gmail.com> Change-Id: I390c54c82fc6405de37a06af6a8d0e80d31735d3
diff --git a/fw-update/item_update_manager.cpp b/fw-update/item_update_manager.cpp index 4e5def4..2d014dd 100644 --- a/fw-update/item_update_manager.cpp +++ b/fw-update/item_update_manager.cpp
@@ -1,6 +1,7 @@ #include "item_update_manager.hpp" #include "activation.hpp" +#include "common/start_lifetime_as.hpp" #include "common/utils.hpp" #include "package_parser.hpp" @@ -173,47 +174,42 @@ return; } -Response ItemUpdateManager::handleRequest(mctp_eid_t /*eid*/, uint8_t command, - const pldm_msg* request, - size_t reqMsgLen) +Response ItemUpdateManager::handleRequest( + mctp_eid_t eid, uint8_t command, const pldm_msg* request, size_t reqMsgLen) { Response response(sizeof(pldm_msg), 0); - if (deviceUpdater) + if (eid != this->eid || !deviceUpdater) { - if (command == PLDM_REQUEST_FIRMWARE_DATA) - { - return deviceUpdater->requestFwData(request, reqMsgLen); - } - else if (command == PLDM_TRANSFER_COMPLETE) - { - return deviceUpdater->transferComplete(request, reqMsgLen); - } - else if (command == PLDM_VERIFY_COMPLETE) - { - return deviceUpdater->verifyComplete(request, reqMsgLen); - } - else if (command == PLDM_APPLY_COMPLETE) - { - return deviceUpdater->applyComplete(request, reqMsgLen); - } - else - { - auto ptr = new (response.data()) pldm_msg; - auto rc = encode_cc_only_resp( - request->hdr.instance_id, request->hdr.type, - request->hdr.command, PLDM_ERROR_INVALID_DATA, ptr); - assert(rc == PLDM_SUCCESS); - } - } - else - { - auto ptr = new (response.data()) pldm_msg; + auto ptr = std::start_lifetime_as<pldm_msg>(response.data()); auto rc = encode_cc_only_resp(request->hdr.instance_id, - request->hdr.type, +request->hdr.command, + request->hdr.type, request->hdr.command, PLDM_FWUP_COMMAND_NOT_EXPECTED, ptr); assert(rc == PLDM_SUCCESS); + return response; } + if (command == PLDM_REQUEST_FIRMWARE_DATA) + { + return deviceUpdater->requestFwData(request, reqMsgLen); + } + else if (command == PLDM_TRANSFER_COMPLETE) + { + return deviceUpdater->transferComplete(request, reqMsgLen); + } + else if (command == PLDM_VERIFY_COMPLETE) + { + return deviceUpdater->verifyComplete(request, reqMsgLen); + } + else if (command == PLDM_APPLY_COMPLETE) + { + return deviceUpdater->applyComplete(request, reqMsgLen); + } + + auto ptr = std::start_lifetime_as<pldm_msg>(response.data()); + auto rc = + encode_cc_only_resp(request->hdr.instance_id, request->hdr.type, + request->hdr.command, PLDM_ERROR_INVALID_DATA, ptr); + assert(rc == PLDM_SUCCESS); return response; }