Bug 91791 - tracee process stack can't be expand beyond tracer stack size limit
Summary: tracee process stack can't be expand beyond tracer stack size limit
Status: NEW
Alias: None
Product: Memory Management
Classification: Unclassified
Component: Other (show other bugs)
Hardware: All Linux
: P1 normal
Assignee: Andrew Morton
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-01-22 12:24 UTC by mike
Modified: 2015-01-25 19:15 UTC (History)
3 users (show)

See Also:
Kernel Version: 3.16.0
Subsystem:
Regression: No
Bisected commit-id:


Attachments
small program that allow to reproduce the problem (637 bytes, text/x-csrc)
2015-01-22 12:24 UTC, mike
Details

Description mike 2015-01-22 12:24:36 UTC
Created attachment 164311 [details]
small program that allow to reproduce the problem

When a tracer try to access a tracee stack area not yet mapped and that is above tracer stack size limit, we got an error.

 You can reproduce the problem with the attach program
- Compile it
 > gcc -g exec.c
- Setup limit on tracer stack size
 > ulimit -Ss 8192
- Run compile program under gdb
 > gdb a./out
- Now under gdb prompt
(gdb) b exec_here
Breakpoint 1 at 0x400632: file exec.c, line 8.
(gdb) r
Starting program: /home/mike/rootfs/proot_stack_pb/a.out 
SP = 0x00007fffffffe1c0
try print *0x00007fffff5fe1b0

Breakpoint 1, exec_here (cmd=0x7fffff6fe1b0 "ls") at exec.c:8
8	    fprintf(stderr, "SP = 0x%016lx\n", alloca(0));
(gdb) print *0x00007fffff5fe1b0
Cannot access memory at address 0x7fffff5fe1b0

 If you try the same sequence but replace 'ulimit -Ss 8192' by 'ulimit -Ss 16384' it will work fine which is the correct behaviour.

 Problem is due to acct_stack_growth() from mm/mmap.c file. There is a check that fail since it use tracer stack size limit instead of the tracee stack size limit.

static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, unsigned long grow)
{
2100         struct mm_struct *mm = vma->vm_mm;
2101         struct rlimit *rlim = current->signal->rlim;
...
2108         /* Stack limit test */
2109         if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur))
2110                 return -ENOMEM;

 Line 2101 we use current process limits which is the tracer process limits.
Comment 1 Oleg Nesterov 2015-01-25 19:15:27 UTC
(In reply to mike from comment #0)
>
> static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size,
> unsigned long grow)
> {
> 2100         struct mm_struct *mm = vma->vm_mm;
> 2101         struct rlimit *rlim = current->signal->rlim;
> ...
> 2108         /* Stack limit test */
> 2109         if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur))
> 2110                 return -ENOMEM;
> 
>  Line 2101 we use current process limits which is the tracer process limits.

Yes, and the same function also checks the caller's RLIMIT_AS/MEMLOCK.

I do not see a simple fix, and in fact I am not sure we really want to
fix this oddity, although I agree that this doesn't look very good.

Unlikely we want to complicate the get_user_pages() paths... Perhaps we
could add task_struct->active_rlim[] and change task_rlimit(), but this
doesn't look good too, imo.

And this is not ptrace-specific. Say, /proc/pid/mem. This case is even
worse, the task can already go away when mem_rw() is called so this path
can't even know which rlimits it should check.

We have mm->owner which we could probably use if current->mm != mm, but
it depends on CONFIG_MEMCG. And personally I think it should die, so it
should not have the new users, imho.

In short, I'd vote for "won't fix".

Note You need to log in before you can comment on or make changes to this bug.