]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
firmware: arm_ffa: Keep framework RX release under lock
authorSudeep Holla <sudeep.holla@kernel.org>
Tue, 28 Apr 2026 18:33:31 +0000 (19:33 +0100)
committerSudeep Holla <sudeep.holla@kernel.org>
Tue, 5 May 2026 15:42:48 +0000 (16:42 +0100)
The framework notification handler drops rx_lock before issuing
FFA_RX_RELEASE, leaving a window where another RX-buffer user can
start a new FF-A transaction before ownership has actually been
returned to firmware.

Move the FFA_RX_RELEASE calls so they execute while rx_lock is still
held on both the kmemdup() failure path and the normal success path.
While doing that, switch the handler to scoped_guard() to keep the
critical section explicit.

Fixes: 285a5ea0f542 ("firmware: arm_ffa: Add support for handling framework notifications")
Link: https://patch.msgid.link/20260428-ffa_fixes-v2-7-8595ae450034@kernel.org
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
drivers/firmware/arm_ffa/driver.c

index 33b417e78684de267d32833a8f51c303b3d34b69..d1e70866a425477331284042122b0781a303505d 100644 (file)
@@ -1492,25 +1492,22 @@ static void handle_fwk_notif_callbacks(u32 bitmap)
        if (!(bitmap & FRAMEWORK_NOTIFY_RX_BUFFER_FULL))
                return;
 
-       mutex_lock(&drv_info->rx_lock);
+       scoped_guard(mutex, &drv_info->rx_lock) {
+               msg = drv_info->rx_buffer;
+               buf = kmemdup((void *)msg + msg->offset, msg->size, GFP_KERNEL);
+               if (!buf) {
+                       ffa_rx_release();
+                       return;
+               }
 
-       msg = drv_info->rx_buffer;
-       buf = kmemdup((void *)msg + msg->offset, msg->size, GFP_KERNEL);
-       if (!buf) {
-               mutex_unlock(&drv_info->rx_lock);
-               return;
+               target = SENDER_ID(msg->send_recv_id);
+               if (msg->offset >= sizeof(*msg))
+                       uuid_copy(&uuid, &msg->uuid);
+               else
+                       uuid_copy(&uuid, &uuid_null);
+               ffa_rx_release();
        }
 
-       target = SENDER_ID(msg->send_recv_id);
-       if (msg->offset >= sizeof(*msg))
-               uuid_copy(&uuid, &msg->uuid);
-       else
-               uuid_copy(&uuid, &uuid_null);
-
-       mutex_unlock(&drv_info->rx_lock);
-
-       ffa_rx_release();
-
        read_lock(&drv_info->notify_lock);
        cb_info = notifier_hnode_get_by_vmid_uuid(notify_id, target, &uuid);
        read_unlock(&drv_info->notify_lock);