mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [RFC 1/2] kmemdup: introduce
@ 2006-09-09  1:35 Alexey Dobriyan
  2006-09-09  1:50 ` Andrew Morton
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Alexey Dobriyan @ 2006-09-09  1:35 UTC (permalink / raw)
  To: linux-kernel

One of idiomatic ways to duplicate a region of memory is

	dst = kmalloc(len, GFP_KERNEL);
	if (!dst)
		return -ENOMEM;
	memcpy(dst, src, len);

which is neat code except a programmer needs to write size twice. Which
sometimes leads to mistakes. If len passed to kmalloc is smaller that len
passed to memcpy, it's straight overwrite-beyond-end. If len passed to
memcpy is smaller than len passed to kmalloc, it's either a) legit
behaviour ;-), or b) cloned buffer will contain garbage in second half.

	[TODO: list of such bugs in Linux, other kernels, userspace]

If programmer is given only one place to play with lengths, I believe, such
mistakes could be avoided.

With kmemdup, the snippet above will be rewritten as:

	dst = kmemdup(src, len, GFP_KERNEL);
	if (!dst)
		return -ENOMEM;

This also leads to smaller code (kzalloc effect).

Not tested yet, this is for semantics commentary.

The plan is to
a) merge kmemdup
b) get some users (patch #2)
c) stick kmemdup conversion into -kj TODO
d) grep for memcpy and caaaarefully convert the rest. Promise to be a bastard.
----------------
e) try to get memdup(3) somehow, but I'm probably dreaming...

P.S.: No idea why kstrdup() and kzalloc() use _____________kmalloc(),
      but I followed the crowd.
---

 include/linux/string.h |    1 +
 mm/util.c              |   18 ++++++++++++++++++
 2 files changed, 19 insertions(+)

--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -99,6 +99,7 @@ extern void * memchr(const void *,int,__
 #endif
 
 extern char *kstrdup(const char *s, gfp_t gfp);
+extern void *kmemdup(const void *src, size_t len, gfp_t gfp);
 
 #ifdef __cplusplus
 }
--- a/mm/util.c
+++ b/mm/util.c
@@ -40,6 +40,24 @@ char *kstrdup(const char *s, gfp_t gfp)
 }
 EXPORT_SYMBOL(kstrdup);
 
+/**
+ * kmemdup - duplicate region of memory
+ *
+ * @src: memory region to duplicate
+ * @len: memory region length
+ * @gfp: GFP mask to use
+ */
+void *kmemdup(const void *src, size_t len, gfp_t gfp)
+{
+	void *p;
+
+	p = ____kmalloc(len, gfp);
+	if (p)
+		memcpy(p, src, len);
+	return p;
+}
+EXPORT_SYMBOL(kmemdup);
+
 /*
  * strndup_user - duplicate an existing string from user space
  *


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC 1/2] kmemdup: introduce
  2006-09-09  1:35 [RFC 1/2] kmemdup: introduce Alexey Dobriyan
@ 2006-09-09  1:50 ` Andrew Morton
  2006-09-09 22:55 ` Pekka Enberg
  2006-09-13 16:17 ` Randy.Dunlap
  2 siblings, 0 replies; 4+ messages in thread
From: Andrew Morton @ 2006-09-09  1:50 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: linux-kernel

On Sat, 9 Sep 2006 05:35:55 +0400
Alexey Dobriyan <adobriyan@gmail.com> wrote:

> P.S.: No idea why kstrdup() and kzalloc() use _____________kmalloc(),

It's all to do with slab debugging and __kmalloc_track_caller(): we want
to record the _caller_ of kstrdup() within the slab object rather than kstrdup()
itself.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC 1/2] kmemdup: introduce
  2006-09-09  1:35 [RFC 1/2] kmemdup: introduce Alexey Dobriyan
  2006-09-09  1:50 ` Andrew Morton
@ 2006-09-09 22:55 ` Pekka Enberg
  2006-09-13 16:17 ` Randy.Dunlap
  2 siblings, 0 replies; 4+ messages in thread
From: Pekka Enberg @ 2006-09-09 22:55 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: linux-kernel

On 9/9/06, Alexey Dobriyan <adobriyan@gmail.com> wrote:
> +/**
> + * kmemdup - duplicate region of memory
> + *
> + * @src: memory region to duplicate
> + * @len: memory region length
> + * @gfp: GFP mask to use
> + */
> +void *kmemdup(const void *src, size_t len, gfp_t gfp)
> +{
> +       void *p;
> +
> +       p = ____kmalloc(len, gfp);
> +       if (p)
> +               memcpy(p, src, len);
> +       return p;
> +}
> +EXPORT_SYMBOL(kmemdup);

Assuming there are enough callers that can be converted to justify
this, looks good to me.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC 1/2] kmemdup: introduce
  2006-09-09  1:35 [RFC 1/2] kmemdup: introduce Alexey Dobriyan
  2006-09-09  1:50 ` Andrew Morton
  2006-09-09 22:55 ` Pekka Enberg
@ 2006-09-13 16:17 ` Randy.Dunlap
  2 siblings, 0 replies; 4+ messages in thread
From: Randy.Dunlap @ 2006-09-13 16:17 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: linux-kernel

On Sat, 9 Sep 2006 05:35:55 +0400 Alexey Dobriyan wrote:

> Not tested yet, this is for semantics commentary.
> 
>  include/linux/string.h |    1 +
>  mm/util.c              |   18 ++++++++++++++++++
>  2 files changed, 19 insertions(+)
> 
> --- a/mm/util.c
> +++ b/mm/util.c
> @@ -40,6 +40,24 @@ char *kstrdup(const char *s, gfp_t gfp)
>  }
>  EXPORT_SYMBOL(kstrdup);
>  
> +/**
> + * kmemdup - duplicate region of memory
> + *

No blank line here, please.  kernel-doc "language" doesn't allow
that.  Hopefully that will be fixed someday.

> + * @src: memory region to duplicate
> + * @len: memory region length
> + * @gfp: GFP mask to use
> + */
> +void *kmemdup(const void *src, size_t len, gfp_t gfp)
> +{
> +	void *p;
> +
> +	p = ____kmalloc(len, gfp);
> +	if (p)
> +		memcpy(p, src, len);
> +	return p;
> +}
> +EXPORT_SYMBOL(kmemdup);

---
~Randy

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2006-09-13 16:16 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-09-09  1:35 [RFC 1/2] kmemdup: introduce Alexey Dobriyan
2006-09-09  1:50 ` Andrew Morton
2006-09-09 22:55 ` Pekka Enberg
2006-09-13 16:17 ` Randy.Dunlap

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®