Loading core/jni/com_android_internal_os_Zygote.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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); Loading Loading @@ -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; } Loading core/jni/fd_utils-inl.h +47 −3 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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; } Loading packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +2 −1 Original line number Diff line number Diff line Loading @@ -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 { Loading services/net/java/android/net/dhcp/DhcpClient.java +8 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } } Loading services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java +1 −51 Original line number Diff line number Diff line Loading @@ -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.*; Loading Loading @@ -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"); Loading Loading @@ -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) { Loading Loading
core/jni/com_android_internal_os_Zygote.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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); Loading Loading @@ -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; } Loading
core/jni/fd_utils-inl.h +47 −3 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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; } Loading
packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java +2 −1 Original line number Diff line number Diff line Loading @@ -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 { Loading
services/net/java/android/net/dhcp/DhcpClient.java +8 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } } Loading
services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java +1 −51 Original line number Diff line number Diff line Loading @@ -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.*; Loading Loading @@ -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"); Loading Loading @@ -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) { Loading