Re: [RFC PATCH v2 3/3] kasan: add interceptors for all string functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





Le 02/04/2019 à 14:58, Dmitry Vyukov a écrit :
On Tue, Apr 2, 2019 at 11:43 AM Christophe Leroy
<christophe.leroy@xxxxxx> 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@xxxxxx>
---
   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);





[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux