Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 07ef191b authored by Sunil Ravi's avatar Sunil Ravi
Browse files

wifi: Clear ring bufffers on detecting buffer corruption

While appending the newly received buffer to ring buffer list,
check the size of the first buffer in the ring buffer list.
If it is invalid(zero size or exceeding the max allowed size),
return failure & clear all the ring buffers.

Bug: 232477451
Test: vts test - 1.6/default/tests/runtests.sh
Test: Manual - Ran basic wifi tests & checked bugreports

Change-Id: Iaa41262f534914b971fe178053f1974248a46e70
parent aff537b7
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -26,20 +26,26 @@ namespace implementation {

Ringbuffer::Ringbuffer(size_t maxSize) : size_(0), maxSize_(maxSize) {}

void Ringbuffer::append(const std::vector<uint8_t>& input) {
enum Ringbuffer::AppendStatus Ringbuffer::append(const std::vector<uint8_t>& input) {
    if (input.size() == 0) {
        return;
        return AppendStatus::FAIL_IP_BUFFER_ZERO;
    }
    if (input.size() > maxSize_) {
        LOG(INFO) << "Oversized message of " << input.size() << " bytes is dropped";
        return;
        return AppendStatus::FAIL_IP_BUFFER_EXCEEDED_MAXSIZE;
    }
    data_.push_back(input);
    size_ += input.size() * sizeof(input[0]);
    while (size_ > maxSize_) {
        if (data_.front().size() <= 0 || data_.front().size() > maxSize_) {
            LOG(ERROR) << "First buffer in the ring buffer is Invalid. Size: "
                       << data_.front().size();
            return AppendStatus::FAIL_RING_BUFFER_CORRUPTED;
        }
        size_ -= data_.front().size() * sizeof(data_.front()[0]);
        data_.pop_front();
    }
    return AppendStatus::SUCCESS;
}

const std::list<std::vector<uint8_t>>& Ringbuffer::getData() const {
+9 −1
Original line number Diff line number Diff line
@@ -31,11 +31,19 @@ namespace implementation {
 */
class Ringbuffer {
  public:
    // Error codes for the append ring buffer operation
    enum AppendStatus {
        SUCCESS,
        FAIL_GENERIC,
        FAIL_IP_BUFFER_ZERO,
        FAIL_IP_BUFFER_EXCEEDED_MAXSIZE,
        FAIL_RING_BUFFER_CORRUPTED
    };
    explicit Ringbuffer(size_t maxSize);

    // Appends the data buffer and deletes from the front until buffer is
    // within |maxSize_|.
    void append(const std::vector<uint8_t>& input);
    enum AppendStatus append(const std::vector<uint8_t>& input);
    const std::list<std::vector<uint8_t>>& getData() const;
    void clear();

+13 −1
Original line number Diff line number Diff line
@@ -1613,6 +1613,7 @@ WifiStatus WifiChip::registerDebugRingBufferCallback() {
                    return;
                }
                WifiDebugRingBufferStatus hidl_status;
                Ringbuffer::AppendStatus appendstatus;
                if (!hidl_struct_util::convertLegacyDebugRingBufferStatusToHidl(status,
                                                                                &hidl_status)) {
                    LOG(ERROR) << "Error converting ring buffer status";
@@ -1623,13 +1624,19 @@ WifiStatus WifiChip::registerDebugRingBufferCallback() {
                    const auto& target = shared_ptr_this->ringbuffer_map_.find(name);
                    if (target != shared_ptr_this->ringbuffer_map_.end()) {
                        Ringbuffer& cur_buffer = target->second;
                        cur_buffer.append(data);
                        appendstatus = cur_buffer.append(data);
                    } else {
                        LOG(ERROR) << "Ringname " << name << " not found";
                        return;
                    }
                    // unique_lock unlocked here
                }
                if (appendstatus == Ringbuffer::AppendStatus::FAIL_RING_BUFFER_CORRUPTED) {
                    LOG(ERROR) << "Ringname " << name << " is corrupted. Clear the ring buffer";
                    shared_ptr_this->writeRingbufferFilesInternal();
                    return;
                }

            };
    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->registerRingBufferCallbackHandler(
            getFirstActiveWlanIfaceName(), on_ring_buffer_data_callback);
@@ -1971,6 +1978,11 @@ bool WifiChip::writeRingbufferFilesInternal() {
            }
            unique_fd file_auto_closer(dump_fd);
            for (const auto& cur_block : cur_buffer.getData()) {
                if (cur_block.size() <= 0 || cur_block.size() > kMaxBufferSizeBytes) {
                    PLOG(ERROR) << "Ring buffer: " << item.first
                                << " is corrupted. Invalid block size: " << cur_block.size();
                    break;
                }
                if (write(dump_fd, cur_block.data(), sizeof(cur_block[0]) * cur_block.size()) ==
                    -1) {
                    PLOG(ERROR) << "Error writing to file";