• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "safe_reader.h"
17 
18 #include <algorithm>
19 #include <cerrno>
20 #include <cstdio>
21 #include <fcntl.h>
22 #include <unistd.h>
23 
24 #include <sys/syscall.h>
25 #include <sys/types.h>
26 
SafeReader()27 SafeReader::SafeReader()
28 {
29     if (syscall(SYS_pipe2, pfd_, O_CLOEXEC | O_NONBLOCK) != 0) {
30         pfd_[PIPE_READ] = -1;
31         pfd_[PIPE_WRITE] = -1;
32     }
33 }
34 
~SafeReader()35 SafeReader::~SafeReader()
36 {
37     if (pfd_[PIPE_READ] > 0) {
38         syscall(SYS_close, pfd_[PIPE_READ]);
39         pfd_[PIPE_READ] = -1;
40     }
41     if (pfd_[PIPE_WRITE] > 0) {
42         syscall(SYS_close, pfd_[PIPE_WRITE]);
43         pfd_[PIPE_WRITE] = -1;
44     }
45 }
46 
IsReadbaleAddr(uintptr_t addr)47 NO_SANITIZE bool SafeReader::IsReadbaleAddr(uintptr_t addr)
48 {
49     if (pfd_[PIPE_WRITE] < 0) {
50         return false;
51     }
52 
53     if (OHOS_TEMP_FAILURE_RETRY(syscall(SYS_write, pfd_[PIPE_WRITE], addr, sizeof(char))) == -1) {
54         return false;
55     }
56 
57     return true;
58 }
59 
CopyReadbaleBufSafe(uintptr_t destPtr,size_t destLen,uintptr_t srcPtr,size_t srcLen)60 NO_SANITIZE size_t SafeReader::CopyReadbaleBufSafe(uintptr_t destPtr, size_t destLen, uintptr_t srcPtr, size_t srcLen)
61 {
62     size_t copeSize = std::min(destLen, srcLen);
63     uintptr_t currentPtr = srcPtr;
64     uintptr_t srcEndPtr = srcPtr + copeSize;
65     size_t destIndex = 0;
66     while (currentPtr < srcEndPtr) {
67         uintptr_t pageEndPtr = GetCurrentPageEndAddr(currentPtr);
68         pageEndPtr = std::min(pageEndPtr, srcEndPtr);
69         if (!IsReadbaleAddr(currentPtr) || !IsReadbaleAddr(pageEndPtr - 1)) {
70             break;
71         }
72         while (currentPtr < pageEndPtr) {
73             reinterpret_cast<uint8_t*>(destPtr)[destIndex++] = *reinterpret_cast<uint8_t*>(currentPtr++);
74         }
75     }
76     return destIndex;
77 }
78 
GetCurrentPageEndAddr(uintptr_t addr)79 uintptr_t SafeReader::GetCurrentPageEndAddr(uintptr_t addr)
80 {
81     uintptr_t pageSize = static_cast<uintptr_t>(getpagesize());
82     return (addr + pageSize) & (~(pageSize - 1));
83 }
84