1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * SPDX-License-Identifier: GPL-2.0
4 *
5 * Legacy blkg rwstat helpers enabled by CONFIG_BLK_CGROUP_RWSTAT.
6 * Do not use in new code.
7 *
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14
15 #include "accesstokenid_test.h"
16 #include <cstdio>
17 #include <cstdlib>
18 #include <fcntl.h>
19 #include <cerrno>
20 #include <unistd.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/mman.h>
24 #include <sys/wait.h>
25 #include <sys/ioctl.h>
26 #include <ctime>
27 #include <climits>
28 #include <pthread.h>
29 #include <sys/syscall.h>
30 #include <grp.h>
31
32 constexpr unsigned char ACCESS_TOKEN_ID_IOCTL_BASE = 'A';
33 constexpr unsigned int GET_TOKEN_ID = 1;
34 constexpr unsigned int SET_TOKEN_ID = 2;
35 constexpr unsigned int GET_FTOKEN_ID = 3;
36 constexpr unsigned int SET_FTOKEN_ID = 4;
37 constexpr unsigned int ACCESS_TOKENID_MAX_NR = 5;
38 #define ACCESS_TOKENID_GET_TOKENID \
39 _IOR(ACCESS_TOKEN_ID_IOCTL_BASE, GET_TOKEN_ID, unsigned long long)
40 #define ACCESS_TOKENID_SET_TOKENID \
41 _IOW(ACCESS_TOKEN_ID_IOCTL_BASE, SET_TOKEN_ID, unsigned long long)
42 #define ACCESS_TOKENID_GET_FTOKENID \
43 _IOR(ACCESS_TOKEN_ID_IOCTL_BASE, GET_FTOKEN_ID, unsigned long long)
44 #define ACCESS_TOKENID_SET_FTOKENID \
45 _IOW(ACCESS_TOKEN_ID_IOCTL_BASE, SET_FTOKEN_ID, unsigned long long)
46 #define ACCESS_TOKENID_ILLEGAL1 \
47 _IOW(ACCESS_TOKEN_ID_IOCTL_BASE, 0, unsigned long long)
48 #define ACCESS_TOKENID_ILLEGAL2 \
49 _IOW(ACCESS_TOKEN_ID_IOCTL_BASE, ACCESS_TOKENID_MAX_NR, unsigned long long)
50
51 constexpr unsigned long long INVAL_TOKEN = 0xffffffffffffffff;
52
53 #define CHILDREN_NUM 3
54 #define WAIT_FOR_SHELL_OP_TIME 1
55 #define FATHER_WAIT_TIME (WAIT_FOR_SHELL_OP_TIME * (CHILDREN_NUM + 1))
56
57 constexpr unsigned int ACCESS_TOKEN_GRPID = 3020;
58 constexpr unsigned int ACCESS_TOKEN_OTHER_UID = 1234;
59 constexpr unsigned int ACCESS_TOKEN_OTHER_GRPID = 1234;
60
61 const char dev_accesstokenid[] = "/dev/access_token_id";
62
63 struct tokeninfo {
64 pid_t pid;
65 pid_t tid;
66 unsigned long long tokenid;
67 unsigned long long ftokenid;
68 };
69
70 namespace {
GenRand64(void)71 static unsigned long long GenRand64(void)
72 {
73 struct timespec time = {0, 0};
74 unsigned long long randvalue = 0;
75 int fd;
76
77 fd = open("/dev/random", O_RDONLY);
78 if (fd > 0) {
79 read(fd, &randvalue, sizeof(unsigned long long));
80 }
81 close(fd);
82
83 sleep(1);
84 clock_gettime(CLOCK_REALTIME, &time);
85
86 return randvalue + time.tv_nsec;
87 }
88
GetTokenid(unsigned long long * token)89 static int GetTokenid(unsigned long long *token)
90 {
91 int fd = open(dev_accesstokenid, O_RDWR);
92 if (fd < 0) {
93 printf("open %s failed\r\n", dev_accesstokenid);
94 return -1;
95 }
96
97 int ret = ioctl(fd, ACCESS_TOKENID_GET_TOKENID, token);
98 if (ret) {
99 printf("ioctl ACCESS_TOKENID_GET_TOKENID failed\r\n");
100 close(fd);
101 return -1;
102 }
103
104 close(fd);
105 return 0;
106 }
107
SetTokenid(unsigned long long * token)108 static int SetTokenid(unsigned long long *token)
109 {
110 int fd = open(dev_accesstokenid, O_RDWR);
111 if (fd < 0) {
112 printf("open %s failed\r\n", dev_accesstokenid);
113 return -1;
114 }
115
116 int ret = ioctl(fd, ACCESS_TOKENID_SET_TOKENID, token);
117 if (ret) {
118 printf("ioctl ACCESS_TOKENID_SET_TOKENID failed\r\n");
119 close(fd);
120 return -1;
121 }
122
123 close(fd);
124 return 0;
125 }
126
GetfTokenid(unsigned long long * ftoken)127 static int GetfTokenid(unsigned long long *ftoken)
128 {
129 int fd = open(dev_accesstokenid, O_RDWR);
130 if (fd < 0) {
131 printf("open %s failed\r\n", dev_accesstokenid);
132 return -1;
133 }
134
135 int ret = ioctl(fd, ACCESS_TOKENID_GET_FTOKENID, ftoken);
136 if (ret) {
137 printf("ioctl ACCESS_TOKENID_GET_FTOKENID failed\r\n");
138 close(fd);
139 return -1;
140 }
141
142 close(fd);
143 return 0;
144 }
145
SetfTokenid(unsigned long long * ftoken)146 static int SetfTokenid(unsigned long long *ftoken)
147 {
148 int fd = open(dev_accesstokenid, O_RDWR);
149 if (fd < 0) {
150 printf("open %s failed\r\n", dev_accesstokenid);
151 return -1;
152 }
153
154 int ret = ioctl(fd, ACCESS_TOKENID_SET_FTOKENID, ftoken);
155 if (ret) {
156 printf("ioctl ACCESS_TOKENID_SET_FTOKENID failed\r\n");
157 close(fd);
158 return -1;
159 }
160
161 close(fd);
162 return 0;
163 }
164
GetCurToken(unsigned long long * token,unsigned long long * ftoken)165 static void GetCurToken(unsigned long long *token, unsigned long long *ftoken)
166 {
167 GetTokenid(token);
168 GetfTokenid(ftoken);
169
170 return;
171 }
172
CheckChildThreadInheritance(void * args)173 static void *CheckChildThreadInheritance(void *args)
174 {
175 struct tokeninfo *tinfo = (struct tokeninfo *) args;
176
177 tinfo->pid = getpid();
178 tinfo->tid = gettid();
179 GetTokenid(&(tinfo->tokenid));
180 GetfTokenid(&(tinfo->ftokenid));
181
182 pthread_exit(nullptr);
183 return nullptr;
184 }
185
CheckChildThreadSetIndepent(void * args)186 static void *CheckChildThreadSetIndepent(void *args)
187 {
188 struct tokeninfo *tinfo = (struct tokeninfo *) args;
189 unsigned long long tokenSet = GenRand64();
190 unsigned long long ftokenSet = GenRand64();
191 unsigned long long tokenidGet = INVAL_TOKEN;
192 unsigned long long ftokenidGet = INVAL_TOKEN;
193
194 tinfo->pid = getpid();
195 tinfo->tid = gettid();
196
197 GetTokenid(&tokenidGet);
198 GetfTokenid(&ftokenidGet);
199 SetTokenid(&tokenSet);
200 SetfTokenid(&ftokenSet);
201 GetTokenid(&(tinfo->tokenid));
202 GetfTokenid(&(tinfo->ftokenid));
203
204 /* Indicate that the tokenid setting of each child thread does not met requirements. */
205 if (ftokenidGet == 0 && tinfo->tokenid == tokenSet && tinfo->ftokenid == ftokenSet && tinfo->ftokenid != 0) {
206 tinfo->ftokenid = INVAL_TOKEN;
207 }
208
209 pthread_exit(nullptr);
210 return nullptr;
211 }
212 }
213
214 using namespace testing::ext;
215 using namespace std;
216
SetUp()217 void AccesstokenidTest::SetUp() {}
218
TearDown()219 void AccesstokenidTest::TearDown() {}
220
SetUpTestCase()221 void AccesstokenidTest::SetUpTestCase() {}
222
TearDownTestCase()223 void AccesstokenidTest::TearDownTestCase() {}
224
225 /**
226 * @tc.name: CheckInitToken
227 * @tc.desc: Test init value of tokenid and ftokenid
228 * @tc.desc: tokenid equals to the father(hdcd) and ftokenid equals to 0
229 * @tc.type: FUNC
230 */
231 HWTEST_F(AccesstokenidTest, CheckInitToken, Function | MediumTest | Level1)
232 {
233 unsigned long long token = INVAL_TOKEN;
234 unsigned long long ftoken = INVAL_TOKEN;
235
236 GetCurToken(&token, &ftoken);
237
238 /* /data/service/el0/access_token/nativetoken.json
239 {"processName":"hdcd","APL":3,"version":1,"tokenId":680034571,"tokenAttr":0,"dcaps":[]}
240 */
241 ASSERT_NE(0, token);
242 ASSERT_EQ(0, ftoken);
243 }
244
245 /**
246 * @tc.name: CheckSetTokenid
247 * @tc.desc: Test setting of tokenid
248 * @tc.desc: tokenid equals to the setting value
249 * @tc.type: FUNC
250 */
251 HWTEST_F(AccesstokenidTest, CheckSetTokenid, Function | MediumTest | Level1)
252 {
253 unsigned long long token = INVAL_TOKEN;
254 unsigned long long tokenSet = GenRand64();
255
256 SetTokenid(&tokenSet);
257 GetTokenid(&token);
258
259 ASSERT_EQ(tokenSet, token);
260 }
261
262 /**
263 * @tc.name: CheckSetfTokenid
264 * @tc.desc: Test setting of ftokenid
265 * @tc.desc: ftokenid equals to the setting value
266 * @tc.type: FUNC
267 */
268 HWTEST_F(AccesstokenidTest, CheckSetfTokenid, Function | MediumTest | Level1)
269 {
270 unsigned long long ftoken = INVAL_TOKEN;
271 unsigned long long ftokenSet = GenRand64();
272
273 SetfTokenid(&ftokenSet);
274 GetfTokenid(&ftoken);
275
276 ASSERT_EQ(ftokenSet, ftoken);
277 }
278
279 /**
280 * @tc.name: CheckChildThreadInheritance
281 * @tc.desc: Test each child thread tokenid equals to father process while ftokenid not equals
282 * @tc.desc: The ftokenid of each child thread equals to 0
283 * @tc.type: FUNC
284 */
285 HWTEST_F(AccesstokenidTest, CheckChildThreadInheritance, Function | MediumTest | Level1)
286 {
287 pthread_t cid[10];
288
289 unsigned long long token = INVAL_TOKEN;
290 unsigned long long ftoken = INVAL_TOKEN;
291 unsigned long long tokenSet = GenRand64();
292 unsigned long long ftokenSet = GenRand64();
293
294 struct tokeninfo tinfo;
295 tinfo.pid = getpid();
296 tinfo.tid = gettid();
297 tinfo.tokenid = INVAL_TOKEN;
298 tinfo.ftokenid = INVAL_TOKEN;
299
300 GetTokenid(&token);
301 GetfTokenid(&ftoken);
302
303 SetTokenid(&tokenSet);
304 SetfTokenid(&ftokenSet);
305
306 for (int i = 0; i < 10; i++) {
307 if (pthread_create(&cid[i], nullptr, CheckChildThreadInheritance, &tinfo) != 0) {
308 printf("thread %d (ID %ld) pthread_create error\n", i, cid[i]);
309 }
310
311 if (pthread_join(cid[i], nullptr) != 0) {
312 printf("thread %d (ID %ld) pthread_join error\n", i, cid[i]);
313 }
314
315 ASSERT_EQ(tinfo.tokenid, tokenSet);
316 ASSERT_NE(tinfo.ftokenid, ftokenSet);
317 ASSERT_EQ(0, tinfo.ftokenid);
318 }
319 }
320
321 /**
322 * @tc.name: CheckChildThreadSetIndepent
323 * @tc.desc: Test each child thread tokenid and ftokenid is independent
324 * @tc.desc: The tokenid and ftokenid of each child thread not equal to father process
325 * @tc.type: FUNC
326 */
327 HWTEST_F(AccesstokenidTest, CheckChildThreadSetIndepent, Function | MediumTest | Level1)
328 {
329 pthread_t cid[10];
330
331 unsigned long long token = INVAL_TOKEN;
332 unsigned long long ftoken = INVAL_TOKEN;
333 unsigned long long tokenSet = GenRand64();
334 unsigned long long ftokenSet = GenRand64();
335
336 struct tokeninfo tinfo;
337 tinfo.pid = getpid();
338 tinfo.tid = gettid();
339 tinfo.tokenid = INVAL_TOKEN;
340 tinfo.ftokenid = INVAL_TOKEN;
341
342 GetTokenid(&token);
343 GetfTokenid(&ftoken);
344
345 SetTokenid(&tokenSet);
346 SetfTokenid(&ftokenSet);
347
348 for (int i = 0; i < 10; i++) {
349 if (pthread_create(&cid[i], nullptr, CheckChildThreadSetIndepent, &tinfo) != 0) {
350 printf("thread %d (ID %ld) pthread_create error\n", i, cid[i]);
351 }
352
353 if (pthread_join(cid[i], nullptr) != 0) {
354 printf("thread %d (ID %ld) pthread_join error\n", i, cid[i]);
355 }
356
357 ASSERT_NE(tinfo.tokenid, tokenSet);
358 ASSERT_NE(tinfo.ftokenid, ftokenSet);
359 ASSERT_NE(0, tinfo.ftokenid);
360 }
361 }
362
363 /**
364 * @tc.name: AbnormalGetTokenid
365 * @tc.desc: Test abnormal ioctl cmd of ACCESS_TOKENID_GET_TOKENID
366 * @tc.desc: using nullptr instead of the address of tokenid to ioctl
367 * @tc.type: FUNC
368 */
369 HWTEST_F(AccesstokenidTest, AbnormalGetTokenid, Function | MediumTest | Level1)
370 {
371 int fd = open(dev_accesstokenid, O_RDWR);
372 if (fd < 0) {
373 printf("open %s failed\r\n", dev_accesstokenid);
374 return;
375 }
376
377 int ret = ioctl(fd, ACCESS_TOKENID_GET_TOKENID, nullptr);
378 close(fd);
379
380 ASSERT_NE(0, ret);
381 }
382
383 /**
384 * @tc.name: AbnormalSetTokenid
385 * @tc.desc: Test abnormal ioctl cmd of ACCESS_TOKENID_SET_TOKENID
386 * @tc.desc: using nullptr instead of the address of tokenid to ioctl
387 * @tc.type: FUNC
388 */
389 HWTEST_F(AccesstokenidTest, AbnormalSetTokenid, Function | MediumTest | Level1)
390 {
391 int fd = open(dev_accesstokenid, O_RDWR);
392 if (fd < 0) {
393 printf("open %s failed\r\n", dev_accesstokenid);
394 return;
395 }
396
397 int ret = ioctl(fd, ACCESS_TOKENID_SET_TOKENID, nullptr);
398 close(fd);
399
400 ASSERT_NE(0, ret);
401 }
402
403 /**
404 * @tc.name: AbnormalGetfTokenid
405 * @tc.desc: Test abnormal ioctl cmd of ACCESS_TOKENID_GET_FTOKENID
406 * @tc.desc: using nullptr instead of the address of ftokenid to ioctl
407 * @tc.type: FUNC
408 */
409 HWTEST_F(AccesstokenidTest, AbnormalGetfTokenid, Function | MediumTest | Level1)
410 {
411 int fd = open(dev_accesstokenid, O_RDWR);
412 if (fd < 0) {
413 printf("open %s failed\r\n", dev_accesstokenid);
414 return;
415 }
416
417 int ret = ioctl(fd, ACCESS_TOKENID_GET_FTOKENID, nullptr);
418 close(fd);
419
420 ASSERT_NE(0, ret);
421 }
422
423 /**
424 * @tc.name: AbnormalSetfTokenid
425 * @tc.desc: Test abnormal ioctl cmd of ACCESS_TOKENID_SET_FTOKENID
426 * @tc.desc: using nullptr instead of the address of ftokenid to ioctl
427 * @tc.type: FUNC
428 */
429 HWTEST_F(AccesstokenidTest, AbnormalSetfTokenid, Function | MediumTest | Level1)
430 {
431 int fd = open(dev_accesstokenid, O_RDWR);
432 if (fd < 0) {
433 printf("open %s failed\r\n", dev_accesstokenid);
434 return;
435 }
436
437 int ret = ioctl(fd, ACCESS_TOKENID_SET_FTOKENID, nullptr);
438 close(fd);
439
440 ASSERT_NE(0, ret);
441 }
442
443 /**
444 * @tc.name: AbnormalIoctlCmd
445 * @tc.desc: Test abnormal ioctl cmd of ACCESS_TOKENID_ILLEGAL1 and ACCESS_TOKENID_ILLEGAL1
446 * @tc.desc: using illegal cmd instead of accesstokenid to ioctl
447 * @tc.type: FUNC
448 */
449 HWTEST_F(AccesstokenidTest, AbnormalIoctlCmd, Function | MediumTest | Level1)
450 {
451 unsigned long long token;
452
453 int fd = open(dev_accesstokenid, O_RDWR);
454 if (fd < 0) {
455 printf("open %s failed\r\n", dev_accesstokenid);
456 return;
457 }
458
459 int ret1 = ioctl(fd, ACCESS_TOKENID_ILLEGAL1, &token);
460 int ret2 = ioctl(fd, ACCESS_TOKENID_ILLEGAL2, &token);
461 close(fd);
462
463 ASSERT_NE(0, ret1);
464 ASSERT_NE(0, ret2);
465 }
466
467 /**
468 * @tc.name: OtherUidSetTokenid
469 * @tc.desc: Test ACCESS_TOKEN_OTHER_UID can not set tokenid
470 * @tc.desc: tokenid can be only set by uid 3020
471 * @tc.type: FUNC
472 */
473 HWTEST_F(AccesstokenidTest, OtherUidSetTokenid, Function | MediumTest | Level1)
474 {
475 unsigned long long tokenSet = GenRand64();
476 int ret;
477
478 ret = setuid(ACCESS_TOKEN_OTHER_UID);
479 if (ret != 0) {
480 printf("setuid error %d \r\n", ret);
481 }
482
483 int fd = open(dev_accesstokenid, O_RDWR);
484 if (fd < 0) {
485 printf("open %s failed\r\n", dev_accesstokenid);
486 return;
487 }
488
489 ret = ioctl(fd, ACCESS_TOKENID_SET_TOKENID, &tokenSet);
490 close(fd);
491
492 ASSERT_NE(0, ret);
493 }
494
495 /**
496 * @tc.name: OtherUidGetTokenid
497 * @tc.desc: Test ACCESS_TOKEN_OTHER_UID can get tokenid
498 * @tc.desc: tokenid can get not only by uid 3020
499 * @tc.type: FUNC
500 */
501 HWTEST_F(AccesstokenidTest, OtherUidGetTokenid, Function | MediumTest | Level1)
502 {
503 unsigned long long token = INVAL_TOKEN;
504 int ret;
505
506 ret = setuid(ACCESS_TOKEN_OTHER_UID);
507 if (ret != 0) {
508 printf("setuid error %d \r\n", ret);
509 }
510
511 int fd = open(dev_accesstokenid, O_RDWR);
512 if (fd < 0) {
513 printf("open %s failed\r\n", dev_accesstokenid);
514 return;
515 }
516
517 ret = ioctl(fd, ACCESS_TOKENID_GET_TOKENID, &token);
518 close(fd);
519
520 ASSERT_EQ(0, ret);
521 }
522
523 /**
524 * @tc.name: WithoutGrpSetfTokenid
525 * @tc.desc: Test ACCESS_TOKEN_OTHER_GRPID can not set ftokenid
526 * @tc.desc: ftokenid can not set by groups without grpid 3020
527 * @tc.type: FUNC
528 */
529 HWTEST_F(AccesstokenidTest, WithoutGrpSetfTokenid, Function | MediumTest | Level1)
530 {
531 int ret;
532 size_t size = 1;
533 gid_t list[1] = {ACCESS_TOKEN_OTHER_GRPID};
534 unsigned long long ftokenSet = GenRand64();
535
536 ret = setgroups(size, list);
537 if (ret != 0) {
538 printf("setgroups error %d \r\n", ret);
539 }
540
541 int fd = open(dev_accesstokenid, O_RDWR);
542 if (fd < 0) {
543 printf("open %s failed\r\n", dev_accesstokenid);
544 return;
545 }
546
547 ret = ioctl(fd, ACCESS_TOKENID_SET_FTOKENID, &ftokenSet);
548 close(fd);
549
550 ASSERT_NE(0, ret);
551 }
552
553 /**
554 * @tc.name: WithoutGrpGetfTokenid
555 * @tc.desc: Test ACCESS_TOKEN_OTHER_GRPID can not get ftokenid
556 * @tc.desc: ftokenid can not get by groups without grpid 3020
557 * @tc.type: FUNC
558 */
559 HWTEST_F(AccesstokenidTest, WithoutGrpGetfTokenid, Function | MediumTest | Level1)
560 {
561 int ret;
562 size_t size = 1;
563 gid_t list[1] = {ACCESS_TOKEN_OTHER_GRPID};
564 unsigned long long ftoken = INVAL_TOKEN;
565
566 ret = setgroups(size, list);
567 if (ret != 0) {
568 printf("setgroups error %d \r\n", ret);
569 }
570
571 int fd = open(dev_accesstokenid, O_RDWR);
572 if (fd < 0) {
573 printf("open %s failed\r\n", dev_accesstokenid);
574 return;
575 }
576
577 ret = ioctl(fd, ACCESS_TOKENID_GET_FTOKENID, &ftoken);
578 close(fd);
579
580 ASSERT_NE(0, ret);
581 }
582
583 /**
584 * @tc.name: WithGrpSetfTokenid
585 * @tc.desc: Test ACCESS_TOKEN_OTHER_GRPID and ACCESS_TOKEN_GRPID can set ftokenid
586 * @tc.desc: ftokenid can set by groups with grpid 3020
587 * @tc.type: FUNC
588 */
589 HWTEST_F(AccesstokenidTest, WithGrpSetfTokenid, Function | MediumTest | Level1)
590 {
591 int ret;
592 size_t size = 2;
593 gid_t list[2] = {ACCESS_TOKEN_OTHER_GRPID, ACCESS_TOKEN_GRPID};
594 unsigned long long ftokenSet = GenRand64();
595
596 ret = setgroups(size, list);
597 if (ret != 0) {
598 printf("setgroups error %d \r\n", ret);
599 }
600
601 int fd = open(dev_accesstokenid, O_RDWR);
602 if (fd < 0) {
603 printf("open %s failed\r\n", dev_accesstokenid);
604 return;
605 }
606
607 ret = ioctl(fd, ACCESS_TOKENID_SET_FTOKENID, &ftokenSet);
608 close(fd);
609
610 ASSERT_EQ(0, ret);
611 }
612
613 /**
614 * @tc.name: WithGrpGetfTokenid
615 * @tc.desc: Test ACCESS_TOKEN_OTHER_GRPID and ACCESS_TOKEN_GRPID can set ftokenid
616 * @tc.desc: ftokenid can set by groups with grpid 3020
617 * @tc.type: FUNC
618 */
619 HWTEST_F(AccesstokenidTest, WithGrpGetfTokenid, Function | MediumTest | Level1)
620 {
621 int ret;
622 size_t size = 2;
623 gid_t list[2] = {ACCESS_TOKEN_OTHER_GRPID, ACCESS_TOKEN_GRPID};
624 unsigned long long ftoken = INVAL_TOKEN;
625
626 ret = setgroups(size, list);
627 if (ret != 0) {
628 printf("setgroups error %d \r\n", ret);
629 }
630
631 int fd = open(dev_accesstokenid, O_RDWR);
632 if (fd < 0) {
633 printf("open %s failed\r\n", dev_accesstokenid);
634 return;
635 }
636
637 ret = ioctl(fd, ACCESS_TOKENID_GET_FTOKENID, &ftoken);
638 close(fd);
639
640 ASSERT_EQ(0, ret);
641 }
642
643