Hide Kernel Symbols for Better Security vs Reproducible Builds

Quote:

If you say Y here, getting information on loaded modules, and
displaying all kernel symbols through a syscall will be restricted
to users with CAP_SYS_MODULE. For software compatibility reasons,
/proc/kallsyms will be restricted to the root user. The RBAC
system can hide that entry even from root.

This option also prevents leaking of kernel addresses through
several /proc entries.

Note that this option is only effective provided the following
conditions are met:

  1. The kernel using grsecurity is not precompiled by some distribution
  2. You have also enabled GRKERNSEC_DMESG
  3. You are using the RBAC system and hiding other files such as your
    kernel image and System.map. Alternatively, enabling this option
    causes the permissions on /boot, /lib/modules, and the kernel
    source directory to change at compile time to prevent
    reading by non-root users.
    If the above conditions are met, this option will aid in providing a
    useful protection against local kernel exploitation of overflows
    and arbitrary read/write vulnerabilities.

It is highly recommended that you enable GRKERNSEC_PERF_HARDEN
in addition to this feature.

Is hiding kernel symbols even possible without grsecurity?

security-misc is already deleting system.map files and restricts kallsyms. Soon we’ll implement make /boot and /lib/modules unreadable for non-root users and maybe even make /boot and /lib/modules unreadable even for root.

and the kernel source directory

Why even the kernel source directory should be hidden?

One idea of kernel recompilation for better hardening was the recompile on the users machine so the kernel would be uniquely compiled and kernel symbols would stay hidden, Rather than using Debian public kernel (from packages.debian.org) which has public well known kernel symbols.

But Debian is working towards reproducible builds. Thereby when compiling the Debian kernel on the user’s machine, it is likely the user would end up with a byte identical versions.

Could we use a reproducibility build kernel and then somehow instruct the kernel (through a kernel parameter or something) automagically randomize its kernel symbols addresses?

https://kernsec.org/wiki/index.php/Bug_Classes/Kernel_pointer_leak

1 Like

HIDESYM is essentially kernel.kptr_restrict which we already set.

1 Like

Assume this is true. Assume we have HIDESYM / kernel.kptr_restrict.

The critical point is…

vs nowadays reproducible builds. The kernel image cannot be in a public known state. It needs to be unique, private.

How the kernel image looks is public knowledge or easily knowable by compiling oneself.

Quote:

In the initial discussion about hiding /proc/kallsyms, a few people pointed out that most installations are distro kernels, and attackers can simply hard-code the addresses for the necessary functions.

system.map (kernel symbol addresses) file can be created from public or self-compiled kernel (vmlinux) (attacker could recompile. Just use the source code, and version and config we are using). Thanks to (mostly or already fully) reproduiclbe builds, the attacker would have the vmlinux binary. And then could deduct the kernel symbol addresses from that. Then hardcode these addresses in malware.

The only way to prevent that is to recompile the vmlinux binary in a… How? Randomize the vmlinux build somehow? A kernel parameter? Somehow supply the kernel with a random file so it can randomize itself?

1 Like
1 Like

The only thing I know that does this is OpenBSD’s KARL which basically generates a new kernel on each reboot. There doesn’t seem to be any equivalent for Linux.

1 Like

In theory, Linux has this feature? Called ASLR. See:
Address space layout randomization - Wikipedia

Yet, these addresses are mostly the same in two different VMs. In one VM:

sudo sysctl -w kernel.kptr_restrict=1 >/dev/null && sudo cat /proc/kallsyms > a

In another VM with the same kernel:

sudo sysctl -w kernel.kptr_restrict=1 >/dev/null && sudo cat /proc/kallsyms > b

Then compare files a and b. There is more similarity than differences, looks like. (Differences could be due to different kernel modules being load.)

1 Like

https://forums.grsecurity.net/viewtopic.php?f=7&t=3367

1 Like

No, ASLR is only for userspace memory. KASLR is for kernel memory and doesn’t change any kernel pointers. One of the reasons KASLR was such a bad idea is because the kernel is full of kernel pointer leaks.

Grsec made a good blog post on it.

As for kstructhunter, structleak should prevent that but because Debian’s repos are so old, it doesn’t yet support that.

1 Like

Actually, it’s randstruct, not structleak.

All these GCC plugins can be confusing sometimes.

1 Like

Excellent! GCC_PLUGIN_RANDSTRUCT was the holy grail I was looking for. Mentioned here:

1 Like

I think you might be confused. Kernel structs and kernel pointers aren’t the same. While randstruct is important, it’s not really the point of this post.

1 Like
1 Like

Mailed forrest who then posted a reply:
exploit - How to hide Kernel Symbols in Linux Kernel Image? Recompliation? - Information Security Stack Exchange

1 Like