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