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