diff options
28 files changed, 359 insertions, 101 deletions
diff --git a/cmds/incident_helper/src/TextParserBase.h b/cmds/incident_helper/src/TextParserBase.h index c41612de4eb3..166796673e25 100644 --- a/cmds/incident_helper/src/TextParserBase.h +++ b/cmds/incident_helper/src/TextParserBase.h @@ -68,4 +68,4 @@ public: virtual status_t Parse(const int in, const int out) const; }; -#endif // TEXT_PARSER_BASE_H
\ No newline at end of file +#endif // TEXT_PARSER_BASE_H diff --git a/cmds/incidentd/README.md b/cmds/incidentd/README.md index ad0fa08c7326..71c6deb18aac 100644 --- a/cmds/incidentd/README.md +++ b/cmds/incidentd/README.md @@ -12,8 +12,8 @@ Run the test on a device manually ``` root$ mmm -j frameworks/base/cmds/incidentd && \ -adb push $OUT/data/nativetest/incidentd_test/* /data/nativetest/incidentd_test/ && \ -adb shell /data/nativetest/incidentd_test/incidentd_test 2>/dev/null +adb push $OUT/data/nativetest/incidentd_test/* /data/nativetest/ && \ +adb shell /data/nativetest/incidentd_test 2>/dev/null ``` Run the test via AndroidTest.xml diff --git a/cmds/incidentd/incidentd.rc b/cmds/incidentd/incidentd.rc index 66667dca2982..1bd146850ea9 100644 --- a/cmds/incidentd/incidentd.rc +++ b/cmds/incidentd/incidentd.rc @@ -19,4 +19,4 @@ service incidentd /system/bin/incidentd on post-fs-data # Create directory for incidentd - mkdir /data/misc/incidents 0770 root root + mkdir /data/misc/incidents 0770 incidentd incidentd diff --git a/cmds/incidentd/src/FdBuffer.cpp b/cmds/incidentd/src/FdBuffer.cpp index 30dd339a629b..0fff4e6dc4a0 100644 --- a/cmds/incidentd/src/FdBuffer.cpp +++ b/cmds/incidentd/src/FdBuffer.cpp @@ -63,12 +63,14 @@ FdBuffer::read(int fd, int64_t timeout) int64_t remainingTime = (mStartTime + timeout) - uptimeMillis(); if (remainingTime <= 0) { + if (DEBUG) ALOGD("timed out due to long read"); mTimedOut = true; break; } int count = poll(&pfds, 1, remainingTime); if (count == 0) { + if (DEBUG) ALOGD("timed out due to block calling poll"); mTimedOut = true; break; } else if (count < 0) { @@ -129,6 +131,7 @@ FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeou int64_t remainingTime = (mStartTime + timeoutMs) - uptimeMillis(); if (remainingTime <= 0) { + if (DEBUG) ALOGD("timed out due to long read"); mTimedOut = true; break; } @@ -136,6 +139,7 @@ FdBuffer::readProcessedDataInStream(int fd, int toFd, int fromFd, int64_t timeou // wait for any pfds to be ready to perform IO int count = poll(pfds, 3, remainingTime); if (count == 0) { + if (DEBUG) ALOGD("timed out due to block calling poll"); mTimedOut = true; break; } else if (count < 0) { diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp index c4b54bbbc022..a97eb861578e 100644 --- a/cmds/incidentd/src/IncidentService.cpp +++ b/cmds/incidentd/src/IncidentService.cpp @@ -43,8 +43,9 @@ String16 const DUMP_PERMISSION("android.permission.DUMP"); String16 const USAGE_STATS_PERMISSION("android.permission.PACKAGE_USAGE_STATS"); static Status -checkIncidentPermissions() +checkIncidentPermissions(const IncidentReportArgs& args) { + // checking calling permission. if (!checkCallingPermission(DUMP_PERMISSION)) { ALOGW("Calling pid %d and uid %d does not have permission: android.permission.DUMP", IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid()); @@ -57,10 +58,24 @@ checkIncidentPermissions() return Status::fromExceptionCode(Status::EX_SECURITY, "Calling process does not have permission: android.permission.USAGE_STATS"); } + + // checking calling request uid permission. + uid_t callingUid = IPCThreadState::self()->getCallingUid(); + switch (args.dest()) { + case DEST_LOCAL: + if (callingUid != AID_SHELL || callingUid != AID_ROOT) { + return Status::fromExceptionCode(Status::EX_SECURITY, + "Calling process does not have permission to get local data."); + } + case DEST_EXPLICIT: + if (callingUid != AID_SHELL || callingUid != AID_ROOT || + callingUid != AID_STATSD || callingUid != AID_SYSTEM) { + return Status::fromExceptionCode(Status::EX_SECURITY, + "Calling process does not have permission to get explicit data."); + } + } return Status::ok(); } - - // ================================================================================ ReportRequestQueue::ReportRequestQueue() { @@ -71,7 +86,7 @@ ReportRequestQueue::~ReportRequestQueue() } void -ReportRequestQueue::addRequest(const sp<ReportRequest>& request) +ReportRequestQueue::addRequest(const sp<ReportRequest>& request) { unique_lock<mutex> lock(mLock); mQueue.push_back(request); @@ -196,7 +211,7 @@ IncidentService::reportIncident(const IncidentReportArgs& args) { ALOGI("reportIncident"); - Status status = checkIncidentPermissions(); + Status status = checkIncidentPermissions(args); if (!status.isOk()) { return status; } @@ -212,7 +227,7 @@ IncidentService::reportIncidentToStream(const IncidentReportArgs& args, { ALOGI("reportIncidentToStream"); - Status status = checkIncidentPermissions(); + Status status = checkIncidentPermissions(args); if (!status.isOk()) { return status; } diff --git a/cmds/incidentd/src/Reporter.cpp b/cmds/incidentd/src/Reporter.cpp index 34930aa57321..bd559d6980f1 100644 --- a/cmds/incidentd/src/Reporter.cpp +++ b/cmds/incidentd/src/Reporter.cpp @@ -251,7 +251,7 @@ Reporter::create_file(int* fd) // Override umask. Not super critical. If it fails go on with life. chmod(filename, 0660); - if (chown(filename, AID_SYSTEM, AID_SYSTEM)) { + if (chown(filename, AID_INCIDENTD, AID_INCIDENTD)) { ALOGE("Unable to change ownership of incident file %s: %s\n", filename, strerror(errno)); status_t err = -errno; unlink(mFilename.c_str()); diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp index 61d16f815e65..0827785811b6 100644 --- a/cmds/incidentd/src/Section.cpp +++ b/cmds/incidentd/src/Section.cpp @@ -19,6 +19,7 @@ #include "Section.h" #include <errno.h> +#include <sys/prctl.h> #include <unistd.h> #include <wait.h> @@ -30,7 +31,6 @@ #include <log/log_event_list.h> #include <log/logprint.h> #include <log/log_read.h> -#include <private/android_filesystem_config.h> // for AID_NOBODY #include <private/android_logger.h> #include "FdBuffer.h" @@ -55,26 +55,20 @@ static pid_t fork_execute_incident_helper(const int id, const char* name, Fpipe& p2cPipe, Fpipe& c2pPipe) { const char* ihArgs[] { INCIDENT_HELPER, "-s", String8::format("%d", id).string(), NULL }; - // fork used in multithreaded environment, avoid adding unnecessary code in child process pid_t pid = fork(); if (pid == 0) { - // child process executes incident helper as nobody - if (setgid(AID_NOBODY) == -1) { - ALOGW("%s can't change gid: %s", name, strerror(errno)); - _exit(EXIT_FAILURE); - } - if (setuid(AID_NOBODY) == -1) { - ALOGW("%s can't change uid: %s", name, strerror(errno)); - _exit(EXIT_FAILURE); - } - - if (dup2(p2cPipe.readFd(), STDIN_FILENO) != 0 || !p2cPipe.close() || - dup2(c2pPipe.writeFd(), STDOUT_FILENO) != 1 || !c2pPipe.close()) { + if (TEMP_FAILURE_RETRY(dup2(p2cPipe.readFd(), STDIN_FILENO)) != 0 + || !p2cPipe.close() + || TEMP_FAILURE_RETRY(dup2(c2pPipe.writeFd(), STDOUT_FILENO)) != 1 + || !c2pPipe.close()) { ALOGW("%s can't setup stdin and stdout for incident helper", name); _exit(EXIT_FAILURE); } + /* make sure the child dies when incidentd dies */ + prctl(PR_SET_PDEATHSIG, SIGKILL); + execv(INCIDENT_HELPER, const_cast<char**>(ihArgs)); ALOGW("%s failed in incident helper process: %s", name, strerror(errno)); @@ -87,11 +81,23 @@ fork_execute_incident_helper(const int id, const char* name, Fpipe& p2cPipe, Fpi } // ================================================================================ +static status_t statusCode(int status) { + if (WIFSIGNALED(status)) { + ALOGD("return by signal: %s", strerror(WTERMSIG(status))); + return -WTERMSIG(status); + } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) { + ALOGD("return by exit: %s", strerror(WEXITSTATUS(status))); + return -WEXITSTATUS(status); + } + return NO_ERROR; +} + static status_t kill_child(pid_t pid) { int status; + ALOGD("try to kill child process %d", pid); kill(pid, SIGKILL); if (waitpid(pid, &status, 0) == -1) return -1; - return WIFEXITED(status) == 0 ? NO_ERROR : -WEXITSTATUS(status); + return statusCode(status); } static status_t wait_child(pid_t pid) { @@ -104,7 +110,7 @@ static status_t wait_child(pid_t pid) { nanosleep(&WAIT_INTERVAL_NS, NULL); } if (!died) return kill_child(pid); - return WIFEXITED(status) == 0 ? NO_ERROR : -WEXITSTATUS(status); + return statusCode(status); } // ================================================================================ static const Privacy* @@ -275,9 +281,9 @@ FileSection::Execute(ReportRequestSet* requests) const status_t readStatus = buffer.readProcessedDataInStream(fd, p2cPipe.writeFd(), c2pPipe.readFd(), this->timeoutMs, mIsSysfs); if (readStatus != NO_ERROR || buffer.timedOut()) { - ALOGW("FileSection '%s' failed to read data from incident helper: %s, timedout: %s, kill: %s", - this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false", - strerror(-kill_child(pid))); + ALOGW("FileSection '%s' failed to read data from incident helper: %s, timedout: %s", + this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false"); + kill_child(pid); return readStatus; } @@ -543,10 +549,10 @@ CommandSection::Execute(ReportRequestSet* requests) const close(cmdPipe.writeFd()); status_t readStatus = buffer.read(ihPipe.readFd(), this->timeoutMs); if (readStatus != NO_ERROR || buffer.timedOut()) { - ALOGW("CommandSection '%s' failed to read data from incident helper: %s, " - "timedout: %s, kill command: %s, kill incident helper: %s", - this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false", - strerror(-kill_child(cmdPid)), strerror(-kill_child(ihPid))); + ALOGW("CommandSection '%s' failed to read data from incident helper: %s, timedout: %s", + this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false"); + kill_child(cmdPid); + kill_child(ihPid); return readStatus; } diff --git a/cmds/incidentd/src/io_util.cpp b/cmds/incidentd/src/io_util.cpp index af4a35cc0015..90f543e30ff7 100644 --- a/cmds/incidentd/src/io_util.cpp +++ b/cmds/incidentd/src/io_util.cpp @@ -23,7 +23,7 @@ status_t write_all(int fd, uint8_t const* buf, size_t size) { while (size > 0) { - ssize_t amt = ::write(fd, buf, size); + ssize_t amt = TEMP_FAILURE_RETRY(::write(fd, buf, size)); if (amt < 0) { return -errno; } diff --git a/cmds/incidentd/src/report_directory.cpp b/cmds/incidentd/src/report_directory.cpp index 65030b3a1799..20111d8ae89a 100644 --- a/cmds/incidentd/src/report_directory.cpp +++ b/cmds/incidentd/src/report_directory.cpp @@ -58,26 +58,9 @@ create_directory(const char* directory) goto done; } } else { - if (mkdir(dir, 0770)) { - ALOGE("No incident reports today. " - "Unable to create incident report dir %s: %s", dir, - strerror(errno)); - err = -errno; - goto done; - } - if (chmod(dir, 0770)) { - ALOGE("No incident reports today. " - "Unable to set permissions for incident report dir %s: %s", dir, - strerror(errno)); - err = -errno; - goto done; - } - if (chown(dir, AID_SYSTEM, AID_SYSTEM)) { - ALOGE("No incident reports today. Unable to change ownership of dir %s: %s\n", - dir, strerror(errno)); - err = -errno; - goto done; - } + ALOGE("No such directory %s, something wrong.", dir); + err = -1; + goto done; } if (!last) { *d++ = '/'; @@ -97,8 +80,7 @@ create_directory(const char* directory) err = BAD_VALUE; goto done; } - if ((st.st_uid != AID_SYSTEM && st.st_uid != AID_ROOT) || - (st.st_gid != AID_SYSTEM && st.st_gid != AID_ROOT)) { + if (st.st_uid != AID_INCIDENTD || st.st_gid != AID_INCIDENTD) { ALOGE("No incident reports today. Owner is %d and group is %d on report directory %s", st.st_uid, st.st_gid, directory); err = BAD_VALUE; diff --git a/core/java/android/os/IPermissionController.aidl b/core/java/android/os/IPermissionController.aidl index 5e8590af11f1..3de953a2dfbe 100644 --- a/core/java/android/os/IPermissionController.aidl +++ b/core/java/android/os/IPermissionController.aidl @@ -22,4 +22,5 @@ interface IPermissionController { boolean checkPermission(String permission, int pid, int uid); String[] getPackagesForUid(int uid); boolean isRuntimePermission(String permission); + int getPackageUid(String packageName, int flags); } diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index e6cf5e6a6cbf..7654e9b6ee22 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -151,6 +151,12 @@ public class Process { */ public static final int OTA_UPDATE_UID = 1061; + /** + * Defines the UID used for incidentd. + * @hide + */ + public static final int INCIDENTD_UID = 1067; + /** {@hide} */ public static final int NOBODY_UID = 9999; diff --git a/core/java/android/text/style/BackgroundColorSpan.java b/core/java/android/text/style/BackgroundColorSpan.java index de05f50c9860..4f471a8a2f85 100644 --- a/core/java/android/text/style/BackgroundColorSpan.java +++ b/core/java/android/text/style/BackgroundColorSpan.java @@ -16,24 +16,48 @@ package android.text.style; +import android.annotation.ColorInt; +import android.annotation.NonNull; import android.os.Parcel; import android.text.ParcelableSpan; import android.text.TextPaint; import android.text.TextUtils; +/** + * Changes the background color of the text to which the span is attached. + * <p> + * For example, to set a green background color for a text you would create a {@link + * android.text.SpannableStringBuilder} based on the text and set the span. + * <pre>{@code + * SpannableString string = new SpannableString("Text with a background color span"); + *string.setSpan(new BackgroundColorSpan(color), 12, 28, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + * }</pre> + * <img src="{@docRoot}reference/android/images/text/style/backgroundcolorspan.png" /> + * <figcaption>Set a background color for the text.</figcaption> + */ public class BackgroundColorSpan extends CharacterStyle implements UpdateAppearance, ParcelableSpan { private final int mColor; - public BackgroundColorSpan(int color) { + /** + * Creates a {@link BackgroundColorSpan} from a color integer. + * <p> + * + * @param color color integer that defines the background color + * @see android.content.res.Resources#getColor(int, Resources.Theme) + */ + public BackgroundColorSpan(@ColorInt int color) { mColor = color; } - public BackgroundColorSpan(Parcel src) { + /** + * Creates a {@link BackgroundColorSpan} from a parcel. + */ + public BackgroundColorSpan(@NonNull Parcel src) { mColor = src.readInt(); } - + public int getSpanTypeId() { return getSpanTypeIdInternal(); } @@ -42,26 +66,40 @@ public class BackgroundColorSpan extends CharacterStyle public int getSpanTypeIdInternal() { return TextUtils.BACKGROUND_COLOR_SPAN; } - + public int describeContents() { return 0; } - public void writeToParcel(Parcel dest, int flags) { + /** + * Flatten this object into a Parcel. + * + * @param dest The Parcel in which the object should be written. + * @param flags Additional flags about how the object should be written. + */ + public void writeToParcel(@NonNull Parcel dest, int flags) { writeToParcelInternal(dest, flags); } /** @hide */ - public void writeToParcelInternal(Parcel dest, int flags) { + public void writeToParcelInternal(@NonNull Parcel dest, int flags) { dest.writeInt(mColor); } + /** + * @return the background color of this span. + * @see BackgroundColorSpan#BackgroundColorSpan(int) + */ + @ColorInt public int getBackgroundColor() { return mColor; } + /** + * Updates the background color of the TextPaint. + */ @Override - public void updateDrawState(TextPaint ds) { - ds.bgColor = mColor; + public void updateDrawState(@NonNull TextPaint textPaint) { + textPaint.bgColor = mColor; } } diff --git a/core/java/android/text/style/ForegroundColorSpan.java b/core/java/android/text/style/ForegroundColorSpan.java index 2bc6d5406ade..08ab2a1f1a20 100644 --- a/core/java/android/text/style/ForegroundColorSpan.java +++ b/core/java/android/text/style/ForegroundColorSpan.java @@ -17,24 +17,48 @@ package android.text.style; import android.annotation.ColorInt; +import android.annotation.NonNull; import android.os.Parcel; import android.text.ParcelableSpan; import android.text.TextPaint; import android.text.TextUtils; +/** + * Changes the color of the text to which the span is attached. + * <p> + * For example, to set a green text color you would create a {@link + * android.text.SpannableStringBuilder} based on the text and set the span. + * <pre>{@code + * SpannableString string = new SpannableString("Text with a foreground color span"); + *string.setSpan(new ForegroundColorSpan(color), 12, 28, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + * }</pre> + * <img src="{@docRoot}reference/android/images/text/style/foregroundcolorspan.png" /> + * <figcaption>Set a text color.</figcaption> + */ public class ForegroundColorSpan extends CharacterStyle implements UpdateAppearance, ParcelableSpan { private final int mColor; + /** + * Creates a {@link ForegroundColorSpan} from a color integer. + * <p> + * To get the color integer associated with a particular color resource ID, use + * {@link android.content.res.Resources#getColor(int, Resources.Theme)} + * + * @param color color integer that defines the text color + */ public ForegroundColorSpan(@ColorInt int color) { mColor = color; } - public ForegroundColorSpan(Parcel src) { + /** + * Creates a {@link ForegroundColorSpan} from a parcel. + */ + public ForegroundColorSpan(@NonNull Parcel src) { mColor = src.readInt(); } - + public int getSpanTypeId() { return getSpanTypeIdInternal(); } @@ -48,22 +72,35 @@ public class ForegroundColorSpan extends CharacterStyle return 0; } - public void writeToParcel(Parcel dest, int flags) { + /** + * Flatten this object into a Parcel. + * + * @param dest The Parcel in which the object should be written. + * @param flags Additional flags about how the object should be written. + */ + public void writeToParcel(@NonNull Parcel dest, int flags) { writeToParcelInternal(dest, flags); } /** @hide */ - public void writeToParcelInternal(Parcel dest, int flags) { + public void writeToParcelInternal(@NonNull Parcel dest, int flags) { dest.writeInt(mColor); } + /** + * @return the foreground color of this span. + * @see ForegroundColorSpan#ForegroundColorSpan(int) + */ @ColorInt public int getForegroundColor() { return mColor; } + /** + * Updates the color of the TextPaint to the foreground color. + */ @Override - public void updateDrawState(TextPaint ds) { - ds.setColor(mColor); + public void updateDrawState(@NonNull TextPaint textPaint) { + textPaint.setColor(mColor); } } diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java index ce8998fcb863..5a09dab552e3 100644 --- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java +++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java @@ -16,6 +16,7 @@ package android.util.apk; +import static android.util.apk.ApkSigningBlockUtils.CONTENT_DIGEST_VERITY_CHUNKED_SHA256; import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_DSA_WITH_SHA256; import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_ECDSA_WITH_SHA256; import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_ECDSA_WITH_SHA512; @@ -42,6 +43,7 @@ import java.io.IOException; import java.io.RandomAccessFile; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; +import java.security.DigestException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.KeyFactory; @@ -105,7 +107,8 @@ public class ApkSignatureSchemeV2Verifier { */ public static X509Certificate[][] verify(String apkFile) throws SignatureNotFoundException, SecurityException, IOException { - return verify(apkFile, true); + VerifiedSigner vSigner = verify(apkFile, true); + return vSigner.certs; } /** @@ -119,10 +122,11 @@ public class ApkSignatureSchemeV2Verifier { */ public static X509Certificate[][] plsCertsNoVerifyOnlyCerts(String apkFile) throws SignatureNotFoundException, SecurityException, IOException { - return verify(apkFile, false); + VerifiedSigner vSigner = verify(apkFile, false); + return vSigner.certs; } - private static X509Certificate[][] verify(String apkFile, boolean verifyIntegrity) + private static VerifiedSigner verify(String apkFile, boolean verifyIntegrity) throws SignatureNotFoundException, SecurityException, IOException { try (RandomAccessFile apk = new RandomAccessFile(apkFile, "r")) { return verify(apk, verifyIntegrity); @@ -138,7 +142,7 @@ public class ApkSignatureSchemeV2Verifier { * verify. * @throws IOException if an I/O error occurs while reading the APK file. */ - private static X509Certificate[][] verify(RandomAccessFile apk, boolean verifyIntegrity) + private static VerifiedSigner verify(RandomAccessFile apk, boolean verifyIntegrity) throws SignatureNotFoundException, SecurityException, IOException { SignatureInfo signatureInfo = findSignature(apk); return verify(apk, signatureInfo, verifyIntegrity); @@ -163,7 +167,7 @@ public class ApkSignatureSchemeV2Verifier { * @param signatureInfo APK Signature Scheme v2 Block and information relevant for verifying it * against the APK file. */ - private static X509Certificate[][] verify( + private static VerifiedSigner verify( RandomAccessFile apk, SignatureInfo signatureInfo, boolean doVerifyIntegrity) throws SecurityException, IOException { @@ -207,7 +211,14 @@ public class ApkSignatureSchemeV2Verifier { ApkSigningBlockUtils.verifyIntegrity(contentDigests, apk, signatureInfo); } - return signerCerts.toArray(new X509Certificate[signerCerts.size()][]); + byte[] verityRootHash = null; + if (contentDigests.containsKey(CONTENT_DIGEST_VERITY_CHUNKED_SHA256)) { + verityRootHash = contentDigests.get(CONTENT_DIGEST_VERITY_CHUNKED_SHA256); + } + + return new VerifiedSigner( + signerCerts.toArray(new X509Certificate[signerCerts.size()][]), + verityRootHash); } private static X509Certificate[] verifySigner( @@ -383,6 +394,24 @@ public class ApkSignatureSchemeV2Verifier { return; } + static byte[] getVerityRootHash(String apkPath) + throws IOException, SignatureNotFoundException, SecurityException { + try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) { + SignatureInfo signatureInfo = findSignature(apk); + VerifiedSigner vSigner = verify(apk, false); + return vSigner.verityRootHash; + } + } + + static byte[] generateApkVerity(String apkPath, ByteBufferFactory bufferFactory) + throws IOException, SignatureNotFoundException, SecurityException, DigestException, + NoSuchAlgorithmException { + try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) { + SignatureInfo signatureInfo = findSignature(apk); + return ApkSigningBlockUtils.generateApkVerity(apkPath, bufferFactory, signatureInfo); + } + } + private static boolean isSupportedSignatureAlgorithm(int sigAlgorithm) { switch (sigAlgorithm) { case SIGNATURE_RSA_PSS_WITH_SHA256: @@ -400,4 +429,20 @@ public class ApkSignatureSchemeV2Verifier { return false; } } + + /** + * Verified APK Signature Scheme v2 signer. + * + * @hide for internal use only. + */ + public static class VerifiedSigner { + public final X509Certificate[][] certs; + public final byte[] verityRootHash; + + public VerifiedSigner(X509Certificate[][] certs, byte[] verityRootHash) { + this.certs = certs; + this.verityRootHash = verityRootHash; + } + + } } diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java index c9e67fe1c9ef..1b04eb2f7d44 100644 --- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java +++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java @@ -16,6 +16,7 @@ package android.util.apk; +import static android.util.apk.ApkSigningBlockUtils.CONTENT_DIGEST_VERITY_CHUNKED_SHA256; import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_DSA_WITH_SHA256; import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_ECDSA_WITH_SHA256; import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_ECDSA_WITH_SHA512; @@ -43,6 +44,7 @@ import java.io.IOException; import java.io.RandomAccessFile; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; +import java.security.DigestException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.KeyFactory; @@ -211,6 +213,10 @@ public class ApkSignatureSchemeV3Verifier { ApkSigningBlockUtils.verifyIntegrity(contentDigests, apk, signatureInfo); } + if (contentDigests.containsKey(CONTENT_DIGEST_VERITY_CHUNKED_SHA256)) { + result.verityRootHash = contentDigests.get(CONTENT_DIGEST_VERITY_CHUNKED_SHA256); + } + return result; } @@ -499,6 +505,24 @@ public class ApkSignatureSchemeV3Verifier { return new VerifiedProofOfRotation(certs, flagsList); } + static byte[] getVerityRootHash(String apkPath) + throws IOException, SignatureNotFoundException, SecurityException { + try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) { + SignatureInfo signatureInfo = findSignature(apk); + VerifiedSigner vSigner = verify(apk, false); + return vSigner.verityRootHash; + } + } + + static byte[] generateApkVerity(String apkPath, ByteBufferFactory bufferFactory) + throws IOException, SignatureNotFoundException, SecurityException, DigestException, + NoSuchAlgorithmException { + try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) { + SignatureInfo signatureInfo = findSignature(apk); + return ApkSigningBlockUtils.generateApkVerity(apkPath, bufferFactory, signatureInfo); + } + } + private static boolean isSupportedSignatureAlgorithm(int sigAlgorithm) { switch (sigAlgorithm) { case SIGNATURE_RSA_PSS_WITH_SHA256: @@ -541,6 +565,8 @@ public class ApkSignatureSchemeV3Verifier { public final X509Certificate[] certs; public final VerifiedProofOfRotation por; + public byte[] verityRootHash; + public VerifiedSigner(X509Certificate[] certs, VerifiedProofOfRotation por) { this.certs = certs; this.por = por; diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java index 555c4740389a..a2a76169c83a 100644 --- a/core/java/android/util/apk/ApkSignatureVerifier.java +++ b/core/java/android/util/apk/ApkSignatureVerifier.java @@ -36,7 +36,9 @@ import libcore.io.IoUtils; import java.io.IOException; import java.io.InputStream; +import java.security.DigestException; import java.security.GeneralSecurityException; +import java.security.NoSuchAlgorithmException; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.util.ArrayList; @@ -367,4 +369,51 @@ public class ApkSignatureVerifier { // v2 didn't work, try jarsigner return verifyV1Signature(apkPath, false); } + + /** + * @return the verity root hash in the Signing Block. + */ + public static byte[] getVerityRootHash(String apkPath) + throws IOException, SignatureNotFoundException, SecurityException { + // first try v3 + try { + return ApkSignatureSchemeV3Verifier.getVerityRootHash(apkPath); + } catch (SignatureNotFoundException e) { + // try older version + } + return ApkSignatureSchemeV2Verifier.getVerityRootHash(apkPath); + } + + /** + * Generates the Merkle tree and verity metadata to the buffer allocated by the {@code + * ByteBufferFactory}. + * + * @return the verity root hash of the generated Merkle tree. + */ + public static byte[] generateApkVerity(String apkPath, ByteBufferFactory bufferFactory) + throws IOException, SignatureNotFoundException, SecurityException, DigestException, + NoSuchAlgorithmException { + // first try v3 + try { + return ApkSignatureSchemeV3Verifier.generateApkVerity(apkPath, bufferFactory); + } catch (SignatureNotFoundException e) { + // try older version + } + return ApkSignatureSchemeV2Verifier.generateApkVerity(apkPath, bufferFactory); + } + + /** + * Result of a successful APK verification operation. + */ + public static class Result { + public final Certificate[][] certs; + public final Signature[] sigs; + public final int signatureSchemeVersion; + + public Result(Certificate[][] certs, Signature[] sigs, int signingVersion) { + this.certs = certs; + this.sigs = sigs; + this.signatureSchemeVersion = signingVersion; + } + } } diff --git a/core/java/android/util/apk/ApkSigningBlockUtils.java b/core/java/android/util/apk/ApkSigningBlockUtils.java index 9d53847f8110..4146f6fab011 100644 --- a/core/java/android/util/apk/ApkSigningBlockUtils.java +++ b/core/java/android/util/apk/ApkSigningBlockUtils.java @@ -306,6 +306,26 @@ final class ApkSigningBlockUtils { } /** + * Generates the fsverity header and hash tree to be used by kernel for the given apk. This + * method does not check whether the root hash exists in the Signing Block or not. + * + * <p>The output is stored in the {@link ByteBuffer} created by the given {@link + * ByteBufferFactory}. + * + * @return the root hash of the generated hash tree. + */ + public static byte[] generateApkVerity(String apkPath, ByteBufferFactory bufferFactory, + SignatureInfo signatureInfo) + throws IOException, SignatureNotFoundException, SecurityException, DigestException, + NoSuchAlgorithmException { + try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) { + ApkVerityBuilder.ApkVerityResult result = ApkVerityBuilder.generateApkVerity(apk, + signatureInfo, bufferFactory); + return result.rootHash; + } + } + + /** * Returns the ZIP End of Central Directory (EoCD) and its offset in the file. * * @throws IOException if an I/O error occurs while reading the file. diff --git a/core/java/android/util/apk/ApkVerityBuilder.java b/core/java/android/util/apk/ApkVerityBuilder.java index 7412ef411fb4..a0d5e4c2dd8e 100644 --- a/core/java/android/util/apk/ApkVerityBuilder.java +++ b/core/java/android/util/apk/ApkVerityBuilder.java @@ -164,11 +164,11 @@ abstract class ApkVerityBuilder { } private void fillUpLastOutputChunk() { - int extra = (int) (BUFFER_SIZE - mOutput.position() % BUFFER_SIZE); - if (extra == 0) { + int lastBlockSize = (int) (mOutput.position() % BUFFER_SIZE); + if (lastBlockSize == 0) { return; } - mOutput.put(ByteBuffer.allocate(extra)); + mOutput.put(ByteBuffer.allocate(BUFFER_SIZE - lastBlockSize)); } } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index bd22b33f9507..799e3e8d38d0 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -155,11 +155,11 @@ public class BatteryStatsImpl extends BatteryStats { MAX_HISTORY_BUFFER = 96*1024; // 96KB MAX_MAX_HISTORY_BUFFER = 128*1024; // 128KB } else { - MAX_HISTORY_ITEMS = 2000; - MAX_MAX_HISTORY_ITEMS = 3000; - MAX_WAKELOCKS_PER_UID = 100; - MAX_HISTORY_BUFFER = 256*1024; // 256KB - MAX_MAX_HISTORY_BUFFER = 320*1024; // 256KB + MAX_HISTORY_ITEMS = 4000; + MAX_MAX_HISTORY_ITEMS = 6000; + MAX_WAKELOCKS_PER_UID = 200; + MAX_HISTORY_BUFFER = 512*1024; // 512KB + MAX_MAX_HISTORY_BUFFER = 640*1024; // 640KB } } diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java index 66b777e8e8e6..2b5103377ecb 100644 --- a/core/java/com/android/internal/util/DumpUtils.java +++ b/core/java/com/android/internal/util/DumpUtils.java @@ -102,6 +102,7 @@ public final class DumpUtils { case android.os.Process.ROOT_UID: case android.os.Process.SYSTEM_UID: case android.os.Process.SHELL_UID: + case android.os.Process.INCIDENTD_UID: return true; } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 547e83c144a4..f1b5fdfc2d2a 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1747,6 +1747,12 @@ <permission android:name="android.permission.SEND_EMBMS_INTENTS" android:protectionLevel="signature|privileged" /> + + <!-- Allows internal management of the sensor framework + @hide --> + <permission android:name="android.permission.MANAGE_SENSORS" + android:protectionLevel="signature" /> + <!-- Must be required by an ImsService to ensure that only the system can bind to it. <p>Protection level: signature|privileged diff --git a/data/etc/platform.xml b/data/etc/platform.xml index 993bae1eea00..c0633cb44e02 100644 --- a/data/etc/platform.xml +++ b/data/etc/platform.xml @@ -165,6 +165,9 @@ <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" /> + <assign-permission name="android.permission.DUMP" uid="incidentd" /> + <assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="incidentd" /> + <assign-permission name="android.permission.ACCESS_LOWPAN_STATE" uid="lowpan" /> <assign-permission name="android.permission.MANAGE_LOWPAN_INTERFACES" uid="lowpan" /> diff --git a/docs/html/reference/images/text/style/backgroundcolorspan.png b/docs/html/reference/images/text/style/backgroundcolorspan.png Binary files differnew file mode 100644 index 000000000000..e7e72714c5bb --- /dev/null +++ b/docs/html/reference/images/text/style/backgroundcolorspan.png diff --git a/docs/html/reference/images/text/style/foregroundcolorspan.png b/docs/html/reference/images/text/style/foregroundcolorspan.png Binary files differnew file mode 100644 index 000000000000..f60db6c55254 --- /dev/null +++ b/docs/html/reference/images/text/style/foregroundcolorspan.png diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 0f43db052622..3baf5e4a2d25 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -135,6 +135,7 @@ <uses-permission android:name="android.permission.RESTRICTED_VR_ACCESS" /> <uses-permission android:name="android.permission.MANAGE_BIND_INSTANT_SERVICE" /> <uses-permission android:name="android.permission.SET_HARMFUL_APP_WARNINGS" /> + <uses-permission android:name="android.permission.MANAGE_SENSORS" /> <application android:label="@string/app_label" android:defaultToDeviceProtectedStorage="true" diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 29d33ce777f5..c0c684c41bc5 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -8601,6 +8601,16 @@ public class ActivityManagerService extends IActivityManager.Stub } return false; } + + @Override + public int getPackageUid(String packageName, int flags) { + try { + return mActivityManagerService.mContext.getPackageManager() + .getPackageUid(packageName, flags); + } catch (NameNotFoundException nnfe) { + return -1; + } + } } class IntentFirewallInterface implements IntentFirewall.AMSInterface { diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 7604b6b8f2df..f72104981bc0 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -4526,27 +4526,30 @@ public class AudioService extends IAudioService.Stub if (mStreamType == srcStream.mStreamType) { return; } - synchronized (VolumeStreamState.class) { - int srcStreamType = srcStream.getStreamType(); - // apply default device volume from source stream to all devices first in case - // some devices are present in this stream state but not in source stream state - int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT); - index = rescaleIndex(index, srcStreamType, mStreamType); - for (int i = 0; i < mIndexMap.size(); i++) { - mIndexMap.put(mIndexMap.keyAt(i), index); - } - // Now apply actual volume for devices in source stream state - SparseIntArray srcMap = srcStream.mIndexMap; - for (int i = 0; i < srcMap.size(); i++) { - int device = srcMap.keyAt(i); - index = srcMap.valueAt(i); + synchronized (mSettingsLock) { + synchronized (VolumeStreamState.class) { + int srcStreamType = srcStream.getStreamType(); + // apply default device volume from source stream to all devices first in case + // some devices are present in this stream state but not in source stream state + int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT); index = rescaleIndex(index, srcStreamType, mStreamType); - - setIndex(index, device, caller); + for (int i = 0; i < mIndexMap.size(); i++) { + mIndexMap.put(mIndexMap.keyAt(i), index); + } + // Now apply actual volume for devices in source stream state + SparseIntArray srcMap = srcStream.mIndexMap; + for (int i = 0; i < srcMap.size(); i++) { + int device = srcMap.keyAt(i); + index = srcMap.valueAt(i); + index = rescaleIndex(index, srcStreamType, mStreamType); + + setIndex(index, device, caller); + } } } } + @GuardedBy("mSettingsLock") public void setAllIndexesToMax() { synchronized (VolumeStreamState.class) { for (int i = 0; i < mIndexMap.size(); i++) { diff --git a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java index 4098b989a16b..0504c79c55bd 100644 --- a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java +++ b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java @@ -62,6 +62,11 @@ public class ServiceManagerPermissionTests extends TestCase { public boolean isRuntimePermission(String permission) { return false; } + + @Override + public int getPackageUid(String packageName, int flags) { + return -1; + } }; ServiceManagerNative.asInterface(BinderInternal.getContextObject()) .setPermissionController(pc); |