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