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