kptr_restrict 来控制/proc/kallsyms 是否显示symbol的地址

来源:互联网 发布:淘宝卖保健品怎么样 编辑:程序博客网 时间:2024/06/07 19:09
通过 kptr_restrict 来控制/proc/kallsyms 是否显示symbol的地址例如这个值是1的时候就可以显示symbollinux-7gzn:~ # cat /proc/sys/kernel/kptr_restrict 1linux-7gzn:~ # cat /proc/kallsyms ffff000008080000 t _headffff000008080000 T _textffff000008080040 t pe_headerffff000008080044 t coff_headerffff000008080058 t optional_header如果把这个值写成2,就可以看到symbol的地址都是零linux-7gzn:~ # echo 2 > /proc/sys/kernel/kptr_restrictlinux-7gzn:~ # cat /proc/sys/kernel/kptr_restrict2linux-7gzn:~ # cat /proc/kallsyms 0000000000000000 t _head0000000000000000 T _text0000000000000000 t pe_header0000000000000000 t coff_header0000000000000000 t optional_header0000000000000000 t extra_header_fie为什么会这样呢?还得从kallsyms.c的源代码中找线索static int s_show(struct seq_file *m, void *p){struct kallsym_iter *iter = m->private;/* Some debugging symbols have no name.  Ignore them. */if (!iter->name[0])return 0;if (iter->module_name[0]) {char type;/* * Label it "global" if it is exported, * "local" if not exported. */type = iter->exported ? toupper(iter->type) :tolower(iter->type);#关键一句,看起来应该是%pK 来控制是否显示地址seq_printf(m, "%pK %c %s\t[%s]\n", (void *)iter->value,   type, iter->name, iter->module_name);} elseseq_printf(m, "%pK %c %s\n", (void *)iter->value,   iter->type, iter->name);return 0;}%pK的实现在 lib/vsprintf.c 中case 'K':switch (kptr_restrict) {case 0:/* Always print %pK values */break;case 1: {const struct cred *cred;/* * kptr_restrict==1 cannot be used in IRQ context * because its test for CAP_SYSLOG would be meaningless. */if (in_irq() || in_serving_softirq() || in_nmi()) {if (spec.field_width == -1)spec.field_width = default_width;return string(buf, end, "pK-error", spec);}/* * Only print the real pointer value if the current * process has CAP_SYSLOG and is running with the * same credentials it started with. This is because * access to files is checked at open() time, but %pK * checks permission at read() time. We don't want to * leak pointer values if a binary opens a file using * %pK and then elevates privileges before reading it. */cred = current_cred();if (!has_capability_noaudit(current, CAP_SYSLOG) ||    !uid_eq(cred->euid, cred->uid) ||    !gid_eq(cred->egid, cred->gid))ptr = NULL;break;}case 2:default:/* Always print 0's for %pK */ptr = NULL;break;}break;原来kptr_restrict 的取值范围为0,1,2.值是2的话,地址就是2,就如我们前面演示的那样,地址全部显示0.一般情况这个值是1,表示root和非root用户都可以查看