1/* 2 * Copyright (c) 2021-2022 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 <errno.h> 17#include <sys/prctl.h> 18#include <sys/stat.h> 19#include <sys/types.h> 20#include <unistd.h> 21 22#ifdef __LINUX__ 23#include <linux/capability.h> 24#include <linux/securebits.h> 25#include <sys/resource.h> 26#include <sys/time.h> 27#else 28#include <sys/capability.h> 29#endif // __LINUX__ 30 31#include "ability_main.h" 32#include "appspawn_message.h" 33#include "appspawn_server.h" 34#include "appspawn_service.h" 35#include "securec.h" 36 37#define DEFAULT_UMASK 002 38#define CAP_NUM 2 39#define ENV_TITLE "LD_LIBRARY_PATH=" 40#define UPPER_BOUND_GID 999 41#define LOWER_BOUND_GID 100 42#define GRP_NUM 2 43#define DEVMGR_GRP 99 44 45static int SetAmbientCapability(int cap) 46{ 47#ifdef __LINUX__ 48 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0)) { 49 printf("[Init] prctl PR_CAP_AMBIENT failed\n"); 50 return -1; 51 } 52#endif 53 return 0; 54} 55 56static int SetCapability(unsigned int capsCnt, const unsigned int *caps) 57{ 58 struct __user_cap_header_struct capHeader; 59 capHeader.version = _LINUX_CAPABILITY_VERSION_3; 60 capHeader.pid = 0; 61 62 // common user, clear all caps 63 struct __user_cap_data_struct capData[CAP_NUM] = {0}; 64 for (unsigned int i = 0; i < capsCnt; ++i) { 65 capData[CAP_TO_INDEX(caps[i])].effective |= CAP_TO_MASK(caps[i]); 66 capData[CAP_TO_INDEX(caps[i])].permitted |= CAP_TO_MASK(caps[i]); 67 capData[CAP_TO_INDEX(caps[i])].inheritable |= CAP_TO_MASK(caps[i]); 68 } 69 70 if (capset(&capHeader, capData) != 0) { 71 APPSPAWN_LOGE("[appspawn] capset failed, err: %d.", errno); 72 return -1; 73 } 74 for (unsigned int i = 0; i < capsCnt; ++i) { 75 if (SetAmbientCapability(caps[i]) != 0) { 76 APPSPAWN_LOGE("[appspawn] SetAmbientCapability failed, err: %d.", errno); 77 return -1; 78 } 79 } 80 return 0; 81} 82 83static int SetProcessName(struct AppSpawnContent *content, AppSpawnClient *client, 84 char *longProcName, uint32_t longProcNameLen) 85{ 86 AppSpawnClientLite *appProperty = (AppSpawnClientLite *)client; 87 return prctl(PR_SET_NAME, appProperty->message.bundleName); 88} 89 90static int SetKeepCapabilities(struct AppSpawnContent *content, AppSpawnClient *client) 91{ 92 APPSPAWN_LOGE("SetKeepCapabilities"); 93#ifdef __LINUX__ 94 if (prctl(PR_SET_SECUREBITS, SECBIT_NO_SETUID_FIXUP | SECBIT_NO_SETUID_FIXUP_LOCKED)) { 95 printf("prctl failed\n"); 96 return -1; 97 } 98#endif 99 return 0; 100} 101 102static int SetUidGid(struct AppSpawnContent *content, AppSpawnClient *client) 103{ 104 AppSpawnClientLite *appProperty = (AppSpawnClientLite *)client; 105 APPSPAWN_LOGE("SetUidGid %d %d", appProperty->message.uID, appProperty->message.gID); 106 if (setgid(appProperty->message.gID) != 0) { 107 APPSPAWN_LOGE("[appspawn] setgid failed, gID %u, err: %d.", appProperty->message.gID, errno); 108 return -1; 109 } 110 111 if (setuid(appProperty->message.uID) != 0) { 112 APPSPAWN_LOGE("[appspawn] setuid failed, uID %u, err: %d.", appProperty->message.uID, errno); 113 return -1; 114 } 115 gid_t groups[GRP_NUM]; 116 // add device groups for system app 117 if (appProperty->message.gID >= LOWER_BOUND_GID && appProperty->message.gID <= UPPER_BOUND_GID) { 118 groups[0] = appProperty->message.gID; 119 groups[1] = DEVMGR_GRP; 120 if (setgroups(GRP_NUM, groups)) { 121 APPSPAWN_LOGE("[appspawn] setgroups failed, uID %u, err: %d.", appProperty->message.uID, errno); 122 return -1; 123 } 124 } 125 126 // umask call always succeeds and return the previous mask value which is not needed here 127 (void)umask(DEFAULT_UMASK); 128 return 0; 129} 130 131static int SetCapabilities(struct AppSpawnContent *content, AppSpawnClient *client) 132{ 133 AppSpawnClientLite *appProperty = (AppSpawnClientLite *)client; 134 APPSPAWN_LOGE("SetCapabilities appProperty->message.capsCnt %d", appProperty->message.capsCnt); 135 // set rlimit 136#ifdef __LINUX__ 137 static const rlim_t DEFAULT_RLIMIT = 40; 138 struct rlimit rlim = {0}; 139 rlim.rlim_cur = DEFAULT_RLIMIT; 140 rlim.rlim_max = DEFAULT_RLIMIT; 141 if (setrlimit(RLIMIT_NICE, &rlim) != 0) { 142 APPSPAWN_LOGE("[appspawn] setrlimit failed, err: %d.", errno); 143 return -1; 144 } 145 146#ifndef APPSPAWN_TEST 147 unsigned int tmpCaps[] = {17}; // 17 means CAP_SYS_RAWIO 148 unsigned int tmpsCapCnt = sizeof(tmpCaps) / sizeof(tmpCaps[0]); 149 if (SetCapability(tmpsCapCnt, tmpCaps) != 0) { 150 APPSPAWN_LOGE("[appspawn] setrlimit failed, err: %d.", errno); 151 return -1; 152 } 153#endif 154#else 155 if (SetCapability(appProperty->message.capsCnt, appProperty->message.caps) != 0) { 156 APPSPAWN_LOGE("[appspawn] SetCapability failed, err: %d.", errno); 157 return -1; 158 } 159#endif // __LINUX__ 160 APPSPAWN_LOGE("SetCapabilities appProperty->message.capsCnt %d", appProperty->message.capsCnt); 161 return 0; 162} 163 164static void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client) 165{ 166 APPSPAWN_LOGI("AbilityMain"); 167 AppSpawnClientLite *appProperty = (AppSpawnClientLite *)client; 168 APPSPAWN_LOGI("[appspawn] invoke, msg<%s,%s,%d,%d>", 169 appProperty->message.bundleName, appProperty->message.identityID, appProperty->message.uID, 170 appProperty->message.gID); 171 172#ifndef APPSPAWN_TEST 173 if (AbilityMain(appProperty->message.identityID) != 0) { 174 APPSPAWN_LOGE("[appspawn] AbilityMain execute failed, pid %d.", getpid()); 175 exit(0x7f); // 0x7f: user specified 176 } 177#endif 178} 179 180void SetContentFunction(AppSpawnContent *content) 181{ 182 APPSPAWN_LOGI("SetContentFunction"); 183 content->runChildProcessor = RunChildProcessor; 184} 185 186int AppSpawnExecuteSpawningHook(AppSpawnContent *content, AppSpawnClient *client) 187{ 188 (void)umask(DEFAULT_UMASK); 189 int ret = SetKeepCapabilities(content, client); 190 if (ret != 0) { 191 return ret; 192 } 193 ret = SetProcessName(content, client, content->longProcName, content->longProcNameLen); 194 if (ret != 0) { 195 return ret; 196 } 197 ret = SetUidGid(content, client); 198 if (ret != 0) { 199 return ret; 200 } 201 ret = SetCapabilities(content, client); 202 if (ret != 0) { 203 return ret; 204 } 205 return 0; 206} 207 208int AppSpawnExecuteClearEnvHook(AppSpawnContent *content, AppSpawnClient *client) 209{ 210 return 0; 211} 212 213int AppSpawnExecutePreReplyHook(AppSpawnContent *content, AppSpawnClient *client) 214{ 215 return 0; 216} 217 218int AppSpawnExecutePostReplyHook(AppSpawnContent *content, AppSpawnClient *client) 219{ 220 return 0; 221} 222 223void AppSpawnEnvClear(AppSpawnContent *content, AppSpawnClient *client) 224{ 225} 226