Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 78907ab5 authored by Dan Pasanen's avatar Dan Pasanen
Browse files

Merge tag 'android-7.1.1_r9' into cm-14.1

Android 7.1.1 release 9

Change-Id: Ibe822ab39b61092a77b1b6912dc5f91d5c31c266
parents 8f7df53a a014b6be
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -454,6 +454,20 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
  SetForkLoad(true);
#endif

  sigset_t sigchld;
  sigemptyset(&sigchld);
  sigaddset(&sigchld, SIGCHLD);

  // Temporarily block SIGCHLD during forks. The SIGCHLD handler might
  // log, which would result in the logging FDs we close being reopened.
  // This would cause failures because the FDs are not whitelisted.
  //
  // Note that the zygote process is single threaded at this point.
  if (sigprocmask(SIG_BLOCK, &sigchld, nullptr) == -1) {
    ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
    RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_BLOCK, { SIGCHLD }) failed.");
  }

  // Close any logging related FDs before we start evaluating the list of
  // file descriptors.
  __android_log_close();
@@ -485,6 +499,11 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
      RuntimeAbort(env, __LINE__, "Unable to reopen whitelisted descriptors.");
    }

    if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
      ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
      RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed.");
    }

    // Keep capabilities across UID change, unless we're staying root.
    if (uid != 0) {
      EnableKeepCapabilities(env);
@@ -618,6 +637,11 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
    SetForkLoad(false);
#endif

    // We blocked SIGCHLD prior to a fork, we unblock it here.
    if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
      ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
      RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed.");
    }
  }
  return pid;
}
+47 −3
Original line number Diff line number Diff line
@@ -245,9 +245,22 @@ class FileDescriptorInfo {
    is_sock(false) {
  }

  static bool StartsWith(const std::string& str, const std::string& prefix) {
    return str.compare(0, prefix.size(), prefix) == 0;
  }

  static bool EndsWith(const std::string& str, const std::string& suffix) {
    if (suffix.size() > str.size()) {
      return false;
    }

    return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
  }

  // Returns true iff. a given path is whitelisted. A path is whitelisted
  // if it belongs to the whitelist (see kPathWhitelist) or if it's a path
  // under /system/framework that ends with ".jar".
  // under /system/framework that ends with ".jar" or if it is a system
  // framework overlay.
  static bool IsWhitelisted(const std::string& path) {
    for (size_t i = 0; i < (sizeof(kPathWhitelist) / sizeof(kPathWhitelist[0])); ++i) {
      if (kPathWhitelist[i] == path) {
@@ -257,10 +270,41 @@ class FileDescriptorInfo {

    static const std::string kFrameworksPrefix = "/system/framework/";
    static const std::string kJarSuffix = ".jar";
    if (path.compare(0, kFrameworksPrefix.size(), kFrameworksPrefix) == 0 &&
        path.compare(path.size() - kJarSuffix.size(), kJarSuffix.size(), kJarSuffix) == 0) {
    if (StartsWith(path, kFrameworksPrefix) && EndsWith(path, kJarSuffix)) {
      return true;
    }

    // Whitelist files needed for Runtime Resource Overlay, like these:
    // /system/vendor/overlay/framework-res.apk
    // /system/vendor/overlay-subdir/pg/framework-res.apk
    // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap
    // /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap
    // See AssetManager.cpp for more details on overlay-subdir.
    static const std::string kOverlayDir = "/system/vendor/overlay/";
    static const std::string kVendorOverlayDir = "/vendor/overlay";
    static const std::string kOverlaySubdir = "/system/vendor/overlay-subdir/";
    static const std::string kApkSuffix = ".apk";

    if ((StartsWith(path, kOverlayDir) || StartsWith(path, kOverlaySubdir)
         || StartsWith(path, kVendorOverlayDir))
        && EndsWith(path, kApkSuffix)
        && path.find("/../") == std::string::npos) {
      return true;
    }

    static const std::string kOverlayIdmapPrefix = "/data/resource-cache/";
    static const std::string kOverlayIdmapSuffix = ".apk@idmap";
    if (StartsWith(path, kOverlayIdmapPrefix) && EndsWith(path, kOverlayIdmapSuffix)
        && path.find("/../") == std::string::npos) {
      return true;
    }

    // All regular files that are placed under this path are whitelisted automatically.
    static const std::string kZygoteWhitelistPath = "/vendor/zygote_whitelist/";
    if (StartsWith(path, kZygoteWhitelistPath) && path.find("/../") == std::string::npos) {
      return true;
    }

    return false;
  }

+2 −1
Original line number Diff line number Diff line
@@ -161,7 +161,8 @@ public class ExternalStorageProvider extends DocumentsProvider {
                    final VolumeInfo privateVol = mStorageManager.findPrivateForEmulated(volume);
                    title = mStorageManager.getBestVolumeDescription(privateVol);
                }
            } else if (volume.getType() == VolumeInfo.TYPE_PUBLIC) {
            } else if (volume.getType() == VolumeInfo.TYPE_PUBLIC
                    && volume.getMountUserId() == userId) {
                rootId = volume.getFsUuid();
                title = mStorageManager.getBestVolumeDescription(volume);
            } else {
+8 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.os.SystemClock;
import android.system.ErrnoException;
import android.system.Os;
import android.system.PacketSocketAddress;
import android.util.EventLog;
import android.util.Log;
import android.util.SparseArray;
import android.util.TimeUtils;
@@ -369,6 +370,13 @@ public class DhcpClient extends StateMachine {
                    if (PACKET_DBG) {
                        Log.d(TAG, HexDump.dumpHexString(mPacket, 0, length));
                    }
                    if (e.errorCode == DhcpErrorEvent.DHCP_NO_COOKIE) {
                        int snetTagId = 0x534e4554;
                        String bugId = "31850211";
                        int uid = -1;
                        String data = DhcpPacket.ParseException.class.getName();
                        EventLog.writeEvent(snetTagId, bugId, uid, data);
                    }
                    logError(e.errorCode);
                }
            }
+1 −51
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import java.net.Inet4Address;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
import junit.framework.TestCase;

import static android.net.dhcp.DhcpPacket.*;
@@ -431,7 +430,7 @@ public class DhcpPacketTest extends TestCase {
        try {
            DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, packet.length, ENCAP_L3);
        } catch (DhcpPacket.ParseException expected) {
            assertDhcpErrorCodes(DhcpErrorEvent.DHCP_NO_COOKIE, expected.errorCode);
            assertDhcpErrorCodes(DhcpErrorEvent.PARSING_ERROR, expected.errorCode);
            return;
        }
        fail("Dhcp packet parsing should have failed");
@@ -473,55 +472,6 @@ public class DhcpPacketTest extends TestCase {
        assertEquals(Integer.toHexString(expected), Integer.toHexString(got));
    }

    public void testTruncatedOfferPackets() throws Exception {
        final byte[] packet = HexDump.hexStringToByteArray(
            // IP header.
            "450001518d0600004011144dc0a82b01c0a82bf7" +
            // UDP header.
            "00430044013d9ac7" +
            // BOOTP header.
            "02010600dfc23d1f0002000000000000c0a82bf7c0a82b0100000000" +
            // MAC address.
            "30766ff2a90c00000000000000000000" +
            // Server name.
            "0000000000000000000000000000000000000000000000000000000000000000" +
            "0000000000000000000000000000000000000000000000000000000000000000" +
            // File.
            "0000000000000000000000000000000000000000000000000000000000000000" +
            "0000000000000000000000000000000000000000000000000000000000000000" +
            "0000000000000000000000000000000000000000000000000000000000000000" +
            "0000000000000000000000000000000000000000000000000000000000000000" +
            // Options
            "638253633501023604c0a82b01330400000e103a04000007083b0400000c4e0104ffffff00" +
            "1c04c0a82bff0304c0a82b010604c0a82b012b0f414e44524f49445f4d455445524544ff");

        for (int len = 0; len < packet.length; len++) {
            try {
                DhcpPacket.decodeFullPacket(packet, len, ENCAP_L3);
            } catch (ParseException e) {
                if (e.errorCode == DhcpErrorEvent.PARSING_ERROR) {
                    fail(String.format("bad truncated packet of length %d", len));
                }
            }
        }
    }

    public void testRandomPackets() throws Exception {
        final int maxRandomPacketSize = 512;
        final Random r = new Random();
        for (int i = 0; i < 10000; i++) {
            byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
            r.nextBytes(packet);
            try {
                DhcpPacket.decodeFullPacket(packet, packet.length, ENCAP_L3);
            } catch (ParseException e) {
                if (e.errorCode == DhcpErrorEvent.PARSING_ERROR) {
                    fail("bad packet: " + HexDump.toHexString(packet));
                }
            }
        }
    }

    private byte[] mtuBytes(int mtu) {
        // 0x1a02: option 26, length 2. 0xff: no more options.
        if (mtu > Short.MAX_VALUE - Short.MIN_VALUE) {