1/* 2 * Copyright (c) 2024 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 <unistd.h> 18#include <stdio.h> 19#include "syscall.h" 20#include "sys/capability.h" 21 22static unsigned int __linux_caps_maps[] = { 23 CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_FOWNER, 24 CAP_KILL, CAP_SETGID, CAP_SETUID, CAP_SETPCAP, CAP_NET_BIND_SERVICE, 25 CAP_NET_BROADCAST, CAP_NET_ADMIN, CAP_NET_RAW, CAP_SYS_PTRACE, CAP_SYS_ADMIN, 26 CAP_SYS_NICE, CAP_SYS_TIME, CAP_SYS_BOOT}; 27 28static unsigned int __ohos_caps_maps[] = { 29 OHOS_CAP_CHOWN, OHOS_CAP_DAC_EXECUTE, OHOS_CAP_DAC_WRITE, OHOS_CAP_DAC_READ_SEARCH, OHOS_CAP_FOWNER, OHOS_CAP_KILL, 30 OHOS_CAP_SETGID, OHOS_CAP_SETUID, OHOS_CAP_NET_BIND_SERVICE, OHOS_CAP_NET_BROADCAST, OHOS_CAP_NET_ADMIN, 31 OHOS_CAP_NET_RAW, OHOS_CAP_FS_MOUNT, OHOS_CAP_FS_FORMAT, OHOS_CAP_SCHED_SETPRIORITY, 32 OHOS_CAP_SET_TIMEOFDAY, OHOS_CAP_CLOCK_SETTIME, OHOS_CAP_CAPSET, OHOS_CAP_REBOOT, OHOS_CAP_SHELL_EXEC}; 33 34static unsigned int linux_caps_to_ohos(unsigned int caps) 35{ 36 int num = sizeof(__linux_caps_maps) / sizeof(int); 37 int loop; 38 unsigned int result = 0; 39 for (loop = 0; loop < num; loop++) { 40 if (!((1 << __linux_caps_maps[loop]) & caps)) { 41 continue; 42 } 43 44 switch (__linux_caps_maps[loop]) { 45 case CAP_CHOWN: 46 result |= 1 << OHOS_CAP_CHOWN; 47 break; 48 case CAP_DAC_OVERRIDE: 49 result |= 1 << OHOS_CAP_DAC_EXECUTE; 50 result |= 1 << OHOS_CAP_DAC_WRITE; 51 result |= 1 << OHOS_CAP_DAC_READ_SEARCH; 52 break; 53 case CAP_DAC_READ_SEARCH: 54 result |= 1 << OHOS_CAP_DAC_READ_SEARCH; 55 break; 56 case CAP_FOWNER: 57 result |= 1 << OHOS_CAP_FOWNER; 58 break; 59 case CAP_KILL: 60 result |= 1 << OHOS_CAP_KILL; 61 break; 62 case CAP_SETGID: 63 result |= 1 << OHOS_CAP_SETGID; 64 break; 65 case CAP_SETUID: 66 result |= 1 << OHOS_CAP_SETUID; 67 break; 68 case CAP_SETPCAP: 69 result |= 1 << OHOS_CAP_CAPSET; 70 break; 71 case CAP_NET_BIND_SERVICE: 72 result |= 1 << OHOS_CAP_NET_BIND_SERVICE; 73 break; 74 case CAP_NET_BROADCAST: 75 result |= 1 << OHOS_CAP_NET_BROADCAST; 76 break; 77 case CAP_NET_ADMIN: 78 result |= 1 << OHOS_CAP_NET_ADMIN; 79 break; 80 case CAP_NET_RAW: 81 result |= 1 << OHOS_CAP_NET_RAW; 82 break; 83 case CAP_SYS_PTRACE: 84 result |= 1 << OHOS_CAP_SHELL_EXEC; 85 break; 86 case CAP_SYS_ADMIN: 87 result |= 1 << OHOS_CAP_FS_MOUNT; 88 result |= 1 << OHOS_CAP_FS_FORMAT; 89 break; 90 case CAP_SYS_NICE: 91 result |= 1 << OHOS_CAP_SCHED_SETPRIORITY; 92 break; 93 case CAP_SYS_TIME: 94 result |= 1 << OHOS_CAP_SET_TIMEOFDAY; 95 result |= 1 << OHOS_CAP_CLOCK_SETTIME; 96 break; 97 case CAP_SYS_BOOT: 98 result |= 1 << OHOS_CAP_REBOOT; 99 break; 100 default: 101 break; 102 } 103 } 104 105 return result; 106} 107 108static unsigned int ohos_caps_to_linux(unsigned int caps) 109{ 110 int num = sizeof(__ohos_caps_maps) / sizeof(int); 111 int loop; 112 unsigned int result = 0; 113 for (loop = 0; loop < num; loop++) { 114 if (!((1 << __ohos_caps_maps[loop]) & caps)) { 115 continue; 116 } 117 118 switch (__ohos_caps_maps[loop]) { 119 case OHOS_CAP_CHOWN: 120 result |= 1 << CAP_CHOWN; 121 break; 122 case OHOS_CAP_DAC_EXECUTE: 123 case OHOS_CAP_DAC_WRITE: 124 result |= 1 << CAP_DAC_OVERRIDE; 125 break; 126 case OHOS_CAP_DAC_READ_SEARCH: 127 result |= 1 << CAP_DAC_READ_SEARCH; 128 break; 129 case OHOS_CAP_FOWNER: 130 result |= 1 << CAP_FOWNER; 131 break; 132 case OHOS_CAP_KILL: 133 result |= 1 << CAP_KILL; 134 break; 135 case OHOS_CAP_SETGID: 136 result |= 1 << CAP_SETGID; 137 break; 138 case OHOS_CAP_SETUID: 139 result |= 1 << CAP_SETUID; 140 break; 141 case OHOS_CAP_CAPSET: 142 result |= 1 << CAP_SETPCAP; 143 break; 144 case OHOS_CAP_NET_BIND_SERVICE: 145 result |= 1 << CAP_NET_BIND_SERVICE; 146 break; 147 case OHOS_CAP_NET_BROADCAST: 148 result |= 1 << CAP_NET_BROADCAST; 149 break; 150 case OHOS_CAP_NET_ADMIN: 151 result |= 1 << CAP_NET_ADMIN; 152 break; 153 case OHOS_CAP_NET_RAW: 154 result |= 1 << CAP_NET_RAW; 155 break; 156 case OHOS_CAP_SHELL_EXEC: 157 result |= 1 << CAP_SYS_PTRACE; 158 break; 159 case OHOS_CAP_FS_MOUNT: 160 case OHOS_CAP_FS_FORMAT: 161 result |= 1 << CAP_SYS_ADMIN; 162 break; 163 case OHOS_CAP_SCHED_SETPRIORITY: 164 result |= 1 << CAP_SYS_NICE; 165 break; 166 case OHOS_CAP_SET_TIMEOFDAY: 167 case OHOS_CAP_CLOCK_SETTIME: 168 result |= 1 << CAP_SYS_TIME; 169 break; 170 case OHOS_CAP_REBOOT: 171 result |= 1 << CAP_SYS_BOOT; 172 break; 173 default: 174 break; 175 } 176 } 177 178 return result; 179} 180 181int linux_capget(cap_user_header_t hdr_ptr, cap_user_data_t data_ptr) 182{ 183 unsigned int capvalue = 0; 184 185 if (hdr_ptr == NULL || data_ptr == NULL) { 186 errno = EINVAL; 187 return -1; 188 } 189 190 switch (hdr_ptr->version) { 191 case _LINUX_CAPABILITY_VERSION_1: 192 case _LINUX_CAPABILITY_VERSION_2: 193 case _LINUX_CAPABILITY_VERSION_3: 194 break; 195 default: 196 errno = EINVAL; 197 return -1; 198 } 199 200 if (syscall(SYS_ohoscapget, hdr_ptr->pid, &capvalue)) { 201 return -1; 202 } 203 204 data_ptr[0].effective = ohos_caps_to_linux(capvalue); 205 data_ptr[0].permitted = ohos_caps_to_linux(capvalue); 206 data_ptr[0].inheritable = ohos_caps_to_linux(capvalue); 207 return 0; 208} 209 210int linux_capset(cap_user_header_t hdr_ptr, const cap_user_data_t data_ptr) 211{ 212 unsigned int capvalue = 0; 213 214 if (hdr_ptr == NULL || data_ptr == NULL) { 215 errno = EINVAL; 216 return -1; 217 } 218 219 if (hdr_ptr->pid) { 220 errno = EPERM; 221 return -1; 222 } 223 224 switch (hdr_ptr->version) { 225 case _LINUX_CAPABILITY_VERSION_1: 226 case _LINUX_CAPABILITY_VERSION_2: 227 case _LINUX_CAPABILITY_VERSION_3: 228 break; 229 default: 230 errno = EINVAL; 231 return -1; 232 } 233 234 capvalue = linux_caps_to_ohos(data_ptr[0].effective); 235 return syscall(SYS_ohoscapset, capvalue); 236} 237 238weak_alias(linux_capget, capget); 239weak_alias(linux_capset, capset); 240 241int ohos_capget(pid_t pid, unsigned int *caps) 242{ 243 return syscall(SYS_ohoscapget, pid, caps); 244} 245 246int ohos_capset(unsigned int caps) 247{ 248 return syscall(SYS_ohoscapset, caps); 249} 250