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