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