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