Loading Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ cc_library { "core/proto/android/os/procrank.proto", "core/proto/android/os/system_properties.proto", "core/proto/android/service/graphicsstats.proto", "libs/incident/proto/android/privacy.proto", "tools/streaming_proto/stream.proto", ], shared: { Loading cmds/incidentd/src/Privacy.cpp +22 −37 Original line number Diff line number Diff line Loading @@ -16,37 +16,18 @@ #include "Privacy.h" #include <android/os/IncidentReportArgs.h> #include <stdlib.h> // DESTINATION enum value const uint8_t DEST_LOCAL = 0; const uint8_t DEST_EXPLICIT = 1; const uint8_t DEST_AUTOMATIC = 2; uint64_t encode_field_id(const Privacy* p) { return (uint64_t)p->type << 32 | p->field_id; } // type of the field, identitical to protobuf definition const uint8_t TYPE_STRING = 9; const uint8_t TYPE_MESSAGE = 11; bool Privacy::IsMessageType() const { return type == TYPE_MESSAGE; } uint64_t Privacy::EncodedFieldId() const { return (uint64_t)type << 32 | field_id; } bool Privacy::IsStringType() const { return type == TYPE_STRING; } bool Privacy::HasChildren() const { return children != NULL && children[0] != NULL; } const Privacy* Privacy::lookup(uint32_t fieldId) const const Privacy* lookup(const Privacy* p, uint32_t fieldId) { if (children == NULL) return NULL; for (int i=0; children[i] != NULL; i++) { if (children[i]->field_id == fieldId) return children[i]; // This assumes the list's field id is in ascending order and must be true. if (children[i]->field_id > fieldId) return NULL; if (p->children == NULL) return NULL; for (int i=0; p->children[i] != NULL; i++) { // NULL-terminated. if (p->children[i]->field_id == fieldId) return p->children[i]; // Incident section gen tool guarantees field ids in ascending order. if (p->children[i]->field_id > fieldId) return NULL; } return NULL; } Loading @@ -54,11 +35,14 @@ Privacy::lookup(uint32_t fieldId) const static bool allowDest(const uint8_t dest, const uint8_t policy) { switch (policy) { case DEST_LOCAL: return dest == DEST_LOCAL; case DEST_EXPLICIT: return dest == DEST_LOCAL || dest == DEST_EXPLICIT; case DEST_AUTOMATIC: case android::os::DEST_LOCAL: return dest == android::os::DEST_LOCAL; case android::os::DEST_EXPLICIT: case DEST_UNSET: return dest == android::os::DEST_LOCAL || dest == android::os::DEST_EXPLICIT || dest == DEST_UNSET; case android::os::DEST_AUTOMATIC: return true; default: return false; Loading @@ -72,18 +56,19 @@ PrivacySpec::operator<(const PrivacySpec& other) const } bool PrivacySpec::CheckPremission(const Privacy* privacy) const PrivacySpec::CheckPremission(const Privacy* privacy, const uint8_t defaultDest) const { uint8_t policy = privacy == NULL ? DEST_DEFAULT_VALUE : privacy->dest; uint8_t policy = privacy != NULL ? privacy->dest : defaultDest; return allowDest(dest, policy); } bool PrivacySpec::RequireAll() const { return dest == DEST_LOCAL; } PrivacySpec::RequireAll() const { return dest == android::os::DEST_LOCAL; } PrivacySpec new_spec_from_args(int dest) { PrivacySpec new_spec_from_args(int dest) { if (dest < 0) return PrivacySpec(); return PrivacySpec(dest); } PrivacySpec get_default_dropbox_spec() { return PrivacySpec(DEST_AUTOMATIC); } No newline at end of file PrivacySpec get_default_dropbox_spec() { return PrivacySpec(android::os::DEST_AUTOMATIC); } No newline at end of file cmds/incidentd/src/Privacy.h +29 −15 Original line number Diff line number Diff line Loading @@ -19,35 +19,46 @@ #include <stdint.h> // This is the default value of DEST enum const uint8_t DEST_DEFAULT_VALUE = 1; // This is the default value of DEST enum, sync with privacy.proto const uint8_t DEST_UNSET = 255; // DEST_UNSET is not exposed to libincident const uint8_t DEST_DEFAULT_VALUE = DEST_UNSET; /* * In order not to depend on libprotobuf-cpp-full nor libplatformprotos in incidentd, * privacy options's data structure are explicitly redefined in this file. * In order to NOT auto-generate large chuck of code by proto compiler in incidentd, * privacy options's data structure are explicitly redefined here and * the values are populated by incident_section_gen tool. * * Each proto field will have a Privacy when it is different from its parent, otherwise * it uses its parent's tag. A message type will have an array of Privacy. */ struct Privacy { // The field number uint32_t field_id; // The field type, see external/protobuf/src/google/protobuf/descriptor.h uint8_t type; // ignore parent's privacy flags if children are set, NULL-terminated // If children is null, it is a primitive field, // otherwise it is a message field which could have overridden privacy tags here. // This array is NULL-terminated. Privacy** children; // the following fields are identitical to // frameworks/base/libs/incident/proto/android/privacy.proto // DESTINATION Enum in frameworks/base/libs/incident/proto/android/privacy.proto. uint8_t dest; const char** patterns; // only set when type is string // A list of regexp rules for stripping string fields in proto. const char** patterns; }; bool IsMessageType() const; bool IsStringType() const; bool HasChildren() const; uint64_t EncodedFieldId() const; // Encode field id used by ProtoOutputStream. uint64_t encode_field_id(const Privacy* p); const Privacy* lookup(uint32_t fieldId) const; }; // Look up the child with given fieldId, if not found, return NULL. const Privacy* lookup(const Privacy* p, uint32_t fieldId); /** * PrivacySpec defines the request has what level of privacy authorization. * For example, a device without user consent should only be able to upload AUTOMATIC fields. * DEST_UNSET are treated as DEST_EXPLICIT. */ class PrivacySpec { public: Loading @@ -58,7 +69,10 @@ public: bool operator<(const PrivacySpec& other) const; bool CheckPremission(const Privacy* privacy) const; // check permission of a policy, if returns true, don't strip the data. bool CheckPremission(const Privacy* privacy, const uint8_t defaultDest = DEST_DEFAULT_VALUE) const; // if returns true, no data need to be stripped. bool RequireAll() const; }; Loading cmds/incidentd/src/PrivacyBuffer.cpp +17 −6 Original line number Diff line number Diff line Loading @@ -14,15 +14,18 @@ * limitations under the License. */ #define LOG_TAG "incidentd" #include "PrivacyBuffer.h" #include "io_util.h" #include <android/util/protobuf.h> #include <cutils/log.h> using namespace android::util; const bool DEBUG = false; /** * Write the field to buf based on the wire type, iterator will point to next field. * If skip is set to true, no data will be written to buf. Return number of bytes written. Loading @@ -30,6 +33,9 @@ using namespace android::util; void PrivacyBuffer::writeFieldOrSkip(uint32_t fieldTag, bool skip) { if (DEBUG) ALOGD("%s field %d (wiretype = %d)", skip ? "skip" : "write", read_field_id(fieldTag), read_wire_type(fieldTag)); uint8_t wireType = read_wire_type(fieldTag); size_t bytesToWrite = 0; uint32_t varint = 0; Loading @@ -55,6 +61,7 @@ PrivacyBuffer::writeFieldOrSkip(uint32_t fieldTag, bool skip) bytesToWrite = 4; break; } if (DEBUG) ALOGD("%s %d bytes of data", skip ? "skip" : "write", (int)bytesToWrite); if (skip) { mData.rp()->move(bytesToWrite); } else { Loading @@ -76,10 +83,13 @@ PrivacyBuffer::stripField(const Privacy* parentPolicy, const PrivacySpec& spec) { if (!mData.hasNext() || parentPolicy == NULL) return BAD_VALUE; uint32_t fieldTag = mData.readRawVarint(); const Privacy* policy = parentPolicy->lookup(read_field_id(fieldTag)); const Privacy* policy = lookup(parentPolicy, read_field_id(fieldTag)); if (policy == NULL || policy->children == NULL) { if (DEBUG) ALOGD("Not a message field %d: dest(%d)", read_field_id(fieldTag), policy != NULL ? policy->dest : parentPolicy->dest); if (policy == NULL || !policy->IsMessageType() || !policy->HasChildren()) { bool skip = !spec.CheckPremission(policy); bool skip = !spec.CheckPremission(policy, parentPolicy->dest); // iterator will point to head of next field writeFieldOrSkip(fieldTag, skip); return NO_ERROR; Loading @@ -87,7 +97,7 @@ PrivacyBuffer::stripField(const Privacy* parentPolicy, const PrivacySpec& spec) // current field is message type and its sub-fields have extra privacy policies uint32_t msgSize = mData.readRawVarint(); EncodedBuffer::Pointer start = mData.rp()->copy(); long long token = mProto.start(policy->EncodedFieldId()); long long token = mProto.start(encode_field_id(policy)); while (mData.rp()->pos() - start.pos() != msgSize) { status_t err = stripField(policy, spec); if (err != NO_ERROR) return err; Loading @@ -112,8 +122,9 @@ PrivacyBuffer::~PrivacyBuffer() status_t PrivacyBuffer::strip(const PrivacySpec& spec) { if (DEBUG) ALOGD("Strip with spec %d", spec.dest); // optimization when no strip happens if (mPolicy == NULL || !mPolicy->HasChildren() || spec.RequireAll()) { if (mPolicy == NULL || mPolicy->children == NULL || spec.RequireAll()) { if (spec.CheckPremission(mPolicy)) mSize = mData.size(); return NO_ERROR; } Loading cmds/incidentd/src/Section.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -210,9 +210,9 @@ HeaderSection::Execute(ReportRequestSet* requests) const { for (ReportRequestSet::iterator it=requests->begin(); it!=requests->end(); it++) { const sp<ReportRequest> request = *it; const vector<vector<int8_t>>& headers = request->args.headers(); const vector<vector<uint8_t>>& headers = request->args.headers(); for (vector<vector<int8_t>>::const_iterator buf=headers.begin(); buf!=headers.end(); buf++) { for (vector<vector<uint8_t>>::const_iterator buf=headers.begin(); buf!=headers.end(); buf++) { if (buf->empty()) continue; // So the idea is only requests with negative fd are written to dropbox file. Loading Loading
Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ cc_library { "core/proto/android/os/procrank.proto", "core/proto/android/os/system_properties.proto", "core/proto/android/service/graphicsstats.proto", "libs/incident/proto/android/privacy.proto", "tools/streaming_proto/stream.proto", ], shared: { Loading
cmds/incidentd/src/Privacy.cpp +22 −37 Original line number Diff line number Diff line Loading @@ -16,37 +16,18 @@ #include "Privacy.h" #include <android/os/IncidentReportArgs.h> #include <stdlib.h> // DESTINATION enum value const uint8_t DEST_LOCAL = 0; const uint8_t DEST_EXPLICIT = 1; const uint8_t DEST_AUTOMATIC = 2; uint64_t encode_field_id(const Privacy* p) { return (uint64_t)p->type << 32 | p->field_id; } // type of the field, identitical to protobuf definition const uint8_t TYPE_STRING = 9; const uint8_t TYPE_MESSAGE = 11; bool Privacy::IsMessageType() const { return type == TYPE_MESSAGE; } uint64_t Privacy::EncodedFieldId() const { return (uint64_t)type << 32 | field_id; } bool Privacy::IsStringType() const { return type == TYPE_STRING; } bool Privacy::HasChildren() const { return children != NULL && children[0] != NULL; } const Privacy* Privacy::lookup(uint32_t fieldId) const const Privacy* lookup(const Privacy* p, uint32_t fieldId) { if (children == NULL) return NULL; for (int i=0; children[i] != NULL; i++) { if (children[i]->field_id == fieldId) return children[i]; // This assumes the list's field id is in ascending order and must be true. if (children[i]->field_id > fieldId) return NULL; if (p->children == NULL) return NULL; for (int i=0; p->children[i] != NULL; i++) { // NULL-terminated. if (p->children[i]->field_id == fieldId) return p->children[i]; // Incident section gen tool guarantees field ids in ascending order. if (p->children[i]->field_id > fieldId) return NULL; } return NULL; } Loading @@ -54,11 +35,14 @@ Privacy::lookup(uint32_t fieldId) const static bool allowDest(const uint8_t dest, const uint8_t policy) { switch (policy) { case DEST_LOCAL: return dest == DEST_LOCAL; case DEST_EXPLICIT: return dest == DEST_LOCAL || dest == DEST_EXPLICIT; case DEST_AUTOMATIC: case android::os::DEST_LOCAL: return dest == android::os::DEST_LOCAL; case android::os::DEST_EXPLICIT: case DEST_UNSET: return dest == android::os::DEST_LOCAL || dest == android::os::DEST_EXPLICIT || dest == DEST_UNSET; case android::os::DEST_AUTOMATIC: return true; default: return false; Loading @@ -72,18 +56,19 @@ PrivacySpec::operator<(const PrivacySpec& other) const } bool PrivacySpec::CheckPremission(const Privacy* privacy) const PrivacySpec::CheckPremission(const Privacy* privacy, const uint8_t defaultDest) const { uint8_t policy = privacy == NULL ? DEST_DEFAULT_VALUE : privacy->dest; uint8_t policy = privacy != NULL ? privacy->dest : defaultDest; return allowDest(dest, policy); } bool PrivacySpec::RequireAll() const { return dest == DEST_LOCAL; } PrivacySpec::RequireAll() const { return dest == android::os::DEST_LOCAL; } PrivacySpec new_spec_from_args(int dest) { PrivacySpec new_spec_from_args(int dest) { if (dest < 0) return PrivacySpec(); return PrivacySpec(dest); } PrivacySpec get_default_dropbox_spec() { return PrivacySpec(DEST_AUTOMATIC); } No newline at end of file PrivacySpec get_default_dropbox_spec() { return PrivacySpec(android::os::DEST_AUTOMATIC); } No newline at end of file
cmds/incidentd/src/Privacy.h +29 −15 Original line number Diff line number Diff line Loading @@ -19,35 +19,46 @@ #include <stdint.h> // This is the default value of DEST enum const uint8_t DEST_DEFAULT_VALUE = 1; // This is the default value of DEST enum, sync with privacy.proto const uint8_t DEST_UNSET = 255; // DEST_UNSET is not exposed to libincident const uint8_t DEST_DEFAULT_VALUE = DEST_UNSET; /* * In order not to depend on libprotobuf-cpp-full nor libplatformprotos in incidentd, * privacy options's data structure are explicitly redefined in this file. * In order to NOT auto-generate large chuck of code by proto compiler in incidentd, * privacy options's data structure are explicitly redefined here and * the values are populated by incident_section_gen tool. * * Each proto field will have a Privacy when it is different from its parent, otherwise * it uses its parent's tag. A message type will have an array of Privacy. */ struct Privacy { // The field number uint32_t field_id; // The field type, see external/protobuf/src/google/protobuf/descriptor.h uint8_t type; // ignore parent's privacy flags if children are set, NULL-terminated // If children is null, it is a primitive field, // otherwise it is a message field which could have overridden privacy tags here. // This array is NULL-terminated. Privacy** children; // the following fields are identitical to // frameworks/base/libs/incident/proto/android/privacy.proto // DESTINATION Enum in frameworks/base/libs/incident/proto/android/privacy.proto. uint8_t dest; const char** patterns; // only set when type is string // A list of regexp rules for stripping string fields in proto. const char** patterns; }; bool IsMessageType() const; bool IsStringType() const; bool HasChildren() const; uint64_t EncodedFieldId() const; // Encode field id used by ProtoOutputStream. uint64_t encode_field_id(const Privacy* p); const Privacy* lookup(uint32_t fieldId) const; }; // Look up the child with given fieldId, if not found, return NULL. const Privacy* lookup(const Privacy* p, uint32_t fieldId); /** * PrivacySpec defines the request has what level of privacy authorization. * For example, a device without user consent should only be able to upload AUTOMATIC fields. * DEST_UNSET are treated as DEST_EXPLICIT. */ class PrivacySpec { public: Loading @@ -58,7 +69,10 @@ public: bool operator<(const PrivacySpec& other) const; bool CheckPremission(const Privacy* privacy) const; // check permission of a policy, if returns true, don't strip the data. bool CheckPremission(const Privacy* privacy, const uint8_t defaultDest = DEST_DEFAULT_VALUE) const; // if returns true, no data need to be stripped. bool RequireAll() const; }; Loading
cmds/incidentd/src/PrivacyBuffer.cpp +17 −6 Original line number Diff line number Diff line Loading @@ -14,15 +14,18 @@ * limitations under the License. */ #define LOG_TAG "incidentd" #include "PrivacyBuffer.h" #include "io_util.h" #include <android/util/protobuf.h> #include <cutils/log.h> using namespace android::util; const bool DEBUG = false; /** * Write the field to buf based on the wire type, iterator will point to next field. * If skip is set to true, no data will be written to buf. Return number of bytes written. Loading @@ -30,6 +33,9 @@ using namespace android::util; void PrivacyBuffer::writeFieldOrSkip(uint32_t fieldTag, bool skip) { if (DEBUG) ALOGD("%s field %d (wiretype = %d)", skip ? "skip" : "write", read_field_id(fieldTag), read_wire_type(fieldTag)); uint8_t wireType = read_wire_type(fieldTag); size_t bytesToWrite = 0; uint32_t varint = 0; Loading @@ -55,6 +61,7 @@ PrivacyBuffer::writeFieldOrSkip(uint32_t fieldTag, bool skip) bytesToWrite = 4; break; } if (DEBUG) ALOGD("%s %d bytes of data", skip ? "skip" : "write", (int)bytesToWrite); if (skip) { mData.rp()->move(bytesToWrite); } else { Loading @@ -76,10 +83,13 @@ PrivacyBuffer::stripField(const Privacy* parentPolicy, const PrivacySpec& spec) { if (!mData.hasNext() || parentPolicy == NULL) return BAD_VALUE; uint32_t fieldTag = mData.readRawVarint(); const Privacy* policy = parentPolicy->lookup(read_field_id(fieldTag)); const Privacy* policy = lookup(parentPolicy, read_field_id(fieldTag)); if (policy == NULL || policy->children == NULL) { if (DEBUG) ALOGD("Not a message field %d: dest(%d)", read_field_id(fieldTag), policy != NULL ? policy->dest : parentPolicy->dest); if (policy == NULL || !policy->IsMessageType() || !policy->HasChildren()) { bool skip = !spec.CheckPremission(policy); bool skip = !spec.CheckPremission(policy, parentPolicy->dest); // iterator will point to head of next field writeFieldOrSkip(fieldTag, skip); return NO_ERROR; Loading @@ -87,7 +97,7 @@ PrivacyBuffer::stripField(const Privacy* parentPolicy, const PrivacySpec& spec) // current field is message type and its sub-fields have extra privacy policies uint32_t msgSize = mData.readRawVarint(); EncodedBuffer::Pointer start = mData.rp()->copy(); long long token = mProto.start(policy->EncodedFieldId()); long long token = mProto.start(encode_field_id(policy)); while (mData.rp()->pos() - start.pos() != msgSize) { status_t err = stripField(policy, spec); if (err != NO_ERROR) return err; Loading @@ -112,8 +122,9 @@ PrivacyBuffer::~PrivacyBuffer() status_t PrivacyBuffer::strip(const PrivacySpec& spec) { if (DEBUG) ALOGD("Strip with spec %d", spec.dest); // optimization when no strip happens if (mPolicy == NULL || !mPolicy->HasChildren() || spec.RequireAll()) { if (mPolicy == NULL || mPolicy->children == NULL || spec.RequireAll()) { if (spec.CheckPremission(mPolicy)) mSize = mData.size(); return NO_ERROR; } Loading
cmds/incidentd/src/Section.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -210,9 +210,9 @@ HeaderSection::Execute(ReportRequestSet* requests) const { for (ReportRequestSet::iterator it=requests->begin(); it!=requests->end(); it++) { const sp<ReportRequest> request = *it; const vector<vector<int8_t>>& headers = request->args.headers(); const vector<vector<uint8_t>>& headers = request->args.headers(); for (vector<vector<int8_t>>::const_iterator buf=headers.begin(); buf!=headers.end(); buf++) { for (vector<vector<uint8_t>>::const_iterator buf=headers.begin(); buf!=headers.end(); buf++) { if (buf->empty()) continue; // So the idea is only requests with negative fd are written to dropbox file. Loading