使用setrlimit()设置堆栈大小并引发堆栈溢出/段错误

在下面的给出示例中,我尝试将stacksize设置为1kb。 为什么现在可以在堆栈中分配一个大小为
8kb
的整数数组?
#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: %un", ints[2047]=42);
}
    
已邀请:
限制是立即设置的,但仅在尝试分配新堆栈或尝试增加现有堆栈时进行检查。内核源代码上的RLIMIT_STACK(或LXR标识符搜索)的grep应该知道。 显然,堆栈的初始大小是文件名+ env字符串+ arg字符串以及在
setup_arg_pages
上分配的一些额外页面所需的任何内容(2.6.33 1,2中的20页,2.6.34 3上的128 Kb)。 综上所述:
initial stack size = MIN(size for filename + arg strings + env strings + extra pages, MAX(size for filename + arg strings + env strings, RLIMIT_STACK))
哪里
size for filename + arg strings + env strings <= MAX(ARG_MAX(32 pages), RLIMIT_STACK/4)
此外,使用Ingo Molnar的
exec-shield
补丁(Fedora,Ubuntu,......)的内核还有一个额外的EXEC_STACK_BIAS“(2MB以上可以覆盖随机化效果。)”,请参阅
acct_stack_growth()
([Ubuntu1],[Ubuntu2]调用新函数
over_stack_limit()
],[Ubuntu3])。 我编辑了原始程序来显示:
#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 sizen");
                if (setrlimit(RLIMIT_STACK, &lim) == -1) {
                        printf("rlimit failedn");
                        return 1;
                }
        }

        foo();

        return 0;
}

void foo() {
        unsigned ints[32768];

        printf("foo: %un", ints[2047]=42);
}
结果如下:
$./rl
foo: 42
$./rl -l
limiting stack size
Segmentation fault
$  
    
我认为
setrlimit
移动了“资源指针”,但是在你ѭѭ新的程序副本之前不会应用新的限制。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/resource.h>

void foo(int chk) {
  unsigned ints[2048];
  ints[2047] = 42;
  printf("foo %d: %un", chk, ints[2047]);
}

int main(int argc, char **argv) {
  char *newarg[] = { "argv[0]", "one", "two" };
  char *newenv[] = { NULL };
  struct rlimit lim;

  newarg[0] = argv[0];
  getrlimit(RLIMIT_STACK, &lim);
  printf("lim: %d / %dn", (int)lim.rlim_cur, (int)lim.rlim_max);
  switch (argc) {
    case 1: /* first call from command line */
      lim.rlim_cur = 65536;
      lim.rlim_max = 65536;
      if (setrlimit(RLIMIT_STACK, &lim) == -1) return EXIT_FAILURE;
      newarg[2] = NULL;
      foo(1);
      execve(argv[0], newarg, newenv);
      break;
    case 2: /* second call */
      lim.rlim_cur = 1024;
      lim.rlim_max = 1024;
      if (setrlimit(RLIMIT_STACK, &lim) == -1) return EXIT_FAILURE;
      foo(2);
      execve(argv[0], newarg, newenv);
      break;
    default: /* third call */
      foo(3);
      break;
  }
  return 0;
}
并且测试运行: $ ./a.out lim:8388608 / -1 foo 1:42 lim:65536/65536 foo 2:42 杀害 为什么在打印限制之前(以及在调用foo之前)进程被杀死,我不知道。     

要回复问题请先登录注册