• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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