1 /*
2 * Copyright (C) 2008 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 #include "dalvik_system_ZygoteHooks.h"
18
19 #include <stdlib.h>
20
21 #include "android-base/stringprintf.h"
22
23 #include "arch/instruction_set.h"
24 #include "art_method-inl.h"
25 #include "debugger.h"
26 #include "java_vm_ext.h"
27 #include "jit/jit.h"
28 #include "jni_internal.h"
29 #include "native_util.h"
30 #include "nativehelper/jni_macros.h"
31 #include "nativehelper/JNIHelp.h"
32 #include "nativehelper/ScopedUtfChars.h"
33 #include "non_debuggable_classes.h"
34 #include "scoped_thread_state_change-inl.h"
35 #include "stack.h"
36 #include "thread-current-inl.h"
37 #include "thread_list.h"
38 #include "trace.h"
39
40 #if defined(__linux__)
41 #include <sys/prctl.h>
42 #endif
43
44 #include <sys/resource.h>
45
46 namespace art {
47
48 // Set to true to always determine the non-debuggable classes even if we would not allow a debugger
49 // to actually attach.
50 static constexpr bool kAlwaysCollectNonDebuggableClasses = kIsDebugBuild;
51
52 using android::base::StringPrintf;
53
EnableDebugger()54 static void EnableDebugger() {
55 #if defined(__linux__)
56 // To let a non-privileged gdbserver attach to this
57 // process, we must set our dumpable flag.
58 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
59 PLOG(ERROR) << "prctl(PR_SET_DUMPABLE) failed for pid " << getpid();
60 }
61
62 // Even if Yama is on a non-privileged native debugger should
63 // be able to attach to the debuggable app.
64 if (prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0) == -1) {
65 // if Yama is off prctl(PR_SET_PTRACER) returns EINVAL - don't log in this
66 // case since it's expected behaviour.
67 if (errno != EINVAL) {
68 PLOG(ERROR) << "prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY) failed for pid " << getpid();
69 }
70 }
71 #endif
72 // We don't want core dumps, though, so set the core dump size to 0.
73 rlimit rl;
74 rl.rlim_cur = 0;
75 rl.rlim_max = RLIM_INFINITY;
76 if (setrlimit(RLIMIT_CORE, &rl) == -1) {
77 PLOG(ERROR) << "setrlimit(RLIMIT_CORE) failed for pid " << getpid();
78 }
79 }
80
81 class ClassSet {
82 public:
83 // The number of classes we reasonably expect to have to look at. Realistically the number is more
84 // ~10 but there is little harm in having some extra.
85 static constexpr int kClassSetCapacity = 100;
86
ClassSet(Thread * const self)87 explicit ClassSet(Thread* const self) : self_(self) {
88 self_->GetJniEnv()->PushFrame(kClassSetCapacity);
89 }
90
~ClassSet()91 ~ClassSet() {
92 self_->GetJniEnv()->PopFrame();
93 }
94
AddClass(ObjPtr<mirror::Class> klass)95 void AddClass(ObjPtr<mirror::Class> klass) REQUIRES(Locks::mutator_lock_) {
96 class_set_.insert(self_->GetJniEnv()->AddLocalReference<jclass>(klass.Ptr()));
97 }
98
GetClasses() const99 const std::unordered_set<jclass>& GetClasses() const {
100 return class_set_;
101 }
102
103 private:
104 Thread* const self_;
105 std::unordered_set<jclass> class_set_;
106 };
107
DoCollectNonDebuggableCallback(Thread * thread,void * data)108 static void DoCollectNonDebuggableCallback(Thread* thread, void* data)
109 REQUIRES(Locks::mutator_lock_) {
110 class NonDebuggableStacksVisitor : public StackVisitor {
111 public:
112 NonDebuggableStacksVisitor(Thread* t, ClassSet* class_set)
113 : StackVisitor(t, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
114 class_set_(class_set) {}
115
116 ~NonDebuggableStacksVisitor() OVERRIDE {}
117
118 bool VisitFrame() OVERRIDE REQUIRES(Locks::mutator_lock_) {
119 if (GetMethod()->IsRuntimeMethod()) {
120 return true;
121 }
122 class_set_->AddClass(GetMethod()->GetDeclaringClass());
123 if (kIsDebugBuild) {
124 LOG(INFO) << GetMethod()->GetDeclaringClass()->PrettyClass()
125 << " might not be fully debuggable/deoptimizable due to "
126 << GetMethod()->PrettyMethod() << " appearing on the stack during zygote fork.";
127 }
128 return true;
129 }
130
131 private:
132 ClassSet* class_set_;
133 };
134 NonDebuggableStacksVisitor visitor(thread, reinterpret_cast<ClassSet*>(data));
135 visitor.WalkStack();
136 }
137
CollectNonDebuggableClasses()138 static void CollectNonDebuggableClasses() REQUIRES(!Locks::mutator_lock_) {
139 Runtime* const runtime = Runtime::Current();
140 Thread* const self = Thread::Current();
141 // Get the mutator lock.
142 ScopedObjectAccess soa(self);
143 ClassSet classes(self);
144 {
145 // Drop the shared mutator lock.
146 ScopedThreadSuspension sts(self, art::ThreadState::kNative);
147 // Get exclusive mutator lock with suspend all.
148 ScopedSuspendAll suspend("Checking stacks for non-obsoletable methods!", /*long_suspend*/false);
149 MutexLock mu(Thread::Current(), *Locks::thread_list_lock_);
150 runtime->GetThreadList()->ForEach(DoCollectNonDebuggableCallback, &classes);
151 }
152 for (jclass klass : classes.GetClasses()) {
153 NonDebuggableClasses::AddNonDebuggableClass(klass);
154 }
155 }
156
EnableDebugFeatures(uint32_t debug_flags)157 static void EnableDebugFeatures(uint32_t debug_flags) {
158 // Must match values in com.android.internal.os.Zygote.
159 enum {
160 DEBUG_ENABLE_JDWP = 1,
161 DEBUG_ENABLE_CHECKJNI = 1 << 1,
162 DEBUG_ENABLE_ASSERT = 1 << 2,
163 DEBUG_ENABLE_SAFEMODE = 1 << 3,
164 DEBUG_ENABLE_JNI_LOGGING = 1 << 4,
165 DEBUG_GENERATE_DEBUG_INFO = 1 << 5,
166 DEBUG_ALWAYS_JIT = 1 << 6,
167 DEBUG_NATIVE_DEBUGGABLE = 1 << 7,
168 DEBUG_JAVA_DEBUGGABLE = 1 << 8,
169 };
170
171 Runtime* const runtime = Runtime::Current();
172 if ((debug_flags & DEBUG_ENABLE_CHECKJNI) != 0) {
173 JavaVMExt* vm = runtime->GetJavaVM();
174 if (!vm->IsCheckJniEnabled()) {
175 LOG(INFO) << "Late-enabling -Xcheck:jni";
176 vm->SetCheckJniEnabled(true);
177 // There's only one thread running at this point, so only one JNIEnv to fix up.
178 Thread::Current()->GetJniEnv()->SetCheckJniEnabled(true);
179 } else {
180 LOG(INFO) << "Not late-enabling -Xcheck:jni (already on)";
181 }
182 debug_flags &= ~DEBUG_ENABLE_CHECKJNI;
183 }
184
185 if ((debug_flags & DEBUG_ENABLE_JNI_LOGGING) != 0) {
186 gLogVerbosity.third_party_jni = true;
187 debug_flags &= ~DEBUG_ENABLE_JNI_LOGGING;
188 }
189
190 Dbg::SetJdwpAllowed((debug_flags & DEBUG_ENABLE_JDWP) != 0);
191 if ((debug_flags & DEBUG_ENABLE_JDWP) != 0) {
192 EnableDebugger();
193 }
194 debug_flags &= ~DEBUG_ENABLE_JDWP;
195
196 const bool safe_mode = (debug_flags & DEBUG_ENABLE_SAFEMODE) != 0;
197 if (safe_mode) {
198 // Only quicken oat files.
199 runtime->AddCompilerOption("--compiler-filter=quicken");
200 runtime->SetSafeMode(true);
201 debug_flags &= ~DEBUG_ENABLE_SAFEMODE;
202 }
203
204 const bool generate_debug_info = (debug_flags & DEBUG_GENERATE_DEBUG_INFO) != 0;
205 if (generate_debug_info) {
206 runtime->AddCompilerOption("--generate-debug-info");
207 debug_flags &= ~DEBUG_GENERATE_DEBUG_INFO;
208 }
209
210 // This is for backwards compatibility with Dalvik.
211 debug_flags &= ~DEBUG_ENABLE_ASSERT;
212
213 if ((debug_flags & DEBUG_ALWAYS_JIT) != 0) {
214 jit::JitOptions* jit_options = runtime->GetJITOptions();
215 CHECK(jit_options != nullptr);
216 jit_options->SetJitAtFirstUse();
217 debug_flags &= ~DEBUG_ALWAYS_JIT;
218 }
219
220 bool needs_non_debuggable_classes = false;
221 if ((debug_flags & DEBUG_JAVA_DEBUGGABLE) != 0) {
222 runtime->AddCompilerOption("--debuggable");
223 runtime->SetJavaDebuggable(true);
224 // Deoptimize the boot image as it may be non-debuggable.
225 runtime->DeoptimizeBootImage();
226 debug_flags &= ~DEBUG_JAVA_DEBUGGABLE;
227 needs_non_debuggable_classes = true;
228 }
229 if (needs_non_debuggable_classes || kAlwaysCollectNonDebuggableClasses) {
230 CollectNonDebuggableClasses();
231 }
232
233 if ((debug_flags & DEBUG_NATIVE_DEBUGGABLE) != 0) {
234 runtime->AddCompilerOption("--debuggable");
235 runtime->AddCompilerOption("--generate-debug-info");
236 runtime->SetNativeDebuggable(true);
237 debug_flags &= ~DEBUG_NATIVE_DEBUGGABLE;
238 }
239
240 if (debug_flags != 0) {
241 LOG(ERROR) << StringPrintf("Unknown bits set in debug_flags: %#x", debug_flags);
242 }
243 }
244
ZygoteHooks_nativePreFork(JNIEnv * env,jclass)245 static jlong ZygoteHooks_nativePreFork(JNIEnv* env, jclass) {
246 Runtime* runtime = Runtime::Current();
247 CHECK(runtime->IsZygote()) << "runtime instance not started with -Xzygote";
248
249 runtime->PreZygoteFork();
250
251 if (Trace::GetMethodTracingMode() != TracingMode::kTracingInactive) {
252 // Tracing active, pause it.
253 Trace::Pause();
254 }
255
256 // Grab thread before fork potentially makes Thread::pthread_key_self_ unusable.
257 return reinterpret_cast<jlong>(ThreadForEnv(env));
258 }
259
ZygoteHooks_nativePostForkChild(JNIEnv * env,jclass,jlong token,jint debug_flags,jboolean is_system_server,jstring instruction_set)260 static void ZygoteHooks_nativePostForkChild(JNIEnv* env,
261 jclass,
262 jlong token,
263 jint debug_flags,
264 jboolean is_system_server,
265 jstring instruction_set) {
266 Thread* thread = reinterpret_cast<Thread*>(token);
267 // Our system thread ID, etc, has changed so reset Thread state.
268 thread->InitAfterFork();
269 EnableDebugFeatures(debug_flags);
270
271 // Update tracing.
272 if (Trace::GetMethodTracingMode() != TracingMode::kTracingInactive) {
273 Trace::TraceOutputMode output_mode = Trace::GetOutputMode();
274 Trace::TraceMode trace_mode = Trace::GetMode();
275 size_t buffer_size = Trace::GetBufferSize();
276
277 // Just drop it.
278 Trace::Abort();
279
280 // Only restart if it was streaming mode.
281 // TODO: Expose buffer size, so we can also do file mode.
282 if (output_mode == Trace::TraceOutputMode::kStreaming) {
283 static constexpr size_t kMaxProcessNameLength = 100;
284 char name_buf[kMaxProcessNameLength] = {};
285 int rc = pthread_getname_np(pthread_self(), name_buf, kMaxProcessNameLength);
286 std::string proc_name;
287
288 if (rc == 0) {
289 // On success use the pthread name.
290 proc_name = name_buf;
291 }
292
293 if (proc_name.empty() || proc_name == "zygote" || proc_name == "zygote64") {
294 // Either no process name, or the name hasn't been changed, yet. Just use pid.
295 pid_t pid = getpid();
296 proc_name = StringPrintf("%u", static_cast<uint32_t>(pid));
297 }
298
299 std::string trace_file = StringPrintf("/data/misc/trace/%s.trace.bin", proc_name.c_str());
300 Trace::Start(trace_file.c_str(),
301 -1,
302 buffer_size,
303 0, // TODO: Expose flags.
304 output_mode,
305 trace_mode,
306 0); // TODO: Expose interval.
307 if (thread->IsExceptionPending()) {
308 ScopedObjectAccess soa(env);
309 thread->ClearException();
310 }
311 }
312 }
313
314 if (instruction_set != nullptr && !is_system_server) {
315 ScopedUtfChars isa_string(env, instruction_set);
316 InstructionSet isa = GetInstructionSetFromString(isa_string.c_str());
317 Runtime::NativeBridgeAction action = Runtime::NativeBridgeAction::kUnload;
318 if (isa != kNone && isa != kRuntimeISA) {
319 action = Runtime::NativeBridgeAction::kInitialize;
320 }
321 Runtime::Current()->InitNonZygoteOrPostFork(
322 env, is_system_server, action, isa_string.c_str());
323 } else {
324 Runtime::Current()->InitNonZygoteOrPostFork(
325 env, is_system_server, Runtime::NativeBridgeAction::kUnload, nullptr);
326 }
327 }
328
ZygoteHooks_startZygoteNoThreadCreation(JNIEnv * env ATTRIBUTE_UNUSED,jclass klass ATTRIBUTE_UNUSED)329 static void ZygoteHooks_startZygoteNoThreadCreation(JNIEnv* env ATTRIBUTE_UNUSED,
330 jclass klass ATTRIBUTE_UNUSED) {
331 Runtime::Current()->SetZygoteNoThreadSection(true);
332 }
333
ZygoteHooks_stopZygoteNoThreadCreation(JNIEnv * env ATTRIBUTE_UNUSED,jclass klass ATTRIBUTE_UNUSED)334 static void ZygoteHooks_stopZygoteNoThreadCreation(JNIEnv* env ATTRIBUTE_UNUSED,
335 jclass klass ATTRIBUTE_UNUSED) {
336 Runtime::Current()->SetZygoteNoThreadSection(false);
337 }
338
339 static JNINativeMethod gMethods[] = {
340 NATIVE_METHOD(ZygoteHooks, nativePreFork, "()J"),
341 NATIVE_METHOD(ZygoteHooks, nativePostForkChild, "(JIZLjava/lang/String;)V"),
342 NATIVE_METHOD(ZygoteHooks, startZygoteNoThreadCreation, "()V"),
343 NATIVE_METHOD(ZygoteHooks, stopZygoteNoThreadCreation, "()V"),
344 };
345
register_dalvik_system_ZygoteHooks(JNIEnv * env)346 void register_dalvik_system_ZygoteHooks(JNIEnv* env) {
347 REGISTER_NATIVE_METHODS("dalvik/system/ZygoteHooks");
348 }
349
350 } // namespace art
351