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