From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.1 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_PASS,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 20F44C10F0B for ; Tue, 2 Apr 2019 14:57:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CD50D204EC for ; Tue, 2 Apr 2019 14:57:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=c-s.fr header.i=@c-s.fr header.b="e+ZqMlJO" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732230AbfDBO5z (ORCPT ); Tue, 2 Apr 2019 10:57:55 -0400 Received: from pegase1.c-s.fr ([93.17.236.30]:55303 "EHLO pegase1.c-s.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726337AbfDBO5z (ORCPT ); Tue, 2 Apr 2019 10:57:55 -0400 Received: from localhost (mailhub1-int [192.168.12.234]) by localhost (Postfix) with ESMTP id 44YXPp33s4z9tytF; Tue, 2 Apr 2019 16:57:50 +0200 (CEST) Authentication-Results: localhost; dkim=pass reason="1024-bit key; insecure key" header.d=c-s.fr header.i=@c-s.fr header.b=e+ZqMlJO; dkim-adsp=pass; dkim-atps=neutral X-Virus-Scanned: Debian amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [192.168.12.234]) (amavisd-new, port 10024) with ESMTP id ed2igWe31gvZ; Tue, 2 Apr 2019 16:57:50 +0200 (CEST) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 44YXPp1njFz9tytC; Tue, 2 Apr 2019 16:57:50 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=c-s.fr; s=mail; t=1554217070; bh=CM9HCFvK0RJH9Ha0RMH2NwK6R4phldsAq8ZUmReVzRs=; h=Subject:To:Cc:References:From:Date:In-Reply-To:From; b=e+ZqMlJOslM6TeygxiVpApst2Dfi/3iZSbag4AXG660B42aZTiGEDdzhcDqtoBYWt BCOtemTW0xvc+Sv5SxiFZuF8Ersmrt7RlertVZOfBiMxmJZ4Kx4i34O68n9a9yRwAN 3WxULSKjSaOLGbOiWWJamlpFBwIaGC34LKzOFM/A= Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id C198F8B8CF; Tue, 2 Apr 2019 16:57:51 +0200 (CEST) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id VVU33_ySrRje; Tue, 2 Apr 2019 16:57:51 +0200 (CEST) Received: from PO15451 (unknown [192.168.4.90]) by messagerie.si.c-s.fr (Postfix) with ESMTP id E3C358B8CD; Tue, 2 Apr 2019 16:57:50 +0200 (CEST) Subject: Re: [RFC PATCH v2 3/3] kasan: add interceptors for all string functions To: Dmitry Vyukov Cc: Benjamin Herrenschmidt , Paul Mackerras , Michael Ellerman , Nicholas Piggin , "Aneesh Kumar K.V" , Andrey Ryabinin , Alexander Potapenko , Daniel Axtens , Linux-MM , linuxppc-dev@lists.ozlabs.org, LKML , kasan-dev References: <51a6d9d7185de310f37ccbd7e4ebfdd6c7e9791f.1553785020.git.christophe.leroy@c-s.fr> <3211b0f8-7b52-01b7-8208-65d746969248@c-s.fr> From: Christophe Leroy Message-ID: <1f24d2ff-ea36-e3f9-113f-69dfff293c3d@c-s.fr> Date: Tue, 2 Apr 2019 16:57:50 +0200 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: fr Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Le 02/04/2019 à 14:58, Dmitry Vyukov a écrit : > On Tue, Apr 2, 2019 at 11:43 AM Christophe Leroy > 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 >>> --- >>> 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 >>> >>> +#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); >>>