1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.seccomp.cts.app; 18 19 import android.content.pm.ApplicationInfo; 20 import android.os.Process; 21 import android.os.UserHandle; 22 import android.util.Log; 23 24 public class ZygotePreload implements android.app.ZygotePreload { 25 static final String TAG = "SeccompDeviceTest"; 26 27 static volatile boolean sResult = false; 28 static volatile int sStartOfIsolatedRange = -1; 29 testSetResUidGidBlocked(int rid, int eid, int sid, boolean expectBlocked, boolean log)30 static private boolean testSetResUidGidBlocked(int rid, int eid, int sid, 31 boolean expectBlocked, boolean log) { 32 boolean blocked = SeccompDeviceTest.testSetresuidBlocked(rid, eid, sid); 33 if (blocked != expectBlocked) { 34 if (log) { 35 Log.e(TAG, "setresuid( " + Integer.toString(rid) + "," 36 + Integer.toString(eid) + "," + Integer.toString(sid) + ")" 37 + " is wrongly " + (expectBlocked ? "allowed." : "blocked.")); 38 } 39 return false; 40 } 41 42 blocked = SeccompDeviceTest.testSetresgidBlocked(rid, eid, sid); 43 if (blocked != expectBlocked) { 44 if (log) { 45 Log.e(TAG, "setresguid( " + Integer.toString(rid) + "," 46 + Integer.toString(eid) + "," + Integer.toString(sid) + ")" 47 + " is wrongly " + (expectBlocked ? "allowed." : "blocked.")); 48 } 49 return false; 50 } 51 52 return true; 53 } 54 testSetResUidGidBlocked(int rid, int eid, int sid)55 static private boolean testSetResUidGidBlocked(int rid, int eid, int sid) { 56 return testSetResUidGidBlocked(rid, eid, sid, true /*expectBlocked */, true /* log */); 57 } 58 testSetResUidGidAllowed(int rid, int eid, int sid)59 static private boolean testSetResUidGidAllowed(int rid, int eid, int sid) { 60 return testSetResUidGidBlocked(rid, eid, sid, false /*expectBlocked */, true /* log */); 61 } 62 testSetResUidGidAllowedNoLog(int rid, int eid, int sid)63 static private boolean testSetResUidGidAllowedNoLog(int rid, int eid, int sid) { 64 return testSetResUidGidBlocked(rid, eid, sid, false /*expectBlocked */, false /* log */); 65 } 66 getSeccomptestResult()67 static synchronized public boolean getSeccomptestResult() { 68 return sResult; 69 } 70 getStartOfIsolatedRange()71 static synchronized public int getStartOfIsolatedRange() { 72 return sStartOfIsolatedRange; 73 } 74 75 /* 76 * This is called from the app_zygote security context, which has two seccomp 77 * filters in place: 78 * 1) The regular app seccomp filter (which allows setresuid/setresgid) 79 * 2) A setresuid/setresgid limiting filter, which restricts the calls to 80 * setresuid/setresgid to be in a particular range. 81 * 82 * This test enforces 2) is in place. 83 */ 84 @Override doPreload(ApplicationInfo appInfo)85 synchronized public void doPreload(ApplicationInfo appInfo) { 86 boolean result = true; 87 88 // root uid 89 result &= testSetResUidGidBlocked(0, 0, 0); 90 // system uid 91 result &= testSetResUidGidBlocked(Process.SYSTEM_UID, Process.SYSTEM_UID, 92 Process.SYSTEM_UID); 93 // mix of uids 94 result &= testSetResUidGidBlocked(0, Process.SYSTEM_UID, 95 Process.SYSTEM_UID); 96 97 // an app uid for the current user, and another user 98 for (int userId = UserHandle.myUserId(); userId <= UserHandle.myUserId() + 1; userId++) { 99 int appStart = UserHandle.getUid(userId, Process.FIRST_APPLICATION_UID); 100 result &= testSetResUidGidBlocked(appStart, appStart, appStart); 101 int appEnd = UserHandle.getUid(userId, Process.LAST_APPLICATION_UID); 102 result &= testSetResUidGidBlocked(appEnd, appEnd, appEnd); 103 } 104 105 // an isolated process uid for the current user, and another user 106 for (int userId = UserHandle.myUserId(); userId <= UserHandle.myUserId() + 1; userId++) { 107 int regularIsolatedStart = UserHandle.getUid(userId, Process.FIRST_ISOLATED_UID); 108 result &= testSetResUidGidBlocked(regularIsolatedStart, regularIsolatedStart, 109 regularIsolatedStart); 110 int regularIsolatedEnd = UserHandle.getUid(userId, Process.LAST_ISOLATED_UID); 111 result &= testSetResUidGidBlocked(regularIsolatedEnd, regularIsolatedEnd, 112 regularIsolatedEnd); 113 } 114 115 // Test all ranges of app zygote UIDs; we don't know here which 116 // isolated UID is assigned to our process, so we will test all ranges, 117 // and verify only one is allowed; then have the caller verify that 118 // this was indeed our allowed range. 119 int isolatedUserStart = UserHandle.getUid(UserHandle.myUserId(), 120 Process.FIRST_APP_ZYGOTE_ISOLATED_UID); 121 int isolatedUserEnd = UserHandle.getUid(UserHandle.myUserId(), 122 Process.LAST_APP_ZYGOTE_ISOLATED_UID); 123 124 for (int i = isolatedUserStart; i < isolatedUserEnd; i += Process.NUM_UIDS_PER_APP_ZYGOTE) { 125 boolean rangeAllowed = testSetResUidGidAllowedNoLog(i, i, i); 126 if (rangeAllowed) { 127 if (sStartOfIsolatedRange != -1) { 128 Log.e(TAG, "Found more than one allowed isolated UID range: " 129 + sStartOfIsolatedRange + ", " + i); 130 result = false; 131 break; 132 } 133 sStartOfIsolatedRange = i; 134 135 // off-by-one and some variants 136 result &= testSetResUidGidBlocked(i - 1, i - 1, i - 1); 137 result &= testSetResUidGidBlocked(i, i - 1, i); 138 result &= testSetResUidGidBlocked(i, i, i - 1); 139 int overEndOfRange = i + Process.NUM_UIDS_PER_APP_ZYGOTE; 140 result &= testSetResUidGidBlocked(overEndOfRange, overEndOfRange, overEndOfRange); 141 result &= testSetResUidGidBlocked(overEndOfRange, i, i); 142 result &= testSetResUidGidBlocked(i, overEndOfRange, overEndOfRange); 143 144 // mixed allowed rgid with dis-allowed euid and suid (and variants) 145 result &= testSetResUidGidBlocked(i, 0, 0); 146 result &= testSetResUidGidBlocked(i, 0, i); 147 result &= testSetResUidGidBlocked(i, i, 0); 148 result &= testSetResUidGidBlocked(0, i, 0); 149 result &= testSetResUidGidBlocked(0, i, i); 150 result &= testSetResUidGidBlocked(0, 0, i); 151 } 152 } 153 154 result &= testSetResUidGidBlocked(Process.LAST_APP_ZYGOTE_ISOLATED_UID + 1, 155 Process.LAST_APP_ZYGOTE_ISOLATED_UID + 1, Process.LAST_APP_ZYGOTE_ISOLATED_UID + 1); 156 157 // Store result 158 sResult = result; 159 } 160 } 161