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

通过 kptr_restrict 来控制/proc/kallsyms 是否显示symbol的地址
例如这个值是1的时候就可以显示symbol
linux-7gzn:~ # cat /proc/sys/kernel/kptr_restrict 
1
linux-7gzn:~ # cat /proc/kallsyms 
ffff000008080000 t _head
ffff000008080000 T _text
ffff000008080040 t pe_header
ffff000008080044 t coff_header
ffff000008080058 t optional_header

如果把这个值写成2,就可以看到symbol的地址都是零
linux-7gzn:~ # echo 2 > /proc/sys/kernel/kptr_restrict
linux-7gzn:~ # cat /proc/sys/kernel/kptr_restrict
2
linux-7gzn:~ # cat /proc/kallsyms 
0000000000000000 t _head
0000000000000000 T _text
0000000000000000 t pe_header
0000000000000000 t coff_header
0000000000000000 t optional_header
0000000000000000 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
用户都可以查看

你可能感兴趣的:(Linux,源码分析)