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