1 /*
2 * Copyright (C) 2020 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 "src/profiling/common/producer_support.h"
18
19 #include "perfetto/ext/base/file_utils.h"
20 #include "perfetto/ext/base/string_splitter.h"
21 #include "perfetto/tracing/core/data_source_config.h"
22
23 #include "perfetto/tracing/core/forward_decls.h"
24 #include "src/traced/probes/packages_list/packages_list_parser.h"
25
26 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
27 #include <sys/system_properties.h>
28 #endif
29
30 namespace perfetto {
31 namespace profiling {
32
CanProfile(const DataSourceConfig & ds_config,uint64_t uid,const std::vector<std::string> & installed_by)33 bool CanProfile(const DataSourceConfig& ds_config,
34 uint64_t uid,
35 const std::vector<std::string>& installed_by) {
36 // We restrict by !PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) because a
37 // sideloaded heapprofd should not be restricted by this. Do note though that,
38 // at the moment, there isn't really a way to sideload a functioning heapprofd
39 // onto user builds.
40 #if !PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) || \
41 !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
42 base::ignore_result(ds_config);
43 base::ignore_result(uid);
44 base::ignore_result(installed_by);
45 return true;
46 #else
47 char buf[PROP_VALUE_MAX + 1] = {};
48 int ret = __system_property_get("ro.build.type", buf);
49 PERFETTO_CHECK(ret >= 0);
50 return CanProfileAndroid(ds_config, uid, installed_by, std::string(buf),
51 "/data/system/packages.list");
52 #endif
53 }
54
CanProfileAndroid(const DataSourceConfig & ds_config,uint64_t uid,const std::vector<std::string> & installed_by,const std::string & build_type,const std::string & packages_list_path)55 bool CanProfileAndroid(const DataSourceConfig& ds_config,
56 uint64_t uid,
57 const std::vector<std::string>& installed_by,
58 const std::string& build_type,
59 const std::string& packages_list_path) {
60 // These are replicated constants from libcutils android_filesystem_config.h
61 constexpr auto kAidAppStart = 10000; // AID_APP_START
62 constexpr auto kAidAppEnd = 19999; // AID_APP_END
63 constexpr auto kAidUserOffset = 100000; // AID_USER_OFFSET
64
65 if (build_type != "user") {
66 return true;
67 }
68
69 uint64_t uid_without_profile = uid % kAidUserOffset;
70 if (uid_without_profile < kAidAppStart || kAidAppEnd < uid_without_profile) {
71 // TODO(fmayer): relax this.
72 return false; // no native services on user.
73 }
74
75 std::string content;
76 if (!base::ReadFile(packages_list_path, &content)) {
77 PERFETTO_ELOG("Failed to read %s.", packages_list_path.c_str());
78 return false;
79 }
80 for (base::StringSplitter ss(std::move(content), '\n'); ss.Next();) {
81 Package pkg;
82 if (!ReadPackagesListLine(ss.cur_token(), &pkg)) {
83 PERFETTO_ELOG("Failed to parse packages.list.");
84 return false;
85 }
86 if (pkg.uid != uid_without_profile)
87 continue;
88 if (!installed_by.empty()) {
89 if (pkg.installed_by.empty()) {
90 PERFETTO_ELOG(
91 "installed_by given in TraceConfig, but cannot parse "
92 "installer from packages.list.");
93 return false;
94 }
95 if (std::find(installed_by.cbegin(), installed_by.cend(),
96 pkg.installed_by) == installed_by.cend()) {
97 return false;
98 }
99 }
100 switch (ds_config.session_initiator()) {
101 case DataSourceConfig::SESSION_INITIATOR_UNSPECIFIED:
102 return pkg.profileable_from_shell || pkg.debuggable;
103 case DataSourceConfig::SESSION_INITIATOR_TRUSTED_SYSTEM:
104 return pkg.profileable || pkg.debuggable;
105 }
106 }
107 // Did not find package.
108 return false;
109 }
110
111 } // namespace profiling
112 } // namespace perfetto
113