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