summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmelle Laine <armellel@google.com>2022-01-24 05:18:40 +0000
committerArmelle Laine <armellel@google.com>2022-01-26 03:40:02 +0000
commitd3586e84c998fba6577f203c62b5405e1ea8d96a (patch)
tree8b858232e50606d2e0a0215b4001ac79ffb3c011
parent16ac6d28aeb70cd5fced6f65061cc74058da0484 (diff)
downloadgatekeeper-d3586e84c998fba6577f203c62b5405e1ea8d96a.tar.gz
Fix race condition in gatekeeper ipc
Current trusty ipc logic (trusty/kernel/lib/trusty/tipc_virtio_dev.c) drops a message on a channel when its receive fifo is full (the receive fifo size is determined by the argument `recv_buf_size` passed in the port_create api). Filling the receive fifo can only happen when a new message is received while the previous one has not been retired yet (via a call to put_msg). HAL to TA IPC won't hit this issue when following the recommended pattern: - HAL: - send a message - wait for its response - send the next message. - TA: - receive a message - retire it from the receive fifo - then send the response. Prior to this fix, gatekeeper TA used to send the response THEN retire the message, while having a receive fifo size of 1. This creates the race condition where the message would be dropped. The fix consists in retiring the message (put_msg) prior to sending the response. Bug: 211378534 Change-Id: I957e72183d92131adb37316f29d7e2963679df29
-rw-r--r--ipc/gatekeeper_ipc.cpp22
1 files changed, 6 insertions, 16 deletions
diff --git a/ipc/gatekeeper_ipc.cpp b/ipc/gatekeeper_ipc.cpp
index 9994697..fd88770 100644
--- a/ipc/gatekeeper_ipc.cpp
+++ b/ipc/gatekeeper_ipc.cpp
@@ -33,20 +33,6 @@ public:
~SessionManager() { device->CloseSession(); }
};
-class MessageDeleter {
-public:
- explicit MessageDeleter(handle_t chan, int id) {
- chan_ = chan;
- id_ = id;
- }
-
- ~MessageDeleter() { put_msg(chan_, id_); }
-
-private:
- handle_t chan_;
- int id_;
-};
-
static gatekeeper_error_t tipc_err_to_gatekeeper_err(long tipc_err) {
switch (tipc_err) {
case NO_ERROR:
@@ -187,8 +173,9 @@ static gatekeeper_error_t handle_msg(handle_t chan) {
return tipc_err_to_gatekeeper_err(rc);
}
- MessageDeleter md(chan, msg_inf.id);
-
+ /* TODO: handle heap allocation failure
+ * and retire the message on failure too
+ */
UniquePtr<uint8_t[]> msg_buf(new uint8_t[msg_inf.len]);
/* read msg content */
@@ -197,6 +184,9 @@ static gatekeeper_error_t handle_msg(handle_t chan) {
rc = read_msg(chan, msg_inf.id, 0, &msg);
+ // retire the message (note msg_inf.id becomes invalid after put_msg)
+ put_msg(chan, msg_inf.id);
+
if (rc < 0) {
TLOGE("failed to read msg (%ld) for chan (%d)\n", rc, chan);
return tipc_err_to_gatekeeper_err(rc);