blob: e4f03cfe4aea3fe9dc65ee4e1ff8628a48eba794 [file] [log] [blame]
/*
* Copyright (C) 2024 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 "src/trace_redaction/scrub_trace_packet.h"
namespace perfetto::trace_redaction {
// The TracePacket message has a simple structure. At its core its one sub
// message (e.g. ProcessTree) and some additional context (e.g. timestamp).
// This makes the per-packet check binary - does it contain one of the
// allow-listed messages?
//
// This transform will be called P times where P is the number of packet in the
// trace.
//
// There are A packet types in the allow-list. The allow-list in a set with logA
// look up. Since the allow-list is relatively small and constant in size,
// allow-list can be considered constant.
//
// There are at most F fields where F is the max number of concurrent fields in
// a trace packet. Given the limit, this can be considered constant.
//
// All together, this implementation can be considered linear in relation to the
// trace size.
base::Status ScrubTracePacket::Transform(const Context& context,
std::string* packet) const {
if (packet == nullptr || packet->empty()) {
return base::ErrStatus("Cannot scrub null or empty trace packet.");
}
const auto& allow_list = context.trace_packet_allow_list;
if (allow_list.empty()) {
return base::ErrStatus("Cannot scrub trace packets, missing allow-list.");
}
protozero::ProtoDecoder d(*packet);
// A packet should only have one data type (proto oneof), but there are other
// values in the packet (e.g. timestamp). If one field is in the allowlist,
// then allow the whole trace packet.
for (auto f = d.ReadField(); f.valid(); f = d.ReadField()) {
if (allow_list.count(f.id()) != 0) {
return base::OkStatus();
}
}
packet->clear();
return base::OkStatus();
}
} // namespace perfetto::trace_redaction