Shell의 설정과 상관 없이 프로그램 상에서 core dump를 남기도록 설정하기

|

6개월만에 포스팅이네!

... 어쨌든, 비슷한 것을 언젠가 찾아봤던 기억이 있긴 하지만..

두가지의 API를 통해서 가능한데, 한가지는 prctl이다.
이것은 한때 linux kernel 2.6.13 부터 2.6.17까지의 hole을 공격하는 해킹 프로그램의 핵심으로 유명한데, 좋은 물건도 악의를 가지고 사용하면 나쁘게 되는 법인가.

manpage 상에서 prctl의 필요한 부분에 대한 설명은 다음과 같다 :

       #include <sys/prctl.h>

       int prctl(int option, unsigned long arg2, unsigned long arg3 , unsigned
       long arg4, unsigned long arg5);

...

       PR_SET_DUMPABLE
              (Since  Linux 2.4) Set the state of the flag determining whether
              core dumps are produced for this process upon delivery of a sig-
              nal  whose  default  behaviour is to produce a core dump.  (Nor-
              mally this flag is set for a  process  by  default,  but  it  is
              cleared  when  a set-user-ID or set-group-ID program is executed
              and also by various system calls that  manipulate  process  UIDs
              and  GIDs).  In kernels up to and including 2.6.12, arg2 must be
              either 0 (process is not dumpable) or 1 (process  is  dumpable).
              Since  kernel 2.6.13, the value 2 is also permitted; this causes
              any binary which normally would not be dumped to be dumped read-
              able   by   root   only.    (See   also   the   description   of
              /proc/sys/fs/suid_dumpable in proc(5).)

그러니까 prctl로 PR_SET_DUMPABLE로 설정하게 되면 프로세스가 core dump를 발생하게 할 수 있다.

그러나 이 자체만으로 해결되는 것은 아니고 한가지를 더 해줘야 하는데, 그것이 바로 setrlimit 이다. 이것은 shell 상에서 ulimit 혹은 limit로 변경할 수 있는 자원에 대해서 프로그램 상에서 변경할 수 있게 해주는데, 여기에 core dump size를 변경해야만 실제로 core가 남게 된다.

역시 manpage를 보게 되면,

       #include <sys/time.h>
       #include <sys/resource.h>

       int setrlimit(int resource, const struct rlimit *rlim);

...

            struct rlimit {
                rlim_t rlim_cur;  /* Soft limit */
                rlim_t rlim_max;  /* Hard limit (ceiling for rlim_cur) */
            };

...

       RLIMIT_CORE
              Maximum  size  of  core file. When 0 no core dump files are cre-
              ated.  When non-zero, larger dumps are truncated to this size.

위 정보를 조합하여 core를 무조건 남기게 하는 코드를 만들어보면,

#include <sys/prctl.h> /* for prctl() */
#include <sys/resource.h> /* for setrlimit() */

...

    struct rlimit corelimit;

...

    corelimit.rlim_cur = RLIM_INFINITY;
    corelimit.rlim_max = RLIM_INFINITY;
    ret = setrlimit(RLIMIT_CORE, &corelimit);
    if (ret < 0) {
        fprintf(stderr, "setrlimit: %s", strerror(errno));
    }

    ret = prctl(PR_SET_DUMPABLE, 1);
    if (ret < 0) {
        fprintf(stderr, "prctl: %s", strerror(errno));
    }

이런 식으로 되겠다.

만일 위 코드에서 corelimit.rlim_cur와 corelimit.rlim_max 부분을 0으로 만들어주면 무조건 core가 남지 않게 된다. argument 나 설정 파일 등을 통해서 유동성있게 구성해도 되겠다.

보너스로, 원하는 디렉토리에 core file을 남길 수도 있다.
알다시피 core file은 프로그램의 현재 작업 디렉토리 상에 남게 되므로, 현재 작업 디렉토리를 바꿔 주면 간단하게 해결된다. 이를테면,

    chdir("/mywork");

아주 간단하게 해결된다.

And