xref: /aosp_15_r20/art/libartservice/service/native/service.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2021 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "service.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <jni.h>
20*795d594fSAndroid Build Coastguard Worker 
21*795d594fSAndroid Build Coastguard Worker #include <filesystem>
22*795d594fSAndroid Build Coastguard Worker #include <string_view>
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker #include "android-base/errors.h"
25*795d594fSAndroid Build Coastguard Worker #include "android-base/file.h"
26*795d594fSAndroid Build Coastguard Worker #include "android-base/properties.h"
27*795d594fSAndroid Build Coastguard Worker #include "android-base/result.h"
28*795d594fSAndroid Build Coastguard Worker #include "class_loader_context.h"
29*795d594fSAndroid Build Coastguard Worker #include "gc/heap.h"
30*795d594fSAndroid Build Coastguard Worker #include "nativehelper/JNIHelp.h"
31*795d594fSAndroid Build Coastguard Worker #include "nativehelper/utils.h"
32*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
33*795d594fSAndroid Build Coastguard Worker #include "tools/tools.h"
34*795d594fSAndroid Build Coastguard Worker 
35*795d594fSAndroid Build Coastguard Worker namespace art {
36*795d594fSAndroid Build Coastguard Worker namespace service {
37*795d594fSAndroid Build Coastguard Worker 
38*795d594fSAndroid Build Coastguard Worker using ::android::base::Dirname;
39*795d594fSAndroid Build Coastguard Worker using ::android::base::Result;
40*795d594fSAndroid Build Coastguard Worker using ::android::base::SetProperty;
41*795d594fSAndroid Build Coastguard Worker 
ValidateAbsoluteNormalPath(const std::string & path_str)42*795d594fSAndroid Build Coastguard Worker Result<void> ValidateAbsoluteNormalPath(const std::string& path_str) {
43*795d594fSAndroid Build Coastguard Worker   if (path_str.empty()) {
44*795d594fSAndroid Build Coastguard Worker     return Errorf("Path is empty");
45*795d594fSAndroid Build Coastguard Worker   }
46*795d594fSAndroid Build Coastguard Worker   if (path_str.find('\0') != std::string::npos) {
47*795d594fSAndroid Build Coastguard Worker     return Errorf("Path '{}' has invalid character '\\0'", path_str);
48*795d594fSAndroid Build Coastguard Worker   }
49*795d594fSAndroid Build Coastguard Worker   std::filesystem::path path(path_str);
50*795d594fSAndroid Build Coastguard Worker   if (!path.is_absolute()) {
51*795d594fSAndroid Build Coastguard Worker     return Errorf("Path '{}' is not an absolute path", path_str);
52*795d594fSAndroid Build Coastguard Worker   }
53*795d594fSAndroid Build Coastguard Worker   if (path.lexically_normal() != path_str) {
54*795d594fSAndroid Build Coastguard Worker     return Errorf("Path '{}' is not in normal form", path_str);
55*795d594fSAndroid Build Coastguard Worker   }
56*795d594fSAndroid Build Coastguard Worker   return {};
57*795d594fSAndroid Build Coastguard Worker }
58*795d594fSAndroid Build Coastguard Worker 
ValidatePathElementSubstring(const std::string & path_element_substring,const std::string & name)59*795d594fSAndroid Build Coastguard Worker Result<void> ValidatePathElementSubstring(const std::string& path_element_substring,
60*795d594fSAndroid Build Coastguard Worker                                           const std::string& name) {
61*795d594fSAndroid Build Coastguard Worker   if (path_element_substring.empty()) {
62*795d594fSAndroid Build Coastguard Worker     return Errorf("{} is empty", name);
63*795d594fSAndroid Build Coastguard Worker   }
64*795d594fSAndroid Build Coastguard Worker   if (path_element_substring.find('/') != std::string::npos) {
65*795d594fSAndroid Build Coastguard Worker     return Errorf("{} '{}' has invalid character '/'", name, path_element_substring);
66*795d594fSAndroid Build Coastguard Worker   }
67*795d594fSAndroid Build Coastguard Worker   if (path_element_substring.find('\0') != std::string::npos) {
68*795d594fSAndroid Build Coastguard Worker     return Errorf("{} '{}' has invalid character '\\0'", name, path_element_substring);
69*795d594fSAndroid Build Coastguard Worker   }
70*795d594fSAndroid Build Coastguard Worker   return {};
71*795d594fSAndroid Build Coastguard Worker }
72*795d594fSAndroid Build Coastguard Worker 
ValidatePathElement(const std::string & path_element,const std::string & name)73*795d594fSAndroid Build Coastguard Worker Result<void> ValidatePathElement(const std::string& path_element, const std::string& name) {
74*795d594fSAndroid Build Coastguard Worker   OR_RETURN(ValidatePathElementSubstring(path_element, name));
75*795d594fSAndroid Build Coastguard Worker   if (path_element == "." || path_element == "..") {
76*795d594fSAndroid Build Coastguard Worker     return Errorf("Invalid {} '{}'", name, path_element);
77*795d594fSAndroid Build Coastguard Worker   }
78*795d594fSAndroid Build Coastguard Worker   return {};
79*795d594fSAndroid Build Coastguard Worker }
80*795d594fSAndroid Build Coastguard Worker 
ValidateDexPath(const std::string & dex_path)81*795d594fSAndroid Build Coastguard Worker Result<void> ValidateDexPath(const std::string& dex_path) {
82*795d594fSAndroid Build Coastguard Worker   OR_RETURN(ValidateAbsoluteNormalPath(dex_path));
83*795d594fSAndroid Build Coastguard Worker   return {};
84*795d594fSAndroid Build Coastguard Worker }
85*795d594fSAndroid Build Coastguard Worker 
ValidateClassLoaderContext(std::string_view dex_path,const std::string & class_loader_context)86*795d594fSAndroid Build Coastguard Worker android::base::Result<void> ValidateClassLoaderContext(std::string_view dex_path,
87*795d594fSAndroid Build Coastguard Worker                                                        const std::string& class_loader_context) {
88*795d594fSAndroid Build Coastguard Worker   if (class_loader_context == ClassLoaderContext::kUnsupportedClassLoaderContextEncoding) {
89*795d594fSAndroid Build Coastguard Worker     return {};
90*795d594fSAndroid Build Coastguard Worker   }
91*795d594fSAndroid Build Coastguard Worker 
92*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(class_loader_context);
93*795d594fSAndroid Build Coastguard Worker   if (context == nullptr) {
94*795d594fSAndroid Build Coastguard Worker     return Errorf("Class loader context '{}' is invalid", class_loader_context);
95*795d594fSAndroid Build Coastguard Worker   }
96*795d594fSAndroid Build Coastguard Worker 
97*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> flattened_context = context->FlattenDexPaths();
98*795d594fSAndroid Build Coastguard Worker   std::string dex_dir = Dirname(dex_path);
99*795d594fSAndroid Build Coastguard Worker   for (const std::string& context_element : flattened_context) {
100*795d594fSAndroid Build Coastguard Worker     std::string context_path = std::filesystem::path(dex_dir).append(context_element);
101*795d594fSAndroid Build Coastguard Worker     OR_RETURN(ValidateDexPath(context_path));
102*795d594fSAndroid Build Coastguard Worker   }
103*795d594fSAndroid Build Coastguard Worker 
104*795d594fSAndroid Build Coastguard Worker   return {};
105*795d594fSAndroid Build Coastguard Worker }
106*795d594fSAndroid Build Coastguard Worker 
GetGarbageCollector()107*795d594fSAndroid Build Coastguard Worker std::string GetGarbageCollector() {
108*795d594fSAndroid Build Coastguard Worker   return Runtime::Current()->GetHeap()->GetForegroundCollectorName();
109*795d594fSAndroid Build Coastguard Worker }
110*795d594fSAndroid Build Coastguard Worker 
111*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT jstring JNICALL
Java_com_android_server_art_ArtJni_validateDexPathNative(JNIEnv * env,jobject,jstring j_dex_path)112*795d594fSAndroid Build Coastguard Worker Java_com_android_server_art_ArtJni_validateDexPathNative(JNIEnv* env, jobject, jstring j_dex_path) {
113*795d594fSAndroid Build Coastguard Worker   std::string dex_path(GET_UTF_OR_RETURN(env, j_dex_path));
114*795d594fSAndroid Build Coastguard Worker 
115*795d594fSAndroid Build Coastguard Worker   if (Result<void> result = ValidateDexPath(dex_path); !result.ok()) {
116*795d594fSAndroid Build Coastguard Worker     return CREATE_UTF_OR_RETURN(env, result.error().message()).release();
117*795d594fSAndroid Build Coastguard Worker   } else {
118*795d594fSAndroid Build Coastguard Worker     return nullptr;
119*795d594fSAndroid Build Coastguard Worker   }
120*795d594fSAndroid Build Coastguard Worker }
121*795d594fSAndroid Build Coastguard Worker 
122*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT jstring JNICALL
Java_com_android_server_art_ArtJni_validateClassLoaderContextNative(JNIEnv * env,jobject,jstring j_dex_path,jstring j_class_loader_context)123*795d594fSAndroid Build Coastguard Worker Java_com_android_server_art_ArtJni_validateClassLoaderContextNative(
124*795d594fSAndroid Build Coastguard Worker     JNIEnv* env, jobject, jstring j_dex_path, jstring j_class_loader_context) {
125*795d594fSAndroid Build Coastguard Worker   ScopedUtfChars dex_path = GET_UTF_OR_RETURN(env, j_dex_path);
126*795d594fSAndroid Build Coastguard Worker   std::string class_loader_context(GET_UTF_OR_RETURN(env, j_class_loader_context));
127*795d594fSAndroid Build Coastguard Worker 
128*795d594fSAndroid Build Coastguard Worker   if (Result<void> result = ValidateClassLoaderContext(dex_path, class_loader_context);
129*795d594fSAndroid Build Coastguard Worker       !result.ok()) {
130*795d594fSAndroid Build Coastguard Worker     return CREATE_UTF_OR_RETURN(env, result.error().message()).release();
131*795d594fSAndroid Build Coastguard Worker   } else {
132*795d594fSAndroid Build Coastguard Worker     return nullptr;
133*795d594fSAndroid Build Coastguard Worker   }
134*795d594fSAndroid Build Coastguard Worker }
135*795d594fSAndroid Build Coastguard Worker 
136*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT jstring JNICALL
Java_com_android_server_art_ArtJni_getGarbageCollectorNative(JNIEnv * env,jobject)137*795d594fSAndroid Build Coastguard Worker Java_com_android_server_art_ArtJni_getGarbageCollectorNative(JNIEnv* env, jobject) {
138*795d594fSAndroid Build Coastguard Worker   return CREATE_UTF_OR_RETURN(env, GetGarbageCollector()).release();
139*795d594fSAndroid Build Coastguard Worker }
140*795d594fSAndroid Build Coastguard Worker 
Java_com_android_server_art_ArtJni_setPropertyNative(JNIEnv * env,jobject,jstring j_key,jstring j_value)141*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT void JNICALL Java_com_android_server_art_ArtJni_setPropertyNative(
142*795d594fSAndroid Build Coastguard Worker     JNIEnv* env, jobject, jstring j_key, jstring j_value) {
143*795d594fSAndroid Build Coastguard Worker   std::string key(GET_UTF_OR_RETURN_VOID(env, j_key));
144*795d594fSAndroid Build Coastguard Worker   std::string value(GET_UTF_OR_RETURN_VOID(env, j_value));
145*795d594fSAndroid Build Coastguard Worker   if (!SetProperty(key, value)) {
146*795d594fSAndroid Build Coastguard Worker     jniThrowExceptionFmt(env,
147*795d594fSAndroid Build Coastguard Worker                          "java/lang/IllegalStateException",
148*795d594fSAndroid Build Coastguard Worker                          "Failed to set property '%s' to '%s'",
149*795d594fSAndroid Build Coastguard Worker                          key.c_str(),
150*795d594fSAndroid Build Coastguard Worker                          value.c_str());
151*795d594fSAndroid Build Coastguard Worker   }
152*795d594fSAndroid Build Coastguard Worker }
153*795d594fSAndroid Build Coastguard Worker 
Java_com_android_server_art_ArtJni_ensureNoProcessInDirNative(JNIEnv * env,jobject,jstring j_dir,jint j_timeout_ms)154*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT void JNICALL Java_com_android_server_art_ArtJni_ensureNoProcessInDirNative(
155*795d594fSAndroid Build Coastguard Worker     JNIEnv* env, jobject, jstring j_dir, jint j_timeout_ms) {
156*795d594fSAndroid Build Coastguard Worker   if (j_timeout_ms < 0) {
157*795d594fSAndroid Build Coastguard Worker     jniThrowExceptionFmt(
158*795d594fSAndroid Build Coastguard Worker         env, "java/lang/IllegalArgumentException", "Negative timeout '%d'", j_timeout_ms);
159*795d594fSAndroid Build Coastguard Worker     return;
160*795d594fSAndroid Build Coastguard Worker   }
161*795d594fSAndroid Build Coastguard Worker   std::string dir(GET_UTF_OR_RETURN_VOID(env, j_dir));
162*795d594fSAndroid Build Coastguard Worker   if (Result<void> result = tools::EnsureNoProcessInDir(dir, j_timeout_ms, /*try_kill=*/true);
163*795d594fSAndroid Build Coastguard Worker       !result.ok()) {
164*795d594fSAndroid Build Coastguard Worker     jniThrowException(env, "java/io/IOException", result.error().message().c_str());
165*795d594fSAndroid Build Coastguard Worker   }
166*795d594fSAndroid Build Coastguard Worker }
167*795d594fSAndroid Build Coastguard Worker 
168*795d594fSAndroid Build Coastguard Worker }  // namespace service
169*795d594fSAndroid Build Coastguard Worker }  // namespace art
170