at v5.16 11 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 */ 2#ifndef _LINUX_FORTIFY_STRING_H_ 3#define _LINUX_FORTIFY_STRING_H_ 4 5#define __FORTIFY_INLINE extern __always_inline __attribute__((gnu_inline)) 6#define __RENAME(x) __asm__(#x) 7 8void fortify_panic(const char *name) __noreturn __cold; 9void __read_overflow(void) __compiletime_error("detected read beyond size of object (1st parameter)"); 10void __read_overflow2(void) __compiletime_error("detected read beyond size of object (2nd parameter)"); 11void __write_overflow(void) __compiletime_error("detected write beyond size of object (1st parameter)"); 12 13#define __compiletime_strlen(p) \ 14({ \ 15 unsigned char *__p = (unsigned char *)(p); \ 16 size_t __ret = (size_t)-1; \ 17 size_t __p_size = __builtin_object_size(p, 1); \ 18 if (__p_size != (size_t)-1) { \ 19 size_t __p_len = __p_size - 1; \ 20 if (__builtin_constant_p(__p[__p_len]) && \ 21 __p[__p_len] == '\0') \ 22 __ret = __builtin_strlen(__p); \ 23 } \ 24 __ret; \ 25}) 26 27#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) 28extern void *__underlying_memchr(const void *p, int c, __kernel_size_t size) __RENAME(memchr); 29extern int __underlying_memcmp(const void *p, const void *q, __kernel_size_t size) __RENAME(memcmp); 30extern void *__underlying_memcpy(void *p, const void *q, __kernel_size_t size) __RENAME(memcpy); 31extern void *__underlying_memmove(void *p, const void *q, __kernel_size_t size) __RENAME(memmove); 32extern void *__underlying_memset(void *p, int c, __kernel_size_t size) __RENAME(memset); 33extern char *__underlying_strcat(char *p, const char *q) __RENAME(strcat); 34extern char *__underlying_strcpy(char *p, const char *q) __RENAME(strcpy); 35extern __kernel_size_t __underlying_strlen(const char *p) __RENAME(strlen); 36extern char *__underlying_strncat(char *p, const char *q, __kernel_size_t count) __RENAME(strncat); 37extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) __RENAME(strncpy); 38#else 39#define __underlying_memchr __builtin_memchr 40#define __underlying_memcmp __builtin_memcmp 41#define __underlying_memcpy __builtin_memcpy 42#define __underlying_memmove __builtin_memmove 43#define __underlying_memset __builtin_memset 44#define __underlying_strcat __builtin_strcat 45#define __underlying_strcpy __builtin_strcpy 46#define __underlying_strlen __builtin_strlen 47#define __underlying_strncat __builtin_strncat 48#define __underlying_strncpy __builtin_strncpy 49#endif 50 51__FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size) 52{ 53 size_t p_size = __builtin_object_size(p, 1); 54 55 if (__builtin_constant_p(size) && p_size < size) 56 __write_overflow(); 57 if (p_size < size) 58 fortify_panic(__func__); 59 return __underlying_strncpy(p, q, size); 60} 61 62__FORTIFY_INLINE char *strcat(char *p, const char *q) 63{ 64 size_t p_size = __builtin_object_size(p, 1); 65 66 if (p_size == (size_t)-1) 67 return __underlying_strcat(p, q); 68 if (strlcat(p, q, p_size) >= p_size) 69 fortify_panic(__func__); 70 return p; 71} 72 73extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen); 74__FORTIFY_INLINE __kernel_size_t strnlen(const char *p, __kernel_size_t maxlen) 75{ 76 size_t p_size = __builtin_object_size(p, 1); 77 size_t p_len = __compiletime_strlen(p); 78 size_t ret; 79 80 /* We can take compile-time actions when maxlen is const. */ 81 if (__builtin_constant_p(maxlen) && p_len != (size_t)-1) { 82 /* If p is const, we can use its compile-time-known len. */ 83 if (maxlen >= p_size) 84 return p_len; 85 } 86 87 /* Do not check characters beyond the end of p. */ 88 ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size); 89 if (p_size <= ret && maxlen != ret) 90 fortify_panic(__func__); 91 return ret; 92} 93 94/* defined after fortified strnlen to reuse it. */ 95__FORTIFY_INLINE __kernel_size_t strlen(const char *p) 96{ 97 __kernel_size_t ret; 98 size_t p_size = __builtin_object_size(p, 1); 99 100 /* Give up if we don't know how large p is. */ 101 if (p_size == (size_t)-1) 102 return __underlying_strlen(p); 103 ret = strnlen(p, p_size); 104 if (p_size <= ret) 105 fortify_panic(__func__); 106 return ret; 107} 108 109/* defined after fortified strlen to reuse it */ 110extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strlcpy); 111__FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size) 112{ 113 size_t p_size = __builtin_object_size(p, 1); 114 size_t q_size = __builtin_object_size(q, 1); 115 size_t q_len; /* Full count of source string length. */ 116 size_t len; /* Count of characters going into destination. */ 117 118 if (p_size == (size_t)-1 && q_size == (size_t)-1) 119 return __real_strlcpy(p, q, size); 120 q_len = strlen(q); 121 len = (q_len >= size) ? size - 1 : q_len; 122 if (__builtin_constant_p(size) && __builtin_constant_p(q_len) && size) { 123 /* Write size is always larger than destination. */ 124 if (len >= p_size) 125 __write_overflow(); 126 } 127 if (size) { 128 if (len >= p_size) 129 fortify_panic(__func__); 130 __underlying_memcpy(p, q, len); 131 p[len] = '\0'; 132 } 133 return q_len; 134} 135 136/* defined after fortified strnlen to reuse it */ 137extern ssize_t __real_strscpy(char *, const char *, size_t) __RENAME(strscpy); 138__FORTIFY_INLINE ssize_t strscpy(char *p, const char *q, size_t size) 139{ 140 size_t len; 141 /* Use string size rather than possible enclosing struct size. */ 142 size_t p_size = __builtin_object_size(p, 1); 143 size_t q_size = __builtin_object_size(q, 1); 144 145 /* If we cannot get size of p and q default to call strscpy. */ 146 if (p_size == (size_t) -1 && q_size == (size_t) -1) 147 return __real_strscpy(p, q, size); 148 149 /* 150 * If size can be known at compile time and is greater than 151 * p_size, generate a compile time write overflow error. 152 */ 153 if (__builtin_constant_p(size) && size > p_size) 154 __write_overflow(); 155 156 /* 157 * This call protects from read overflow, because len will default to q 158 * length if it smaller than size. 159 */ 160 len = strnlen(q, size); 161 /* 162 * If len equals size, we will copy only size bytes which leads to 163 * -E2BIG being returned. 164 * Otherwise we will copy len + 1 because of the final '\O'. 165 */ 166 len = len == size ? size : len + 1; 167 168 /* 169 * Generate a runtime write overflow error if len is greater than 170 * p_size. 171 */ 172 if (len > p_size) 173 fortify_panic(__func__); 174 175 /* 176 * We can now safely call vanilla strscpy because we are protected from: 177 * 1. Read overflow thanks to call to strnlen(). 178 * 2. Write overflow thanks to above ifs. 179 */ 180 return __real_strscpy(p, q, len); 181} 182 183/* defined after fortified strlen and strnlen to reuse them */ 184__FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count) 185{ 186 size_t p_len, copy_len; 187 size_t p_size = __builtin_object_size(p, 1); 188 size_t q_size = __builtin_object_size(q, 1); 189 190 if (p_size == (size_t)-1 && q_size == (size_t)-1) 191 return __underlying_strncat(p, q, count); 192 p_len = strlen(p); 193 copy_len = strnlen(q, count); 194 if (p_size < p_len + copy_len + 1) 195 fortify_panic(__func__); 196 __underlying_memcpy(p + p_len, q, copy_len); 197 p[p_len + copy_len] = '\0'; 198 return p; 199} 200 201__FORTIFY_INLINE void *memset(void *p, int c, __kernel_size_t size) 202{ 203 size_t p_size = __builtin_object_size(p, 0); 204 205 if (__builtin_constant_p(size) && p_size < size) 206 __write_overflow(); 207 if (p_size < size) 208 fortify_panic(__func__); 209 return __underlying_memset(p, c, size); 210} 211 212__FORTIFY_INLINE void *memcpy(void *p, const void *q, __kernel_size_t size) 213{ 214 size_t p_size = __builtin_object_size(p, 0); 215 size_t q_size = __builtin_object_size(q, 0); 216 217 if (__builtin_constant_p(size)) { 218 if (p_size < size) 219 __write_overflow(); 220 if (q_size < size) 221 __read_overflow2(); 222 } 223 if (p_size < size || q_size < size) 224 fortify_panic(__func__); 225 return __underlying_memcpy(p, q, size); 226} 227 228__FORTIFY_INLINE void *memmove(void *p, const void *q, __kernel_size_t size) 229{ 230 size_t p_size = __builtin_object_size(p, 0); 231 size_t q_size = __builtin_object_size(q, 0); 232 233 if (__builtin_constant_p(size)) { 234 if (p_size < size) 235 __write_overflow(); 236 if (q_size < size) 237 __read_overflow2(); 238 } 239 if (p_size < size || q_size < size) 240 fortify_panic(__func__); 241 return __underlying_memmove(p, q, size); 242} 243 244extern void *__real_memscan(void *, int, __kernel_size_t) __RENAME(memscan); 245__FORTIFY_INLINE void *memscan(void *p, int c, __kernel_size_t size) 246{ 247 size_t p_size = __builtin_object_size(p, 0); 248 249 if (__builtin_constant_p(size) && p_size < size) 250 __read_overflow(); 251 if (p_size < size) 252 fortify_panic(__func__); 253 return __real_memscan(p, c, size); 254} 255 256__FORTIFY_INLINE int memcmp(const void *p, const void *q, __kernel_size_t size) 257{ 258 size_t p_size = __builtin_object_size(p, 0); 259 size_t q_size = __builtin_object_size(q, 0); 260 261 if (__builtin_constant_p(size)) { 262 if (p_size < size) 263 __read_overflow(); 264 if (q_size < size) 265 __read_overflow2(); 266 } 267 if (p_size < size || q_size < size) 268 fortify_panic(__func__); 269 return __underlying_memcmp(p, q, size); 270} 271 272__FORTIFY_INLINE void *memchr(const void *p, int c, __kernel_size_t size) 273{ 274 size_t p_size = __builtin_object_size(p, 0); 275 276 if (__builtin_constant_p(size) && p_size < size) 277 __read_overflow(); 278 if (p_size < size) 279 fortify_panic(__func__); 280 return __underlying_memchr(p, c, size); 281} 282 283void *__real_memchr_inv(const void *s, int c, size_t n) __RENAME(memchr_inv); 284__FORTIFY_INLINE void *memchr_inv(const void *p, int c, size_t size) 285{ 286 size_t p_size = __builtin_object_size(p, 0); 287 288 if (__builtin_constant_p(size) && p_size < size) 289 __read_overflow(); 290 if (p_size < size) 291 fortify_panic(__func__); 292 return __real_memchr_inv(p, c, size); 293} 294 295extern void *__real_kmemdup(const void *src, size_t len, gfp_t gfp) __RENAME(kmemdup); 296__FORTIFY_INLINE void *kmemdup(const void *p, size_t size, gfp_t gfp) 297{ 298 size_t p_size = __builtin_object_size(p, 0); 299 300 if (__builtin_constant_p(size) && p_size < size) 301 __read_overflow(); 302 if (p_size < size) 303 fortify_panic(__func__); 304 return __real_kmemdup(p, size, gfp); 305} 306 307/* defined after fortified strlen and memcpy to reuse them */ 308__FORTIFY_INLINE char *strcpy(char *p, const char *q) 309{ 310 size_t p_size = __builtin_object_size(p, 1); 311 size_t q_size = __builtin_object_size(q, 1); 312 size_t size; 313 314 if (p_size == (size_t)-1 && q_size == (size_t)-1) 315 return __underlying_strcpy(p, q); 316 size = strlen(q) + 1; 317 /* Compile-time check for const size overflow. */ 318 if (__builtin_constant_p(size) && p_size < size) 319 __write_overflow(); 320 /* Run-time check for dynamic size overflow. */ 321 if (p_size < size) 322 fortify_panic(__func__); 323 memcpy(p, q, size); 324 return p; 325} 326 327/* Don't use these outside the FORITFY_SOURCE implementation */ 328#undef __underlying_memchr 329#undef __underlying_memcmp 330#undef __underlying_memcpy 331#undef __underlying_memmove 332#undef __underlying_memset 333#undef __underlying_strcat 334#undef __underlying_strcpy 335#undef __underlying_strlen 336#undef __underlying_strncat 337#undef __underlying_strncpy 338 339#endif /* _LINUX_FORTIFY_STRING_H_ */