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 RemovePermissionFromKernel(tokenID);
57 return ACCESS_TOKEN_OK;
58 }
59 struct IoctlAddPermData data;
60 data.token = tokenID;
61
62 for (uint32_t i = 0; i < size; ++i) {
63 uint32_t opCode = opCodeList[i];
64 uint32_t idx = opCode / UINT32_T_BITS;
65 uint32_t bitIdx = opCode % UINT32_T_BITS;
66 if (statusList[i]) { // granted
67 data.perm[idx] |= static_cast<uint32_t>(0x01) << bitIdx;
68 } else {
69 data.perm[idx] &= ~(static_cast<uint32_t>(0x01) << bitIdx);
70 }
71 }
72
73 int32_t fd = open(TOKENID_DEVNODE, O_RDWR);
74 if (fd < 0) {
75 return ACCESS_TOKEN_OPEN_ERROR;
76 }
77 int32_t ret = ioctl(fd, ACCESS_TOKENID_ADD_PERMISSIONS, &data);
78 close(fd);
79 if (ret != ACCESS_TOKEN_OK) {
80 return errno;
81 }
82
83 return ACCESS_TOKEN_OK;
84 }
85
RemovePermissionFromKernel(uint32_t tokenID)86 int32_t RemovePermissionFromKernel(uint32_t tokenID)
87 {
88 int32_t fd = open(TOKENID_DEVNODE, O_RDWR);
89 if (fd < 0) {
90 return ACCESS_TOKEN_OPEN_ERROR;
91 }
92 int32_t ret = ioctl(fd, ACCESS_TOKENID_REMOVE_PERMISSIONS, &tokenID);
93 close(fd);
94 if (ret) {
95 return errno;
96 }
97
98 return ACCESS_TOKEN_OK;
99 }
100
SetPermissionToKernel(uint32_t tokenID,int32_t opCode,bool status)101 int32_t SetPermissionToKernel(uint32_t tokenID, int32_t opCode, bool status)
102 {
103 struct IoctlSetGetPermData data = {
104 .token = tokenID,
105 .opCode = opCode,
106 .isGranted = status,
107 };
108
109 int32_t fd = open(TOKENID_DEVNODE, O_RDWR);
110 if (fd < 0) {
111 return ACCESS_TOKEN_OPEN_ERROR;
112 }
113 int32_t ret = ioctl(fd, ACCESS_TOKENID_SET_PERMISSION, &data);
114 close(fd);
115 if (ret != ACCESS_TOKEN_OK) {
116 return errno;
117 }
118
119 return ACCESS_TOKEN_OK;
120 }
121
GetPermissionFromKernel(uint32_t tokenID,int32_t opCode,bool & isGranted)122 int32_t GetPermissionFromKernel(uint32_t tokenID, int32_t opCode, bool& isGranted)
123 {
124 struct IoctlSetGetPermData data = {
125 .token = tokenID,
126 .opCode = opCode,
127 .isGranted = false,
128 };
129 isGranted = false;
130
131 int32_t fd = open(TOKENID_DEVNODE, O_RDWR);
132 if (fd < 0) {
133 return ACCESS_TOKEN_OPEN_ERROR;
134 }
135 int32_t ret = ioctl(fd, ACCESS_TOKENID_GET_PERMISSION, &data);
136 close(fd);
137 if (ret < 0) {
138 return errno;
139 }
140 isGranted = (ret == 1);
141 return ACCESS_TOKEN_OK;
142 }
143 } // namespace AccessToken
144 } // namespace Security
145 } // namespace OHOS
146