1 /* 2 * Copyright (C) 2010 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 dalvik.system; 18 19 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; 20 21 import android.annotation.SystemApi; 22 import android.compat.annotation.UnsupportedAppUsage; 23 24 import java.util.Objects; 25 import libcore.util.NonNull; 26 27 /** 28 * Interface that enables {@code StrictMode} to install callbacks to implement 29 * its policy detection and penalty behavior in {@code libcore} code. 30 * <p> 31 * The framework separately defines {@code StrictMode.ThreadPolicy} and 32 * {@code StrictMode.VmPolicy}, so we mirror that separation here; the former is 33 * designed for per-thread policies, and the latter for process-wide policies. 34 * <p> 35 * Note that this is all best-effort to catch most accidental mistakes and isn't 36 * intended to be a perfect mechanism, nor provide any sort of security. 37 * 38 * @hide 39 */ 40 @SystemApi(client = MODULE_LIBRARIES) 41 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) 42 @libcore.api.IntraCoreApi 43 public final class BlockGuard { 44 45 // TODO: refactor class name to something more generic, since its scope is 46 // growing beyond just blocking/logging. 47 48 /** 49 * Per-thread interface used to implement {@code StrictMode.ThreadPolicy}. 50 * 51 * @hide 52 */ 53 @SystemApi(client = MODULE_LIBRARIES) 54 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) 55 @libcore.api.IntraCoreApi 56 public interface Policy { 57 /** 58 * Called on disk writes. 59 * 60 * @hide 61 */ 62 @SystemApi(client = MODULE_LIBRARIES) 63 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) onWriteToDisk()64 void onWriteToDisk(); 65 66 /** 67 * Called on disk reads. 68 * 69 * @hide 70 */ 71 @UnsupportedAppUsage 72 @SystemApi(client = MODULE_LIBRARIES) 73 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) onReadFromDisk()74 void onReadFromDisk(); 75 76 /** 77 * Called on network operations. 78 * 79 * @hide 80 */ 81 @UnsupportedAppUsage 82 @libcore.api.IntraCoreApi onNetwork()83 void onNetwork(); 84 85 /** 86 * Called on unbuffered input/ouput operations. 87 * 88 * @hide 89 */ 90 @SystemApi(client = MODULE_LIBRARIES) 91 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) onUnbufferedIO()92 void onUnbufferedIO(); 93 94 /** 95 * Called on explicit GC request, i.e. Runtime.gc(). 96 * 97 * @hide 98 */ onExplicitGc()99 void onExplicitGc(); 100 101 /** 102 * Returns the policy bitmask, for shipping over Binder calls 103 * to remote threads/processes and reinstantiating the policy 104 * there. The bits in the mask are from the {@code DISALLOW_*} and 105 * {@code PENALTY_*} constants declared in {@code StrictMode} class. 106 * 107 * @return policy bitmask 108 * 109 * @hide 110 */ 111 @SystemApi(client = MODULE_LIBRARIES) 112 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) getPolicyMask()113 int getPolicyMask(); 114 } 115 116 /** 117 * Per-process interface used to implement {@code StrictMode.VmPolicy}. 118 * @hide 119 */ 120 @SystemApi(client = MODULE_LIBRARIES) 121 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) 122 public interface VmPolicy { 123 /** 124 * Called by core libraries code when the given path is accessed. This 125 * allows an implementation to alert developers to unexpected path 126 * access, such as trying to access encrypted files before the 127 * encryption key has been installed. 128 * <p> 129 * This only needs to be called once when a path is first accessed by 130 * the process; it doesn't need to be invoked for each subsequent 131 * read/write. (In contrast, we always need to call the per-thread 132 * policy for every read/write, since ownership of an open file can move 133 * between threads.) 134 * <p> 135 * Note that this is all best-effort to catch most accidental mistakes 136 * and isn't intended to be a perfect mechanism, nor provide any sort of 137 * security. 138 * 139 * @param path The path in the local file system that is being accessed 140 * for reading or writing. 141 * 142 * @hide 143 */ 144 @SystemApi(client = MODULE_LIBRARIES) 145 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) onPathAccess(@onNull String path)146 void onPathAccess(@NonNull String path); 147 } 148 149 /** 150 * @deprecated no longer actively used, but kept intact for hidden API lists. 151 * 152 * @hide 153 */ 154 @Deprecated 155 public static class BlockGuardPolicyException extends RuntimeException { 156 // bitmask of DISALLOW_*, PENALTY_*, etc flags 157 @UnsupportedAppUsage 158 private final int mPolicyState; 159 @UnsupportedAppUsage 160 private final int mPolicyViolated; 161 @UnsupportedAppUsage 162 private final String mMessage; // may be null 163 BlockGuardPolicyException(int policyState, int policyViolated)164 public BlockGuardPolicyException(int policyState, int policyViolated) { 165 this(policyState, policyViolated, null); 166 } 167 168 @UnsupportedAppUsage BlockGuardPolicyException(int policyState, int policyViolated, String message)169 public BlockGuardPolicyException(int policyState, int policyViolated, String message) { 170 mPolicyState = policyState; 171 mPolicyViolated = policyViolated; 172 mMessage = message; 173 fillInStackTrace(); 174 } 175 getPolicy()176 public int getPolicy() { 177 return mPolicyState; 178 } 179 getPolicyViolation()180 public int getPolicyViolation() { 181 return mPolicyViolated; 182 } 183 getMessage()184 public String getMessage() { 185 // Note: do not change this format casually. It's 186 // somewhat unfortunately Parceled and passed around 187 // Binder calls and parsed back into an Exception by 188 // Android's StrictMode. This was the least invasive 189 // option and avoided a gross mix of Java Serialization 190 // combined with Parcels. 191 return "policy=" + mPolicyState + " violation=" + mPolicyViolated + 192 (mMessage == null ? "" : (" msg=" + mMessage)); 193 } 194 } 195 196 /** 197 * The default, permissive per-thread policy. 198 * 199 * @hide 200 */ 201 @UnsupportedAppUsage 202 @SystemApi(client = MODULE_LIBRARIES) 203 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) 204 public static final Policy LAX_POLICY = new Policy() { 205 @Override public String toString() { return "LAX_POLICY"; } 206 @Override public void onWriteToDisk() {} 207 @Override public void onReadFromDisk() {} 208 @Override public void onNetwork() {} 209 @Override public void onUnbufferedIO() {} 210 @Override public void onExplicitGc() {} 211 212 @Override 213 public int getPolicyMask() { 214 return 0; 215 } 216 }; 217 218 /** 219 * The default, permissive per-process policy. 220 * 221 * @hide 222 */ 223 @SystemApi(client = MODULE_LIBRARIES) 224 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) 225 public static final VmPolicy LAX_VM_POLICY = new VmPolicy() { 226 @Override public String toString() { return "LAX_VM_POLICY"; } 227 @Override public void onPathAccess(String path) {} 228 }; 229 230 @UnsupportedAppUsage 231 private static ThreadLocal<Policy> threadPolicy = new ThreadLocal<Policy>() { 232 @Override protected Policy initialValue() { 233 return LAX_POLICY; 234 } 235 }; 236 237 private static volatile VmPolicy vmPolicy = LAX_VM_POLICY; 238 239 /** 240 * Get the per-thread policy for the current thread. 241 * 242 * @return the current thread's policy. Will return the {@link #LAX_POLICY} 243 * instance if nothing else is set. 244 * 245 * @hide 246 */ 247 @UnsupportedAppUsage 248 @SystemApi(client = MODULE_LIBRARIES) 249 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) 250 @libcore.api.IntraCoreApi getThreadPolicy()251 public static @NonNull Policy getThreadPolicy() { 252 return threadPolicy.get(); 253 } 254 255 /** 256 * Sets the per-thread policy for the current thread. 257 * <p> 258 * This should only be called by {@code StrictMode}, since there can only be 259 * one policy active at any given time. 260 * 261 * @param policy policy to set. Use the public {@link #LAX_POLICY} if you 262 * want to unset the active policy. 263 * 264 * @hide 265 */ 266 @UnsupportedAppUsage 267 @SystemApi(client = MODULE_LIBRARIES) 268 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) setThreadPolicy(@onNull Policy policy)269 public static void setThreadPolicy(@NonNull Policy policy) { 270 threadPolicy.set(Objects.requireNonNull(policy)); 271 } 272 273 /** 274 * Get the per-process policy for the current process. 275 * 276 * @return the current process's policy. Will return the 277 * {@link #LAX_VM_POLICY} instance if nothing else is set. 278 * 279 * @hide 280 */ 281 @SystemApi(client = MODULE_LIBRARIES) 282 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) getVmPolicy()283 public static @NonNull VmPolicy getVmPolicy() { 284 return vmPolicy; 285 } 286 287 /** 288 * Set the per-process policy for the current process. 289 * <p> 290 * This should only be called by {@code StrictMode}, since there can only be 291 * one policy active at any given time. 292 * 293 * @param policy policy to set. Use the public {@link #LAX_VM_POLICY} if you 294 * want to unset the active policy. 295 * 296 * @hide 297 */ 298 @SystemApi(client = MODULE_LIBRARIES) 299 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) setVmPolicy(@onNull VmPolicy policy)300 public static void setVmPolicy(@NonNull VmPolicy policy) { 301 vmPolicy = Objects.requireNonNull(policy); 302 } 303 BlockGuard()304 private BlockGuard() {} 305 } 306