summaryrefslogtreecommitdiff
path: root/core/java/android/util/EventLog.java
diff options
context:
space:
mode:
authorRubin Xu <rubinxu@google.com>2020-02-05 11:38:08 +0000
committerRubin Xu <rubinxu@google.com>2020-02-20 15:47:29 +0000
commit1480ce7b87ff012ff6016d7469c1520291ecd72f (patch)
tree830f84fc69bcda717b3161824f005f6ef011a2e9 /core/java/android/util/EventLog.java
parent1ef019d3e073098aacd37edf99ce5d0b3425ffd3 (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.java110
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);