前一子上班r, Samuel 跑^:

“咦? 你之前某 Server 的r候, 怎N程式自己a生 Core dump 啊?”

“就是用 setrlimit(2) 的啊!”

“那我看一下樯段艺罩不..”

]想到就_始了酷的~ 我花M了不少工夫才lF樯觞N.

在 Linux 上, AO是不 Core dump 的, 而要程式a生 Core dump 的方法就是利用 bash built-in 的 ulimit 指令. 我去年@篇 How to enlarge Coredump Size and File Descriptor Limitations 好也有到.

不^意外常常有, 所以除了 System administrator O ulimit -c unlimited 之外, 我自己也诔淌窖e面利用 setrlimit(2) @b system call, 程式在绦r, 能虿还 administrator 有]有用 ulimit O定 Core dumpsize, 保C一定a生 Core dump. 在程式 crash 的r候, Core dump 是很重要索啊! 就像 CSI 一, Cf.

可是在看完 Samuel 的程式r, 我和他就X得很奇怪, 是 work 才, 因橥拥 code 的程式已在 production server 上跑了一段rg, 不}才, @r候, 我才猛然想起, 管C器的 administrator 曾f^有r候 Core dump 不霈F. “God! 不褪峭}吧?”

和 Samuel 人找完Y料的答案, 就是@篇文章的C了. 我lF, 如果一程式按照上面的方法都o法a生 Core dump, 那要看看@程式是否是用了 setuid(2) @ System call. 我lF,  setuid(2)  seteuid(2) ^後的程式, 是]有k法a生 Core dump .

好巧不巧, 通常 Server 榱艘恍┌踩缘目剂, 也作 setuid(2) 或 seteuid(2) 磉_到 Running with Least Privilege (相 Windows 的指令就是 Run As). 也就是f, setuid(2) 一定是不能略^的. 解Q方法有煞N.

第一N是只有@程式有效. 用的方法就是 prctl(2). @方法是可以改 source, 然後 rebuild 的r下才能用. Sample code 如下:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <pwd.h>
#include <sys/resource.h>
#include <sys/prctl.h>

#define SU_USER "nobody"

int main(void)
{
     struct rlimit corelimit;
     struct passwd *pw = NULL;
     char           *cp = NULL;

     /* if switch to nobody failed */
     if (NULL == (pw = getpwnam(SU_USER)))
     {
         fprintf(stderr, "Cannot get uid from user(%s). Error: %s\n",
                          SU_USER, strerror(errno));
         return -1;
     }

     /* try to switch to nobody */
     if ((setuid(pw->pw_uid) < 0) || (seteuid(pw->pw_uid) < 0))
     {
         fprintf(stderr, "Cannot switch to user(%s). Error: %s\n",
                          SU_USER, strerror(errno));
         return -2;
     }

     /* force to make coredump */
     if (prctl(PR_SET_DUMPABLE, 1) < 0)
     {
         fprintf(stderr, "Cannot enable core dumping. Error: %s\n",
                          strerror(errno));
         return -3;
     }

     /* set core size to unlimited */
     corelimit.rlim_cur = RLIM_INFINITY;
     corelimit.rlim_max = RLIM_INFINITY;
     if (setrlimit(RLIMIT_CORE, &corelimit) < 0)
     {
         fprintf(stderr, "Setrlimit failed! Error: %s\n",
                          strerror(errno));
         return -4;
     }

     /* force to coredump */
     *cp = ‘1′;

     return 0;
}

@N方法要注意的事情有:

  • 一定要用 root 绦.
    setuid 然後一般 user 去绦械姆椒ú恍.
    (e.g. sudo chown root a.out; sudo chgrp root a.out; sudo chmod 4755 a.out)
  •  Core dump a生的目和绦n在同一目下, @目的嘞抟欢ㄒ root @ user, root @ group 同r都可以入才行. 要注意@ case, 不要把 root 成是 super-user, 而是要作 regular user.
    比方f, (drwxrwxr-x, root root) 和 (drwxrwxrwx, nobody nogroup) 可以, 但是 (drwxr-xr-x root root) 和 (drwxrwxr-x root nogroup) 都不行. 很t! 我也不知道樯觞N~

第二N方法是 system-wide 的, 也就是绊到所有在系y绦械某淌. 方法就是/proc/sys/fs/suid_dumpable. 因檫@和 kernel 的版本有P, man 5 proc 比^保U. @是在o法 source code, 而且原程式]有用 prctl(2) 情r下的⑹昼.

要注意的事情和第一N方法一, 把 /proc/sys/fs/suid_dumpable O成 1 或 2 的差e, 是Q定 core dumpfile 的碛姓. 如果O成 1, 就偷谝环N方法一邮潜 switch 的 owner (本例是 nobody). 如果O 2 就一定是 root, 但是@似乎要 kernel 2.6.13 以上才有 support? 我不是很_定.

希望@篇文章o大家作⒖!

PS: @篇竟然了快二周末, 真是蚓玫~