xref: /openbmc/linux/mm/util.c (revision c21b37f6)
1 #include <linux/slab.h>
2 #include <linux/string.h>
3 #include <linux/module.h>
4 #include <linux/err.h>
5 #include <asm/uaccess.h>
6 
7 /**
8  * kstrdup - allocate space for and copy an existing string
9  * @s: the string to duplicate
10  * @gfp: the GFP mask used in the kmalloc() call when allocating memory
11  */
12 char *kstrdup(const char *s, gfp_t gfp)
13 {
14 	size_t len;
15 	char *buf;
16 
17 	if (!s)
18 		return NULL;
19 
20 	len = strlen(s) + 1;
21 	buf = kmalloc_track_caller(len, gfp);
22 	if (buf)
23 		memcpy(buf, s, len);
24 	return buf;
25 }
26 EXPORT_SYMBOL(kstrdup);
27 
28 /**
29  * kstrndup - allocate space for and copy an existing string
30  * @s: the string to duplicate
31  * @max: read at most @max chars from @s
32  * @gfp: the GFP mask used in the kmalloc() call when allocating memory
33  */
34 char *kstrndup(const char *s, size_t max, gfp_t gfp)
35 {
36 	size_t len;
37 	char *buf;
38 
39 	if (!s)
40 		return NULL;
41 
42 	len = strnlen(s, max);
43 	buf = kmalloc_track_caller(len+1, gfp);
44 	if (buf) {
45 		memcpy(buf, s, len);
46 		buf[len] = '\0';
47 	}
48 	return buf;
49 }
50 EXPORT_SYMBOL(kstrndup);
51 
52 /**
53  * kmemdup - duplicate region of memory
54  *
55  * @src: memory region to duplicate
56  * @len: memory region length
57  * @gfp: GFP mask to use
58  */
59 void *kmemdup(const void *src, size_t len, gfp_t gfp)
60 {
61 	void *p;
62 
63 	p = kmalloc_track_caller(len, gfp);
64 	if (p)
65 		memcpy(p, src, len);
66 	return p;
67 }
68 EXPORT_SYMBOL(kmemdup);
69 
70 /**
71  * krealloc - reallocate memory. The contents will remain unchanged.
72  * @p: object to reallocate memory for.
73  * @new_size: how many bytes of memory are required.
74  * @flags: the type of memory to allocate.
75  *
76  * The contents of the object pointed to are preserved up to the
77  * lesser of the new and old sizes.  If @p is %NULL, krealloc()
78  * behaves exactly like kmalloc().  If @size is 0 and @p is not a
79  * %NULL pointer, the object pointed to is freed.
80  */
81 void *krealloc(const void *p, size_t new_size, gfp_t flags)
82 {
83 	void *ret;
84 	size_t ks;
85 
86 	if (unlikely(!new_size)) {
87 		kfree(p);
88 		return ZERO_SIZE_PTR;
89 	}
90 
91 	ks = ksize(p);
92 	if (ks >= new_size)
93 		return (void *)p;
94 
95 	ret = kmalloc_track_caller(new_size, flags);
96 	if (ret) {
97 		memcpy(ret, p, min(new_size, ks));
98 		kfree(p);
99 	}
100 	return ret;
101 }
102 EXPORT_SYMBOL(krealloc);
103 
104 /*
105  * strndup_user - duplicate an existing string from user space
106  * @s: The string to duplicate
107  * @n: Maximum number of bytes to copy, including the trailing NUL.
108  */
109 char *strndup_user(const char __user *s, long n)
110 {
111 	char *p;
112 	long length;
113 
114 	length = strnlen_user(s, n);
115 
116 	if (!length)
117 		return ERR_PTR(-EFAULT);
118 
119 	if (length > n)
120 		return ERR_PTR(-EINVAL);
121 
122 	p = kmalloc(length, GFP_KERNEL);
123 
124 	if (!p)
125 		return ERR_PTR(-ENOMEM);
126 
127 	if (copy_from_user(p, s, length)) {
128 		kfree(p);
129 		return ERR_PTR(-EFAULT);
130 	}
131 
132 	p[length - 1] = '\0';
133 
134 	return p;
135 }
136 EXPORT_SYMBOL(strndup_user);
137