Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/trusty/trusty/user/app/avb/ipc/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 10 kB image not shown  

Quelle  avb_ipc.cpp

  Sprache: C
 

/*
 * Copyright 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include <UniquePtr.h>
#include <trusty_ipc.h>
#include <uapi/err.h>

#include "avb_ipc.h"
#include "avb_manager.h"
#include "secure_storage.h"

const char kAvbServiceName[] = "com.android.trusty.avb";
const int kAvbServiceNumBufs = 1;
const int kAvbServiceBufSize = 2048;
const uint32_t kAvbServiceFlags = IPC_PORT_ALLOW_NS_CONNECT;
static bool boot_state_locked = false;

avb::AvbManager* g_avb_manager;

namespace avb {

// Deserializes request in |in_buf|, calls |operation| to execute request,
// and serializes response to |out_buf|. Returns a Trusty error code if there
// is a problem during serializing the response or deserializing the request.
template <typename Request, typename Response>
static int ExecuteCommand(void (AvbManager::*operation)(const Request&,
                                                        Response*),
                          const uint8_t* in_buf,
                          uint32_t in_size,
                          UniquePtr<uint8_t[]>* out_buf,
                          uint32_t* out_size,
                          AvbError* error) {
    Request req;
    int rc = req.Deserialize(in_buf, in_buf + in_size);
    if (rc < 0) {
        TLOGE("Error deserializing request: %d\n", rc);
        return rc;
    }
    Response rsp;
    (g_avb_manager->*operation)(req, &rsp);

    *error = rsp.get_error();
    *out_size = rsp.GetSerializedSize();
    if (*out_size > kAvbServiceBufSize) {
        TLOGE("Response size too large: %d\n", *out_size);
        *out_size = 0;
        return ERR_TOO_BIG;
    }

    if (*out_size == 0) {
        return NO_ERROR;
    }

    out_buf->reset(new uint8_t[*out_size]);
    if (out_buf->get() == nullptr) {
        *out_size = 0;
        return ERR_NO_MEMORY;
    }

    if (rsp.Serialize(out_buf->get(), out_buf->get() + *out_size) !=
        *out_size) {
        TLOGE("Error serializing response message\n");
        return ERR_NOT_VALID;
    }

    return NO_ERROR;
}

// Dispatches command |cmd|. Fulfills request in |in_buf|, and writes response
// to |out_buf|. Returns a Trusty error code if there is a problem serializing
// the response or deserializing the request. Avb specific errors are put in
// |error|.
static int ProcessRequest(uint32_t cmd,
                          const uint8_t* in_buf,
                          uint32_t in_size,
                          UniquePtr<uint8_t[]>* out_buf,
                          uint32_t* out_size,
                          AvbError* error) {
    if (boot_state_locked) {
        switch (cmd) {
        case WRITE_ROLLBACK_INDEX:
        case WRITE_PERMANENT_ATTRIBUTES:
        case WRITE_LOCK_STATE:
            *out_size = 0;
            *error = AvbError::kInvalid;
            return NO_ERROR;
        }
    }
    switch (cmd) {
    case READ_ROLLBACK_INDEX:
        return ExecuteCommand(&AvbManager::ReadRollbackIndex, in_buf, in_size,
                              out_buf, out_size, error);
    case WRITE_ROLLBACK_INDEX:
        return ExecuteCommand(&AvbManager::WriteRollbackIndex, in_buf, in_size,
                              out_buf, out_size, error);
    case AVB_GET_VERSION:
        return ExecuteCommand(&AvbManager::GetVersion, in_buf, in_size, out_buf,
                              out_size, error);
    case READ_PERMANENT_ATTRIBUTES:
        return ExecuteCommand(&AvbManager::ReadPermanentAttributes, in_buf,
                              in_size, out_buf, out_size, error);
    case WRITE_PERMANENT_ATTRIBUTES:
        return ExecuteCommand(&AvbManager::WritePermanentAttributes, in_buf,
                              in_size, out_buf, out_size, error);
    case READ_LOCK_STATE:
        return ExecuteCommand(&AvbManager::ReadLockState, in_buf, in_size,
                              out_buf, out_size, error);
    case WRITE_LOCK_STATE:
        return ExecuteCommand(&AvbManager::WriteLockState, in_buf, in_size,
                              out_buf, out_size, error);
    case LOCK_BOOT_STATE:
        *out_size = 0;
        *error = AvbError::kNone;
        boot_state_locked = true;
        return NO_ERROR;

    default:
        return ERR_NOT_VALID;
    }
}

// Reads the message described by |msg_info| from channel and processes it.
// Writes the response message back to |channel|. Returns a Trusty error code if
// there is any I/O problem.
static int ProcessOneMessage(handle_t channel, const ipc_msg_info_t& msg_info) {
    if (msg_info.len > kAvbServiceBufSize) {
        TLOGE("Message too large on channel %x: %zu", channel, msg_info.len);
        return ERR_TOO_BIG;
    }
    UniquePtr<uint8_t[]> msg_buf(new uint8_t[msg_info.len]);

    struct iovec request_iov = {msg_buf.get(), msg_info.len};
    ipc_msg_t request_msg = {
            1,             // number of iovecs
            &request_iov,  // iovecs pointer
            0,             // number of handles
            nullptr        // handles pointer
    };

    int rc = read_msg(channel, msg_info.id, 0, &request_msg);

    if (rc < 0) {
        TLOGE("Failed to read msg for channel %x: %d\n", channel, rc);
        return rc;
    }

    if (((size_t)rc) < sizeof(avb_message)) {
        TLOGE("Invalid message of size %zu for channel %x\n", (size_t)rc,
              channel);
        return ERR_NOT_VALID;
    }

    // Parse and handle request
    avb_message* avb_request_header =
            reinterpret_cast<struct avb_message*>(msg_buf.get());
    UniquePtr<uint8_t[]> out_buf;
    uint32_t out_size = 0;
    AvbError error;
    rc = ProcessRequest(avb_request_header->cmd, avb_request_header->payload,
                        msg_info.len - sizeof(avb_message), &out_buf, &out_size,
                        &error);
    if (rc < 0) {
        TLOGE("Unable to handle request: %d", rc);
        return rc;
    }

    // Send response message back to caller
    avb_message avb_response_header = {
            .cmd = avb_request_header->cmd | AVB_RESP_BIT,
            .result = error,
            .payload = {},
    };
    struct iovec response_iov[2] = {
            {&avb_response_header, sizeof(avb_response_header)},
            {out_buf.get(), out_size},
    };
    ipc_msg_t response_msg = {
            2,             // number of iovecs
            response_iov,  // iovecs pointer
            0,             // number of handles
            nullptr        // handles pointer
    };
    rc = send_msg(channel, &response_msg);
    if (rc < 0) {
        TLOGE("Failed to send_msg on channel %x: %d\n", channel, rc);
        return rc;
    }
    return NO_ERROR;
}

// Receives all pending messages from |channel| and processes them, sending
// responses as appropriate. Returns a Trusty error code if there is a
// problem with message processing or I/O.
static int ProcessMessages(handle_t channel) {
    while (true) {
        ipc_msg_info_t msg_info;
        int rc = get_msg(channel, &msg_info);
        if (rc == ERR_NO_MSG) {
            break;
        }

        if (rc != NO_ERROR) {
            TLOGE("Failed to get_msg on channel %x: %d\n", channel, rc);
            return rc;
        }

        rc = ProcessOneMessage(channel, msg_info);
        if (rc != NO_ERROR) {
            put_msg(channel, msg_info.id);
            return rc;
        }

        rc = put_msg(channel, msg_info.id);
        if (rc != NO_ERROR) {
            TLOGE("Failed to put_msg on channel %x: %d\n", rc, channel);
            return rc;
        }
    }

    return NO_ERROR;
}

// Handles an |event| on a channel. If it is an incoming message, it is
// processed. Otherwise, the event indicates a channel hangup or error, so
// the channel is closed.
static void HandleChannelEvent(const uevent_t& event) {
    if ((event.event & IPC_HANDLE_POLL_ERROR) ||
        (event.event & IPC_HANDLE_POLL_READY)) {
        // close it as it is in an error state
        TLOGE("Error event on channel %x: 0x%x\n", event.event, event.handle);
        close(event.handle);
    }

    if (event.event & IPC_HANDLE_POLL_HUP) {
        // closed by peer
        close(event.handle);
        return;
    }

    if (event.event & IPC_HANDLE_POLL_MSG) {
        if (ProcessMessages(event.handle) != NO_ERROR) {
            close(event.handle);
        }
    }
}

// Handles an |event| on a port. If it is an incoming connection event,
// the connection is accepted. Any other event is unexpected.
static void HandlePortEvent(const uevent_t& event) {
    if (event.event & IPC_HANDLE_POLL_READY) {
        // incoming connection: accept it
        uuid_t peer_uuid;
        int rc = accept(event.handle, &peer_uuid);
        if (rc < 0) {
            TLOGE("Failed to accept on port %d: %d\n", event.handle, rc);
        }
    } else {
        TLOGE("Unexpected event on port %d: 0x%x\n", event.handle, event.event);
    }
}

}  // namespace avb

int main(void) {
    avb::AvbManager avb_manager(new avb::SecureStorage);
    g_avb_manager = &avb_manager;

    TLOGD("Initializing AVB App\n");

    int rc = port_create(kAvbServiceName, kAvbServiceNumBufs,
                         kAvbServiceBufSize, kAvbServiceFlags);
    if (rc < 0) {
        TLOGE("Failed to initialize AVB app: %d", rc);
        return rc;
    }

    handle_t port = static_cast<handle_t>(rc);

    // enter main event loop
    while (true) {
        uevent_t event;
        event.handle = INVALID_IPC_HANDLE;
        event.event = 0;
        event.cookie = nullptr;
        rc = wait_any(&event, INFINITE_TIME);

        if (rc == NO_ERROR) {  // got an event
            if (event.handle == port) {
                avb::HandlePortEvent(event);
            } else {
                avb::HandleChannelEvent(event);
            }
        } else {
            TLOGE("wait_any failed: %d\n", rc);
        }
    }

    g_avb_manager = nullptr;
    return 0;
}

Messung V0.5 in Prozent
C=93 H=96 G=94

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet am  2026-06-26) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.