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 } 166 getPolicy()167 public int getPolicy() { 168 return mPolicyState; 169 } 170 getPolicyViolation()171 public int getPolicyViolation() { 172 return mPolicyViolated; 173 } 174 getMessage()175 public String getMessage() { 176 // Note: do not change this format casually. It's 177 // somewhat unfortunately Parceled and passed around 178 // Binder calls and parsed back into an Exception by 179 // Android's StrictMode. This was the least invasive 180 // option and avoided a gross mix of Java Serialization 181 // combined with Parcels. 182 return "policy=" + mPolicyState + " violation=" + mPolicyViolated + 183 (mMessage == null ? "" : (" msg=" + mMessage)); 184 } 185 } 186 187 /** 188 * The default, permissive per-thread policy. 189 * 190 * @hide 191 */ 192 @UnsupportedAppUsage 193 @SystemApi(client = MODULE_LIBRARIES) 194 public static final Policy LAX_POLICY = new Policy() { 195 @Override public String toString() { return "LAX_POLICY"; } 196 @Override public void onWriteToDisk() {} 197 @Override public void onReadFromDisk() {} 198 @Override public void onNetwork() {} 199 @Override public void onUnbufferedIO() {} 200 @Override public void onExplicitGc() {} 201 202 @Override 203 public int getPolicyMask() { 204 return 0; 205 } 206 }; 207 208 /** 209 * The default, permissive per-process policy. 210 * 211 * @hide 212 */ 213 @SystemApi(client = MODULE_LIBRARIES) 214 public static final VmPolicy LAX_VM_POLICY = new VmPolicy() { 215 @Override public String toString() { return "LAX_VM_POLICY"; } 216 @Override public void onPathAccess(String path) {} 217 }; 218 219 @UnsupportedAppUsage 220 private static ThreadLocal<Policy> threadPolicy = new ThreadLocal<Policy>() { 221 @Override protected Policy initialValue() { 222 return LAX_POLICY; 223 } 224 }; 225 226 private static volatile VmPolicy vmPolicy = LAX_VM_POLICY; 227 228 /** 229 * Get the per-thread policy for the current thread. 230 * 231 * @return the current thread's policy. Will return the {@link #LAX_POLICY} 232 * instance if nothing else is set. 233 * 234 * @hide 235 */ 236 @UnsupportedAppUsage 237 @SystemApi(client = MODULE_LIBRARIES) 238 @libcore.api.IntraCoreApi getThreadPolicy()239 public static @NonNull Policy getThreadPolicy() { 240 return threadPolicy.get(); 241 } 242 243 /** 244 * Sets the per-thread policy for the current thread. 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_POLICY} if you 250 * want to unset the active policy. 251 * 252 * @hide 253 */ 254 @UnsupportedAppUsage 255 @SystemApi(client = MODULE_LIBRARIES) setThreadPolicy(@onNull Policy policy)256 public static void setThreadPolicy(@NonNull Policy policy) { 257 threadPolicy.set(Objects.requireNonNull(policy)); 258 } 259 260 /** 261 * Get the per-process policy for the current process. 262 * 263 * @return the current process's policy. Will return the 264 * {@link #LAX_VM_POLICY} instance if nothing else is set. 265 * 266 * @hide 267 */ 268 @SystemApi(client = MODULE_LIBRARIES) getVmPolicy()269 public static @NonNull VmPolicy getVmPolicy() { 270 return vmPolicy; 271 } 272 273 /** 274 * Set the per-process policy for the current process. 275 * <p> 276 * This should only be called by {@code StrictMode}, since there can only be 277 * one policy active at any given time. 278 * 279 * @param policy policy to set. Use the public {@link #LAX_VM_POLICY} if you 280 * want to unset the active policy. 281 * 282 * @hide 283 */ 284 @SystemApi(client = MODULE_LIBRARIES) setVmPolicy(@onNull VmPolicy policy)285 public static void setVmPolicy(@NonNull VmPolicy policy) { 286 vmPolicy = Objects.requireNonNull(policy); 287 } 288 BlockGuard()289 private BlockGuard() {} 290 } 291