diff mbox series

mm: new primitive kvmemdup()

Message ID 20221219042126.3396-1-sunhao.th@gmail.com (mailing list archive)
State New
Headers show
Series mm: new primitive kvmemdup() | expand

Commit Message

Hao Sun Dec. 19, 2022, 4:21 a.m. UTC
Similar to kmemdup(), but support large amount of bytes with kvmalloc()
and does *not* guarantee that the result will be physically contiguous.
Use only in cases where kvmalloc() is needed and free it with kvfree().

Suggested-by: Daniel Borkmann <daniel@iogearbox.net> 
Signed-off-by: Hao Sun <sunhao.th@gmail.com>
---
This pattern has been used in several places and we're also going to
do this[1], seems reasonable to add this so that bpf and in future
others could make use of it.

[1] https://lore.kernel.org/bpf/7d274284-0fcc-061c-582e-3dfb629c6a44@iogearbox.net/T/#t
---
 include/linux/string.h |  1 +
 mm/util.c              | 24 +++++++++++++++++++++++-
 2 files changed, 24 insertions(+), 1 deletion(-)


base-commit: f9ff5644bcc04221bae56f922122f2b7f5d24d62

Comments

kernel test robot Dec. 19, 2022, 6:18 a.m. UTC | #1
Hi Hao,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on f9ff5644bcc04221bae56f922122f2b7f5d24d62]

url:    https://github.com/intel-lab-lkp/linux/commits/Hao-Sun/mm-new-primitive-kvmemdup/20221219-122348
base:   f9ff5644bcc04221bae56f922122f2b7f5d24d62
patch link:    https://lore.kernel.org/r/20221219042126.3396-1-sunhao.th%40gmail.com
patch subject: [PATCH] mm: new primitive kvmemdup()
config: sh-allmodconfig
compiler: sh4-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/29c8ee8f5f8fcd8f52aa6912bdb55f3dc135b5a0
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Hao-Sun/mm-new-primitive-kvmemdup/20221219-122348
        git checkout 29c8ee8f5f8fcd8f52aa6912bdb55f3dc135b5a0
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=sh olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=sh SHELL=/bin/bash security/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> security/apparmor/policy_unpack.c:164:14: error: conflicting types for 'kvmemdup'; have 'void *(const void *, size_t)' {aka 'void *(const void *, unsigned int)'}
     164 | static void *kvmemdup(const void *src, size_t len)
         |              ^~~~~~~~
   In file included from include/linux/bitmap.h:11,
                    from include/linux/cpumask.h:12,
                    from include/linux/smp.h:13,
                    from include/linux/lockdep.h:14,
                    from include/linux/rcupdate.h:29,
                    from include/linux/rculist.h:11,
                    from include/linux/pid.h:5,
                    from include/linux/sched.h:14,
                    from include/linux/audit.h:12,
                    from security/apparmor/include/audit.h:14,
                    from security/apparmor/policy_unpack.c:23:
   include/linux/string.h:180:14: note: previous declaration of 'kvmemdup' with type 'void *(const void *, size_t,  gfp_t)' {aka 'void *(const void *, unsigned int,  unsigned int)'}
     180 | extern void *kvmemdup(const void *src, size_t len, gfp_t gfp) __realloc_size(2);
         |              ^~~~~~~~


vim +164 security/apparmor/policy_unpack.c

736ec752d95e91 John Johansen   2010-07-29  163  
8e51f9087f4024 Matthew Garrett 2018-02-08 @164  static void *kvmemdup(const void *src, size_t len)
8e51f9087f4024 Matthew Garrett 2018-02-08  165  {
8e51f9087f4024 Matthew Garrett 2018-02-08  166  	void *p = kvmalloc(len, GFP_KERNEL);
8e51f9087f4024 Matthew Garrett 2018-02-08  167  
8e51f9087f4024 Matthew Garrett 2018-02-08  168  	if (p)
8e51f9087f4024 Matthew Garrett 2018-02-08  169  		memcpy(p, src, len);
8e51f9087f4024 Matthew Garrett 2018-02-08  170  	return p;
8e51f9087f4024 Matthew Garrett 2018-02-08  171  }
8e51f9087f4024 Matthew Garrett 2018-02-08  172
kernel test robot Dec. 19, 2022, 6:29 a.m. UTC | #2
Hi Hao,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on f9ff5644bcc04221bae56f922122f2b7f5d24d62]

url:    https://github.com/intel-lab-lkp/linux/commits/Hao-Sun/mm-new-primitive-kvmemdup/20221219-122348
base:   f9ff5644bcc04221bae56f922122f2b7f5d24d62
patch link:    https://lore.kernel.org/r/20221219042126.3396-1-sunhao.th%40gmail.com
patch subject: [PATCH] mm: new primitive kvmemdup()
config: x86_64-rhel-8.3
compiler: gcc-11 (Debian 11.3.0-8) 11.3.0
reproduce (this is a W=1 build):
        # https://github.com/intel-lab-lkp/linux/commit/29c8ee8f5f8fcd8f52aa6912bdb55f3dc135b5a0
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Hao-Sun/mm-new-primitive-kvmemdup/20221219-122348
        git checkout 29c8ee8f5f8fcd8f52aa6912bdb55f3dc135b5a0
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        make W=1 O=build_dir ARCH=x86_64 olddefconfig
        make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> security/apparmor/policy_unpack.c:164:14: error: conflicting types for 'kvmemdup'; have 'void *(const void *, size_t)' {aka 'void *(const void *, long unsigned int)'}
     164 | static void *kvmemdup(const void *src, size_t len)
         |              ^~~~~~~~
   In file included from include/linux/bitmap.h:11,
                    from include/linux/cpumask.h:12,
                    from arch/x86/include/asm/cpumask.h:5,
                    from arch/x86/include/asm/msr.h:11,
                    from arch/x86/include/asm/processor.h:23,
                    from arch/x86/include/asm/cpufeature.h:5,
                    from arch/x86/include/asm/thread_info.h:53,
                    from include/linux/thread_info.h:60,
                    from arch/x86/include/asm/preempt.h:9,
                    from include/linux/preempt.h:78,
                    from include/linux/rcupdate.h:27,
                    from include/linux/rculist.h:11,
                    from include/linux/pid.h:5,
                    from include/linux/sched.h:14,
                    from include/linux/audit.h:12,
                    from security/apparmor/include/audit.h:14,
                    from security/apparmor/policy_unpack.c:23:
   include/linux/string.h:180:14: note: previous declaration of 'kvmemdup' with type 'void *(const void *, size_t,  gfp_t)' {aka 'void *(const void *, long unsigned int,  unsigned int)'}
     180 | extern void *kvmemdup(const void *src, size_t len, gfp_t gfp) __realloc_size(2);
         |              ^~~~~~~~


vim +164 security/apparmor/policy_unpack.c

736ec752d95e91 John Johansen   2010-07-29  163  
8e51f9087f4024 Matthew Garrett 2018-02-08 @164  static void *kvmemdup(const void *src, size_t len)
8e51f9087f4024 Matthew Garrett 2018-02-08  165  {
8e51f9087f4024 Matthew Garrett 2018-02-08  166  	void *p = kvmalloc(len, GFP_KERNEL);
8e51f9087f4024 Matthew Garrett 2018-02-08  167  
8e51f9087f4024 Matthew Garrett 2018-02-08  168  	if (p)
8e51f9087f4024 Matthew Garrett 2018-02-08  169  		memcpy(p, src, len);
8e51f9087f4024 Matthew Garrett 2018-02-08  170  	return p;
8e51f9087f4024 Matthew Garrett 2018-02-08  171  }
8e51f9087f4024 Matthew Garrett 2018-02-08  172
diff mbox series

Patch

diff --git a/include/linux/string.h b/include/linux/string.h
index db28802ab0a6..c062c581a98b 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -177,6 +177,7 @@  extern char *kstrdup(const char *s, gfp_t gfp) __malloc;
 extern const char *kstrdup_const(const char *s, gfp_t gfp);
 extern char *kstrndup(const char *s, size_t len, gfp_t gfp);
 extern void *kmemdup(const void *src, size_t len, gfp_t gfp) __realloc_size(2);
+extern void *kvmemdup(const void *src, size_t len, gfp_t gfp) __realloc_size(2);
 extern char *kmemdup_nul(const char *s, size_t len, gfp_t gfp);
 
 extern char **argv_split(gfp_t gfp, const char *str, int *argcp);
diff --git a/mm/util.c b/mm/util.c
index b56c92fb910f..cec9327b27b4 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -120,7 +120,8 @@  EXPORT_SYMBOL(kstrndup);
  * @len: memory region length
  * @gfp: GFP mask to use
  *
- * Return: newly allocated copy of @src or %NULL in case of error
+ * Return: newly allocated copy of @src or %NULL in case of error,
+ * result is physically contiguous. Use kfree() to free.
  */
 void *kmemdup(const void *src, size_t len, gfp_t gfp)
 {
@@ -133,6 +134,27 @@  void *kmemdup(const void *src, size_t len, gfp_t gfp)
 }
 EXPORT_SYMBOL(kmemdup);
 
+/**
+ * kvmemdup - duplicate region of memory
+ *
+ * @src: memory region to duplicate
+ * @len: memory region length
+ * @gfp: GFP mask to use
+ *
+ * Return: newly allocated copy of @src or %NULL in case of error,
+ * result may be not physically contiguous. Use kvfree() to free.
+ */
+void *kvmemdup(const void *src, size_t len, gfp_t gfp)
+{
+	void *p;
+
+	p = kvmalloc(len, gfp);
+	if (p)
+		memcpy(p, src, len);
+	return p;
+}
+EXPORT_SYMBOL(kvmemdup);
+
 /**
  * kmemdup_nul - Create a NUL-terminated string from unterminated data
  * @s: The data to stringify