设置堆栈大小通过setrlimit()和挑起堆栈溢出/段错误 [英] Set stack size with setrlimit() and provoke a stack overflow/segfault
问题描述
在给定的例子下面我尝试设置堆栈大小为1KB。
为什么现在可以在堆栈大小为
? 8KB
上分配的int数组美孚()
的#include<&stdio.h中GT;
#包括LT&; SYS / RESOURCE.H>无效美孚(无效);诠释主(){
结构RLIMIT LIM = {1024,1024}; 如果(了setrlimit(RLIMIT_STACK,&安培; LIM)== -1)
返回1; 富(); 返回0;
}无效美孚(){
无符号整数[2048]; 的printf(富:%U \\ N,整型[2047] = 42);
}
该限制立即设置而只是试图分配一个新的堆栈或者试图扩大现有的堆栈时检查。在内核源代码的RLIMIT_STACK(或LXR标识符搜索)grep命令应该告诉
显然,堆栈的初始大小无论是需要对文件名+ ENV字符串+ ARG串加上 setup_arg_pages
(20页2.6分配一些额外的页面。 33 1 ,的 2 ,128 KB的2.6.34的 3 )。
在总结:
初始堆栈大小= MIN(大小文件名+ ARG字符串+ ENV字符串+额外的页面,MAX(大小文件名+ ARG字符串+ ENV字符串,RLIMIT_STACK))
其中,
大小文件名+ ARG字符串+ ENV弦< = MAX(ARG_MAX(32页),RLIMIT_STACK / 4)
此外,与英格·蒙内的 EXEC屏蔽
补丁(的Fedora,Ubuntu的,...)内核有一个额外的EXEC_STACK_BIAS (2MB的覆盖随机化效果)。,看到调用新功能 over_stack_limit()
从 acct_stack_growth()
(<一个href=\"http://kernel.ubuntu.com/git?p=ubuntu/ubuntu-maverick.git;a=blob;f=mm/mmap.c;h=f768a242656b182d09a401a4d0882b2c3ed33f4e;hb=HEAD#l1764\"相对=nofollow> [Ubuntu1] ,<一个href=\"http://kernel.ubuntu.com/git?p=ubuntu/ubuntu-maverick.git;a=blob;f=mm/mmap.c;h=f768a242656b182d09a401a4d0882b2c3ed33f4e;hb=HEAD#l1749\"相对=nofollow> [Ubuntu2] ,<一个href=\"http://kernel.ubuntu.com/git?p=ubuntu/ubuntu-maverick.git;a=blob;f=include/linux/resource.h;h=d2aef9a9ebed090383350c1c8d1c2f3cdfddcbfd;hb=HEAD#l57\"相对=nofollow> [Ubuntu3] )。
我已经编辑了原来的程序,以显示这一点:
的#include&LT;&stdio.h中GT;
#包括LT&; SYS / RESOURCE.H&GT;无效美孚(无效);INT主(INT ARGC,CHAR *的argv []){
结构RLIMIT LIM = {1,1};
如果(argc个大于1&放大器;&放大器;的argv [1] [0] ==' - '和;&放大器;的argv [1] [8] =='L'){
的printf(限制堆栈大小\\ n);
如果(了setrlimit(RLIMIT_STACK,&安培; LIM)== -1){
的printf(RLIMIT失败\\ n);
返回1;
}
} 富(); 返回0;
}无效美孚(){
无符号整数[32768] 的printf(富:%U \\ N,整型[2047] = 42);
}
这会导致:
$。/ RL
富:42
$。/ RL -l
限制堆栈大小
分段故障
$
In the given example below I try to set the stacksize to 1kb.
Why is it now possible to allocate an array of ints on the stack with size 8kb
in foo()
?
#include <stdio.h>
#include <sys/resource.h>
void foo(void);
int main() {
struct rlimit lim = {1024, 1024};
if (setrlimit(RLIMIT_STACK, &lim) == -1)
return 1;
foo();
return 0;
}
void foo() {
unsigned ints[2048];
printf("foo: %u\n", ints[2047]=42);
}
The limit is set immediately but only checked when trying to allocate a new stack or trying to grow the existing stack. A grep for RLIMIT_STACK (or a LXR identifier search) on the kernel sources should tell.
Apparently, the initial size of the stack is whatever is needed to the filename + env strings + arg strings plus some extra pages allocated on setup_arg_pages
(20 pages in 2.6.33 1,2, 128 Kb on 2.6.34 3).
In summary:
initial stack size = MIN(size for filename + arg strings + env strings + extra pages, MAX(size for filename + arg strings + env strings, RLIMIT_STACK))
where
size for filename + arg strings + env strings <= MAX(ARG_MAX(32 pages), RLIMIT_STACK/4)
Additionally, kernels with Ingo Molnar's exec-shield
patch (Fedora, Ubuntu, ...) have an additional EXEC_STACK_BIAS "(2MB more to cover randomization effects.)", see the call to the new function over_stack_limit()
from acct_stack_growth()
([Ubuntu1], [Ubuntu2], [Ubuntu3]).
I've edited the original program to show this:
#include <stdio.h>
#include <sys/resource.h>
void foo(void);
int main(int argc, char *argv[]) {
struct rlimit lim = {1, 1};
if (argc > 1 && argv[1][0] == '-' && argv[1][8]=='l') {
printf("limiting stack size\n");
if (setrlimit(RLIMIT_STACK, &lim) == -1) {
printf("rlimit failed\n");
return 1;
}
}
foo();
return 0;
}
void foo() {
unsigned ints[32768];
printf("foo: %u\n", ints[2047]=42);
}
Which results in:
$./rl
foo: 42
$./rl -l
limiting stack size
Segmentation fault
$
这篇关于设置堆栈大小通过setrlimit()和挑起堆栈溢出/段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!