|
@@ -12,10 +12,30 @@
|
|
|
#include <linux/hugetlb.h>
|
|
|
#include <linux/vmalloc.h>
|
|
|
|
|
|
+#include <asm/sections.h>
|
|
|
#include <asm/uaccess.h>
|
|
|
|
|
|
#include "internal.h"
|
|
|
|
|
|
+static inline int is_kernel_rodata(unsigned long addr)
|
|
|
+{
|
|
|
+ return addr >= (unsigned long)__start_rodata &&
|
|
|
+ addr < (unsigned long)__end_rodata;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * kfree_const - conditionally free memory
|
|
|
+ * @x: pointer to the memory
|
|
|
+ *
|
|
|
+ * Function calls kfree only if @x is not in .rodata section.
|
|
|
+ */
|
|
|
+void kfree_const(const void *x)
|
|
|
+{
|
|
|
+ if (!is_kernel_rodata((unsigned long)x))
|
|
|
+ kfree(x);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(kfree_const);
|
|
|
+
|
|
|
/**
|
|
|
* kstrdup - allocate space for and copy an existing string
|
|
|
* @s: the string to duplicate
|
|
@@ -37,6 +57,24 @@ char *kstrdup(const char *s, gfp_t gfp)
|
|
|
}
|
|
|
EXPORT_SYMBOL(kstrdup);
|
|
|
|
|
|
+/**
|
|
|
+ * kstrdup_const - conditionally duplicate an existing const string
|
|
|
+ * @s: the string to duplicate
|
|
|
+ * @gfp: the GFP mask used in the kmalloc() call when allocating memory
|
|
|
+ *
|
|
|
+ * Function returns source string if it is in .rodata section otherwise it
|
|
|
+ * fallbacks to kstrdup.
|
|
|
+ * Strings allocated by kstrdup_const should be freed by kfree_const.
|
|
|
+ */
|
|
|
+const char *kstrdup_const(const char *s, gfp_t gfp)
|
|
|
+{
|
|
|
+ if (is_kernel_rodata((unsigned long)s))
|
|
|
+ return s;
|
|
|
+
|
|
|
+ return kstrdup(s, gfp);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(kstrdup_const);
|
|
|
+
|
|
|
/**
|
|
|
* kstrndup - allocate space for and copy an existing string
|
|
|
* @s: the string to duplicate
|