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