• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #ifndef CODE_SIGN_JIT_BUFFER_INTEGRITY_H
17 #define CODE_SIGN_JIT_BUFFER_INTEGRITY_H
18 
19 #include <cstdint>
20 #include <cstring>
21 
22 #include "errcode.h"
23 #include "jit_code_signer.h"
24 #include "jit_fort_helper.h"
25 #include "securec.h"
26 
27 namespace OHOS {
28 namespace Security {
29 namespace CodeSign {
30 
31 #define CAST_TO_CONST_BYTES(buffer) (reinterpret_cast<const Byte *const>(buffer))
32 #define CAST_TO_BYTES(buffer) (reinterpret_cast<Byte *>(buffer))
33 
34 #define CHECK_NULL_AND_RETURN_CODE(ptr) do { \
35     if ((ptr) == nullptr) { \
36         return JitCodeSignErrCode::CS_ERR_NO_SIGNER; \
37     } \
38 } while (0)
39 
40 /**
41  * @brief Create Jit Code signer of specific level
42  * @return error code, see errcode.h
43  */
CreateJitCodeSigner()44 static inline JitCodeSigner *CreateJitCodeSigner()
45 {
46     return new JitCodeSigner();
47 }
48 
49 /**
50  * @brief Return whether Jit code signing is supported
51  * @return true if supported, otherwise false
52  */
IsSupportJitCodeSigner()53 static bool IsSupportJitCodeSigner()
54 {
55     return IsSupportPACFeature();
56 }
57 
58 /**
59  * @brief Register start address of tmp buffer if patching target address of buffer
60  * @param signer jit code signer
61  * @param tmpBuffer tmp buffer storing jit code
62  * @return error code, see errcode.h
63  */
RegisterTmpBuffer(JitCodeSigner * signer,void * tmpBuffer)64 static inline int32_t RegisterTmpBuffer(JitCodeSigner *signer, void *tmpBuffer)
65 {
66     CHECK_NULL_AND_RETURN_CODE(signer);
67     signer->RegisterTmpBuffer(CAST_TO_BYTES(tmpBuffer));
68     return CS_SUCCESS;
69 }
70 
71 /**
72  * @brief Sign an intruction when appending it to tmp buffer
73  * @param signer jit code signer
74  * @param instr an instruction to be signed
75  * @return error code, see errcode.h
76  */
AppendInstruction(JitCodeSigner * signer,Instr instr)77 static inline int32_t AppendInstruction(JitCodeSigner *signer, Instr instr)
78 {
79     CHECK_NULL_AND_RETURN_CODE(signer);
80     signer->SignInstruction(instr);
81     return CS_SUCCESS;
82 }
83 
84 /**
85  * @brief Sign data when appending it to tmp buffer
86  * @param signer jit code signer
87  * @param data data to be signed
88  * @param size data size
89  * @return error code, see errcode.h
90  */
AppendData(JitCodeSigner * signer,const void * const data,uint32_t size)91 static inline int32_t AppendData(JitCodeSigner *signer, const void *const data, uint32_t size)
92 {
93     CHECK_NULL_AND_RETURN_CODE(signer);
94     return signer->SignData(CAST_TO_CONST_BYTES(data), size);
95 }
96 
97 /**
98  * @brief Declare the next intsructions to be fixed up later
99  * @param signer jit code signer
100  * @param n the amount of intsructions
101  * @return error code, see errcode.h
102  */
103 static inline int32_t WillFixUp(JitCodeSigner *signer, uint32_t n = 1)
104 {
105     CHECK_NULL_AND_RETURN_CODE(signer);
106     signer->SkipNext(n);
107     return CS_SUCCESS;
108 }
109 
110 /**
111  * @brief Patch an intruction at offset
112  * @param signer jit code signer
113  * @param instr target intruction
114  * @return error code, see errcode.h
115  */
PatchInstruction(JitCodeSigner * signer,int offset,Instr instr)116 static inline int32_t PatchInstruction(JitCodeSigner *signer, int offset, Instr instr)
117 {
118     CHECK_NULL_AND_RETURN_CODE(signer);
119     return signer->PatchInstruction(offset, instr);
120 }
121 
122 /**
123  * @brief Patch an intruction at address
124  * @param signer jit code signer
125  * @param address address of patching instruction
126  * @param instr target intruction
127  * @return error code, see errcode.h
128  */
PatchInstruction(JitCodeSigner * signer,void * address,Instr insn)129 static inline int32_t PatchInstruction(JitCodeSigner *signer,
130     void *address, Instr insn)
131 {
132     CHECK_NULL_AND_RETURN_CODE(signer);
133     return signer->PatchInstruction(CAST_TO_BYTES(address), insn);
134 }
135 
136 /**
137  * @brief Patch data at offset of buffer
138  * @param signer jit code signer
139  * @param data data to be signed
140  * @param size data size
141  * @return error code, see errcode.h
142  */
PatchData(JitCodeSigner * signer,int offset,const void * const data,uint32_t size)143 static inline int32_t PatchData(JitCodeSigner *signer, int offset,
144     const void *const data, uint32_t size)
145 {
146     CHECK_NULL_AND_RETURN_CODE(signer);
147     return signer->PatchData(offset, CAST_TO_CONST_BYTES(data), size);
148 }
149 
150 /**
151  * @brief Patch data at address
152  * @param signer jit code signer
153  * @param address address of patching instruction
154  * @param data data to be signed
155  * @param size data size
156  * @return error code, see errcode.h
157  */
PatchData(JitCodeSigner * signer,void * address,const void * const data,uint32_t size)158 static inline int32_t PatchData(JitCodeSigner *signer, void *address,
159     const void *const data, uint32_t size)
160 {
161     CHECK_NULL_AND_RETURN_CODE(signer);
162     return signer->PatchData(CAST_TO_BYTES(address),
163         CAST_TO_CONST_BYTES(data), size);
164 }
165 
166 /**
167  * @brief Reset jit memory
168  * @param jitMemory jit memory to be reset
169  * @param size memory size
170  * @return error code, see errcode.h
171  */
ResetJitCode(void * jitMemory,int size)172 static inline int32_t ResetJitCode(void *jitMemory, int size)
173 {
174     if (jitMemory == nullptr) {
175         return CS_ERR_JIT_MEMORY;
176     }
177 #ifndef JIT_FORT_DISABLE
178     int32_t prctlRet = PrctlWrapper(JITFORT_PRCTL_OPTION, JITFORT_SWITCH_IN, 0);
179     if (prctlRet < 0) {
180         return CS_ERR_JITFORT_IN;
181     }
182 #endif
183     (void) __builtin_memset(jitMemory, 0, size);
184 #ifndef JIT_FORT_DISABLE
185     prctlRet = PrctlWrapper(JITFORT_PRCTL_OPTION, JITFORT_SWITCH_OUT, 0);
186     if (prctlRet < 0) {
187         return CS_ERR_JITFORT_OUT;
188     }
189 #endif
190     return CS_SUCCESS;
191 }
192 
193 /**
194  * @brief Copy jit code for cache to jit memory
195  * @param signer jit code signer
196  * @param jitMemory dest address
197  * @param tmpBuffer tmp buffer stored jit code
198  * @param size memory size
199  * @return error code, see errcode.h
200  */
CopyToJitCode(JitCodeSigner * signer,void * jitMemory,void * tmpBuffer,int size)201 static inline int32_t CopyToJitCode(
202     JitCodeSigner *signer, void *jitMemory, void *tmpBuffer, int size)
203 {
204     if (jitMemory == nullptr) {
205         return CS_ERR_JIT_MEMORY;
206     }
207     if (tmpBuffer == nullptr) {
208         return CS_ERR_TMP_BUFFER;
209     }
210     int32_t ret = CS_SUCCESS;
211     // try not to depend on other dynamic library in JITFORT
212 #ifndef JIT_FORT_DISABLE
213     int32_t prctlRet = PrctlWrapper(JITFORT_PRCTL_OPTION, JITFORT_SWITCH_IN, 0);
214     if (prctlRet < 0) {
215         return CS_ERR_JITFORT_IN;
216     }
217 #endif
218     if (IsSupportJitCodeSigner()) {
219         CHECK_NULL_AND_RETURN_CODE(signer);
220         ret = signer->ValidateCodeCopy(reinterpret_cast<Instr *>(jitMemory),
221             reinterpret_cast<Byte *>(tmpBuffer), size);
222     } else {
223         void *ptr = __builtin_memcpy(jitMemory, tmpBuffer, size);
224         if (reinterpret_cast<uintptr_t>(ptr) - reinterpret_cast<uintptr_t>(jitMemory) !=
225             static_cast<uintptr_t>(size)) {
226             ret = CS_ERR_MEMORY;
227         }
228     }
229 #ifndef JIT_FORT_DISABLE
230     prctlRet = PrctlWrapper(JITFORT_PRCTL_OPTION, JITFORT_SWITCH_OUT, 0);
231 
232     if (IsSupportJitCodeSigner()) {
233         signer->FlushLog();
234     }
235 
236     if (prctlRet < 0) {
237         return CS_ERR_JITFORT_OUT;
238     }
239 #endif
240     return ret;
241 }
242 }
243 }
244 }
245 #endif