[RFC PATCH v2 3/3] kasan: add interceptors for all string functions
Christophe Leroy
christophe.leroy at c-s.fr
Wed Apr 3 01:57:50 AEDT 2019
Le 02/04/2019 à 14:58, Dmitry Vyukov a écrit :
> On Tue, Apr 2, 2019 at 11:43 AM Christophe Leroy
> <christophe.leroy at c-s.fr> wrote:
>>
>> Hi Dmitry, Andrey and others,
>>
>> Do you have any comments to this series ?
>>
>> I'd like to know if this approach is ok or if it is better to keep doing
>> as in https://patchwork.ozlabs.org/patch/1055788/
>
> Hi Christophe,
>
> Forking every kernel function does not look like a scalable approach
> to me. There is not much special about str* functions. There is
> something a bit special about memset/memcpy as compiler emits them for
> struct set/copy.
> Could powerpc do the same as x86 and map some shadow early enough
> (before "prom")? Then we would not need anything of this? Sorry if we
> already discussed this, I am losing context quickly.
Hi Dmitry,
I'm afraid we can't map shadow ram that early. This code gets run by
third party BIOS SW which manages the MMU and provides a 1:1 mapping, so
there is no way we can map shadow memory.
If you feel providing interceptors for the string functions is not a
good idea, I'm ok with it, I'll keep the necessary string functions in
prom_init.c
I was proposing the interceptor's approach because behind the specific
need for handling early prom_init code, I thought it was also a way to
limit KASAN performance impact on string functions, and it was also a
way to handle all the optimised string functions provided by architectures.
In my series I have a patch that disables powerpc's optimised string
functions (https://patchwork.ozlabs.org/patch/1055780/). The
interceptor's approach was a way to avoid that. As far as I can see, at
the time being the other arches don't disable their optimised string
functions, meaning the KASAN checks are skipped.
Thanks
Christophe
>
>
>
>
>> Thanks
>> Christophe
>>
>> Le 28/03/2019 à 16:00, Christophe Leroy a écrit :
>>> In the same spirit as commit 393f203f5fd5 ("x86_64: kasan: add
>>> interceptors for memset/memmove/memcpy functions"), this patch
>>> adds interceptors for string manipulation functions so that we
>>> can compile lib/string.o without kasan support hence allow the
>>> string functions to also be used from places where kasan has
>>> to be disabled.
>>>
>>> Signed-off-by: Christophe Leroy <christophe.leroy at c-s.fr>
>>> ---
>>> v2: Fixed a few checkpatch stuff and added missing EXPORT_SYMBOL() and missing #undefs
>>>
>>> include/linux/string.h | 79 ++++++++++
>>> lib/Makefile | 2 +
>>> lib/string.c | 8 +
>>> mm/kasan/string.c | 394 +++++++++++++++++++++++++++++++++++++++++++++++++
>>> 4 files changed, 483 insertions(+)
>>>
>>> diff --git a/include/linux/string.h b/include/linux/string.h
>>> index 7927b875f80c..3d2aff2ed402 100644
>>> --- a/include/linux/string.h
>>> +++ b/include/linux/string.h
>>> @@ -19,54 +19,117 @@ extern void *memdup_user_nul(const void __user *, size_t);
>>> */
>>> #include <asm/string.h>
>>>
>>> +#if defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__)
>>> +/*
>>> + * For files that are not instrumented (e.g. mm/slub.c) we
>>> + * should use not instrumented version of mem* functions.
>>> + */
>>> +#define memset16 __memset16
>>> +#define memset32 __memset32
>>> +#define memset64 __memset64
>>> +#define memzero_explicit __memzero_explicit
>>> +#define strcpy __strcpy
>>> +#define strncpy __strncpy
>>> +#define strlcpy __strlcpy
>>> +#define strscpy __strscpy
>>> +#define strcat __strcat
>>> +#define strncat __strncat
>>> +#define strlcat __strlcat
>>> +#define strcmp __strcmp
>>> +#define strncmp __strncmp
>>> +#define strcasecmp __strcasecmp
>>> +#define strncasecmp __strncasecmp
>>> +#define strchr __strchr
>>> +#define strchrnul __strchrnul
>>> +#define strrchr __strrchr
>>> +#define strnchr __strnchr
>>> +#define skip_spaces __skip_spaces
>>> +#define strim __strim
>>> +#define strstr __strstr
>>> +#define strnstr __strnstr
>>> +#define strlen __strlen
>>> +#define strnlen __strnlen
>>> +#define strpbrk __strpbrk
>>> +#define strsep __strsep
>>> +#define strspn __strspn
>>> +#define strcspn __strcspn
>>> +#define memscan __memscan
>>> +#define memcmp __memcmp
>>> +#define memchr __memchr
>>> +#define memchr_inv __memchr_inv
>>> +#define strreplace __strreplace
>>> +
>>> +#ifndef __NO_FORTIFY
>>> +#define __NO_FORTIFY /* FORTIFY_SOURCE uses __builtin_memcpy, etc. */
>>> +#endif
>>> +
>>> +#endif
>>> +
>>> #ifndef __HAVE_ARCH_STRCPY
>>> extern char * strcpy(char *,const char *);
>>> +char *__strcpy(char *, const char *);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRNCPY
>>> extern char * strncpy(char *,const char *, __kernel_size_t);
>>> +char *__strncpy(char *, const char *, __kernel_size_t);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRLCPY
>>> size_t strlcpy(char *, const char *, size_t);
>>> +size_t __strlcpy(char *, const char *, size_t);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRSCPY
>>> ssize_t strscpy(char *, const char *, size_t);
>>> +ssize_t __strscpy(char *, const char *, size_t);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRCAT
>>> extern char * strcat(char *, const char *);
>>> +char *__strcat(char *, const char *);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRNCAT
>>> extern char * strncat(char *, const char *, __kernel_size_t);
>>> +char *__strncat(char *, const char *, __kernel_size_t);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRLCAT
>>> extern size_t strlcat(char *, const char *, __kernel_size_t);
>>> +size_t __strlcat(char *, const char *, __kernel_size_t);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRCMP
>>> extern int strcmp(const char *,const char *);
>>> +int __strcmp(const char *, const char *);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRNCMP
>>> extern int strncmp(const char *,const char *,__kernel_size_t);
>>> +int __strncmp(const char *, const char *, __kernel_size_t);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRCASECMP
>>> extern int strcasecmp(const char *s1, const char *s2);
>>> +int __strcasecmp(const char *s1, const char *s2);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRNCASECMP
>>> extern int strncasecmp(const char *s1, const char *s2, size_t n);
>>> +int __strncasecmp(const char *s1, const char *s2, size_t n);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRCHR
>>> extern char * strchr(const char *,int);
>>> +char *__strchr(const char *, int);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRCHRNUL
>>> extern char * strchrnul(const char *,int);
>>> +char *__strchrnul(const char *, int);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRNCHR
>>> extern char * strnchr(const char *, size_t, int);
>>> +char *__strnchr(const char *, size_t, int);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRRCHR
>>> extern char * strrchr(const char *,int);
>>> +char *__strrchr(const char *, int);
>>> #endif
>>> extern char * __must_check skip_spaces(const char *);
>>> +char * __must_check __skip_spaces(const char *);
>>>
>>> extern char *strim(char *);
>>> +char *__strim(char *);
>>>
>>> static inline __must_check char *strstrip(char *str)
>>> {
>>> @@ -75,27 +138,35 @@ static inline __must_check char *strstrip(char *str)
>>>
>>> #ifndef __HAVE_ARCH_STRSTR
>>> extern char * strstr(const char *, const char *);
>>> +char *__strstr(const char *, const char *);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRNSTR
>>> extern char * strnstr(const char *, const char *, size_t);
>>> +char *__strnstr(const char *, const char *, size_t);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRLEN
>>> extern __kernel_size_t strlen(const char *);
>>> +__kernel_size_t __strlen(const char *);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRNLEN
>>> extern __kernel_size_t strnlen(const char *,__kernel_size_t);
>>> +__kernel_size_t __strnlen(const char *, __kernel_size_t);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRPBRK
>>> extern char * strpbrk(const char *,const char *);
>>> +char *__strpbrk(const char *, const char *);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRSEP
>>> extern char * strsep(char **,const char *);
>>> +char *__strsep(char **, const char *);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRSPN
>>> extern __kernel_size_t strspn(const char *,const char *);
>>> +__kernel_size_t __strspn(const char *, const char *);
>>> #endif
>>> #ifndef __HAVE_ARCH_STRCSPN
>>> extern __kernel_size_t strcspn(const char *,const char *);
>>> +__kernel_size_t __strcspn(const char *, const char *);
>>> #endif
>>>
>>> #ifndef __HAVE_ARCH_MEMSET
>>> @@ -104,14 +175,17 @@ extern void * memset(void *,int,__kernel_size_t);
>>>
>>> #ifndef __HAVE_ARCH_MEMSET16
>>> extern void *memset16(uint16_t *, uint16_t, __kernel_size_t);
>>> +void *__memset16(uint16_t *, uint16_t, __kernel_size_t);
>>> #endif
>>>
>>> #ifndef __HAVE_ARCH_MEMSET32
>>> extern void *memset32(uint32_t *, uint32_t, __kernel_size_t);
>>> +void *__memset32(uint32_t *, uint32_t, __kernel_size_t);
>>> #endif
>>>
>>> #ifndef __HAVE_ARCH_MEMSET64
>>> extern void *memset64(uint64_t *, uint64_t, __kernel_size_t);
>>> +void *__memset64(uint64_t *, uint64_t, __kernel_size_t);
>>> #endif
>>>
>>> static inline void *memset_l(unsigned long *p, unsigned long v,
>>> @@ -146,12 +220,15 @@ extern void * memmove(void *,const void *,__kernel_size_t);
>>> #endif
>>> #ifndef __HAVE_ARCH_MEMSCAN
>>> extern void * memscan(void *,int,__kernel_size_t);
>>> +void *__memscan(void *, int, __kernel_size_t);
>>> #endif
>>> #ifndef __HAVE_ARCH_MEMCMP
>>> extern int memcmp(const void *,const void *,__kernel_size_t);
>>> +int __memcmp(const void *, const void *, __kernel_size_t);
>>> #endif
>>> #ifndef __HAVE_ARCH_MEMCHR
>>> extern void * memchr(const void *,int,__kernel_size_t);
>>> +void *__memchr(const void *, int, __kernel_size_t);
>>> #endif
>>> #ifndef __HAVE_ARCH_MEMCPY_MCSAFE
>>> static inline __must_check unsigned long memcpy_mcsafe(void *dst,
>>> @@ -168,7 +245,9 @@ static inline void memcpy_flushcache(void *dst, const void *src, size_t cnt)
>>> }
>>> #endif
>>> void *memchr_inv(const void *s, int c, size_t n);
>>> +void *__memchr_inv(const void *s, int c, size_t n);
>>> char *strreplace(char *s, char old, char new);
>>> +char *__strreplace(char *s, char old, char new);
>>>
>>> extern void kfree_const(const void *x);
>>>
>>> diff --git a/lib/Makefile b/lib/Makefile
>>> index 30b9b0bfbba9..19d0237f9b9c 100644
>>> --- a/lib/Makefile
>>> +++ b/lib/Makefile
>>> @@ -18,6 +18,8 @@ KCOV_INSTRUMENT_list_debug.o := n
>>> KCOV_INSTRUMENT_debugobjects.o := n
>>> KCOV_INSTRUMENT_dynamic_debug.o := n
>>>
>>> +KASAN_SANITIZE_string.o := n
>>> +
>>> lib-y := ctype.o string.o string_sysfs.o vsprintf.o cmdline.o \
>>> rbtree.o radix-tree.o timerqueue.o xarray.o \
>>> idr.o int_sqrt.o extable.o \
>>> diff --git a/lib/string.c b/lib/string.c
>>> index f3886c5175ac..31a253201bba 100644
>>> --- a/lib/string.c
>>> +++ b/lib/string.c
>>> @@ -85,7 +85,9 @@ EXPORT_SYMBOL(strcasecmp);
>>> * @dest: Where to copy the string to
>>> * @src: Where to copy the string from
>>> */
>>> +#ifndef CONFIG_KASAN
>>> #undef strcpy
>>> +#endif
>>> char *strcpy(char *dest, const char *src)
>>> {
>>> char *tmp = dest;
>>> @@ -243,7 +245,9 @@ EXPORT_SYMBOL(strscpy);
>>> * @dest: The string to be appended to
>>> * @src: The string to append to it
>>> */
>>> +#ifndef CONFIG_KASAN
>>> #undef strcat
>>> +#endif
>>> char *strcat(char *dest, const char *src)
>>> {
>>> char *tmp = dest;
>>> @@ -319,7 +323,9 @@ EXPORT_SYMBOL(strlcat);
>>> * @cs: One string
>>> * @ct: Another string
>>> */
>>> +#ifndef CONFIG_KASAN
>>> #undef strcmp
>>> +#endif
>>> int strcmp(const char *cs, const char *ct)
>>> {
>>> unsigned char c1, c2;
>>> @@ -773,7 +779,9 @@ EXPORT_SYMBOL(memmove);
>>> * @ct: Another area of memory
>>> * @count: The size of the area.
>>> */
>>> +#ifndef CONFIG_KASAN
>>> #undef memcmp
>>> +#endif
>>> __visible int memcmp(const void *cs, const void *ct, size_t count)
>>> {
>>> const unsigned char *su1, *su2;
>>> diff --git a/mm/kasan/string.c b/mm/kasan/string.c
>>> index 083b967255a2..0db31bbbf643 100644
>>> --- a/mm/kasan/string.c
>>> +++ b/mm/kasan/string.c
>>> @@ -35,6 +35,42 @@ void *memset(void *addr, int c, size_t len)
>>> return __memset(addr, c, len);
>>> }
>>>
>>> +#undef memset16
>>> +void *memset16(uint16_t *s, uint16_t v, size_t count)
>>> +{
>>> + check_memory_region((unsigned long)s, count << 1, true, _RET_IP_);
>>> +
>>> + return __memset16(s, v, count);
>>> +}
>>> +EXPORT_SYMBOL(memset16);
>>> +
>>> +#undef memset32
>>> +void *memset32(uint32_t *s, uint32_t v, size_t count)
>>> +{
>>> + check_memory_region((unsigned long)s, count << 2, true, _RET_IP_);
>>> +
>>> + return __memset32(s, v, count);
>>> +}
>>> +EXPORT_SYMBOL(memset32);
>>> +
>>> +#undef memset64
>>> +void *memset64(uint64_t *s, uint64_t v, size_t count)
>>> +{
>>> + check_memory_region((unsigned long)s, count << 3, true, _RET_IP_);
>>> +
>>> + return __memset64(s, v, count);
>>> +}
>>> +EXPORT_SYMBOL(memset64);
>>> +
>>> +#undef memzero_explicit
>>> +void memzero_explicit(void *s, size_t count)
>>> +{
>>> + check_memory_region((unsigned long)s, count, true, _RET_IP_);
>>> +
>>> + return __memzero_explicit(s, count);
>>> +}
>>> +EXPORT_SYMBOL(memzero_explicit);
>>> +
>>> #undef memmove
>>> void *memmove(void *dest, const void *src, size_t len)
>>> {
>>> @@ -52,3 +88,361 @@ void *memcpy(void *dest, const void *src, size_t len)
>>>
>>> return __memcpy(dest, src, len);
>>> }
>>> +
>>> +#undef strcpy
>>> +char *strcpy(char *dest, const char *src)
>>> +{
>>> + size_t len = __strlen(src) + 1;
>>> +
>>> + check_memory_region((unsigned long)src, len, false, _RET_IP_);
>>> + check_memory_region((unsigned long)dest, len, true, _RET_IP_);
>>> +
>>> + return __strcpy(dest, src);
>>> +}
>>> +EXPORT_SYMBOL(strcpy);
>>> +
>>> +#undef strncpy
>>> +char *strncpy(char *dest, const char *src, size_t count)
>>> +{
>>> + size_t len = min(__strlen(src) + 1, count);
>>> +
>>> + check_memory_region((unsigned long)src, len, false, _RET_IP_);
>>> + check_memory_region((unsigned long)dest, count, true, _RET_IP_);
>>> +
>>> + return __strncpy(dest, src, count);
>>> +}
>>> +EXPORT_SYMBOL(strncpy);
>>> +
>>> +#undef strlcpy
>>> +size_t strlcpy(char *dest, const char *src, size_t size)
>>> +{
>>> + size_t len = __strlen(src) + 1;
>>> +
>>> + check_memory_region((unsigned long)src, len, false, _RET_IP_);
>>> + check_memory_region((unsigned long)dest, min(len, size), true, _RET_IP_);
>>> +
>>> + return __strlcpy(dest, src, size);
>>> +}
>>> +EXPORT_SYMBOL(strlcpy);
>>> +
>>> +#undef strscpy
>>> +ssize_t strscpy(char *dest, const char *src, size_t count)
>>> +{
>>> + int len = min(__strlen(src) + 1, count);
>>> +
>>> + check_memory_region((unsigned long)src, len, false, _RET_IP_);
>>> + check_memory_region((unsigned long)dest, len, true, _RET_IP_);
>>> +
>>> + return __strscpy(dest, src, count);
>>> +}
>>> +EXPORT_SYMBOL(strscpy);
>>> +
>>> +#undef strcat
>>> +char *strcat(char *dest, const char *src)
>>> +{
>>> + size_t slen = __strlen(src) + 1;
>>> + size_t dlen = __strlen(dest);
>>> +
>>> + check_memory_region((unsigned long)src, slen, false, _RET_IP_);
>>> + check_memory_region((unsigned long)dest, dlen, false, _RET_IP_);
>>> + check_memory_region((unsigned long)(dest + dlen), slen, true, _RET_IP_);
>>> +
>>> + return __strcat(dest, src);
>>> +}
>>> +EXPORT_SYMBOL(strcat);
>>> +
>>> +#undef strncat
>>> +char *strncat(char *dest, const char *src, size_t count)
>>> +{
>>> + size_t slen = min(__strlen(src) + 1, count);
>>> + size_t dlen = __strlen(dest);
>>> +
>>> + check_memory_region((unsigned long)src, slen, false, _RET_IP_);
>>> + check_memory_region((unsigned long)dest, dlen, false, _RET_IP_);
>>> + check_memory_region((unsigned long)(dest + dlen), slen, true, _RET_IP_);
>>> +
>>> + return __strncat(dest, src, count);
>>> +}
>>> +EXPORT_SYMBOL(strncat);
>>> +
>>> +#undef strlcat
>>> +size_t strlcat(char *dest, const char *src, size_t count)
>>> +{
>>> + size_t slen = min(__strlen(src) + 1, count);
>>> + size_t dlen = __strlen(dest);
>>> +
>>> + check_memory_region((unsigned long)src, slen, false, _RET_IP_);
>>> + check_memory_region((unsigned long)dest, dlen, false, _RET_IP_);
>>> + check_memory_region((unsigned long)(dest + dlen), slen, true, _RET_IP_);
>>> +
>>> + return __strlcat(dest, src, count);
>>> +}
>>> +EXPORT_SYMBOL(strlcat);
>>> +
>>> +#undef strcmp
>>> +int strcmp(const char *cs, const char *ct)
>>> +{
>>> + size_t len = min(__strlen(cs) + 1, __strlen(ct) + 1);
>>> +
>>> + check_memory_region((unsigned long)cs, len, false, _RET_IP_);
>>> + check_memory_region((unsigned long)ct, len, false, _RET_IP_);
>>> +
>>> + return __strcmp(cs, ct);
>>> +}
>>> +EXPORT_SYMBOL(strcmp);
>>> +
>>> +#undef strncmp
>>> +int strncmp(const char *cs, const char *ct, size_t count)
>>> +{
>>> + size_t len = min3(__strlen(cs) + 1, __strlen(ct) + 1, count);
>>> +
>>> + check_memory_region((unsigned long)cs, len, false, _RET_IP_);
>>> + check_memory_region((unsigned long)ct, len, false, _RET_IP_);
>>> +
>>> + return __strncmp(cs, ct, count);
>>> +}
>>> +EXPORT_SYMBOL(strncmp);
>>> +
>>> +#undef strcasecmp
>>> +int strcasecmp(const char *s1, const char *s2)
>>> +{
>>> + size_t len = min(__strlen(s1) + 1, __strlen(s2) + 1);
>>> +
>>> + check_memory_region((unsigned long)s1, len, false, _RET_IP_);
>>> + check_memory_region((unsigned long)s2, len, false, _RET_IP_);
>>> +
>>> + return __strcasecmp(s1, s2);
>>> +}
>>> +EXPORT_SYMBOL(strcasecmp);
>>> +
>>> +#undef strncasecmp
>>> +int strncasecmp(const char *s1, const char *s2, size_t len)
>>> +{
>>> + size_t sz = min3(__strlen(s1) + 1, __strlen(s2) + 1, len);
>>> +
>>> + check_memory_region((unsigned long)s1, sz, false, _RET_IP_);
>>> + check_memory_region((unsigned long)s2, sz, false, _RET_IP_);
>>> +
>>> + return __strncasecmp(s1, s2, len);
>>> +}
>>> +EXPORT_SYMBOL(strncasecmp);
>>> +
>>> +#undef strchr
>>> +char *strchr(const char *s, int c)
>>> +{
>>> + size_t len = __strlen(s) + 1;
>>> +
>>> + check_memory_region((unsigned long)s, len, false, _RET_IP_);
>>> +
>>> + return __strchr(s, c);
>>> +}
>>> +EXPORT_SYMBOL(strchr);
>>> +
>>> +#undef strchrnul
>>> +char *strchrnul(const char *s, int c)
>>> +{
>>> + size_t len = __strlen(s) + 1;
>>> +
>>> + check_memory_region((unsigned long)s, len, false, _RET_IP_);
>>> +
>>> + return __strchrnul(s, c);
>>> +}
>>> +EXPORT_SYMBOL(strchrnul);
>>> +
>>> +#undef strrchr
>>> +char *strrchr(const char *s, int c)
>>> +{
>>> + size_t len = __strlen(s) + 1;
>>> +
>>> + check_memory_region((unsigned long)s, len, false, _RET_IP_);
>>> +
>>> + return __strrchr(s, c);
>>> +}
>>> +EXPORT_SYMBOL(strrchr);
>>> +
>>> +#undef strnchr
>>> +char *strnchr(const char *s, size_t count, int c)
>>> +{
>>> + size_t len = __strlen(s) + 1;
>>> +
>>> + check_memory_region((unsigned long)s, len, false, _RET_IP_);
>>> +
>>> + return __strnchr(s, count, c);
>>> +}
>>> +EXPORT_SYMBOL(strnchr);
>>> +
>>> +#undef skip_spaces
>>> +char *skip_spaces(const char *str)
>>> +{
>>> + size_t len = __strlen(str) + 1;
>>> +
>>> + check_memory_region((unsigned long)str, len, false, _RET_IP_);
>>> +
>>> + return __skip_spaces(str);
>>> +}
>>> +EXPORT_SYMBOL(skip_spaces);
>>> +
>>> +#undef strim
>>> +char *strim(char *s)
>>> +{
>>> + size_t len = __strlen(s) + 1;
>>> +
>>> + check_memory_region((unsigned long)s, len, false, _RET_IP_);
>>> +
>>> + return __strim(s);
>>> +}
>>> +EXPORT_SYMBOL(strim);
>>> +
>>> +#undef strstr
>>> +char *strstr(const char *s1, const char *s2)
>>> +{
>>> + size_t l1 = __strlen(s1) + 1;
>>> + size_t l2 = __strlen(s2) + 1;
>>> +
>>> + check_memory_region((unsigned long)s1, l1, false, _RET_IP_);
>>> + check_memory_region((unsigned long)s2, l2, false, _RET_IP_);
>>> +
>>> + return __strstr(s1, s2);
>>> +}
>>> +EXPORT_SYMBOL(strstr);
>>> +
>>> +#undef strnstr
>>> +char *strnstr(const char *s1, const char *s2, size_t len)
>>> +{
>>> + size_t l1 = min(__strlen(s1) + 1, len);
>>> + size_t l2 = __strlen(s2) + 1;
>>> +
>>> + check_memory_region((unsigned long)s1, l1, false, _RET_IP_);
>>> + check_memory_region((unsigned long)s2, l2, false, _RET_IP_);
>>> +
>>> + return __strnstr(s1, s2, len);
>>> +}
>>> +EXPORT_SYMBOL(strnstr);
>>> +
>>> +#undef strlen
>>> +size_t strlen(const char *s)
>>> +{
>>> + size_t len = __strlen(s);
>>> +
>>> + check_memory_region((unsigned long)s, len + 1, false, _RET_IP_);
>>> +
>>> + return len;
>>> +}
>>> +EXPORT_SYMBOL(strlen);
>>> +
>>> +#undef strnlen
>>> +size_t strnlen(const char *s, size_t count)
>>> +{
>>> + size_t len = __strnlen(s, count);
>>> +
>>> + check_memory_region((unsigned long)s, min(len + 1, count), false, _RET_IP_);
>>> +
>>> + return len;
>>> +}
>>> +EXPORT_SYMBOL(strnlen);
>>> +
>>> +#undef strpbrk
>>> +char *strpbrk(const char *cs, const char *ct)
>>> +{
>>> + size_t ls = __strlen(cs) + 1;
>>> + size_t lt = __strlen(ct) + 1;
>>> +
>>> + check_memory_region((unsigned long)cs, ls, false, _RET_IP_);
>>> + check_memory_region((unsigned long)ct, lt, false, _RET_IP_);
>>> +
>>> + return __strpbrk(cs, ct);
>>> +}
>>> +EXPORT_SYMBOL(strpbrk);
>>> +
>>> +#undef strsep
>>> +char *strsep(char **s, const char *ct)
>>> +{
>>> + char *cs = *s;
>>> +
>>> + check_memory_region((unsigned long)s, sizeof(*s), true, _RET_IP_);
>>> +
>>> + if (cs) {
>>> + int ls = __strlen(cs) + 1;
>>> + int lt = __strlen(ct) + 1;
>>> +
>>> + check_memory_region((unsigned long)cs, ls, false, _RET_IP_);
>>> + check_memory_region((unsigned long)ct, lt, false, _RET_IP_);
>>> + }
>>> +
>>> + return __strsep(s, ct);
>>> +}
>>> +EXPORT_SYMBOL(strsep);
>>> +
>>> +#undef strspn
>>> +size_t strspn(const char *s, const char *accept)
>>> +{
>>> + size_t ls = __strlen(s) + 1;
>>> + size_t la = __strlen(accept) + 1;
>>> +
>>> + check_memory_region((unsigned long)s, ls, false, _RET_IP_);
>>> + check_memory_region((unsigned long)accept, la, false, _RET_IP_);
>>> +
>>> + return __strspn(s, accept);
>>> +}
>>> +EXPORT_SYMBOL(strspn);
>>> +
>>> +#undef strcspn
>>> +size_t strcspn(const char *s, const char *reject)
>>> +{
>>> + size_t ls = __strlen(s) + 1;
>>> + size_t lr = __strlen(reject) + 1;
>>> +
>>> + check_memory_region((unsigned long)s, ls, false, _RET_IP_);
>>> + check_memory_region((unsigned long)reject, lr, false, _RET_IP_);
>>> +
>>> + return __strcspn(s, reject);
>>> +}
>>> +EXPORT_SYMBOL(strcspn);
>>> +
>>> +#undef memscan
>>> +void *memscan(void *addr, int c, size_t size)
>>> +{
>>> + check_memory_region((unsigned long)addr, size, false, _RET_IP_);
>>> +
>>> + return __memscan(addr, c, size);
>>> +}
>>> +EXPORT_SYMBOL(memscan);
>>> +
>>> +#undef memcmp
>>> +int memcmp(const void *cs, const void *ct, size_t count)
>>> +{
>>> + check_memory_region((unsigned long)cs, count, false, _RET_IP_);
>>> + check_memory_region((unsigned long)ct, count, false, _RET_IP_);
>>> +
>>> + return __memcmp(cs, ct, count);
>>> +}
>>> +EXPORT_SYMBOL(memcmp);
>>> +
>>> +#undef memchr
>>> +void *memchr(const void *s, int c, size_t n)
>>> +{
>>> + check_memory_region((unsigned long)s, n, false, _RET_IP_);
>>> +
>>> + return __memchr(s, c, n);
>>> +}
>>> +EXPORT_SYMBOL(memchr);
>>> +
>>> +#undef memchr_inv
>>> +void *memchr_inv(const void *start, int c, size_t bytes)
>>> +{
>>> + check_memory_region((unsigned long)start, bytes, false, _RET_IP_);
>>> +
>>> + return __memchr_inv(start, c, bytes);
>>> +}
>>> +EXPORT_SYMBOL(memchr_inv);
>>> +
>>> +#undef strreplace
>>> +char *strreplace(char *s, char old, char new)
>>> +{
>>> + size_t len = __strlen(s) + 1;
>>> +
>>> + check_memory_region((unsigned long)s, len, true, _RET_IP_);
>>> +
>>> + return __strreplace(s, old, new);
>>> +}
>>> +EXPORT_SYMBOL(strreplace);
>>>
More information about the Linuxppc-dev
mailing list