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 "perm_setproc.h"
17
18 #include <cerrno>
19 #include <cstdint>
20 #include <fcntl.h>
21 #include <sys/ioctl.h>
22 #include <unistd.h>
23 namespace OHOS {
24 namespace Security {
25 namespace AccessToken {
26 const uint32_t UINT32_T_BITS = 32;
27 const uint32_t MAX_PERM_SIZE = 64;
28 struct IoctlAddPermData {
29 uint32_t token;
30 uint32_t perm[MAX_PERM_SIZE] = { 0 };
31 };
32
33 struct IoctlSetGetPermData {
34 uint32_t token;
35 uint32_t opCode;
36 bool isGranted;
37 };
38
39 #define ACCESS_TOKENID_ADD_PERMISSIONS \
40 _IOW(ACCESS_TOKEN_ID_IOCTL_BASE, ADD_PERMISSIONS, struct IoctlAddPermData)
41 #define ACCESS_TOKENID_REMOVE_PERMISSIONS \
42 _IOW(ACCESS_TOKEN_ID_IOCTL_BASE, REMOVE_PERMISSIONS, uint32_t)
43 #define ACCESS_TOKENID_GET_PERMISSION \
44 _IOW(ACCESS_TOKEN_ID_IOCTL_BASE, GET_PERMISSION, struct IoctlSetGetPermData)
45 #define ACCESS_TOKENID_SET_PERMISSION \
46 _IOW(ACCESS_TOKEN_ID_IOCTL_BASE, SET_PERMISSION, struct IoctlSetGetPermData)
47
AddPermissionToKernel(uint32_t tokenID,const std::vector<uint32_t> & opCodeList,const std::vector<bool> & statusList)48 int32_t AddPermissionToKernel(
49 uint32_t tokenID, const std::vector<uint32_t>& opCodeList, const std::vector<bool>& statusList)
50 {
51 if (opCodeList.size() != statusList.size()) {
52 return ACCESS_TOKEN_PARAM_INVALID;
53 }
54 size_t size = opCodeList.size();
55 if (size == 0) {
56 return RemovePermissionFromKernel(tokenID);
57 }
58 struct IoctlAddPermData data;
59 data.token = tokenID;
60
61 for (uint32_t i = 0; i < size; ++i) {
62 uint32_t opCode = opCodeList[i];
63 uint32_t idx = opCode / UINT32_T_BITS;
64 uint32_t bitIdx = opCode % UINT32_T_BITS;
65 if (statusList[i]) { // granted
66 data.perm[idx] |= static_cast<uint32_t>(0x01) << bitIdx;
67 } else {
68 data.perm[idx] &= ~(static_cast<uint32_t>(0x01) << bitIdx);
69 }
70 }
71
72 int32_t fd = open(TOKENID_DEVNODE, O_RDWR);
73 if (fd < 0) {
74 return ACCESS_TOKEN_OPEN_ERROR;
75 }
76 int32_t ret = ioctl(fd, ACCESS_TOKENID_ADD_PERMISSIONS, &data);
77 close(fd);
78 if (ret != ACCESS_TOKEN_OK) {
79 return errno;
80 }
81
82 return ACCESS_TOKEN_OK;
83 }
84
RemovePermissionFromKernel(uint32_t tokenID)85 int32_t RemovePermissionFromKernel(uint32_t tokenID)
86 {
87 int32_t fd = open(TOKENID_DEVNODE, O_RDWR);
88 if (fd < 0) {
89 return ACCESS_TOKEN_OPEN_ERROR;
90 }
91 int32_t ret = ioctl(fd, ACCESS_TOKENID_REMOVE_PERMISSIONS, &tokenID);
92 close(fd);
93 if (ret) {
94 return errno;
95 }
96
97 return ACCESS_TOKEN_OK;
98 }
99
SetPermissionToKernel(uint32_t tokenID,int32_t opCode,bool status)100 int32_t SetPermissionToKernel(uint32_t tokenID, int32_t opCode, bool status)
101 {
102 struct IoctlSetGetPermData data = {
103 .token = tokenID,
104 .opCode = opCode,
105 .isGranted = status,
106 };
107
108 int32_t fd = open(TOKENID_DEVNODE, O_RDWR);
109 if (fd < 0) {
110 return ACCESS_TOKEN_OPEN_ERROR;
111 }
112 int32_t ret = ioctl(fd, ACCESS_TOKENID_SET_PERMISSION, &data);
113 close(fd);
114 if (ret != ACCESS_TOKEN_OK) {
115 return errno;
116 }
117
118 return ACCESS_TOKEN_OK;
119 }
120
GetPermissionFromKernel(uint32_t tokenID,int32_t opCode,bool & isGranted)121 int32_t GetPermissionFromKernel(uint32_t tokenID, int32_t opCode, bool& isGranted)
122 {
123 struct IoctlSetGetPermData data = {
124 .token = tokenID,
125 .opCode = opCode,
126 .isGranted = false,
127 };
128 isGranted = false;
129
130 int32_t fd = open(TOKENID_DEVNODE, O_RDWR);
131 if (fd < 0) {
132 return ACCESS_TOKEN_OPEN_ERROR;
133 }
134 int32_t ret = ioctl(fd, ACCESS_TOKENID_GET_PERMISSION, &data);
135 close(fd);
136 if (ret < 0) {
137 return errno;
138 }
139 isGranted = (ret == 1);
140 return ACCESS_TOKEN_OK;
141 }
142 } // namespace AccessToken
143 } // namespace Security
144 } // namespace OHOS
145