• 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 "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