When kallsyms doesn't show addresses even though kptr_restrict is 0

When I did grep kernel symbol address, addresses were all zero.

masami@saga:~$ grep slab_alloc /proc/kallsyms 
0000000000000000 t ___slab_alloc
0000000000000000 t __slab_alloc

So, I checked kptr_restrict if it's not zero.

masami@saga:~$ sudo sysctl kernel.kptr_restrict
kernel.kptr_restrict = 0

Um, kptr_restrict was already zero. By the way, how about kernel config that enables KALLSYMS ? Current kernel version is here.

masami@saga:~$ uname -a
Linux saga 4.18.13-300.fc29.x86_64 #1 SMP Wed Oct 10 17:22:50 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

So, in /boot there is kernel configs that I could check it.

masami@saga:~$ grep -i kallsyms /boot/config-4.18.13-300.fc29.x86_64
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y
CONFIG_KALLSYMS_BASE_RELATIVE=y

Ok, KALLSYMS is enabled. But how come I couldn't get addresses? Let's check kernel functions.

When you open /proc/kallsyms, kallsyms_show_value() is called. In my case, kptr_restrict is 0, so kallsyms_for_perf() is called.

int kallsyms_show_value(void)
{
    switch (kptr_restrict) {
    case 0:
        if (kallsyms_for_perf())
            return 1;
    /* fallthrough */
    case 1:
        if (has_capability_noaudit(current, CAP_SYSLOG))
            return 1;
    /* fallthrough */
    default:
        return 0;
    }
}

kallsyms_for_perf() is following simple function.

static inline int kallsyms_for_perf(void)
{
#ifdef CONFIG_PERF_EVENTS
    extern int sysctl_perf_event_paranoid;
    if (sysctl_perf_event_paranoid <= 1)
        return 1;
#endif
    return 0;
}

As you can see, thee is #ifdef macro. so, check CONFIG_PERF_EVENTS in kernel config.

masami@saga:~$ grep CONFIG_PERF_EVENTS /boot/config-4.18.13-300.fc29.x86_64
CONFIG_PERF_EVENTS=y
CONFIG_PERF_EVENTS_INTEL_UNCORE=m
CONFIG_PERF_EVENTS_INTEL_RAPL=m
CONFIG_PERF_EVENTS_INTEL_CSTATE=m
CONFIG_PERF_EVENTS_AMD_POWER=m

Ok, if perf_event_paranoid is less than or equal to 1, it returns 1, otherwise return 0. Let's check perf_event_paranoid.

masami@saga:~$ sudo sysctl kernel.perf_event_paranoid
kernel.perf_event_paranoid = 2

Ah, I got it. However, what value can I use for? According to Documentation/sysctl/kernel.txt, there is a paragraph that describes perf_event_paranoid values. Maybe 1 is okay for me now.

masami@saga:~$ sudo sysctl -w kernel.perf_event_paranoid=1
kernel.perf_event_paranoid = 1

Then check symbols again.

masami@saga:~$ grep slab_alloc /proc/kallsyms 
ffffffff96272150 t ___slab_alloc
ffffffff96272790 t __slab_alloc

got it :)

Understanding the Linux Kernel: From I/O Ports to Process Management

Understanding the Linux Kernel: From I/O Ports to Process Management