Skip to contentSkip to conversation

Stack size protection broken on ppc64

PATCH In review Michael Neuling 7 participants 31 messages Feb 6, 2010 – Feb 12, 2010

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

On recent ppc64 kernels, limiting the stack (using 'ulimit -s blah') is now more restrictive than it was before. On 2.6.31 with 4k pages I could run 'ulimit -s 16; /usr/bin/test' without a problem. Now with mainline, even 'ulimit -s 64; /usr/bin/test' gets killed.

Using 64k pages is even worse. I can't even run '/bin/ls' with a 1MB stack (ulimit -s 1024; /bin/ls). Hence, it seems new kernels are too restrictive, rather than the old kernels being too liberal.

I've not tested with any other architectures.

Bisecting, I found that this is the culprit (which is in 2.6.32)

commit fc63cf237078c86214abcb2ee9926d8ad289da9b
Author: Anton Blanchard <[email protected]>
exec: setup_arg_pages() fails to return errors

Looking at the patch, it's probably just unmasking a preexisting issue. The error path for expand_stack() (and others) was modified to:
---

	ret = expand_stack(vma, stack_base);
	if (ret)
		ret = -EFAULT;

out_unlock:

	up_write(&mm->mmap_sem);

- return 0;
+ return ret;
}
EXPORT_SYMBOL(setup_arg_pages);
---

So previously expand_stack errors were not returned correctly by setup_arg_pages, but now they are.

Any clues how to fix this?

Mikey

#1 lore raw

Hi,

Quoted 8 lines

On recent ppc64 kernels, limiting the stack (using 'ulimit -s blah') is now more restrictive than it was before. On 2.6.31 with 4k pages I could run 'ulimit -s 16; /usr/bin/test' without a problem. Now with mainline, even 'ulimit -s 64; /usr/bin/test' gets killed.

Using 64k pages is even worse. I can't even run '/bin/ls' with a 1MB stack (ulimit -s 1024; /bin/ls). Hence, it seems new kernels are too restrictive, rather than the old kernels being too liberal.

It looks like this is causing it:

#define EXTRA_STACK_VM_PAGES 20 /* random */

...

#ifdef CONFIG_STACK_GROWSUP
        stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
#else
        stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;

#endif

Which got added back in 2005 in a memory overcommit patch. It only took 5 years for us to go back and review that random setting :)

The comment from Andries explains the purpose:

(1) It reserves a reasonable amount of virtual stack space (amount randomly chosen, no guarantees given) when the process is started, so that the common utilities will not be killed by segfault on stack extension.

This explains why 64kB is much worse. The extra stack reserve should be in kB and we also need to be careful not to ask for more than our rlimit.

Anton

#2 lore raw
Quoted 26 lines
Quoted 8 lines

On recent ppc64 kernels, limiting the stack (using 'ulimit -s blah') is now more restrictive than it was before. On 2.6.31 with 4k pages I could run 'ulimit -s 16; /usr/bin/test' without a problem. Now with mainline, even 'ulimit -s 64; /usr/bin/test' gets killed.

Using 64k pages is even worse. I can't even run '/bin/ls' with a 1MB stack (ulimit -s 1024; /bin/ls). Hence, it seems new kernels are too restrictive, rather than the old kernels being too liberal.

It looks like this is causing it:

#define EXTRA_STACK_VM_PAGES 20 /* random */

...

#ifdef CONFIG_STACK_GROWSUP
        stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
#else
        stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;

#endif

Which got added back in 2005 in a memory overcommit patch. It only took 5 years for us to go back and review that random setting :)

The comment from Andries explains the purpose:

Quoted 7 lines

(1) It reserves a reasonable amount of virtual stack space (amount randomly chosen, no guarantees given) when the process is started, so that the common utilities will not be killed by segfault on stack extension.

This explains why 64kB is much worse. The extra stack reserve should be in kB and we also need to be careful not to ask for more than our rlimit.

Cool, thanks. The following is based on this and fixes the problem for me on PPC64 ie. the !CONFIG_STACK_GROWSUP case.

Mikey

[PATCH] Restrict stack space reservation to rlimit

When reserving stack space for a new process, make sure we're not attempting to allocate more than rlimit allows.

Also, reserve the same stack size independent of page size.

This fixes a bug unmasked by fc63cf237078c86214abcb2ee9926d8ad289da9b

---
 fs/exec.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
fs/exec.c +6 -3
Index: clone1/fs/exec.c
===================================================================
@@ -554,7 +554,7 @@ static int shift_arg_pages(struct vm_are
 	return 0;
 }
 
-#define EXTRA_STACK_VM_PAGES	20	/* random */
+#define EXTRA_STACK_VM_SIZE	81920UL	/* randomly 20 4K pages */
 
 /*
  * Finalizes the stack vm_area_struct. The flags and permissions are updated,
@@ -627,10 +627,13 @@ int setup_arg_pages(struct linux_binprm 
 			goto out_unlock;
 	}
 
+	stack_base = min(EXTRA_STACK_VM_SIZE,
+			 current->signal->rlim[RLIMIT_STACK].rlim_cur) -
+		PAGE_SIZE;
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_end + stack_base;
 #else
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_start - stack_base;
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)
#3 lore raw

Hi,

Quoted 2 lines

Cool, thanks. The following is based on this and fixes the problem for me on PPC64 ie. the !CONFIG_STACK_GROWSUP case.

Thanks! Seeing the original setting of EXTRA_STACK_VM_PAGES is more or less random, I wonder if we should round EXTRA_STACK_VM_SIZE up to 128kB (or even down to 64kB) so it operates better with > 4kB pages.

But in the end its probably of little use for the default OVERCOMMIT_GUESS setting, so the main thing is we dont terminate processes incorrectly.

Anton

#4 lore raw

PATCH 1/1 Restrict stack space reservation to rlimit

In reply to Michael Neuling

apkm, linus: this or something like it needs to go into 2.6.33 (& 32) to fix 'ulimit -s'.

Mikey

[PATCH] Restrict stack space reservation to rlimit

When reserving stack space for a new process, make sure we're not attempting to allocate more than rlimit allows.

Also, reserve the same stack size independent of page size.

This fixes a bug unmasked by fc63cf237078c86214abcb2ee9926d8ad289da9b

---
 fs/exec.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
fs/exec.c +6 -3
Index: clone1/fs/exec.c
===================================================================
@@ -554,7 +554,7 @@ static int shift_arg_pages(struct vm_are
 	return 0;
 }
 
-#define EXTRA_STACK_VM_PAGES	20	/* random */
+#define EXTRA_STACK_VM_SIZE	81920UL	/* randomly 20 4K pages */
 
 /*
  * Finalizes the stack vm_area_struct. The flags and permissions are updated,
@@ -627,10 +627,13 @@ int setup_arg_pages(struct linux_binprm 
 			goto out_unlock;
 	}
 
+	stack_base = min(EXTRA_STACK_VM_SIZE,
+			 current->signal->rlim[RLIMIT_STACK].rlim_cur) -
+		PAGE_SIZE;
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_end + stack_base;
 #else
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_start - stack_base;
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)
#5 lore raw

PATCH 1/1 Restrict stack space reservation to rlimit

When reserving stack space for a new process, make sure we're not attempting to allocate more than rlimit allows.

Also, reserve the same stack size independent of page size.

This fixes a bug cause by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba "mm: variable length argument support" and unmasked by fc63cf237078c86214abcb2ee9926d8ad289da9b
"exec: setup_arg_pages() fails to return errors".

---
Update commit message to include patch name and SHA1 of related patches.

 fs/exec.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
fs/exec.c +6 -3
Index: clone1/fs/exec.c
===================================================================
@@ -554,7 +554,7 @@ static int shift_arg_pages(struct vm_are
 	return 0;
 }
 
-#define EXTRA_STACK_VM_PAGES	20	/* random */
+#define EXTRA_STACK_VM_SIZE	81920UL	/* randomly 20 4K pages */
 
 /*
  * Finalizes the stack vm_area_struct. The flags and permissions are updated,
@@ -627,10 +627,13 @@ int setup_arg_pages(struct linux_binprm 
 			goto out_unlock;
 	}
 
+	stack_base = min(EXTRA_STACK_VM_SIZE,
+			 current->signal->rlim[RLIMIT_STACK].rlim_cur) -
+		PAGE_SIZE;
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_end + stack_base;
 #else
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_start - stack_base;
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)
#6 lore raw

Re: [PATCH] Restrict stack space reservation to rlimit

In reply to Michael Neuling

Hi

Quoted 2 lines

apkm, linus: this or something like it needs to go into 2.6.33 (& 32) to fix 'ulimit -s'.

"fix ulimit -s" is too cool explanation ;-)
we are not ESPer. please consider to provide what bug is exist.

Quoted 8 lines

Mikey

[PATCH] Restrict stack space reservation to rlimit

When reserving stack space for a new process, make sure we're not attempting to allocate more than rlimit allows.

Also, reserve the same stack size independent of page size.

Why do we need page size independent stack size? It seems to have compatibility breaking risk.

Quoted 43 lines

This fixes a bug unmasked by fc63cf237078c86214abcb2ee9926d8ad289da9b

---
 fs/exec.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

Index: clone1/fs/exec.c
===================================================================

fs/exec.c +6 -4
@@ -554,7 +554,7 @@ static int shift_arg_pages(struct vm_are
 	return 0;
 }
 
-#define EXTRA_STACK_VM_PAGES	20	/* random */
+#define EXTRA_STACK_VM_SIZE	81920UL	/* randomly 20 4K pages */
 
 /*
  * Finalizes the stack vm_area_struct. The flags and permissions are updated,
@@ -627,10 +627,13 @@ int setup_arg_pages(struct linux_binprm 
 			goto out_unlock;
 	}
 
+	stack_base = min(EXTRA_STACK_VM_SIZE,
+			 current->signal->rlim[RLIMIT_STACK].rlim_cur) -
+		PAGE_SIZE;
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_end + stack_base;
 #else
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_start - stack_base;
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)
--

To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#7 lore raw

Re: [PATCH] Restrict stack space reservation to rlimit

Hi,

Quoted 2 lines

Why do we need page size independent stack size? It seems to have compatibility breaking risk.

I don't think so. The current behaviour is clearly wrong, we dont need a 16x larger stack just because you went from a 4kB to a 64kB base page size. The user application stack usage is the same in both cases.

Anton

#8 lore raw

Re: [PATCH] Restrict stack space reservation to rlimit

Quoted 9 lines

Hi,

Quoted 2 lines

Why do we need page size independent stack size? It seems to have compatibility breaking risk.

I don't think so. The current behaviour is clearly wrong, we dont need a 16x larger stack just because you went from a 4kB to a 64kB base page size. The user application stack usage is the same in both cases.

I didn't discuss which behavior is better. Michael said he want to apply his patch to 2.6.32 & 2.6.33. stable tree never accept the breaking compatibility patch.

Your answer doesn't explain why can't we wait it until next merge window.

btw, personally, I like page size indepent stack size. but I'm not sure why making stack size independency is related to bug fix.

#9 lore raw

Re: [PATCH] Restrict stack space reservation to rlimit

Hi,

Quoted 9 lines

I didn't discuss which behavior is better. Michael said he want to apply his patch to 2.6.32 & 2.6.33. stable tree never accept the breaking compatibility patch.

Your answer doesn't explain why can't we wait it until next merge window.

btw, personally, I like page size indepent stack size. but I'm not sure why making stack size independency is related to bug fix.

OK sorry, I misunderstood your initial mail. I agree fixing the bit that regressed in 2.6.32 is the most important thing. The difference in page size is clearly wrong but since it isn't a regression we could probably live with it until 2.6.34

Anton

#10 lore raw

Re: [PATCH] Restrict stack space reservation to rlimit

Quoted 10 lines

Hi,

Quoted 7 lines

I didn't discuss which behavior is better. Michael said he want to apply his patch to 2.6.32 & 2.6.33. stable tree never accept the breaking compatibility patch.

Your answer doesn't explain why can't we wait it until next merge window.

Quoted 7 lines
Quoted 2 lines

btw, personally, I like page size indepent stack size. but I'm not sure why making stack size independency is related to bug fix.

OK sorry, I misunderstood your initial mail. I agree fixing the bit that regressed in 2.6.32 is the most important thing. The difference in page size is clearly wrong but since it isn't a regression we could probably live with it until 2.6.34

thanks!

#11 lore raw

PATCH 1/1 Restrict stack space reservation to rlimit

In reply to KOSAKI Motohiro
Quoted 10 lines
Quoted 9 lines

Hi,

Quoted 2 lines

Why do we need page size independent stack size? It seems to have compatibility breaking risk.

I don't think so. The current behaviour is clearly wrong, we dont need a 16x larger stack just because you went from a 4kB to a 64kB base page size. The user application stack usage is the same in both cases.

Quoted 8 lines

I didn't discuss which behavior is better. Michael said he want to apply his patch to 2.6.32 & 2.6.33. stable tree never accept the breaking compatibility patch.

Your answer doesn't explain why can't we wait it until next merge window.

btw, personally, I like page size indepent stack size. but I'm not sure why making stack size independency is related to bug fix.

I tend to agree.

Below is just the bug fix to limit the reservation size based rlimit. We still reserve different stack sizes based on the page size as before (unless we hit rlimit of course).

Mikey

Restrict stack space reservation to rlimit

When reserving stack space for a new process, make sure we're not attempting to allocate more than rlimit allows.

This fixes a bug cause by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba "mm: variable length argument support" and unmasked by fc63cf237078c86214abcb2ee9926d8ad289da9b
"exec: setup_arg_pages() fails to return errors".

---
 fs/exec.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
fs/exec.c +5 -2
Index: linux-2.6-ozlabs/fs/exec.c
===================================================================
@@ -627,10 +627,13 @@ int setup_arg_pages(struct linux_binprm 
 			goto out_unlock;
 	}
 
+	stack_base = min(EXTRA_STACK_VM_PAGES * PAGE_SIZE,
+			 current->signal->rlim[RLIMIT_STACK].rlim_cur -
+			   PAGE_SIZE);
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_end + stack_base;
 #else
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_start - stack_base;
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)
#12 lore raw

Re: [PATCH] Restrict stack space reservation to rlimit

Quoted 16 lines
Quoted 16 lines
Quoted 9 lines

Hi,

Quoted 2 lines

Why do we need page size independent stack size? It seems to have compatibility breaking risk.

I don't think so. The current behaviour is clearly wrong, we dont need a 16x larger stack just because you went from a 4kB to a 64kB base page size. The user application stack usage is the same in both cases.

I didn't discuss which behavior is better. Michael said he want to apply his patch to 2.6.32 & 2.6.33. stable tree never accept the breaking compatibility patch.

Your answer doesn't explain why can't we wait it until next merge window.

Quoted 8 lines
Quoted 2 lines

btw, personally, I like page size indepent stack size. but I'm not sure why making stack size independency is related to bug fix.

I tend to agree.

Below is just the bug fix to limit the reservation size based rlimit. We still reserve different stack sizes based on the page size as before (unless we hit rlimit of course).

Thanks.

I agree your patch in almost part. but I have very few requests.

Quoted 11 lines

Mikey

Restrict stack space reservation to rlimit

When reserving stack space for a new process, make sure we're not attempting to allocate more than rlimit allows.

This fixes a bug cause by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba "mm: variable length argument support" and unmasked by fc63cf237078c86214abcb2ee9926d8ad289da9b
"exec: setup_arg_pages() fails to return errors".

Your initial mail have following problem use-case. please append it into the patch description.

On recent ppc64 kernels, limiting the stack (using 'ulimit -s blah') is now more restrictive than it was before. On 2.6.31 with 4k pages I could run 'ulimit -s 16; /usr/bin/test' without a problem. Now with mainline, even 'ulimit -s 64; /usr/bin/test' gets killed.

Quoted 13 lines
---
 fs/exec.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

Index: linux-2.6-ozlabs/fs/exec.c
===================================================================

fs/exec.c int setup_arg_pages(struct linux_binprm · line 632

Quoted 6 lines
fs/exec.c +3 -0
@@ -627,10 +627,13 @@ int setup_arg_pages(struct linux_binprm 
 			goto out_unlock;
 	}
 
+	stack_base = min(EXTRA_STACK_VM_PAGES * PAGE_SIZE,
+			 current->signal->rlim[RLIMIT_STACK].rlim_cur -
+			   PAGE_SIZE);

This line is a bit unclear why "- PAGE_SIZE" is necessary. personally, I like following likes explicit comments.

	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
	stack_lim = ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur);

	/* Initial stack must not cause stack overflow. */
	if (stack_expand + PAGE_SIZE > stack_lim)
		stack_expand = stack_lim - PAGE_SIZE;

note: accessing rlim_cur require ACCESS_ONCE.

Thought?

Quoted 10 lines
fs/exec.c +2 -2
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_end + stack_base;
 #else
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_start - stack_base;
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)
#13 lore raw

Re: [PATCH] Restrict stack space reservation to rlimit

Quoted 16 lines · KOSAKI Motohiro

fs/exec.c int setup_arg_pages(struct linux_binprm · line 632

Quoted 9 lines
fs/exec.c +3 -0
@@ -627,10 +627,13 @@ int setup_arg_pages(struct linux_binprm
                       goto out_unlock;
       }
 
+     stack_base = min(EXTRA_STACK_VM_PAGES * PAGE_SIZE,
+                      current->signal->rlim[RLIMIT_STACK].rlim_cur -
+                        PAGE_SIZE);

This line is a bit unclear why "- PAGE_SIZE" is necessary. personally, I like following likes explicit comments.

       stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE; stack_lim = ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur);

Quoted 8 lines

       /* Initial stack must not cause stack overflow. */ if (stack_expand + PAGE_SIZE > stack_lim) stack_expand = stack_lim - PAGE_SIZE;

note: accessing rlim_cur require ACCESS_ONCE.

Thought?

It's better to use the helper function: rlimit().
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#14 lore raw

Re: [PATCH] Restrict stack space reservation to rlimit

Quoted 22 lines
Quoted 20 lines · KOSAKI Motohiro

fs/exec.c int setup_arg_pages(struct linux_binprm · line 632

Quoted 9 lines
fs/exec.c +3 -0
@@ -627,10 +627,13 @@ int setup_arg_pages(struct linux_binprm
                       goto out_unlock;
       }
 
+     stack_base = min(EXTRA_STACK_VM_PAGES * PAGE_SIZE,
+                      current->signal->rlim[RLIMIT_STACK].rlim_cur -
+                        PAGE_SIZE);

This line is a bit unclear why "- PAGE_SIZE" is necessary. personally, I like following likes explicit comments.

       stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE; stack_lim = ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur);

       /* Initial stack must not cause stack overflow. */ if (stack_expand + PAGE_SIZE > stack_lim) stack_expand = stack_lim - PAGE_SIZE;

Quoted 6 lines
Quoted 4 lines

note: accessing rlim_cur require ACCESS_ONCE.

Thought?

It's better to use the helper function: rlimit().

AFAIK, stable tree doesn't have rlimit(). but yes, making two patch (for mainline and for stable) is good opinion.

#15 lore raw

PATCH 1/1 Restrict initial stack space expansion to rlimit

When reserving stack space for a new process, make sure we're not attempting to expand the stack by more than rlimit allows.

This fixes a bug caused by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba "mm:
variable length argument support" and unmasked by fc63cf237078c86214abcb2ee9926d8ad289da9b "exec: setup_arg_pages() fails to return errors". This bug means when limiting the stack to less the 20*PAGE_SIZE (eg. 80K on 4K pages or 'ulimit -s 79') all processes will be killed before they start. This is particularly bad with 64K pages, where a ulimit below 1280K will kill every process.

---
Attempts to answer comments from Kosaki Motohiro.

Tested on PPC only, hence !CONFIG_STACK_GROWSUP. Someone should probably ACK for an arch with CONFIG_STACK_GROWSUP.

As noted, stable needs the same patch, but 2.6.32 doesn't have the rlimit() helper.

 fs/exec.c |   21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)
fs/exec.c +18 -3
Index: linux-2.6-ozlabs/fs/exec.c
===================================================================
@@ -555,6 +555,7 @@ static int shift_arg_pages(struct vm_are
 }
 
 #define EXTRA_STACK_VM_PAGES	20	/* random */
+#define ALIGN_DOWN(addr,size)	((addr)&(~((size)-1)))
 
 /*
  * Finalizes the stack vm_area_struct. The flags and permissions are updated,
@@ -570,7 +571,7 @@ int setup_arg_pages(struct linux_binprm 
 	struct vm_area_struct *vma = bprm->vma;
 	struct vm_area_struct *prev = NULL;
 	unsigned long vm_flags;
-	unsigned long stack_base;
+	unsigned long stack_base, stack_expand, stack_expand_lim, stack_size;
 
 #ifdef CONFIG_STACK_GROWSUP
 	/* Limit stack size to 1GB */
@@ -627,10 +628,24 @@ int setup_arg_pages(struct linux_binprm 
 			goto out_unlock;
 	}
 
+	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_size = vma->vm_end - vma->vm_start;
+	if (rlimit(RLIMIT_STACK) < stack_size)
+		stack_expand_lim = 0; /* don't shrick the stack */
+	else
+		/*
+		 * Align this down to a page boundary as expand_stack
+		 * will align it up.
+		 */
+		stack_expand_lim = ALIGN_DOWN(rlimit(RLIMIT_STACK) - stack_size,
+					      PAGE_SIZE);
+	/* Initial stack must not cause stack overflow. */
+	if (stack_expand > stack_expand_lim)
+		stack_expand = stack_expand_lim;
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_end + stack_expand;
 #else
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_start - stack_expand;
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)
#16 lore raw

Re: [PATCH] Restrict initial stack space expansion to rlimit

Quoted 63 lines

When reserving stack space for a new process, make sure we're not attempting to expand the stack by more than rlimit allows.

This fixes a bug caused by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba "mm:
variable length argument support" and unmasked by fc63cf237078c86214abcb2ee9926d8ad289da9b "exec: setup_arg_pages() fails to return errors". This bug means when limiting the stack to less the 20*PAGE_SIZE (eg. 80K on 4K pages or 'ulimit -s 79') all processes will be killed before they start. This is particularly bad with 64K pages, where a ulimit below 1280K will kill every process.

---
Attempts to answer comments from Kosaki Motohiro.

Tested on PPC only, hence !CONFIG_STACK_GROWSUP. Someone should probably ACK for an arch with CONFIG_STACK_GROWSUP.

As noted, stable needs the same patch, but 2.6.32 doesn't have the rlimit() helper.

 fs/exec.c |   21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

Index: linux-2.6-ozlabs/fs/exec.c
===================================================================

fs/exec.c +15 -1
@@ -555,6 +555,7 @@ static int shift_arg_pages(struct vm_are
 }
 
 #define EXTRA_STACK_VM_PAGES	20	/* random */
+#define ALIGN_DOWN(addr,size)	((addr)&(~((size)-1)))
 
 /*
  * Finalizes the stack vm_area_struct. The flags and permissions are updated,
@@ -570,7 +571,7 @@ int setup_arg_pages(struct linux_binprm 
 	struct vm_area_struct *vma = bprm->vma;
 	struct vm_area_struct *prev = NULL;
 	unsigned long vm_flags;
-	unsigned long stack_base;
+	unsigned long stack_base, stack_expand, stack_expand_lim, stack_size;
 
 #ifdef CONFIG_STACK_GROWSUP
 	/* Limit stack size to 1GB */
@@ -627,10 +628,24 @@ int setup_arg_pages(struct linux_binprm 
 			goto out_unlock;
 	}
 
+	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_size = vma->vm_end - vma->vm_start;
+	if (rlimit(RLIMIT_STACK) < stack_size)
+		stack_expand_lim = 0; /* don't shrick the stack */
+	else
+		/*
+		 * Align this down to a page boundary as expand_stack
+		 * will align it up.
+		 */
+		stack_expand_lim = ALIGN_DOWN(rlimit(RLIMIT_STACK) - stack_size,
+					      PAGE_SIZE);
+	/* Initial stack must not cause stack overflow. */
+	if (stack_expand > stack_expand_lim)

fs/exec.c int setup_arg_pages(struct linux_binprm · line 651

Quoted 10 lines
fs/exec.c +3 -2
+		stack_expand = stack_expand_lim;
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_end + stack_expand;
 #else
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_start - stack_expand;
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)

Umm.. It looks correct. but the nested complex if statement seems a bit ugly. Instead, How about following?

note: it's untested.

===============
From: Michael Neuling <[email protected]>
Subject: Restrict initial stack space expansion to rlimit

When reserving stack space for a new process, make sure we're not attempting to expand the stack by more than rlimit allows.

This fixes a bug caused by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba "mm:
variable length argument support" and unmasked by fc63cf237078c86214abcb2ee9926d8ad289da9b "exec: setup_arg_pages() fails to return errors". This bug means when limiting the stack to less the 20*PAGE_SIZE (eg. 80K on 4K pages or 'ulimit -s 79') all processes will be killed before they start. This is particularly bad with 64K pages, where a ulimit below 1280K will kill every process.

---
Attempts to answer comments from Kosaki Motohiro.

Tested on PPC only, hence !CONFIG_STACK_GROWSUP. Someone should probably ACK for an arch with CONFIG_STACK_GROWSUP.

As noted, stable needs the same patch, but 2.6.32 doesn't have the rlimit() helper.

fs/exec.c +22 -2
index 6f7fb0c..325bad4 100644
@@ -573,6 +573,9 @@ int setup_arg_pages(struct linux_binprm *bprm,
 	struct vm_area_struct *prev = NULL;
 	unsigned long vm_flags;
 	unsigned long stack_base;
+	unsigned long stack_size;
+	unsigned long stack_expand;
+	unsigned long rlim_stack;
 
 #ifdef CONFIG_STACK_GROWSUP
 	/* Limit stack size to 1GB */
@@ -629,10 +632,27 @@ int setup_arg_pages(struct linux_binprm *bprm,
 			goto out_unlock;
 	}
 
+	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_size = vma->vm_end - vma->vm_start;
+	/*
+	 * Align this down to a page boundary as expand_stack
+	 * will align it up.
+	 */
+	rlim_stack = rlimit(RLIMIT_STACK) & PAGE_MASK;
+	if (rlim_stack < stack_size)
+		rlim_stack = stack_size;
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	if (stack_size + stack_expand > rlim_stack) {
+		stack_base = vma->vm_start + rlim_stack;
+	} else {
+		stack_base = vma->vm_end + stack_expand;
+	}
 #else
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	if (stack_size + stack_expand > rlim_stack) {
+		stack_base = vma->vm_end - rlim_stack;
+	} else {
+		stack_base = vma->vm_start - stack_expand;
+	}
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)
#17 lore raw

Re: [PATCH] Restrict initial stack space expansion to rlimit

Quoted 32 lines · In message <[email protected]> you wrote:
Quoted 32 lines

When reserving stack space for a new process, make sure we're not attempting to expand the stack by more than rlimit allows.

This fixes a bug caused by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba "mm:
variable length argument support" and unmasked by fc63cf237078c86214abcb2ee9926d8ad289da9b "exec: setup_arg_pages() fails to return errors". This bug means when limiting the stack to less the 20*PAGE_SIZE (eg. 80K on 4K pages or 'ulimit -s 79') all processes will be killed before they start. This is particularly bad with 64K pages, where a ulimit below 1280K will kill every process.

---
Attempts to answer comments from Kosaki Motohiro.

Tested on PPC only, hence !CONFIG_STACK_GROWSUP. Someone should probably ACK for an arch with CONFIG_STACK_GROWSUP.

As noted, stable needs the same patch, but 2.6.32 doesn't have the rlimit() helper.

 fs/exec.c |   21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

Index: linux-2.6-ozlabs/fs/exec.c
===================================================================

fs/exec.c +0 -0
@@ -555,6 +555,7 @@ static int shift_arg_pages(struct vm_are
 }
 
Quoted 5 lines

fs/exec.c static int shift_arg_pages(struct vm_are · line 561

Quoted 5 lines
fs/exec.c +1 -0
 #define EXTRA_STACK_VM_PAGES	20	/* random */
+#define ALIGN_DOWN(addr,size)	((addr)&(~((size)-1)))
 
 /*
  * Finalizes the stack vm_area_struct. The flags and permissions are updat

ed,

Quoted 13 lines
Quoted 13 lines
fs/exec.c +1 -1
@@ -570,7 +571,7 @@ int setup_arg_pages(struct linux_binprm 
 	struct vm_area_struct *vma = bprm->vma;
 	struct vm_area_struct *prev = NULL;
 	unsigned long vm_flags;
-	unsigned long stack_base;
+	unsigned long stack_base, stack_expand, stack_expand_lim, stack_size;
 
 #ifdef CONFIG_STACK_GROWSUP
 	/* Limit stack size to 1GB */
@@ -627,10 +628,24 @@ int setup_arg_pages(struct linux_binprm 
 			goto out_unlock;
 	}
 
Quoted 10 lines

fs/exec.c int setup_arg_pages(struct linux_binprm *bprm,

Quoted 10 lines
fs/exec.c +10 -0
+	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_size = vma->vm_end - vma->vm_start;
+	if (rlimit(RLIMIT_STACK) < stack_size)
+		stack_expand_lim = 0; /* don't shrick the stack */
+	else
+		/*
+		 * Align this down to a page boundary as expand_stack
+		 * will align it up.
+		 */
+		stack_expand_lim = ALIGN_DOWN(rlimit(RLIMIT_STACK) - stack_size

,

Quoted 8 lines
Quoted 8 lines
fs/exec.c +5 -1
+					      PAGE_SIZE);
+	/* Initial stack must not cause stack overflow. */
+	if (stack_expand > stack_expand_lim)
+		stack_expand = stack_expand_lim;
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_end + stack_expand;
 #else
Quoted 8 lines

fs/exec.c int setup_arg_pages(struct linux_binprm *bprm, · line 658

Quoted 5 lines
fs/exec.c +1 -1
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_start - stack_expand;
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)

Umm.. It looks correct. but the nested complex if statement seems a bit ugly. Instead, How about following?

I don't like the duplicated code in the #ifdef/else but I can live with it.

Quoted 1 line

note: it's untested.

Works for me on ppc64 with 4k and 64k pages. Thanks!

I'd still like someone with a CONFIG_STACK_GROWSUP arch to test/ACK it as well.

Mikey

Quoted 78 lines

===============
From: Michael Neuling <[email protected]>
Subject: Restrict initial stack space expansion to rlimit

When reserving stack space for a new process, make sure we're not attempting to expand the stack by more than rlimit allows.

This fixes a bug caused by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba "mm:
variable length argument support" and unmasked by fc63cf237078c86214abcb2ee9926d8ad289da9b "exec: setup_arg_pages() fails to return errors". This bug means when limiting the stack to less the 20*PAGE_SIZE (eg. 80K on 4K pages or 'ulimit -s 79') all processes will be killed before they start. This is particularly bad with 64K pages, where a ulimit below 1280K will kill every process.

---
Attempts to answer comments from Kosaki Motohiro.

Tested on PPC only, hence !CONFIG_STACK_GROWSUP. Someone should probably ACK for an arch with CONFIG_STACK_GROWSUP.

As noted, stable needs the same patch, but 2.6.32 doesn't have the rlimit() helper.

fs/exec.c +22 -2
index 6f7fb0c..325bad4 100644
@@ -573,6 +573,9 @@ int setup_arg_pages(struct linux_binprm *bprm,
 	struct vm_area_struct *prev = NULL;
 	unsigned long vm_flags;
 	unsigned long stack_base;
+	unsigned long stack_size;
+	unsigned long stack_expand;
+	unsigned long rlim_stack;
 
 #ifdef CONFIG_STACK_GROWSUP
 	/* Limit stack size to 1GB */
@@ -629,10 +632,27 @@ int setup_arg_pages(struct linux_binprm *bprm,
 			goto out_unlock;
 	}
 
+	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_size = vma->vm_end - vma->vm_start;
+	/*
+	 * Align this down to a page boundary as expand_stack
+	 * will align it up.
+	 */
+	rlim_stack = rlimit(RLIMIT_STACK) & PAGE_MASK;
+	if (rlim_stack < stack_size)
+		rlim_stack = stack_size;
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	if (stack_size + stack_expand > rlim_stack) {
+		stack_base = vma->vm_start + rlim_stack;
+	} else {
+		stack_base = vma->vm_end + stack_expand;
+	}
 #else
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	if (stack_size + stack_expand > rlim_stack) {
+		stack_base = vma->vm_end - rlim_stack;
+	} else {
+		stack_base = vma->vm_start - stack_expand;
+	}
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)
#18 lore raw

Re: [PATCH] Restrict initial stack space expansion to rlimit

Quoted 16 lines · On Tue, 09 Feb 2010 19:59:27 +1100 Michael Neuling <[email protected]> wrote:
Quoted 7 lines
Quoted 7 lines
(quoted diff) +4 -1
+	/* Initial stack must not cause stack overflow. */
+	if (stack_expand > stack_expand_lim)
+		stack_expand = stack_expand_lim;
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_end + stack_expand;
 #else
Quoted 8 lines

Review

Quoted 5 lines
(quoted diff) +1 -1
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_start - stack_expand;
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)

Umm.. It looks correct. but the nested complex if statement seems a bit ugly. Instead, How about following?

Quoted 1 line

I don't like the duplicated code in the #ifdef/else but I can live with it.

cleanup the cleanup:

fs/exec.c renamed from fs/exec.c~fs-execc-restrict-initial-stack-space-expansion-to-rlimit-cleanup-cleanup +5 -8
@@ -637,20 +637,17 @@ int setup_arg_pages(struct linux_binprm 
 	 * will align it up.
 	 */
 	rlim_stack = rlimit(RLIMIT_STACK) & PAGE_MASK;
-	if (rlim_stack < stack_size)
-		rlim_stack = stack_size;
+	rlim_stack = min(rlim_stack, stack_size);
 #ifdef CONFIG_STACK_GROWSUP
-	if (stack_size + stack_expand > rlim_stack) {
+	if (stack_size + stack_expand > rlim_stack)
 		stack_base = vma->vm_start + rlim_stack;
-	} else {
+	else
 		stack_base = vma->vm_end + stack_expand;
-	}
 #else
-	if (stack_size + stack_expand > rlim_stack) {
+	if (stack_size + stack_expand > rlim_stack)
 		stack_base = vma->vm_end - rlim_stack;
-	} else {
+	else
 		stack_base = vma->vm_start - stack_expand;
-	}
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)

_

Quoted 6 lines
Quoted 1 line

note: it's untested.

Works for me on ppc64 with 4k and 64k pages. Thanks!

I'd still like someone with a CONFIG_STACK_GROWSUP arch to test/ACK it as well.

There's only one CONFIG_GROWSUP arch - parisc.

Guys, here's the rolled-up patch. Could someone please test it on parisc?

err, I'm not sure what one needs to do to test it, actually. Presumably it involves setting an unusual `ulimit -s'. Can someone please suggest a test plan?

From: Michael Neuling <[email protected]>

When reserving stack space for a new process, make sure we're not attempting to expand the stack by more than rlimit allows.

This fixes a bug caused by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba ("mm:
variable length argument support") and unmasked by fc63cf237078c86214abcb2ee9926d8ad289da9b ("exec: setup_arg_pages() fails to return errors").

This bug means that when limiting the stack to less the 20*PAGE_SIZE (eg. 80K on 4K pages or 'ulimit -s 79') all processes will be killed before they start. This is particularly bad with 64K pages, where a ulimit below 1280K will kill every process.

Cc KOSAKI Motohiro <[email protected]>
Cc Americo Wang <[email protected]>
Cc Anton Blanchard <[email protected]>
Cc Oleg Nesterov <[email protected]>
Cc James Morris <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Serge Hallyn <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
 fs/exec.c |   21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)
fs/exec.c renamed from fs/exec.c~fs-execc-restrict-initial-stack-space-expansion-to-rlimit +19 -2
diff -puN fs/exec.c~fs-execc-restrict-initial-stack-space-expansion-to-rlimit fs/exec.c
@@ -571,6 +571,9 @@ int setup_arg_pages(struct linux_binprm 
 	struct vm_area_struct *prev = NULL;
 	unsigned long vm_flags;
 	unsigned long stack_base;
+	unsigned long stack_size;
+	unsigned long stack_expand;
+	unsigned long rlim_stack;
 
 #ifdef CONFIG_STACK_GROWSUP
 	/* Limit stack size to 1GB */
@@ -627,10 +630,24 @@ int setup_arg_pages(struct linux_binprm 
 			goto out_unlock;
 	}
 
+	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_size = vma->vm_end - vma->vm_start;
+	/*
+	 * Align this down to a page boundary as expand_stack
+	 * will align it up.
+	 */
+	rlim_stack = rlimit(RLIMIT_STACK) & PAGE_MASK;
+	rlim_stack = min(rlim_stack, stack_size);
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	if (stack_size + stack_expand > rlim_stack)
+		stack_base = vma->vm_start + rlim_stack;
+	else
+		stack_base = vma->vm_end + stack_expand;
 #else
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	if (stack_size + stack_expand > rlim_stack)
+		stack_base = vma->vm_end - rlim_stack;
+	else
+		stack_base = vma->vm_start - stack_expand;
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)

_

#19 lore raw

Re: [PATCH] Restrict initial stack space expansion to rlimit

Quoted 11 lines
Quoted 7 lines
Quoted 2 lines

note: it's untested.

Works for me on ppc64 with 4k and 64k pages. Thanks!

I'd still like someone with a CONFIG_STACK_GROWSUP arch to test/ACK it as well.

There's only one CONFIG_GROWSUP arch - parisc.

Guys, here's the rolled-up patch.

FYI the rolled up patch still works fine on PPC64. Thanks.

Quoted 5 lines

Could someone please test it on parisc?

err, I'm not sure what one needs to do to test it, actually. Presumably it involves setting an unusual `ulimit -s'. Can someone please suggest a test plan?

How about doing:
'ulimit -s 15; ls'
before and after the patch is applied. Before it's applied, 'ls' should be killed. After the patch is applied, 'ls' should no longer be killed.

I'm suggesting a stack limit of 15KB since it's small enough to trigger 20*PAGE_SIZE. Also 15KB not a multiple of PAGE_SIZE, which is a trickier case to handle correctly with this code.

4K pages on parisc should be fine to test with.

Mikey

Quoted 27 lines

From: Michael Neuling <[email protected]>

When reserving stack space for a new process, make sure we're not attempting to expand the stack by more than rlimit allows.

This fixes a bug caused by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba ("mm:
variable length argument support") and unmasked by fc63cf237078c86214abcb2ee9926d8ad289da9b ("exec: setup_arg_pages() fails to return errors").

This bug means that when limiting the stack to less the 20*PAGE_SIZE (eg. 80K on 4K pages or 'ulimit -s 79') all processes will be killed before they start. This is particularly bad with 64K pages, where a ulimit below 1280K will kill every process.

Cc KOSAKI Motohiro <[email protected]>
Cc Americo Wang <[email protected]>
Cc Anton Blanchard <[email protected]>
Cc Oleg Nesterov <[email protected]>
Cc James Morris <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Serge Hallyn <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Quoted 4 lines
 fs/exec.c |   21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff -puN fs/exec.c~fs-execc-restrict-initial-stack-space-expansion-to-rlimit

fs/exec.c

Quoted 41 lines
fs/exec.c renamed from fs/exec.c~fs-execc-restrict-initial-stack-space-expansion-to-rlimit +19 -2
@@ -571,6 +571,9 @@ int setup_arg_pages(struct linux_binprm 
 	struct vm_area_struct *prev = NULL;
 	unsigned long vm_flags;
 	unsigned long stack_base;
+	unsigned long stack_size;
+	unsigned long stack_expand;
+	unsigned long rlim_stack;
 
 #ifdef CONFIG_STACK_GROWSUP
 	/* Limit stack size to 1GB */
@@ -627,10 +630,24 @@ int setup_arg_pages(struct linux_binprm 
 			goto out_unlock;
 	}
 
+	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_size = vma->vm_end - vma->vm_start;
+	/*
+	 * Align this down to a page boundary as expand_stack
+	 * will align it up.
+	 */
+	rlim_stack = rlimit(RLIMIT_STACK) & PAGE_MASK;
+	rlim_stack = min(rlim_stack, stack_size);
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	if (stack_size + stack_expand > rlim_stack)
+		stack_base = vma->vm_start + rlim_stack;
+	else
+		stack_base = vma->vm_end + stack_expand;
 #else
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	if (stack_size + stack_expand > rlim_stack)
+		stack_base = vma->vm_end - rlim_stack;
+	else
+		stack_base = vma->vm_start - stack_expand;
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)

_

#20 lore raw

Re: [PATCH] Restrict initial stack space expansion to rlimit

Quoted 5 lines · Michael Neuling
Quoted 5 lines
Quoted 2 lines

I'd still like someone with a CONFIG_STACK_GROWSUP arch to test/ACK it as well.

There's only one CONFIG_GROWSUP arch - parisc.
Could someone please test it on parisc?

I did.

Quoted 10 lines

How about doing:

   'ulimit -s 15; ls'

before and after the patch is applied. Before it's applied, 'ls' should be killed. After the patch is applied, 'ls' should no longer be killed.

I'm suggesting a stack limit of 15KB since it's small enough to trigger 20*PAGE_SIZE. Also 15KB not a multiple of PAGE_SIZE, which is a trickier case to handle correctly with this code.

4K pages on parisc should be fine to test with.

Mikey, thanks for the suggested test plan.

I'm not sure if your patch does it correct for parisc/stack-grows-up-case.

I tested your patch on a 4k pages kernel:

root@c3000:~# uname -a
Linux c3000 2.6.33-rc7-32bit #221 Tue Feb 9 23:17:06 CET 2010 parisc GNU/Linux

Without your patch:

root@c3000:~# ulimit -s 15; ls
Killed
-> correct.

With your patch:

root@c3000:~# ulimit -s 15; ls
Killed
_or_:
root@c3000:~# ulimit -s 15; ls
Segmentation fault
-> ??

Any idea?

Helge

Quoted 70 lines
Quoted 26 lines

From: Michael Neuling<[email protected]>

When reserving stack space for a new process, make sure we're not attempting to expand the stack by more than rlimit allows.

This fixes a bug caused by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba ("mm:
variable length argument support") and unmasked by fc63cf237078c86214abcb2ee9926d8ad289da9b ("exec: setup_arg_pages() fails to return errors").

This bug means that when limiting the stack to less the 20*PAGE_SIZE (eg. 80K on 4K pages or 'ulimit -s 79') all processes will be killed before they start. This is particularly bad with 64K pages, where a ulimit below 1280K will kill every process.

Cc KOSAKI Motohiro<[email protected]>
Cc Americo Wang<[email protected]>
Cc Anton Blanchard<[email protected]>
Cc Oleg Nesterov<[email protected]>
Cc James Morris<[email protected]>
Cc Ingo Molnar<[email protected]>
Cc Serge Hallyn<[email protected]>
Cc Benjamin Herrenschmidt<[email protected]>
Quoted 4 lines
  fs/exec.c |   21 +++++++++++++++++++--
  1 file changed, 19 insertions(+), 2 deletions(-)

diff -puN fs/exec.c~fs-execc-restrict-initial-stack-space-expansion-to-rlimit

fs/exec.c

Quoted 39 lines
fs/exec.c renamed from fs/exec.c~fs-execc-restrict-initial-stack-space-expansion-to-rlimit +19 -2
@@ -571,6 +571,9 @@ int setup_arg_pages(struct linux_binprm
  	struct vm_area_struct *prev = NULL;
  	unsigned long vm_flags;
  	unsigned long stack_base;
+	unsigned long stack_size;
+	unsigned long stack_expand;
+	unsigned long rlim_stack;
 
  #ifdef CONFIG_STACK_GROWSUP
  	/* Limit stack size to 1GB */
@@ -627,10 +630,24 @@ int setup_arg_pages(struct linux_binprm
  			goto out_unlock;
  	}
 
+	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_size = vma->vm_end - vma->vm_start;
+	/*
+	 * Align this down to a page boundary as expand_stack
+	 * will align it up.
+	 */
+	rlim_stack = rlimit(RLIMIT_STACK)&  PAGE_MASK;
+	rlim_stack = min(rlim_stack, stack_size);
  #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	if (stack_size + stack_expand>  rlim_stack)
+		stack_base = vma->vm_start + rlim_stack;
+	else
+		stack_base = vma->vm_end + stack_expand;
  #else
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	if (stack_size + stack_expand>  rlim_stack)
+		stack_base = vma->vm_end - rlim_stack;
+	else
+		stack_base = vma->vm_start - stack_expand;
  #endif
  	ret = expand_stack(vma, stack_base);
  	if (ret)
#21 lore raw

Re: [PATCH] Restrict initial stack space expansion to rlimit

Quoted 34 lines · Michael Neuling
Quoted 5 lines
Quoted 5 lines
Quoted 2 lines

I'd still like someone with a CONFIG_STACK_GROWSUP arch to test/ACK it as well.

There's only one CONFIG_GROWSUP arch - parisc.
Could someone please test it on parisc?

I did.

Quoted 10 lines

How about doing:

   'ulimit -s 15; ls'

before and after the patch is applied. Before it's applied, 'ls' should be killed. After the patch is applied, 'ls' should no longer be killed.

I'm suggesting a stack limit of 15KB since it's small enough to trigger 20*PAGE_SIZE. Also 15KB not a multiple of PAGE_SIZE, which is a trickier case to handle correctly with this code.

4K pages on parisc should be fine to test with.

Mikey, thanks for the suggested test plan.

I'm not sure if your patch does it correct for parisc/stack-grows-up-case.

I tested your patch on a 4k pages kernel:

root@c3000:~# uname -a
Linux c3000 2.6.33-rc7-32bit #221 Tue Feb 9 23:17:06 CET 2010 parisc GNU/Linux

Without your patch:

root@c3000:~# ulimit -s 15; ls
Killed
-> correct.

With your patch:

Quoted 8 lines
root@c3000:~# ulimit -s 15; ls
Killed
_or_:
root@c3000:~# ulimit -s 15; ls
Segmentation fault
-> ??

Any idea?

My x86_64 box also makes segmentation fault. I think "ulimit -s 15" is too small stack for ls. "ulimit -s 27; ls " wroks perfectly fine.

#22 lore raw

Re: [PATCH] Restrict initial stack space expansion to rlimit

Quoted 20 lines · In message <[email protected]> you wrote:
Quoted 20 lines · Michael Neuling
Quoted 5 lines
Quoted 5 lines
Quoted 2 lines

I'd still like someone with a CONFIG_STACK_GROWSUP arch to test/ACK it as well.

There's only one CONFIG_GROWSUP arch - parisc.
Could someone please test it on parisc?

I did.

Quoted 10 lines

How about doing:

   'ulimit -s 15; ls'

before and after the patch is applied. Before it's applied, 'ls' should be killed. After the patch is applied, 'ls' should no longer be killed.

I'm suggesting a stack limit of 15KB since it's small enough to trigger 20*PAGE_SIZE. Also 15KB not a multiple of PAGE_SIZE, which is a trickier case to handle correctly with this code.

4K pages on parisc should be fine to test with.

Quoted 7 lines
Quoted 7 lines

Mikey, thanks for the suggested test plan.

I'm not sure if your patch does it correct for parisc/stack-grows-up-case.

I tested your patch on a 4k pages kernel:

root@c3000:~# uname -a
Linux c3000 2.6.33-rc7-32bit #221 Tue Feb 9 23:17:06 CET 2010 parisc GNU/Li

nux

Quoted 14 lines
Quoted 14 lines

Without your patch:

root@c3000:~# ulimit -s 15; ls
Killed
-> correct.

With your patch:

root@c3000:~# ulimit -s 15; ls
Killed
_or_:
root@c3000:~# ulimit -s 15; ls
Segmentation fault
-> ??
Quoted 3 lines
Quoted 1 line

Any idea?

My x86_64 box also makes segmentation fault. I think "ulimit -s 15" is too sm

all stack for ls.

Quoted 1 line

"ulimit -s 27; ls " wroks perfectly fine.

Arrh. I asked Helge offline earlier to check what use to work on parisc on 2.6.31.

I guess PPC has a nice clean non-bloated ABI :-D

Mikey

#23 lore raw

Re: [PATCH] Restrict initial stack space expansion to rlimit

In reply to KOSAKI Motohiro
Quoted 20 lines · In message <[email protected]> you wrote:
Quoted 20 lines · Michael Neuling
Quoted 5 lines
Quoted 5 lines
Quoted 2 lines

I'd still like someone with a CONFIG_STACK_GROWSUP arch to test/ACK it as well.

There's only one CONFIG_GROWSUP arch - parisc.
Could someone please test it on parisc?

I did.

Quoted 10 lines

How about doing:

   'ulimit -s 15; ls'

before and after the patch is applied. Before it's applied, 'ls' should be killed. After the patch is applied, 'ls' should no longer be killed.

I'm suggesting a stack limit of 15KB since it's small enough to trigger 20*PAGE_SIZE. Also 15KB not a multiple of PAGE_SIZE, which is a trickier case to handle correctly with this code.

4K pages on parisc should be fine to test with.

Quoted 7 lines
Quoted 7 lines

Mikey, thanks for the suggested test plan.

I'm not sure if your patch does it correct for parisc/stack-grows-up-case.

I tested your patch on a 4k pages kernel:

root@c3000:~# uname -a
Linux c3000 2.6.33-rc7-32bit #221 Tue Feb 9 23:17:06 CET 2010 parisc GNU/Li

nux

Quoted 14 lines
Quoted 14 lines

Without your patch:

root@c3000:~# ulimit -s 15; ls
Killed
-> correct.

With your patch:

root@c3000:~# ulimit -s 15; ls
Killed
_or_:
root@c3000:~# ulimit -s 15; ls
Segmentation fault
-> ??
Quoted 3 lines
Quoted 1 line

Any idea?

My x86_64 box also makes segmentation fault. I think "ulimit -s 15" is too sm

all stack for ls.

Quoted 1 line

"ulimit -s 27; ls " wroks perfectly fine.

Arrh. I asked Helge offline earlier to check what use to work on parisc on 2.6.31.

I guess PPC has a nice clean non-bloated ABI :-D

Mikey

#24 lore raw

Re: [PATCH] Restrict initial stack space expansion to rlimit

Quoted 45 lines · Michael Neuling
Quoted 20 lines · In message<[email protected]> you wrote:
Quoted 20 lines · Michael Neuling
Quoted 5 lines
Quoted 5 lines
Quoted 2 lines

I'd still like someone with a CONFIG_STACK_GROWSUP arch to test/ACK it as well.

There's only one CONFIG_GROWSUP arch - parisc.
Could someone please test it on parisc?

I did.

Quoted 10 lines

How about doing:

    'ulimit -s 15; ls'

before and after the patch is applied. Before it's applied, 'ls' should be killed. After the patch is applied, 'ls' should no longer be killed.

I'm suggesting a stack limit of 15KB since it's small enough to trigger 20*PAGE_SIZE. Also 15KB not a multiple of PAGE_SIZE, which is a trickier case to handle correctly with this code.

4K pages on parisc should be fine to test with.

Quoted 7 lines
Quoted 7 lines

Mikey, thanks for the suggested test plan.

I'm not sure if your patch does it correct for parisc/stack-grows-up-case.

I tested your patch on a 4k pages kernel:

root@c3000:~# uname -a
Linux c3000 2.6.33-rc7-32bit #221 Tue Feb 9 23:17:06 CET 2010 parisc GNU/Li

nux

Quoted 16 lines
Quoted 15 lines

Without your patch:

root@c3000:~# ulimit -s 15; ls
Killed
->  correct.

With your patch:

root@c3000:~# ulimit -s 15; ls
Killed
_or_:
root@c3000:~# ulimit -s 15; ls
Segmentation fault
->  ??

Any idea?

Quoted 8 lines
Quoted 1 line

My x86_64 box also makes segmentation fault. I think "ulimit -s 15" is too sm

all stack for ls.

Quoted 1 line

"ulimit -s 27; ls " wroks perfectly fine.

Arrh. I asked Helge offline earlier to check what use to work on parisc on 2.6.31.

I guess PPC has a nice clean non-bloated ABI :-D

Hi Mikey,

I tested again, and it works for me with "ulimit -s 27" as well (on a 4k, 32bit kernel). Still, I'm not 100% sure if your patch is correct.
Anyway, it seems to work.

But what makes me wonder is, why EXTRA_STACK_VM_PAGES is defined in pages at all. You wrote in your patch description:

Quoted 4 lines

This bug means that when limiting the stack to less the 20*PAGE_SIZE (eg. 80K on 4K pages or 'ulimit -s 79') all processes will be killed before they start. This is particularly bad with 64K pages, where a ulimit below 1280K will kill every process.

Wouldn't it make sense to define and use EXTRA_STACK_VM_SIZE instead (e.g. as 20*4096 = 80k)? This extra stack reservation should IMHO be independend of the actual kernel page size.

Helge

#25 lore raw

Re: [PATCH] Restrict initial stack space expansion to rlimit

Quoted 11 lines · In message <[email protected]> you wrote:
Quoted 10 lines · Michael Neuling
Quoted 9 lines · In message<[email protected]> you wrote:
Quoted 9 lines · Michael Neuling
Quoted 5 lines
Quoted 5 lines
Quoted 2 lines

I'd still like someone with a CONFIG_STACK_GROWSUP arch to test/ACK it as well.

There's only one CONFIG_GROWSUP arch - parisc.
Could someone please test it on parisc?

I did.

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

How about doing:

    'ulimit -s 15; ls'

before and after the patch is applied. Before it's applied, 'ls' should be killed. After the patch is applied, 'ls' should no longer be killed.

I'm suggesting a stack limit of 15KB since it's small enough to trigger 20*PAGE_SIZE. Also 15KB not a multiple of PAGE_SIZE, which is a trickie

r

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 3 lines

case to handle correctly with this code.

4K pages on parisc should be fine to test with.

Mikey, thanks for the suggested test plan.

I'm not sure if your patch does it correct for parisc/stack-grows-up-case

.

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

I tested your patch on a 4k pages kernel:

root@c3000:~# uname -a
Linux c3000 2.6.33-rc7-32bit #221 Tue Feb 9 23:17:06 CET 2010 parisc GNU/

Li

Quoted 15 lines
Quoted 15 lines

nux

Quoted 14 lines
Quoted 14 lines

Without your patch:

root@c3000:~# ulimit -s 15; ls
Killed
->  correct.

With your patch:

root@c3000:~# ulimit -s 15; ls
Killed
_or_:
root@c3000:~# ulimit -s 15; ls
Segmentation fault
->  ??
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 1 line

Any idea?

My x86_64 box also makes segmentation fault. I think "ulimit -s 15" is too

sm

Quoted 6 lines
Quoted 6 lines

all stack for ls.

Quoted 1 line

"ulimit -s 27; ls " wroks perfectly fine.

Arrh. I asked Helge offline earlier to check what use to work on parisc on 2.6.31.

Quoted 7 lines
Quoted 1 line

I guess PPC has a nice clean non-bloated ABI :-D

Hi Mikey,

I tested again, and it works for me with "ulimit -s 27" as well (on a 4k, 32bit kernel).
Still, I'm not 100% sure if your patch is correct.

Thanks for retesting

Did "ulimit -s 27" fail before you applied?

Quoted 3 lines

Anyway, it seems to work.

But what makes me wonder is, why EXTRA_STACK_VM_PAGES is defined in pages at

all.

Quoted 9 lines

You wrote in your patch description:

Quoted 4 lines

This bug means that when limiting the stack to less the 20*PAGE_SIZE (eg. 80K on 4K pages or 'ulimit -s 79') all processes will be killed before they start. This is particularly bad with 64K pages, where a ulimit below 1280K will kill every process.

Wouldn't it make sense to define and use EXTRA_STACK_VM_SIZE instead (e.g. as 20*4096 = 80k)? This extra stack reservation should IMHO be independend of the actual kernel page size.

If you look back through this thread, that has already been noted but it's a separate issue to this bug, so that change will be deferred till 2.6.34.

Mikey

#26 lore raw

PATCH 1/1 Create initial stack independent of PAGE_SIZE

In reply to Andrew Morton

Currently we create the initial stack based on the PAGE_SIZE. This is unnecessary.

This creates this initial stack independent of the PAGE_SIZE.

It also bumps up the number of 4k pages allocated from 20 to 32, to align with 64K page systems.

---
This is the second half of my original patch. This can be targeted for 2.6.34 as it's just a cleanup.

Tested on PPC64 with 4k and 64k pages.

 fs/exec.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
fs/exec.c +1 -3
Index: linux-2.6-ozlabs/fs/exec.c
===================================================================
@@ -554,8 +554,6 @@ static int shift_arg_pages(struct vm_are
 	return 0;
 }
 
-#define EXTRA_STACK_VM_PAGES	20	/* random */
-
 /*
  * Finalizes the stack vm_area_struct. The flags and permissions are updated,
  * the stack is optionally relocated, and some extra space is added.
@@ -630,7 +628,7 @@ int setup_arg_pages(struct linux_binprm 
 			goto out_unlock;
 	}
 
-	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_expand = 131072UL; /* randomly 32*4k (or 2*64k) pages */
 	stack_size = vma->vm_end - vma->vm_start;
 	/*
 	 * Align this down to a page boundary as expand_stack
#27 lore raw

Re: [PATCH] Create initial stack independent of PAGE_SIZE

Quoted 2 lines

Currently we create the initial stack based on the PAGE_SIZE. This is unnecessary.

I don't think this is enough explanation. In past mail, you described why page size dependency is harmful. I hope you add it into the patch description.

IOW, we don't need to change the unnecessary-but-non-harmful behavior.

Quoted 5 lines

This creates this initial stack independent of the PAGE_SIZE.

It also bumps up the number of 4k pages allocated from 20 to 32, to align with 64K page systems.

Why do we need page-aligning? Do you mean this code doesn't works on 128K (or more larger) page systems?

Quoted 33 lines

---
This is the second half of my original patch. This can be targeted for 2.6.34 as it's just a cleanup.

Tested on PPC64 with 4k and 64k pages.

 fs/exec.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

Index: linux-2.6-ozlabs/fs/exec.c
===================================================================

fs/exec.c +1 -3
@@ -554,8 +554,6 @@ static int shift_arg_pages(struct vm_are
 	return 0;
 }
 
-#define EXTRA_STACK_VM_PAGES	20	/* random */
-
 /*
  * Finalizes the stack vm_area_struct. The flags and permissions are updated,
  * the stack is optionally relocated, and some extra space is added.
@@ -630,7 +628,7 @@ int setup_arg_pages(struct linux_binprm 
 			goto out_unlock;
 	}
 
-	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_expand = 131072UL; /* randomly 32*4k (or 2*64k) pages */
 	stack_size = vma->vm_end - vma->vm_start;
 	/*
 	 * Align this down to a page boundary as expand_stack
#28 lore raw

Re: [PATCH] Create initial stack independent of PAGE_SIZE

Quoted 6 lines · In message <[email protected]> you wrote:
Quoted 2 lines

Currently we create the initial stack based on the PAGE_SIZE. This is unnecessary.

I don't think this is enough explanation. In past mail, you described why page size dependency is harmful. I hope you add it into the patch description.

I don't think it's harmful, it's just irrelevant. Stack size is independent of page size.

Quoted 10 lines

IOW, we don't need to change the unnecessary-but-non-harmful behavior.

Quoted 5 lines

This creates this initial stack independent of the PAGE_SIZE.

It also bumps up the number of 4k pages allocated from 20 to 32, to align with 64K page systems.

Why do we need page-aligning? Do you mean this code doesn't works on 128K (or more larger) page systems?

If the "random" setting is not a common multiple of the 4k and 64k pages, they will end up getting aligned differently, hence causing what we are trying to avoid in the first place with this patch.

I should probably add this as a comment in the code comment?

Mikey

Quoted 21 lines
Quoted 21 lines

---
This is the second half of my original patch. This can be targeted for 2.6.34 as it's just a cleanup.

Tested on PPC64 with 4k and 64k pages.

 fs/exec.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

Index: linux-2.6-ozlabs/fs/exec.c
===================================================================

fs/exec.c +0 -0
@@ -554,8 +554,6 @@ static int shift_arg_pages(struct vm_are
 	return 0;
 }
 
Quoted 4 lines

fs/exec.c static int shift_arg_pages(struct vm_are

Quoted 4 lines
fs/exec.c +0 -2
-#define EXTRA_STACK_VM_PAGES	20	/* random */
-
 /*
  * Finalizes the stack vm_area_struct. The flags and permissions are updat

ed,

Quoted 13 lines
Quoted 10 lines
fs/exec.c +1 -1
  * the stack is optionally relocated, and some extra space is added.
@@ -630,7 +628,7 @@ int setup_arg_pages(struct linux_binprm 
 			goto out_unlock;
 	}
 
-	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_expand = 131072UL; /* randomly 32*4k (or 2*64k) pages */
 	stack_size = vma->vm_end - vma->vm_start;
 	/*
 	 * Align this down to a page boundary as expand_stack
Reviewed-by
#29 lore raw

Re: [PATCH] Create initial stack independent of PAGE_SIZE

Quoted 10 lines
Quoted 6 lines · In message <[email protected]> you wrote:
Quoted 2 lines

Currently we create the initial stack based on the PAGE_SIZE. This is unnecessary.

I don't think this is enough explanation. In past mail, you described why page size dependency is harmful. I hope you add it into the patch description.

I don't think it's harmful, it's just irrelevant. Stack size is independent of page size.

ok.

Quoted 8 lines
Quoted 8 lines

IOW, we don't need to change the unnecessary-but-non-harmful behavior.

Quoted 5 lines

This creates this initial stack independent of the PAGE_SIZE.

It also bumps up the number of 4k pages allocated from 20 to 32, to align with 64K page systems.

Quoted 6 lines
Quoted 2 lines

Why do we need page-aligning? Do you mean this code doesn't works on 128K (or more larger) page systems?

If the "random" setting is not a common multiple of the 4k and 64k pages, they will end up getting aligned differently, hence causing what we are trying to avoid in the first place with this patch.

I see. ok,

Quoted 2 lines

I should probably add this as a comment in the code comment?

probably, It's not big matter.

Thanks :)

Quoted 42 lines

Mikey

Quoted 21 lines
Quoted 21 lines

---
This is the second half of my original patch. This can be targeted for 2.6.34 as it's just a cleanup.

Tested on PPC64 with 4k and 64k pages.

 fs/exec.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

Index: linux-2.6-ozlabs/fs/exec.c
===================================================================

fs/exec.c +0 -0
@@ -554,8 +554,6 @@ static int shift_arg_pages(struct vm_are
 	return 0;
 }
 
Quoted 4 lines

fs/exec.c static int shift_arg_pages(struct vm_are

Quoted 4 lines
fs/exec.c +0 -2
-#define EXTRA_STACK_VM_PAGES	20	/* random */
-
 /*
  * Finalizes the stack vm_area_struct. The flags and permissions are updat

ed,

Quoted 13 lines
Quoted 10 lines
fs/exec.c +1 -1
  * the stack is optionally relocated, and some extra space is added.
@@ -630,7 +628,7 @@ int setup_arg_pages(struct linux_binprm 
 			goto out_unlock;
 	}
 
-	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_expand = 131072UL; /* randomly 32*4k (or 2*64k) pages */
 	stack_size = vma->vm_end - vma->vm_start;
 	/*
 	 * Align this down to a page boundary as expand_stack
#30 lore raw

Re: [PATCH] Restrict stack space reservation to rlimit

In reply to KOSAKI Motohiro
Quoted 7 lines · In message <[email protected]> you wrote:
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

Hi,

Quoted 2 lines

Why do we need page size independent stack size? It seems to have compatibility breaking risk.

I don't think so. The current behaviour is clearly wrong, we dont need

a

Quoted 35 lines
Quoted 9 lines
Quoted 9 lines
Quoted 2 lines

16x larger stack just because you went from a 4kB to a 64kB base page size. The user application stack usage is the same in both cases.

I didn't discuss which behavior is better. Michael said he want to apply his patch to 2.6.32 & 2.6.33. stable tree never accept the breaking compatibility patch.

Your answer doesn't explain why can't we wait it until next merge window.

Quoted 8 lines
Quoted 2 lines

btw, personally, I like page size indepent stack size. but I'm not sure why making stack size independency is related to bug fix.

I tend to agree.

Below is just the bug fix to limit the reservation size based rlimit. We still reserve different stack sizes based on the page size as before (unless we hit rlimit of course).

Thanks.

I agree your patch in almost part. but I have very few requests.

Quoted 11 lines

Mikey

Restrict stack space reservation to rlimit

When reserving stack space for a new process, make sure we're not attempting to allocate more than rlimit allows.

This fixes a bug cause by b6a2fea39318e43fee84fa7b0b90d68bed92d2ba "mm: variable length argument support" and unmasked by fc63cf237078c86214abcb2ee9926d8ad289da9b
"exec: setup_arg_pages() fails to return errors".

Quoted 7 lines

Your initial mail have following problem use-case. please append it into the patch description.

On recent ppc64 kernels, limiting the stack (using 'ulimit -s blah') is now more restrictive than it was before. On 2.6.31 with 4k pages I could run 'ulimit -s 16; /usr/bin/test' without a problem. Now with mainline, even 'ulimit -s 64; /usr/bin/test' gets killed.

Ok, I'll add this info in.

Quoted 17 lines
Quoted 17 lines
---
 fs/exec.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

Index: linux-2.6-ozlabs/fs/exec.c
===================================================================

fs/exec.c +0 -0
@@ -627,10 +627,13 @@ int setup_arg_pages(struct linux_binprm 
 			goto out_unlock;
 	}
 
Quoted 5 lines

fs/exec.c int setup_arg_pages(struct linux_binprm · line 632

Quoted 3 lines
fs/exec.c +3 -0
+	stack_base = min(EXTRA_STACK_VM_PAGES * PAGE_SIZE,
+			 current->signal->rlim[RLIMIT_STACK].rlim_cur -
+			   PAGE_SIZE);

This line is a bit unclear why "- PAGE_SIZE" is necessary.

This is because the stack is already 1 page in size. I'm going to change that code to make it clearer... hopefully :-)

Quoted 9 lines

personally, I like following likes explicit comments.

	stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
	stack_lim = ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur);

	/* Initial stack must not cause stack overflow. */
	if (stack_expand + PAGE_SIZE > stack_lim)
		stack_expand = stack_lim - PAGE_SIZE;
Quoted 4 lines

note: accessing rlim_cur require ACCESS_ONCE.

Thought?

Thanks, looks better/clearer to me too. I'll change, new patch coming....

Mikey

Quoted 15 lines
Quoted 12 lines
fs/exec.c +2 -2
 #ifdef CONFIG_STACK_GROWSUP
-	stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_end + stack_base;
 #else
-	stack_base = vma->vm_start - EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+	stack_base = vma->vm_start - stack_base;
 #endif
 	ret = expand_stack(vma, stack_base);
 	if (ret)