本文共 2452 字,大约阅读时间需要 8 分钟。
通过 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); } else seq_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用户都可以查看
转载地址:http://nejmi.baihongyu.com/