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