diff options
| author | Rubin Xu <rubinxu@google.com> | 2020-02-05 11:38:08 +0000 |
|---|---|---|
| committer | Rubin Xu <rubinxu@google.com> | 2020-02-20 15:47:29 +0000 |
| commit | 1480ce7b87ff012ff6016d7469c1520291ecd72f (patch) | |
| tree | 830f84fc69bcda717b3161824f005f6ef011a2e9 /core/java/android/util/EventLog.java | |
| parent | 1ef019d3e073098aacd37edf99ce5d0b3425ffd3 (diff) | |
Support security logging on org-owned managed profile devices
When security logging is enabled on org-owned profile devices,
Security events will be redacted to preserve privacy on the personal
profile as follows:
* TAG_ADB_SHELL_CMD
Shell command will be redacted.
* TAG_MEDIA_MOUNT
* TAG_MEDIA_UNMOUNT
The media's volume name will be redacted.
* TAG_APP_PROCESS_START
* TAG_CERT_AUTHORITY_INSTALLED
* TAG_CERT_AUTHORITY_REMOVED
* TAG_KEY_GENERATED
* TAG_KEY_IMPORT
* TAG_KEY_DESTRUCTION
* TAG_KEY_INTEGRITY_VIOLATION
Only events happening inside the managed profile will be returned
to the admin.
Bug: 148437300
Test: atest FrameworksServicesTests:DevicePolicyManagerTest
Test: atest FrameworksServicesTests:SecurityEventTest
Test: atest FrameworksCoreTests:EventLogTest
Test: atest com.android.cts.devicepolicy.MixedDeviceOwnerTest#testSecurityLoggingWithSingleUser
Test: atest com.android.cts.devicepolicy.MixedDeviceOwnerTest#testSecurityLoggingWithTwoUsers
Test: atest com.android.cts.devicepolicy.MixedDeviceOwnerTest#testSecurityLoggingEnabledLogged
Test: atest com.android.cts.devicepolicy.OrgOwnedProfileOwnerTest#testSecurityLogging
Change-Id: I2e52229a3163b3e0dc3d80d71700023394d84587
Diffstat (limited to 'core/java/android/util/EventLog.java')
| -rw-r--r-- | core/java/android/util/EventLog.java | 110 |
1 files changed, 97 insertions, 13 deletions
diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java index c9dc05b5aeb5..ead4e46cd28b 100644 --- a/core/java/android/util/EventLog.java +++ b/core/java/android/util/EventLog.java @@ -16,6 +16,8 @@ package android.util; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; @@ -62,7 +64,7 @@ public class EventLog { private Exception mLastWtf; // Layout of event log entry received from Android logger. - // see system/core/include/log/log.h + // see system/core/liblog/include/log/log_read.h private static final int LENGTH_OFFSET = 0; private static final int HEADER_SIZE_OFFSET = 2; private static final int PROCESS_OFFSET = 4; @@ -73,7 +75,7 @@ public class EventLog { // Layout for event log v1 format, v2 and v3 use HEADER_SIZE_OFFSET private static final int V1_PAYLOAD_START = 20; - private static final int DATA_OFFSET = 4; + private static final int TAG_LENGTH = 4; // Value types private static final byte INT_TYPE = 0; @@ -121,26 +123,26 @@ public class EventLog { /** @return the type tag code of the entry */ public int getTag() { - int offset = mBuffer.getShort(HEADER_SIZE_OFFSET); - if (offset == 0) { - offset = V1_PAYLOAD_START; - } - return mBuffer.getInt(offset); + return mBuffer.getInt(getHeaderSize()); } + private int getHeaderSize() { + int length = mBuffer.getShort(HEADER_SIZE_OFFSET); + if (length != 0) { + return length; + } + return V1_PAYLOAD_START; + } /** @return one of Integer, Long, Float, String, null, or Object[] of same. */ public synchronized Object getData() { try { - int offset = mBuffer.getShort(HEADER_SIZE_OFFSET); - if (offset == 0) { - offset = V1_PAYLOAD_START; - } + int offset = getHeaderSize(); mBuffer.limit(offset + mBuffer.getShort(LENGTH_OFFSET)); - if ((offset + DATA_OFFSET) >= mBuffer.limit()) { + if ((offset + TAG_LENGTH) >= mBuffer.limit()) { // no payload return null; } - mBuffer.position(offset + DATA_OFFSET); // Just after the tag. + mBuffer.position(offset + TAG_LENGTH); // Just after the tag. return decodeObject(); } catch (IllegalArgumentException e) { Log.wtf(TAG, "Illegal entry payload: tag=" + getTag(), e); @@ -153,6 +155,28 @@ public class EventLog { } } + /** + * Construct a new EventLog object from the current object, copying all log metadata + * but replacing the actual payload with the content provided. + * @hide + */ + public Event withNewData(@Nullable Object object) { + byte[] payload = encodeObject(object); + if (payload.length > 65535 - TAG_LENGTH) { + throw new IllegalArgumentException("Payload too long"); + } + int headerLength = getHeaderSize(); + byte[] newBytes = new byte[headerLength + TAG_LENGTH + payload.length]; + // Copy header (including the 4 bytes of tag integer at the beginning of payload) + System.arraycopy(mBuffer.array(), 0, newBytes, 0, headerLength + TAG_LENGTH); + // Fill in encoded objects + System.arraycopy(payload, 0, newBytes, headerLength + TAG_LENGTH, payload.length); + Event result = new Event(newBytes); + // Patch payload length in header + result.mBuffer.putShort(LENGTH_OFFSET, (short) (payload.length + TAG_LENGTH)); + return result; + } + /** @return the loggable item at the current position in mBuffer. */ private Object decodeObject() { byte type = mBuffer.get(); @@ -190,6 +214,66 @@ public class EventLog { } } + private static @NonNull byte[] encodeObject(@Nullable Object object) { + if (object == null) { + return new byte[0]; + } + if (object instanceof Integer) { + return ByteBuffer.allocate(1 + 4) + .order(ByteOrder.nativeOrder()) + .put(INT_TYPE) + .putInt((Integer) object) + .array(); + } else if (object instanceof Long) { + return ByteBuffer.allocate(1 + 8) + .order(ByteOrder.nativeOrder()) + .put(LONG_TYPE) + .putLong((Long) object) + .array(); + } else if (object instanceof Float) { + return ByteBuffer.allocate(1 + 4) + .order(ByteOrder.nativeOrder()) + .put(FLOAT_TYPE) + .putFloat((Float) object) + .array(); + } else if (object instanceof String) { + String string = (String) object; + byte[] bytes; + try { + bytes = string.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + bytes = new byte[0]; + } + return ByteBuffer.allocate(1 + 4 + bytes.length) + .order(ByteOrder.nativeOrder()) + .put(STRING_TYPE) + .putInt(bytes.length) + .put(bytes) + .array(); + } else if (object instanceof Object[]) { + Object[] objects = (Object[]) object; + if (objects.length > 255) { + throw new IllegalArgumentException("Object array too long"); + } + byte[][] bytes = new byte[objects.length][]; + int totalLength = 0; + for (int i = 0; i < objects.length; i++) { + bytes[i] = encodeObject(objects[i]); + totalLength += bytes[i].length; + } + ByteBuffer buffer = ByteBuffer.allocate(1 + 1 + totalLength) + .order(ByteOrder.nativeOrder()) + .put(LIST_TYPE) + .put((byte) objects.length); + for (int i = 0; i < objects.length; i++) { + buffer.put(bytes[i]); + } + return buffer.array(); + } else { + throw new IllegalArgumentException("Unknown object type " + object); + } + } + /** @hide */ public static Event fromBytes(byte[] data) { return new Event(data); |
