• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <cstdlib>
17 #include <cstdio>
18 #include <iostream>
19 #include <fstream>
20 #include <unistd.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <dirent.h>
24 #include <fcntl.h>
25 #include <securec.h>
26 #include <sys/prctl.h>
27 #include <sys/wait.h>
28 #include <sys/mman.h>
29 #include <pwd.h>
30 #include <string>
31 #ifdef SUPPORT_SELINUX_TRANSITTO
32 #include <policycoreutils.h>
33 #include <selinux/selinux.h>
34 #endif
35 
36 #include "bundle_mgr_interface.h"
37 #include "bundle_mgr_proxy.h"
38 #include "iservice_registry.h"
39 #include "system_ability_definition.h"
40 #include "system_ability_manager_proxy.h"
41 #include "hilog/log.h"
42 
43 using namespace std;
44 
45 constexpr OHOS::HiviewDFX::HiLogLabel TRANS_LOG_LABLE = { LOG_CORE, 0xD002D0C, "TRANSITTO" };
46 
GetApplicationInfo(const string & bundleName,int & uid)47 bool GetApplicationInfo(const string& bundleName, int& uid)
48 {
49     OHOS::sptr<OHOS::ISystemAbilityManager> systemAbilityManager =
50         OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
51     if (systemAbilityManager == nullptr) {
52         OHOS::HiviewDFX::HiLog::Error(TRANS_LOG_LABLE, "fail to get system abilityManger.");
53         return false;
54     }
55 
56     OHOS::sptr<OHOS::IRemoteObject> remoteObject =
57         systemAbilityManager->GetSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
58     if (remoteObject == nullptr) {
59         OHOS::HiviewDFX::HiLog::Error(TRANS_LOG_LABLE, "fail to get bundle service.");
60         return false;
61     }
62 
63     OHOS::sptr<OHOS::AppExecFwk::BundleMgrProxy> bundleMgrProxy =
64         OHOS::iface_cast<OHOS::AppExecFwk::BundleMgrProxy>(remoteObject);
65     if (bundleMgrProxy == nullptr) {
66         OHOS::HiviewDFX::HiLog::Error(TRANS_LOG_LABLE, "fail to get bundle proxy.");
67         return false;
68     }
69 
70     OHOS::HiviewDFX::HiLog::Info(TRANS_LOG_LABLE, "start to get ApplicationInfo");
71     // 0: GET_BASIC_APPLICATION_INFO
72     uid = bundleMgrProxy->GetUidByDebugBundleName(bundleName, OHOS::AppExecFwk::Constants::ANY_USERID);
73     if (uid < 0) {
74         OHOS::HiviewDFX::HiLog::Error(TRANS_LOG_LABLE, "fail to get application info, uid is %{public}d.", uid);
75         return false;
76     }
77     OHOS::HiviewDFX::HiLog::Info(TRANS_LOG_LABLE, "get ApplicationInfo success uid is %{private}d.", uid);
78     return true;
79 }
80 
ChangeUidGid(int uid,int gid)81 bool ChangeUidGid(int uid, int gid)
82 {
83     OHOS::HiviewDFX::HiLog::Info(TRANS_LOG_LABLE, "start change uid gid.");
84     if (setresgid(gid, gid, gid) < 0) {
85         OHOS::HiviewDFX::HiLog::Error(TRANS_LOG_LABLE, "fail set gid, errno is %{publci}d.", errno);
86         return false;
87     }
88 
89     if (setresuid(uid, uid, uid) < 0) {
90         OHOS::HiviewDFX::HiLog::Error(TRANS_LOG_LABLE, "fail set uid, errno is %{publci}d.", errno);
91         return false;
92     }
93     return true;
94 }
95 
InitEnv(int uid)96 void InitEnv(int uid)
97 {
98     OHOS::HiviewDFX::HiLog::Info(TRANS_LOG_LABLE, "start set env.");
99 
100     unsetenv("IFS");
101 
102     passwd* pw = getpwuid(uid);
103     if (pw != nullptr) {
104         setenv("LOGNAME", pw->pw_name, 1);
105         setenv("SHELL", pw->pw_shell, 1);
106         setenv("USER", pw->pw_name, 1);
107     } else {
108         OHOS::HiviewDFX::HiLog::Error(TRANS_LOG_LABLE, "fail to getpwuid, errno is %{public}d.", errno);
109     }
110     return;
111 }
112 
SetSelinux()113 bool SetSelinux()
114 {
115     OHOS::HiviewDFX::HiLog::Info(TRANS_LOG_LABLE, "start change selinux context.");
116     string seContext = "u:r:transitto_hap:s0";
117 #ifdef SUPPORT_SELINUX_TRANSITTO
118     if (setcon(seContext.c_str()) != 0) {
119         OHOS::HiviewDFX::HiLog::Error(TRANS_LOG_LABLE, "fail to set selinux context, errno is %{public}d.", errno);
120         return false;
121     }
122 #endif
123     OHOS::HiviewDFX::HiLog::Info(TRANS_LOG_LABLE, "change selinux context successfully.");
124     return true;
125 }
126 
Help()127 void Help()
128 {
129     cout << "\ntransitto is a debuggable tool. your command can transit to the domain of debuggable bundle.\n"
130             "usage:\n"
131             "transitto <debuggable bundleName> <command>\n" << endl;
132 }
133 
CheckValid(int argc,char ** argv)134 bool CheckValid(int argc, char** argv)
135 {
136     if (argc <= 1) {
137         cout << "argc is empty" << endl;
138         Help();
139         return false;
140     }
141 
142     string secCom = argv[1];
143     if (argc == 2 && (secCom == "-h" || secCom == "--help")) {
144         Help();
145         return false;
146     }
147 
148     int oldUid = getuid();
149     // 0, root, 2000 shell
150     if (oldUid != 0 && oldUid != 2000) {
151         cout << "only root or shell can run this object" << endl;
152         Help();
153         return false;
154     }
155     return true;
156 }
157 
main(int argc,char * argv[])158 int main(int argc, char* argv[])
159 {
160     if (!CheckValid(argc, argv)) {
161         return -1;
162     }
163 
164     string bundleName = argv[1];
165     int* bundleUidPtr = static_cast<int*>(mmap(nullptr, sizeof(int),
166         PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0));
167     if (bundleUidPtr == MAP_FAILED || bundleUidPtr == nullptr) {
168         OHOS::HiviewDFX::HiLog::Error(TRANS_LOG_LABLE, "mmap fail.");
169         return -1;
170     }
171     *bundleUidPtr = -1;
172 
173     int pid = fork(); // for security_bounded_transition single thread
174     if (pid == 0) {
175         int uid = -1;
176         GetApplicationInfo(bundleName, uid);
177         *bundleUidPtr = uid;
178         _exit(0);
179     } else {
180         wait(nullptr);
181     }
182 
183     int uid = *bundleUidPtr;
184     munmap(bundleUidPtr, sizeof(int));
185 
186     string commod = (argc > 2) ? argv[2] : ""; // 2 com
187     // normal_hap uid = 200000 * usrid + bundleid % 200000, userid is 100 or 0(shared)
188     if (uid <= 20000000 || !ChangeUidGid(uid, uid) || !SetSelinux()) {
189         OHOS::HiviewDFX::HiLog::Error(TRANS_LOG_LABLE, "uid is %{public}d.", uid);
190         return -1;
191     }
192 
193     InitEnv(uid);
194     if (argc > 2 && execvp(argv[2], argv + 2) < 0) { // 2: offset
195         OHOS::HiviewDFX::HiLog::Error(TRANS_LOG_LABLE,
196             "fail to execvp, com is %{public}s, errno %{public}d.", argv[2], errno); // 2: offset
197         return -1;
198     }
199 
200     execlp("/system/bin/sh", "sh", nullptr);
201     return 0;
202 }