已关闭
fix: capacity check fd size, memFlag check enum range #2748
linxinyu93创建于 8月24日关闭于 9月1日
fix: capacity check fd size, memFlag check enum range #2748
已关闭
共 3 个文件变更+172-8
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | - * Copyright (C) 2023 Huawei Device Co., Ltd. | 2 | + * Copyright (C) 2026 Huawei Device Co., Ltd. |
| 3 | * Licensed under the Apache License, Version 2.0 (the "License"); | 3 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | * you may not use this file except in compliance with 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 | 5 | * You may obtain a copy of the License at |
| @@ -14,6 +14,8 @@ | |||
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | #include "av_hardware_memory.h" | 16 | #include "av_hardware_memory.h" |
| 17 | +#include <sys/stat.h> | ||
| 18 | +#include <sys/types.h> | ||
| 17 | #include <unistd.h> | 19 | #include <unistd.h> |
| 18 | #include <unordered_map> | 20 | #include <unordered_map> |
| 19 | #include "ashmem.h" | 21 | #include "ashmem.h" |
| @@ -114,6 +116,45 @@ bool AVHardwareAllocator::GetIsSecure() | |||
| 114 | return isSecure_; | 116 | return isSecure_; |
| 115 | } | 117 | } |
| 116 | 118 | ||
| 119 | +#ifdef MEDIA_OHOS | ||
| 120 | +int64_t AVHardwareAllocator::GetFdSize() | ||
| 121 | +{ | ||
| 122 | + struct stat st {}; | ||
| 123 | + if (fstat(fd_, &st) != 0) { | ||
| 124 | + MEDIA_LOG_E("fstat failed, fd:%{public}d", fd_); | ||
| 125 | + return -1; | ||
| 126 | + } | ||
| 127 | + int64_t fdSize = static_cast<int64_t>(st.st_size); | ||
| 128 | + if (fdSize > 0) { | ||
| 129 | + return fdSize; | ||
| 130 | + } | ||
| 131 | + off_t end = lseek(fd_, 0, SEEK_END); | ||
| 132 | + if (end <= 0) { | ||
| 133 | + MEDIA_LOG_E("fd size unqueryable, fd:%{public}d", fd_); | ||
| 134 | + return -1; | ||
| 135 | + } | ||
| 136 | + fdSize = static_cast<int64_t>(end); | ||
| 137 | + (void)lseek(fd_, 0, SEEK_SET); | ||
| 138 | + MEDIA_LOG_I("fstat st_size is 0, lseek fallback size:%{public}" PRId64 ", fd:%{public}d", fdSize, fd_); | ||
| 139 | + return fdSize; | ||
| 140 | +} | ||
| 141 | + | ||
| 142 | +unsigned int AVHardwareAllocator::GetProtFlag() | ||
| 143 | +{ | ||
| 144 | + switch (memFlag_) { | ||
| 145 | + case MemoryFlag::MEMORY_READ_ONLY: | ||
| 146 | + return PROT_READ; | ||
| 147 | + case MemoryFlag::MEMORY_WRITE_ONLY: | ||
| 148 | + return PROT_WRITE; | ||
| 149 | + case MemoryFlag::MEMORY_READ_WRITE: | ||
| 150 | + return PROT_READ | PROT_WRITE; | ||
| 151 | + default: | ||
| 152 | + MEDIA_LOG_W("memFlag is invalid, memFlag:%{public}d", static_cast<int>(memFlag_)); | ||
| 153 | + return PROT_READ | PROT_WRITE; | ||
| 154 | + } | ||
| 155 | +} | ||
| 156 | +#endif | ||
| 157 | + | ||
| 117 | Status AVHardwareAllocator::MapMemoryAddr() | 158 | Status AVHardwareAllocator::MapMemoryAddr() |
| 118 | { | 159 | { |
| 119 | #ifdef MEDIA_OHOS | 160 | #ifdef MEDIA_OHOS |
| @@ -128,15 +169,14 @@ Status AVHardwareAllocator::MapMemoryAddr() | |||
| 128 | } | 169 | } |
| 129 | return Status::ERROR_NO_MEMORY; | 170 | return Status::ERROR_NO_MEMORY; |
| 130 | }; | 171 | }; |
| 172 | + FALSE_RETURN_V_MSG_E(fd_ > 0, Status::ERROR_INVALID_OPERATION, "fd is invalid, fd:%{public}d", fd_); | ||
| 131 | FALSE_RETURN_V_MSG_E(capacity_ > 0, Status::ERROR_INVALID_DATA, "capacity is invalid, capacity:%{public}d", | 173 | FALSE_RETURN_V_MSG_E(capacity_ > 0, Status::ERROR_INVALID_DATA, "capacity is invalid, capacity:%{public}d", |
| 132 | capacity_); | 174 | capacity_); |
| 133 | - unsigned int prot = PROT_READ | PROT_WRITE; | 175 | + int64_t fdSize = GetFdSize(); |
| 134 | - FALSE_RETURN_V_MSG_E(fd_ > 0, Status::ERROR_INVALID_OPERATION, "fd is invalid, fd:%{public}d", fd_); | 176 | + FALSE_RETURN_V_MSG_E(fdSize > 0, Status::ERROR_INVALID_DATA, "get fd size failed, fd:%{public}d", fd_); |
| 135 | - if (memFlag_ == MemoryFlag::MEMORY_READ_ONLY) { | 177 | + FALSE_RETURN_V_MSG_E(capacity_ <= fdSize, Status::ERROR_INVALID_DATA, |
| 136 | - prot &= ~PROT_WRITE; | 178 | + "capacity not match fd, capacity:%{public}d, fdSize:%{public}" PRId64, capacity_, fdSize); |
| 137 | - } else if (memFlag_ == MemoryFlag::MEMORY_WRITE_ONLY) { | 179 | + unsigned int prot = GetProtFlag(); |
| 138 | - prot &= ~PROT_READ; | ||
| 139 | - } | ||
| 140 | void *addr = ::mmap(nullptr, static_cast<size_t>(capacity_), static_cast<int>(prot), MAP_SHARED, fd_, 0); | 180 | void *addr = ::mmap(nullptr, static_cast<size_t>(capacity_), static_cast<int>(prot), MAP_SHARED, fd_, 0); |
| 141 | FALSE_RETURN_V_MSG_E(addr != MAP_FAILED, Status::ERROR_INVALID_OPERATION, "mmap failed, please check params"); | 181 | FALSE_RETURN_V_MSG_E(addr != MAP_FAILED, Status::ERROR_INVALID_OPERATION, "mmap failed, please check params"); |
| 142 | allocBase_ = reinterpret_cast<uint8_t *>(addr); | 182 | allocBase_ = reinterpret_cast<uint8_t *>(addr); |
| @@ -37,6 +37,8 @@ public: | |||
| 37 | private: | 37 | private: |
| 38 | AVHardwareAllocator(); | 38 | AVHardwareAllocator(); |
| 39 | Status MapMemoryAddr(); | 39 | Status MapMemoryAddr(); |
| 40 | + int64_t GetFdSize(); | ||
| 41 | + unsigned int GetProtFlag(); | ||
| 40 | 42 | ||
| 41 | int32_t fd_; | 43 | int32_t fd_; |
| 42 | int32_t capacity_; | 44 | int32_t capacity_; |
| @@ -13,6 +13,9 @@ | |||
| 13 | * limitations under the License. | 13 | * limitations under the License. |
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | +#include <sys/mman.h> | ||
| 17 | +#include <sys/stat.h> | ||
| 18 | +#include <unistd.h> | ||
| 16 | #include "av_hardware_memory.h" | 19 | #include "av_hardware_memory.h" |
| 17 | #include "av_shared_allocator.h" | 20 | #include "av_shared_allocator.h" |
| 18 | #include "av_shared_memory_ext.h" | 21 | #include "av_shared_memory_ext.h" |
| @@ -334,6 +337,125 @@ HWTEST_F(AVBufferInnerUnitTest, AVBuffer_CreateWithInvalid_005, TestSize.Level1) | |||
| 334 | EXPECT_EQ(nullptr, buffer_); | 337 | EXPECT_EQ(nullptr, buffer_); |
| 335 | } | 338 | } |
| 336 | 339 | ||
| 340 | +/** | ||
| 341 | + * @tc.name: AVBuffer_CreateWithInvalid_006 | ||
| 342 | + * @tc.desc: create hardware memory with capacity exceeding fd size | ||
| 343 | + * @tc.type: FUNC | ||
| 344 | + */ | ||
| 345 | +HWTEST_F(AVBufferInnerUnitTest, AVBuffer_CreateWithInvalid_006, TestSize.Level1) | ||
| 346 | +{ | ||
| 347 | + memFlag_ = MemoryFlag::MEMORY_READ_WRITE; | ||
| 348 | + DmabufHeapBuffer dmaBuffer = {.size = capacity_, .heapFlags = 0}; | ||
| 349 | + int32_t dmaHeapFd = HardwareHeapFactory::GetInstance().GetHardwareHeapFd(); | ||
| 350 | + DmabufHeapBufferAlloc(dmaHeapFd, &dmaBuffer); | ||
| 351 | + dmaBufferLst_.push_back(dmaBuffer); | ||
| 352 | + | ||
| 353 | + allocator_ = AVAllocatorFactory::CreateHardwareAllocator(dmaBuffer.fd, capacity_ * 2, memFlag_); | ||
| 354 | + buffer_ = AVBuffer::CreateAVBuffer(allocator_); | ||
| 355 | + EXPECT_EQ(nullptr, buffer_); | ||
| 356 | +} | ||
| 357 | + | ||
| 358 | +/** | ||
| 359 | + * @tc.name: AVHardwareAllocator_GetFdSize_001 | ||
| 360 | + * @tc.desc: GetFdSize returns -1 when fstat fails (invalid fd) | ||
| 361 | + * @tc.type: FUNC | ||
| 362 | + */ | ||
| 363 | +HWTEST_F(AVBufferInnerUnitTest, AVHardwareAllocator_GetFdSize_001, TestSize.Level1) | ||
| 364 | +{ | ||
| 365 | + auto alloc = std::make_shared<AVHardwareAllocator>(); | ||
| 366 | + alloc->fd_ = -1; | ||
| 367 | + EXPECT_EQ(static_cast<int64_t>(-1), alloc->GetFdSize()); | ||
| 368 | +} | ||
| 369 | + | ||
| 370 | +/** | ||
| 371 | + * @tc.name: AVHardwareAllocator_GetFdSize_002 | ||
| 372 | + * @tc.desc: GetFdSize returns fd size via fstat (st_size>0) or lseek fallback (st_size==0) | ||
| 373 | + * @tc.type: FUNC | ||
| 374 | + */ | ||
| 375 | +HWTEST_F(AVBufferInnerUnitTest, AVHardwareAllocator_GetFdSize_002, TestSize.Level1) | ||
| 376 | +{ | ||
| 377 | + DmabufHeapBuffer dmaBuffer = {.size = capacity_, .heapFlags = 0}; | ||
| 378 | + int32_t dmaHeapFd = HardwareHeapFactory::GetInstance().GetHardwareHeapFd(); | ||
| 379 | + DmabufHeapBufferAlloc(dmaHeapFd, &dmaBuffer); | ||
| 380 | + dmaBufferLst_.push_back(dmaBuffer); | ||
| 381 | + | ||
| 382 | + struct stat st {}; | ||
| 383 | + ASSERT_EQ(0, fstat(dmaBuffer.fd, &st)); | ||
| 384 | + allocator_ = AVAllocatorFactory::CreateHardwareAllocator(dmaBuffer.fd, capacity_, memFlag_); | ||
| 385 | + ASSERT_NE(nullptr, allocator_); | ||
| 386 | + auto hwAlloc = std::static_pointer_cast<AVHardwareAllocator>(allocator_); | ||
| 387 | + if (st.st_size > 0) { | ||
| 388 | + EXPECT_EQ(static_cast<int64_t>(st.st_size), hwAlloc->GetFdSize()); | ||
| 389 | + } else { | ||
| 390 | + EXPECT_EQ(static_cast<int64_t>(capacity_), hwAlloc->GetFdSize()); | ||
| 391 | + } | ||
| 392 | +} | ||
| 393 | + | ||
| 394 | +/** | ||
| 395 | + * @tc.name: AVHardwareAllocator_GetFdSize_003 | ||
| 396 | + * @tc.desc: GetFdSize returns -1 when st_size==0 and lseek fails (pipe fd) | ||
| 397 | + * @tc.type: FUNC | ||
| 398 | + */ | ||
| 399 | +HWTEST_F(AVBufferInnerUnitTest, AVHardwareAllocator_GetFdSize_003, TestSize.Level1) | ||
| 400 | +{ | ||
| 401 | + int pipefd[2]; | ||
| 402 | + ASSERT_EQ(0, pipe(pipefd)); | ||
| 403 | + auto alloc = std::make_shared<AVHardwareAllocator>(); | ||
| 404 | + alloc->fd_ = pipefd[0]; | ||
| 405 | + alloc->isAllocated_ = true; | ||
| 406 | + EXPECT_EQ(static_cast<int64_t>(-1), alloc->GetFdSize()); | ||
| 407 | + close(pipefd[0]); | ||
| 408 | + close(pipefd[1]); | ||
| 409 | +} | ||
| 410 | + | ||
| 411 | +/** | ||
| 412 | + * @tc.name: AVHardwareAllocator_GetProtFlag_001 | ||
| 413 | + * @tc.desc: GetProtFlag returns PROT_READ for MEMORY_READ_ONLY | ||
| 414 | + * @tc.type: FUNC | ||
| 415 | + */ | ||
| 416 | +HWTEST_F(AVBufferInnerUnitTest, AVHardwareAllocator_GetProtFlag_001, TestSize.Level1) | ||
| 417 | +{ | ||
| 418 | + auto alloc = std::make_shared<AVHardwareAllocator>(); | ||
| 419 | + alloc->memFlag_ = MemoryFlag::MEMORY_READ_ONLY; | ||
| 420 | + EXPECT_EQ(static_cast<unsigned int>(PROT_READ), alloc->GetProtFlag()); | ||
| 421 | +} | ||
| 422 | + | ||
| 423 | +/** | ||
| 424 | + * @tc.name: AVHardwareAllocator_GetProtFlag_002 | ||
| 425 | + * @tc.desc: GetProtFlag returns PROT_WRITE for MEMORY_WRITE_ONLY | ||
| 426 | + * @tc.type: FUNC | ||
| 427 | + */ | ||
| 428 | +HWTEST_F(AVBufferInnerUnitTest, AVHardwareAllocator_GetProtFlag_002, TestSize.Level1) | ||
| 429 | +{ | ||
| 430 | + auto alloc = std::make_shared<AVHardwareAllocator>(); | ||
| 431 | + alloc->memFlag_ = MemoryFlag::MEMORY_WRITE_ONLY; | ||
| 432 | + EXPECT_EQ(static_cast<unsigned int>(PROT_WRITE), alloc->GetProtFlag()); | ||
| 433 | +} | ||
| 434 | + | ||
| 435 | +/** | ||
| 436 | + * @tc.name: AVHardwareAllocator_GetProtFlag_003 | ||
| 437 | + * @tc.desc: GetProtFlag returns PROT_READ|PROT_WRITE for MEMORY_READ_WRITE | ||
| 438 | + * @tc.type: FUNC | ||
| 439 | + */ | ||
| 440 | +HWTEST_F(AVBufferInnerUnitTest, AVHardwareAllocator_GetProtFlag_003, TestSize.Level1) | ||
| 441 | +{ | ||
| 442 | + auto alloc = std::make_shared<AVHardwareAllocator>(); | ||
| 443 | + alloc->memFlag_ = MemoryFlag::MEMORY_READ_WRITE; | ||
| 444 | + EXPECT_EQ(static_cast<unsigned int>(PROT_READ | PROT_WRITE), alloc->GetProtFlag()); | ||
| 445 | +} | ||
| 446 | + | ||
| 447 | +/** | ||
| 448 | + * @tc.name: AVHardwareAllocator_GetProtFlag_004 | ||
| 449 | + * @tc.desc: GetProtFlag falls back to PROT_READ|PROT_WRITE for invalid memFlag | ||
| 450 | + * @tc.type: FUNC | ||
| 451 | + */ | ||
| 452 | +HWTEST_F(AVBufferInnerUnitTest, AVHardwareAllocator_GetProtFlag_004, TestSize.Level1) | ||
| 453 | +{ | ||
| 454 | + auto alloc = std::make_shared<AVHardwareAllocator>(); | ||
| 455 | + alloc->memFlag_ = static_cast<MemoryFlag>(0xFF); | ||
| 456 | + EXPECT_EQ(static_cast<unsigned int>(PROT_READ | PROT_WRITE), alloc->GetProtFlag()); | ||
| 457 | +} | ||
| 458 | + | ||
| 337 | /** | 459 | /** |
| 338 | * @tc.name: AVBuffer_Create_Local_SharedMemory_001 | 460 | * @tc.name: AVBuffer_Create_Local_SharedMemory_001 |
| 339 | * @tc.desc: create local shared memory with allocator and align_ = 2 | 461 | * @tc.desc: create local shared memory with allocator and align_ = 2 |