1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * SPDX-License-Identifier: GPL-2.0
4 *
5 * Unless required by applicable law or agreed to in writing, software
6 * distributed under the License is distributed on an "AS IS" BASIS,
7 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8 * See the License for the specific language governing permissions and
9 * limitations under the License.
10 */
11
12#include <fcntl.h>
13#include <pthread.h>
14#include <cstdint>
15#include <sys/ioctl.h>
16#include <unistd.h>
17#include <bits/syscall.h>
18#include <cstdio>
19#include "accesstokenidcommon.h"
20
21namespace OHOS {
22namespace Kernel {
23namespace AccessToken {
24const char *g_devaccesstokenid = "/dev/access_token_id";
25
26int GetTokenid(unsigned long long *token)
27{
28    int fd = open(g_devaccesstokenid, O_RDWR);
29    if (fd < 0) {
30        return -1;
31    }
32    int ret = ioctl(fd, ACCESS_TOKENID_GET_TOKENID, token);
33    if (ret != 0) {
34        close(fd);
35        return -1;
36    }
37    close(fd);
38    return 0;
39}
40
41int SetTokenid(unsigned long long *token)
42{
43    int fd = open(g_devaccesstokenid, O_RDWR);
44    if (fd < 0) {
45        return -1;
46    }
47    int ret = ioctl(fd, ACCESS_TOKENID_SET_TOKENID, token);
48    if (ret != 0) {
49        close(fd);
50        return -1;
51    }
52    close(fd);
53    return 0;
54}
55
56void SetUidAndGrp()
57{
58    int ret = 0;
59    size_t groupListSize = LIST_NUM_2;
60    gid_t groupList[LIST_NUM_2] = {ACCESS_TOKEN_GRPID, TEST_VALUE};
61
62    ret = setgroups(groupListSize, groupList);
63    if (ret != 0) {
64        return;
65    }
66
67    ret = setuid(ACCESS_TOKEN_UID);
68    if (ret != 0) {
69        printf("SetUidAndGrp setuid error %d \n", ret);
70    }
71
72    return;
73}
74
75void SetUidAndGrpOther()
76{
77    int ret = 0;
78    size_t groupListSize = LIST_NUM_1;
79    gid_t groupList[LIST_NUM_1] = {ACCESS_TOKEN_OTHER_GRPID};
80
81    ret = setgroups(groupListSize, groupList);
82    if (ret != 0) {
83        return;
84    }
85
86    ret = setuid(ACCESS_TOKEN_OTHER_UID);
87    if (ret != 0) {
88        printf("SetUidAndGrp setuid error %d \n", ret);
89    }
90
91    return;
92}
93
94void SetRandTokenAndCheck(const unsigned long long *dataToken)
95{
96    pid_t pid = getpid();
97    pid_t tid = syscall(__NR_gettid);
98    unsigned long long token = INVAL_TOKEN;
99    unsigned long long tokenSet = *dataToken;
100
101    SetTokenid(&tokenSet);
102    GetTokenid(&token);
103
104    if (token != tokenSet) {
105        printf("pid:%d tid:%d token test failed, token:%llu tokenSet:%llu\n",
106               pid, tid, token, tokenSet);
107    } else {
108        printf("pid:%d tid:%d token test succeed, token:%llu tokenSet:%llu\n",
109               pid, tid, token, tokenSet);
110    }
111
112    sleep(WAIT_FOR_SHELL_OP_TIME);
113
114    GetTokenid(&token);
115    if (token != tokenSet) {
116        printf("pid:%d tid:%d token test failed, token:%llu tokenSet:%llu\n",
117               pid, tid, token, tokenSet);
118    } else {
119        printf("pid:%d tid:%d token test succeed, token:%llu tokenSet:%llu\n",
120               pid, tid, token, tokenSet);
121    }
122    return;
123}
124
125void *TokenTest(void *dataToken)
126{
127    SetRandTokenAndCheck(static_cast<unsigned long long *>(dataToken));
128    return nullptr;
129}
130
131void ThreadTest(void *dataToken)
132{
133    pthread_t tid1;
134    pthread_t tid2;
135    pthread_t tid3;
136    int ret = 0;
137
138    ret = pthread_create(&tid1, nullptr, TokenTest, dataToken);
139    if (ret != 0) {
140        return;
141    }
142
143    ret = pthread_create(&tid2, nullptr, TokenTest, dataToken);
144    if (ret != 0) {
145        return;
146    }
147
148    ret = pthread_create(&tid3, nullptr, TokenTest, dataToken);
149    if (ret != 0) {
150        return;
151    }
152
153    pthread_join(tid1, nullptr);
154    pthread_join(tid2, nullptr);
155    pthread_join(tid3, nullptr);
156
157    return;
158}
159
160int AccessTokenidThreadTest(uint8_t *dataToken)
161{
162    TokenTest(static_cast<void *>(dataToken));
163    ThreadTest(static_cast<void *>(dataToken));
164    return 0;
165}
166
167int AccessTokenidGrpTest(uint8_t *dataToken)
168{
169    SetUidAndGrp();
170    TokenTest(static_cast<void *>(dataToken));
171    ThreadTest(static_cast<void *>(dataToken));
172    return 0;
173}
174
175int AccessTokenidGrpTestOther(uint8_t *dataToken)
176{
177    SetUidAndGrpOther();
178    TokenTest(static_cast<void *>(dataToken));
179    ThreadTest(static_cast<void *>(dataToken));
180    return 0;
181}
182
183int GetfTokenid(unsigned long long *ftoken)
184{
185    int fd = open(g_devaccesstokenid, O_RDWR);
186    if (fd < 0) {
187        return -1;
188    }
189
190    int ret = ioctl(fd, ACCESS_TOKENID_GET_FTOKENID, ftoken);
191    if (ret != 0) {
192        close(fd);
193        return -1;
194    }
195
196    close(fd);
197    return 0;
198}
199
200int SetfTokenid(unsigned long long *ftoken)
201{
202    int fd = open(g_devaccesstokenid, O_RDWR);
203    if (fd < 0) {
204        return -1;
205    }
206
207    int ret = ioctl(fd, ACCESS_TOKENID_SET_FTOKENID, ftoken);
208    if (ret != 0) {
209        close(fd);
210        return -1;
211    }
212
213    close(fd);
214    return 0;
215}
216
217void SetRandfTokenAndCheck(const unsigned long long *dataFtoken)
218{
219    pid_t pid = getpid();
220    pid_t tid = syscall(__NR_gettid);
221    unsigned long long ftoken = INVAL_TOKEN;
222    unsigned long long ftokenSet = *dataFtoken;
223
224    SetfTokenid(&ftokenSet);
225    GetfTokenid(&ftoken);
226
227    if (ftoken != ftokenSet) {
228        printf("pid:%d tid:%d ftoken test failed, ftoken:%llu ftokenSet:%llu\n",
229               pid, tid, ftoken, ftokenSet);
230    } else {
231        printf("pid:%d tid:%d ftoken test succeed, ftoken:%llu ftokenSet:%llu\n",
232               pid, tid, ftoken, ftokenSet);
233    }
234
235    sleep(WAIT_FOR_SHELL_OP_TIME);
236
237    GetfTokenid(&ftoken);
238    if (ftoken != ftokenSet) {
239        printf("pid:%d tid:%d ftoken test failed, ftoken:%llu ftokenSet:%llu\n",
240               pid, tid, ftoken, ftokenSet);
241    } else {
242        printf("pid:%d tid:%d ftoken test succeed, ftoken:%llu ftokenSet:%llu\n",
243               pid, tid, ftoken, ftokenSet);
244    }
245    return;
246}
247
248void *FTokenTest(void *dataFtoken)
249{
250    SetRandfTokenAndCheck(static_cast<unsigned long long *>(dataFtoken));
251    return nullptr;
252}
253
254int AccessfTokenidThreadTest(uint8_t *dataFtoken)
255{
256    FTokenTest(static_cast<void *>(dataFtoken));
257    ThreadTest(static_cast<void *>(dataFtoken));
258    return 0;
259}
260
261int AccessfTokenidGrpTest(uint8_t *dataFtoken)
262{
263    SetUidAndGrp();
264    FTokenTest(static_cast<void *>(dataFtoken));
265    ThreadTest(static_cast<void *>(dataFtoken));
266    return 0;
267}
268
269int AccessfTokenidGrpTestOther(uint8_t *dataFtoken)
270{
271    SetUidAndGrpOther();
272    FTokenTest(static_cast<void *>(dataFtoken));
273    ThreadTest(static_cast<void *>(dataFtoken));
274    return 0;
275}
276
277bool SetfTokenidCmdFuzzTest(const uint8_t *data, size_t size)
278{
279    bool ret = false;
280    if ((data == nullptr) || (size < sizeof(unsigned long long))) {
281        return ret;
282    } else {
283        unsigned long long tokenId = *(reinterpret_cast<const unsigned long long *>(data));
284        ret = SetfTokenid(&tokenId);
285    }
286    return ret;
287}
288
289bool GetfTokenidCmdFuzzTest(const uint8_t *data, size_t size)
290{
291    bool ret = false;
292    if ((data == nullptr) || (size < sizeof(unsigned long long))) {
293        return ret;
294    } else {
295        unsigned long long tokenId = *(reinterpret_cast<const unsigned long long *>(data));
296        ret = GetfTokenid(&tokenId);
297    }
298    return ret;
299}
300
301bool GetTokenidCmdFuzzTest(const uint8_t *data, size_t size)
302{
303    bool ret = false;
304    if ((data == nullptr) || (size < sizeof(unsigned long long))) {
305        return ret;
306    } else {
307        unsigned long long tokenId = *(reinterpret_cast<const unsigned long long *>(data));
308        ret = GetTokenid(&tokenId);
309    }
310    return ret;
311}
312
313bool SetTokenidCmdFuzzTest(const uint8_t *data, size_t size)
314{
315    bool ret = false;
316    if ((data == nullptr) || (size < sizeof(unsigned long long))) {
317        return ret;
318    } else {
319        unsigned long long tokenId = *(reinterpret_cast<const unsigned long long *>(data));
320        ret = SetTokenid(&tokenId);
321    }
322    return ret;
323}
324} // namespace AccessToken
325} // namespace Kernel
326} // namespace OHOS
327