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