xref: /openbmc/linux/mm/util.c (revision f42b3800)
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 = 0;
85 
86 	if (unlikely(!new_size)) {
87 		kfree(p);
88 		return ZERO_SIZE_PTR;
89 	}
90 
91 	if (p)
92 		ks = ksize(p);
93 
94 	if (ks >= new_size)
95 		return (void *)p;
96 
97 	ret = kmalloc_track_caller(new_size, flags);
98 	if (ret && p) {
99 		memcpy(ret, p, ks);
100 		kfree(p);
101 	}
102 	return ret;
103 }
104 EXPORT_SYMBOL(krealloc);
105 
106 /*
107  * strndup_user - duplicate an existing string from user space
108  * @s: The string to duplicate
109  * @n: Maximum number of bytes to copy, including the trailing NUL.
110  */
111 char *strndup_user(const char __user *s, long n)
112 {
113 	char *p;
114 	long length;
115 
116 	length = strnlen_user(s, n);
117 
118 	if (!length)
119 		return ERR_PTR(-EFAULT);
120 
121 	if (length > n)
122 		return ERR_PTR(-EINVAL);
123 
124 	p = kmalloc(length, GFP_KERNEL);
125 
126 	if (!p)
127 		return ERR_PTR(-ENOMEM);
128 
129 	if (copy_from_user(p, s, length)) {
130 		kfree(p);
131 		return ERR_PTR(-EFAULT);
132 	}
133 
134 	p[length - 1] = '\0';
135 
136 	return p;
137 }
138 EXPORT_SYMBOL(strndup_user);
139