xref: /xnu-12377.41.6/san/memory/kasan-memintrinsics.c (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
1 /*
2  * Copyright (c) 2016 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #include <string.h>
30 #include <mach/boolean.h>
31 
32 #include <mach/boolean.h>
33 #include <machine/limits.h>
34 #include <kern/debug.h>
35 #include <san/kcov.h>
36 
37 #include "kasan_internal.h"
38 #include "memintrinsics.h"
39 
40 void
__asan_bcopy(const void * src,void * dst,size_t sz)41 __asan_bcopy(const void *src, void *dst, size_t sz)
42 {
43 	kasan_check_range(src, sz, TYPE_MEMR);
44 	kasan_check_range(dst, sz, TYPE_MEMW);
45 	__nosan_bcopy(src, dst, sz);
46 }
47 
48 void *
__asan_memmove(void * src,const void * dst,size_t sz)49 __asan_memmove(void *src, const void *dst, size_t sz)
50 {
51 	kasan_check_range(src, sz, TYPE_MEMR);
52 	kasan_check_range(dst, sz, TYPE_MEMW);
53 	return __nosan_memmove(src, dst, sz);
54 }
55 
56 void *
__asan_memcpy(void * dst,const void * src,size_t sz)57 __asan_memcpy(void *dst, const void *src, size_t sz)
58 {
59 	kasan_check_range(src, sz, TYPE_MEMR);
60 	kasan_check_range(dst, sz, TYPE_MEMW);
61 	return __nosan_memcpy(dst, src, sz);
62 }
63 
64 void *
__asan_memset(void * dst,int c,size_t sz)65 __asan_memset(void *dst, int c, size_t sz)
66 {
67 	kasan_check_range(dst, sz, TYPE_MEMW);
68 	return __nosan_memset(dst, c, sz);
69 }
70 
71 void
__asan_bzero(void * dst,size_t sz)72 __asan_bzero(void *dst, size_t sz)
73 {
74 	kasan_check_range(dst, sz, TYPE_MEMW);
75 	__nosan_bzero(dst, sz);
76 }
77 
78 int
__asan_bcmp(const void * a,const void * b,size_t len)79 __asan_bcmp(const void *a, const void *b, size_t len)
80 {
81 	kasan_check_range(a, len, TYPE_MEMR);
82 	kasan_check_range(b, len, TYPE_MEMR);
83 #if CONFIG_KCOV
84 	kcov_trace_cmp_func(__builtin_return_address(0), KCOV_CMP_FUNC_MEMCMP, a, len, b, len, false);
85 #endif
86 	return __nosan_bcmp(a, b, len);
87 }
88 
89 int
__asan_memcmp(const void * a,const void * b,size_t n)90 __asan_memcmp(const void *a, const void *b, size_t n)
91 {
92 	kasan_check_range(a, n, TYPE_MEMR);
93 	kasan_check_range(b, n, TYPE_MEMR);
94 #if CONFIG_KCOV
95 	kcov_trace_cmp_func(__builtin_return_address(0), KCOV_CMP_FUNC_MEMCMP, a, n, b, n, false);
96 #endif
97 	return __nosan_memcmp(a, b, n);
98 }
99 
100 size_t
__asan_strlcpy(char * dst,const char * src,size_t sz)101 __asan_strlcpy(char *dst, const char *src, size_t sz)
102 {
103 	kasan_check_range(dst, sz, TYPE_STRW);
104 	return __nosan_strlcpy(dst, src, sz);
105 }
106 
107 size_t
__asan_strlcat(char * dst,const char * src,size_t sz)108 __asan_strlcat(char *dst, const char *src, size_t sz)
109 {
110 	kasan_check_range(dst, sz, TYPE_STRW);
111 	return __nosan_strlcat(dst, src, sz);
112 }
113 
114 char *
__asan_strncpy(char * dst,const char * src,size_t sz)115 __asan_strncpy(char *dst, const char *src, size_t sz)
116 {
117 	kasan_check_range(dst, sz, TYPE_STRW);
118 	return __nosan_strncpy(dst, src, sz);
119 }
120 
121 char *
__asan_strncat(char * dst,const char * src,size_t sz)122 __asan_strncat(char *dst, const char *src, size_t sz)
123 {
124 	kasan_check_range(dst, strlen(dst) + sz + 1, TYPE_STRW);
125 	return __nosan_strncat(dst, src, sz);
126 }
127 
128 size_t
__asan_strnlen(const char * src,size_t sz)129 __asan_strnlen(const char *src, size_t sz)
130 {
131 	size_t n = __nosan_strnlen(src, sz);
132 	if (n < sz) {
133 		sz = n + 1; // Include NUL
134 	}
135 	kasan_check_range(src, sz, TYPE_STRR);
136 	return n;
137 }
138 
139 size_t
__asan_strlen(const char * src)140 __asan_strlen(const char *src)
141 {
142 	size_t sz = __nosan_strlen(src);
143 	kasan_check_range(src, sz + 1, TYPE_STRR);
144 	return sz;
145 }
146 
147 int
__asan_strcmp(const char * __null_terminated s1,const char * __null_terminated s2)148 __asan_strcmp(const char *__null_terminated s1, const char *__null_terminated s2)
149 {
150 	size_t l1 = __asan_strlen(s1);
151 	size_t l2 = __asan_strlen(s2);
152 #if CONFIG_KCOV
153 	kcov_trace_cmp_func(__builtin_return_address(0), KCOV_CMP_FUNC_STRCMP, s1, l1, s2, l2, false);
154 #else
155 	(void)l1;
156 	(void)l2;
157 #endif
158 	return __nosan_strcmp(s1, s2);
159 }
160 
161 __ptrcheck_unavailable_r("strlcmp or strbufcmp")
162 int
__asan_strncmp(const char * __unsafe_indexable s1,const char * __unsafe_indexable s2,size_t n)163 __asan_strncmp(const char *__unsafe_indexable s1, const char *__unsafe_indexable s2, size_t n)
164 {
165 	size_t l1 = __asan_strnlen(s1, n);
166 	size_t l2 = __asan_strnlen(s2, n);
167 #if CONFIG_KCOV
168 	kcov_trace_cmp_func(__builtin_return_address(0), KCOV_CMP_FUNC_STRNCMP, s1, l1, s2, l2, false);
169 #else
170 	(void)l1;
171 	(void)l2;
172 #endif
173 	return __nosan_strncmp(s1, s2, n);
174 }
175 
176 int
__asan_strlcmp(const char * __counted_by (n)s1,const char * s2,size_t n)177 __asan_strlcmp(const char *__counted_by(n)s1, const char *s2, size_t n)
178 {
179 	size_t l1 = __asan_strnlen(s1, n);
180 	size_t l2 = __asan_strlen(s2);
181 #if CONFIG_KCOV
182 	kcov_trace_cmp_func(__builtin_return_address(0), KCOV_CMP_FUNC_STRNCMP, s1, l1, s2, l2, false);
183 #else
184 	(void)l1;
185 	(void)l2;
186 #endif
187 	return __nosan_strlcmp(s1, s2, n);
188 }
189 
190 int
__asan_strbufcmp(const char * __counted_by (s1len)s1,size_t s1len,const char * __counted_by (s2len)s2,size_t s2len)191 __asan_strbufcmp(const char *__counted_by(s1len)s1, size_t s1len, const char *__counted_by(s2len)s2, size_t s2len)
192 {
193 	size_t l1 = __asan_strnlen(s1, s1len);
194 	size_t l2 = __asan_strnlen(s2, s2len);
195 #if CONFIG_KCOV
196 	kcov_trace_cmp_func(__builtin_return_address(0), KCOV_CMP_FUNC_STRBUFCMP, s1, l1, s2, l2, false);
197 #else
198 	(void)l1;
199 	(void)l2;
200 #endif
201 	return __nosan_strbufcmp(s1, s1len, s2, s2len);
202 }
203 
204 int
__asan_strcasecmp(const char * __null_terminated s1,const char * __null_terminated s2)205 __asan_strcasecmp(const char *__null_terminated s1, const char *__null_terminated s2)
206 {
207 	size_t l1 = __asan_strlen(s1);
208 	size_t l2 = __asan_strlen(s2);
209 #if CONFIG_KCOV
210 	kcov_trace_cmp_func(__builtin_return_address(0), KCOV_CMP_FUNC_STRCMP, s1, l1, s2, l2, false);
211 #else
212 	(void)l1;
213 	(void)l2;
214 #endif
215 	return __nosan_strcasecmp(s1, s2);
216 }
217 
218 __ptrcheck_unavailable_r("strlcasecmp or strbufcasecmp")
219 int
__asan_strncasecmp(const char * __unsafe_indexable s1,const char * __unsafe_indexable s2,size_t n)220 __asan_strncasecmp(const char *__unsafe_indexable s1, const char *__unsafe_indexable s2, size_t n)
221 {
222 	size_t l1 = __asan_strnlen(s1, n);
223 	size_t l2 = __asan_strnlen(s2, n);
224 #if CONFIG_KCOV
225 	kcov_trace_cmp_func(__builtin_return_address(0), KCOV_CMP_FUNC_STRNCMP, s1, l1, s2, l2, false);
226 #else
227 	(void)l1;
228 	(void)l2;
229 #endif
230 	return __nosan_strncasecmp(s1, s2, n);
231 }
232 
233 int
__asan_strlcasecmp(const char * __counted_by (n)s1,const char * s2,size_t n)234 __asan_strlcasecmp(const char *__counted_by(n)s1, const char *s2, size_t n)
235 {
236 	size_t l1 = __asan_strnlen(s1, n);
237 	size_t l2 = __asan_strlen(s2);
238 #if CONFIG_KCOV
239 	kcov_trace_cmp_func(__builtin_return_address(0), KCOV_CMP_FUNC_STRNCMP, s1, l1, s2, l2, false);
240 #else
241 	(void)l1;
242 	(void)l2;
243 #endif
244 	return __nosan_strlcasecmp(s1, s2, n);
245 }
246 
247 int
__asan_strbufcasecmp(const char * __counted_by (s1len)s1,size_t s1len,const char * __counted_by (s2len)s2,size_t s2len)248 __asan_strbufcasecmp(const char *__counted_by(s1len)s1, size_t s1len, const char *__counted_by(s2len)s2, size_t s2len)
249 {
250 	size_t l1 = __asan_strnlen(s1, s1len);
251 	size_t l2 = __asan_strnlen(s2, s2len);
252 #if CONFIG_KCOV
253 	kcov_trace_cmp_func(__builtin_return_address(0), KCOV_CMP_FUNC_STRBUFCMP, s1, l1, s2, l2, false);
254 #else
255 	(void)l1;
256 	(void)l2;
257 #endif
258 	return __nosan_strbufcasecmp(s1, s1len, s2, s2len);
259 }
260