已关闭
fix: capacity check fd size, memFlag check enum range #2748
fix: capacity check fd size, memFlag check enum range #2748
已关闭
linxinyu93创建于 8月24日关闭于 9月1日
共 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 at5 * 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+ 
117Status AVHardwareAllocator::MapMemoryAddr()158Status AVHardwareAllocator::MapMemoryAddr()
118{159{
119#ifdef MEDIA_OHOS160#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:
37private:37private:
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_001460 * @tc.name: AVBuffer_Create_Local_SharedMemory_001
339 * @tc.desc: create local shared memory with allocator and align_ = 2461 * @tc.desc: create local shared memory with allocator and align_ = 2