0001
0002 #ifndef _LINUX_FORTIFY_STRING_H_
0003 #define _LINUX_FORTIFY_STRING_H_
0004
0005 #include <linux/const.h>
0006
0007 #define __FORTIFY_INLINE extern __always_inline __gnu_inline __overloadable
0008 #define __RENAME(x) __asm__(#x)
0009
0010 void fortify_panic(const char *name) __noreturn __cold;
0011 void __read_overflow(void) __compiletime_error("detected read beyond size of object (1st parameter)");
0012 void __read_overflow2(void) __compiletime_error("detected read beyond size of object (2nd parameter)");
0013 void __read_overflow2_field(size_t avail, size_t wanted) __compiletime_warning("detected read beyond size of field (2nd parameter); maybe use struct_group()?");
0014 void __write_overflow(void) __compiletime_error("detected write beyond size of object (1st parameter)");
0015 void __write_overflow_field(size_t avail, size_t wanted) __compiletime_warning("detected write beyond size of field (1st parameter); maybe use struct_group()?");
0016
0017 #define __compiletime_strlen(p) \
0018 ({ \
0019 unsigned char *__p = (unsigned char *)(p); \
0020 size_t __ret = (size_t)-1; \
0021 size_t __p_size = __builtin_object_size(p, 1); \
0022 if (__p_size != (size_t)-1) { \
0023 size_t __p_len = __p_size - 1; \
0024 if (__builtin_constant_p(__p[__p_len]) && \
0025 __p[__p_len] == '\0') \
0026 __ret = __builtin_strlen(__p); \
0027 } \
0028 __ret; \
0029 })
0030
0031 #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)
0032 extern void *__underlying_memchr(const void *p, int c, __kernel_size_t size) __RENAME(memchr);
0033 extern int __underlying_memcmp(const void *p, const void *q, __kernel_size_t size) __RENAME(memcmp);
0034 extern void *__underlying_memcpy(void *p, const void *q, __kernel_size_t size) __RENAME(memcpy);
0035 extern void *__underlying_memmove(void *p, const void *q, __kernel_size_t size) __RENAME(memmove);
0036 extern void *__underlying_memset(void *p, int c, __kernel_size_t size) __RENAME(memset);
0037 extern char *__underlying_strcat(char *p, const char *q) __RENAME(strcat);
0038 extern char *__underlying_strcpy(char *p, const char *q) __RENAME(strcpy);
0039 extern __kernel_size_t __underlying_strlen(const char *p) __RENAME(strlen);
0040 extern char *__underlying_strncat(char *p, const char *q, __kernel_size_t count) __RENAME(strncat);
0041 extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size) __RENAME(strncpy);
0042 #else
0043 #define __underlying_memchr __builtin_memchr
0044 #define __underlying_memcmp __builtin_memcmp
0045 #define __underlying_memcpy __builtin_memcpy
0046 #define __underlying_memmove __builtin_memmove
0047 #define __underlying_memset __builtin_memset
0048 #define __underlying_strcat __builtin_strcat
0049 #define __underlying_strcpy __builtin_strcpy
0050 #define __underlying_strlen __builtin_strlen
0051 #define __underlying_strncat __builtin_strncat
0052 #define __underlying_strncpy __builtin_strncpy
0053 #endif
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068 #define unsafe_memcpy(dst, src, bytes, justification) \
0069 __underlying_memcpy(dst, src, bytes)
0070
0071
0072
0073
0074
0075
0076
0077 #define POS __pass_object_size(1)
0078 #define POS0 __pass_object_size(0)
0079
0080 __FORTIFY_INLINE __diagnose_as(__builtin_strncpy, 1, 2, 3)
0081 char *strncpy(char * const POS p, const char *q, __kernel_size_t size)
0082 {
0083 size_t p_size = __builtin_object_size(p, 1);
0084
0085 if (__builtin_constant_p(size) && p_size < size)
0086 __write_overflow();
0087 if (p_size < size)
0088 fortify_panic(__func__);
0089 return __underlying_strncpy(p, q, size);
0090 }
0091
0092 __FORTIFY_INLINE __diagnose_as(__builtin_strcat, 1, 2)
0093 char *strcat(char * const POS p, const char *q)
0094 {
0095 size_t p_size = __builtin_object_size(p, 1);
0096
0097 if (p_size == (size_t)-1)
0098 return __underlying_strcat(p, q);
0099 if (strlcat(p, q, p_size) >= p_size)
0100 fortify_panic(__func__);
0101 return p;
0102 }
0103
0104 extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen);
0105 __FORTIFY_INLINE __kernel_size_t strnlen(const char * const POS p, __kernel_size_t maxlen)
0106 {
0107 size_t p_size = __builtin_object_size(p, 1);
0108 size_t p_len = __compiletime_strlen(p);
0109 size_t ret;
0110
0111
0112 if (__builtin_constant_p(maxlen) && p_len != (size_t)-1) {
0113
0114 if (maxlen >= p_size)
0115 return p_len;
0116 }
0117
0118
0119 ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size);
0120 if (p_size <= ret && maxlen != ret)
0121 fortify_panic(__func__);
0122 return ret;
0123 }
0124
0125
0126
0127
0128
0129
0130 #define strlen(p) \
0131 __builtin_choose_expr(__is_constexpr(__builtin_strlen(p)), \
0132 __builtin_strlen(p), __fortify_strlen(p))
0133 __FORTIFY_INLINE __diagnose_as(__builtin_strlen, 1)
0134 __kernel_size_t __fortify_strlen(const char * const POS p)
0135 {
0136 __kernel_size_t ret;
0137 size_t p_size = __builtin_object_size(p, 1);
0138
0139
0140 if (p_size == (size_t)-1)
0141 return __underlying_strlen(p);
0142 ret = strnlen(p, p_size);
0143 if (p_size <= ret)
0144 fortify_panic(__func__);
0145 return ret;
0146 }
0147
0148
0149 extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strlcpy);
0150 __FORTIFY_INLINE size_t strlcpy(char * const POS p, const char * const POS q, size_t size)
0151 {
0152 size_t p_size = __builtin_object_size(p, 1);
0153 size_t q_size = __builtin_object_size(q, 1);
0154 size_t q_len;
0155 size_t len;
0156
0157 if (p_size == (size_t)-1 && q_size == (size_t)-1)
0158 return __real_strlcpy(p, q, size);
0159 q_len = strlen(q);
0160 len = (q_len >= size) ? size - 1 : q_len;
0161 if (__builtin_constant_p(size) && __builtin_constant_p(q_len) && size) {
0162
0163 if (len >= p_size)
0164 __write_overflow();
0165 }
0166 if (size) {
0167 if (len >= p_size)
0168 fortify_panic(__func__);
0169 __underlying_memcpy(p, q, len);
0170 p[len] = '\0';
0171 }
0172 return q_len;
0173 }
0174
0175
0176 extern ssize_t __real_strscpy(char *, const char *, size_t) __RENAME(strscpy);
0177 __FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, size_t size)
0178 {
0179 size_t len;
0180
0181 size_t p_size = __builtin_object_size(p, 1);
0182 size_t q_size = __builtin_object_size(q, 1);
0183
0184
0185 if (p_size == (size_t) -1 && q_size == (size_t) -1)
0186 return __real_strscpy(p, q, size);
0187
0188
0189
0190
0191
0192 if (__builtin_constant_p(size) && size > p_size)
0193 __write_overflow();
0194
0195
0196
0197
0198
0199 len = strnlen(q, size);
0200
0201
0202
0203
0204
0205 len = len == size ? size : len + 1;
0206
0207
0208
0209
0210
0211 if (len > p_size)
0212 fortify_panic(__func__);
0213
0214
0215
0216
0217
0218
0219 return __real_strscpy(p, q, len);
0220 }
0221
0222
0223 __FORTIFY_INLINE __diagnose_as(__builtin_strncat, 1, 2, 3)
0224 char *strncat(char * const POS p, const char * const POS q, __kernel_size_t count)
0225 {
0226 size_t p_len, copy_len;
0227 size_t p_size = __builtin_object_size(p, 1);
0228 size_t q_size = __builtin_object_size(q, 1);
0229
0230 if (p_size == (size_t)-1 && q_size == (size_t)-1)
0231 return __underlying_strncat(p, q, count);
0232 p_len = strlen(p);
0233 copy_len = strnlen(q, count);
0234 if (p_size < p_len + copy_len + 1)
0235 fortify_panic(__func__);
0236 __underlying_memcpy(p + p_len, q, copy_len);
0237 p[p_len + copy_len] = '\0';
0238 return p;
0239 }
0240
0241 __FORTIFY_INLINE void fortify_memset_chk(__kernel_size_t size,
0242 const size_t p_size,
0243 const size_t p_size_field)
0244 {
0245 if (__builtin_constant_p(size)) {
0246
0247
0248
0249
0250
0251
0252
0253 if (p_size > p_size_field && p_size < size)
0254 __write_overflow();
0255
0256
0257 if (p_size_field < size)
0258 __write_overflow_field(p_size_field, size);
0259 }
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274 if (p_size != (size_t)(-1) && p_size < size)
0275 fortify_panic("memset");
0276 }
0277
0278 #define __fortify_memset_chk(p, c, size, p_size, p_size_field) ({ \
0279 size_t __fortify_size = (size_t)(size); \
0280 fortify_memset_chk(__fortify_size, p_size, p_size_field), \
0281 __underlying_memset(p, c, __fortify_size); \
0282 })
0283
0284
0285
0286
0287
0288 #define memset(p, c, s) __fortify_memset_chk(p, c, s, \
0289 __builtin_object_size(p, 0), __builtin_object_size(p, 1))
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322 __FORTIFY_INLINE void fortify_memcpy_chk(__kernel_size_t size,
0323 const size_t p_size,
0324 const size_t q_size,
0325 const size_t p_size_field,
0326 const size_t q_size_field,
0327 const char *func)
0328 {
0329 if (__builtin_constant_p(size)) {
0330
0331
0332
0333
0334
0335
0336
0337 if (p_size > p_size_field && p_size < size)
0338 __write_overflow();
0339 if (q_size > q_size_field && q_size < size)
0340 __read_overflow2();
0341
0342
0343 if (p_size_field < size)
0344 __write_overflow_field(p_size_field, size);
0345
0346
0347
0348
0349
0350 if ((IS_ENABLED(KBUILD_EXTRA_WARN1) || p_size_field < size) &&
0351 q_size_field < size)
0352 __read_overflow2_field(q_size_field, size);
0353 }
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368 if ((p_size != (size_t)(-1) && p_size < size) ||
0369 (q_size != (size_t)(-1) && q_size < size))
0370 fortify_panic(func);
0371 }
0372
0373 #define __fortify_memcpy_chk(p, q, size, p_size, q_size, \
0374 p_size_field, q_size_field, op) ({ \
0375 size_t __fortify_size = (size_t)(size); \
0376 fortify_memcpy_chk(__fortify_size, p_size, q_size, \
0377 p_size_field, q_size_field, #op); \
0378 __underlying_##op(p, q, __fortify_size); \
0379 })
0380
0381
0382
0383
0384
0385 #define memcpy(p, q, s) __fortify_memcpy_chk(p, q, s, \
0386 __builtin_object_size(p, 0), __builtin_object_size(q, 0), \
0387 __builtin_object_size(p, 1), __builtin_object_size(q, 1), \
0388 memcpy)
0389 #define memmove(p, q, s) __fortify_memcpy_chk(p, q, s, \
0390 __builtin_object_size(p, 0), __builtin_object_size(q, 0), \
0391 __builtin_object_size(p, 1), __builtin_object_size(q, 1), \
0392 memmove)
0393
0394 extern void *__real_memscan(void *, int, __kernel_size_t) __RENAME(memscan);
0395 __FORTIFY_INLINE void *memscan(void * const POS0 p, int c, __kernel_size_t size)
0396 {
0397 size_t p_size = __builtin_object_size(p, 0);
0398
0399 if (__builtin_constant_p(size) && p_size < size)
0400 __read_overflow();
0401 if (p_size < size)
0402 fortify_panic(__func__);
0403 return __real_memscan(p, c, size);
0404 }
0405
0406 __FORTIFY_INLINE __diagnose_as(__builtin_memcmp, 1, 2, 3)
0407 int memcmp(const void * const POS0 p, const void * const POS0 q, __kernel_size_t size)
0408 {
0409 size_t p_size = __builtin_object_size(p, 0);
0410 size_t q_size = __builtin_object_size(q, 0);
0411
0412 if (__builtin_constant_p(size)) {
0413 if (p_size < size)
0414 __read_overflow();
0415 if (q_size < size)
0416 __read_overflow2();
0417 }
0418 if (p_size < size || q_size < size)
0419 fortify_panic(__func__);
0420 return __underlying_memcmp(p, q, size);
0421 }
0422
0423 __FORTIFY_INLINE __diagnose_as(__builtin_memchr, 1, 2, 3)
0424 void *memchr(const void * const POS0 p, int c, __kernel_size_t size)
0425 {
0426 size_t p_size = __builtin_object_size(p, 0);
0427
0428 if (__builtin_constant_p(size) && p_size < size)
0429 __read_overflow();
0430 if (p_size < size)
0431 fortify_panic(__func__);
0432 return __underlying_memchr(p, c, size);
0433 }
0434
0435 void *__real_memchr_inv(const void *s, int c, size_t n) __RENAME(memchr_inv);
0436 __FORTIFY_INLINE void *memchr_inv(const void * const POS0 p, int c, size_t size)
0437 {
0438 size_t p_size = __builtin_object_size(p, 0);
0439
0440 if (__builtin_constant_p(size) && p_size < size)
0441 __read_overflow();
0442 if (p_size < size)
0443 fortify_panic(__func__);
0444 return __real_memchr_inv(p, c, size);
0445 }
0446
0447 extern void *__real_kmemdup(const void *src, size_t len, gfp_t gfp) __RENAME(kmemdup);
0448 __FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp)
0449 {
0450 size_t p_size = __builtin_object_size(p, 0);
0451
0452 if (__builtin_constant_p(size) && p_size < size)
0453 __read_overflow();
0454 if (p_size < size)
0455 fortify_panic(__func__);
0456 return __real_kmemdup(p, size, gfp);
0457 }
0458
0459
0460 __FORTIFY_INLINE __diagnose_as(__builtin_strcpy, 1, 2)
0461 char *strcpy(char * const POS p, const char * const POS q)
0462 {
0463 size_t p_size = __builtin_object_size(p, 1);
0464 size_t q_size = __builtin_object_size(q, 1);
0465 size_t size;
0466
0467
0468 if (p_size == (size_t)-1 && q_size == (size_t)-1)
0469 return __underlying_strcpy(p, q);
0470 size = strlen(q) + 1;
0471
0472 if (__builtin_constant_p(size) && p_size < size)
0473 __write_overflow();
0474
0475 if (p_size < size)
0476 fortify_panic(__func__);
0477 __underlying_memcpy(p, q, size);
0478 return p;
0479 }
0480
0481
0482 #undef __underlying_memchr
0483 #undef __underlying_memcmp
0484 #undef __underlying_strcat
0485 #undef __underlying_strcpy
0486 #undef __underlying_strlen
0487 #undef __underlying_strncat
0488 #undef __underlying_strncpy
0489
0490 #undef POS
0491 #undef POS0
0492
0493 #endif