Skip to contentSkip to conversation

NoMoreModuleVmalloc - Try alloc_pages_exact before vmalloc, if fails do vmalloc

PATCH In review Lucas Tanure 2 participants 4 messages Jul 13, 2014 – Jul 17, 2014

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 NoMoreModuleVmalloc - Try alloc_pages_exact before vmalloc, if fails do vmalloc

Convert vmalloc() call to alloc_pages_exact(). If alloc_pages_exact() fails, then fall back to vmalloc(). If the address is a vmalloc address, then call vfree(), otherwise call free_pages_exact().

---
 kernel/module.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)
kernel/module.c +12 -4
index ae79ce6..50c1e77 100644
@@ -2484,6 +2484,7 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
 				  struct load_info *info)
 {
 	int err;
+	bool alloc_from_vmalloc = false;
 
 	info->len = len;
 	if (info->len < sizeof(*(info->hdr)))
@@ -2494,12 +2495,19 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
 		return err;
 
 	/* Suck in entire file: we'll want most of it. */
-	info->hdr = vmalloc(info->len);
-	if (!info->hdr)
-		return -ENOMEM;
+	info->hdr = alloc_pages_exact(info->len, GFP_KERNEL);
+	if (!info->hdr) {
+		info->hdr = vmalloc(info->len);
+		if (!info->hdr)
+			return -ENOMEM;
+		alloc_from_vmalloc = true;
+	}
 
 	if (copy_from_user(info->hdr, umod, info->len) != 0) {
-		vfree(info->hdr);
+		if(alloc_from_vmalloc)
+			vfree(info->hdr);
+		else
+			free_pages_exact(info->hdr,info->len);
 		return -EFAULT;
 	}
 
Signature · 1 line
2.0.1
#1 lore raw
Quoted 3 lines · Lucas Tanure

Convert vmalloc() call to alloc_pages_exact(). If alloc_pages_exact() fails, then fall back to vmalloc(). If the address is a vmalloc address, then call vfree(), otherwise call free_pages_exact().

Hi Lucas,

This patch is wrong.

Firstly, you didn't list a motivation for getting rid of vmalloc. But this patch doesn't make modules avoid vmalloc, it just makes the temporary copy we create avoid vmalloc.

It also doesn't avoid the vfree() on the normal path; I'm pretty sure this would crash if you tested it.

Thanks,
Rusty.

Quoted 43 lines
---
 kernel/module.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)
kernel/module.c +12 -4
index ae79ce6..50c1e77 100644
@@ -2484,6 +2484,7 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
 				  struct load_info *info)
 {
 	int err;
+	bool alloc_from_vmalloc = false;
 
 	info->len = len;
 	if (info->len < sizeof(*(info->hdr)))
@@ -2494,12 +2495,19 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
 		return err;
 
 	/* Suck in entire file: we'll want most of it. */
-	info->hdr = vmalloc(info->len);
-	if (!info->hdr)
-		return -ENOMEM;
+	info->hdr = alloc_pages_exact(info->len, GFP_KERNEL);
+	if (!info->hdr) {
+		info->hdr = vmalloc(info->len);
+		if (!info->hdr)
+			return -ENOMEM;
+		alloc_from_vmalloc = true;
+	}
 
 	if (copy_from_user(info->hdr, umod, info->len) != 0) {
-		vfree(info->hdr);
+		if(alloc_from_vmalloc)
+			vfree(info->hdr);
+		else
+			free_pages_exact(info->hdr,info->len);
 		return -EFAULT;
 	}
 
Signature · 1 line
2.0.1
#2 lore raw

Hi Russell,

I found that project
http://kernelnewbies.org/KernelProjects/NoMoreModuleVmalloc.
So I thought that doing first a alloc_pages_exact would be the goal. The kernel/module.c doesn't need this task any more, or I just did in the wrong way ?

Thanks
--
Lucas Tanure
+55 (19) 988176559

Quoted 62 lines · Rusty Russell
Quoted 3 lines · Lucas Tanure

Convert vmalloc() call to alloc_pages_exact(). If alloc_pages_exact() fails, then fall back to vmalloc(). If the address is a vmalloc address, then call vfree(), otherwise call free_pages_exact().

Hi Lucas,

This patch is wrong.

Firstly, you didn't list a motivation for getting rid of vmalloc. But this patch doesn't make modules avoid vmalloc, it just makes the temporary copy we create avoid vmalloc.

It also doesn't avoid the vfree() on the normal path; I'm pretty sure this would crash if you tested it.

Thanks,
Rusty.

Quoted 43 lines
---
 kernel/module.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)
kernel/module.c +12 -5
index ae79ce6..50c1e77 100644
@@ -2484,6 +2484,7 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
                                struct load_info *info)
 {
      int err;
+     bool alloc_from_vmalloc = false;
 
      info->len = len;
      if (info->len < sizeof(*(info->hdr)))
@@ -2494,12 +2495,19 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
              return err;
 
      /* Suck in entire file: we'll want most of it. */
-     info->hdr = vmalloc(info->len);
-     if (!info->hdr)
-             return -ENOMEM;
+     info->hdr = alloc_pages_exact(info->len, GFP_KERNEL);
+     if (!info->hdr) {
+             info->hdr = vmalloc(info->len);
+             if (!info->hdr)
+                     return -ENOMEM;
+             alloc_from_vmalloc = true;
+     }
 
      if (copy_from_user(info->hdr, umod, info->len) != 0) {
-             vfree(info->hdr);
+             if(alloc_from_vmalloc)
+                     vfree(info->hdr);
+             else
+                     free_pages_exact(info->hdr,info->len);
              return -EFAULT;
      }
 
--

2.0.1

#3 lore raw
Quoted 7 lines · Lucas Tanure

Hi Russell,

I found that project
http://kernelnewbies.org/KernelProjects/NoMoreModuleVmalloc.
So I thought that doing first a alloc_pages_exact would be the goal. The kernel/module.c doesn't need this task any more, or I just did in the wrong way ?

Hmm, that's hardly a newbie project!

arch/x86/kernel/module.c contains the module_alloc() code for x86. You'd need to repalce that, and set module_free() too.

And it's not entirely clear that replacing it with kmalloc is actually useful, since it will break CONFIG_DEBUG_SET_MODULE_RONX=y.

Cheers,
Rusty.