Closed vpetersson closed 5 years ago
Kernel configs are not available unless the kernel was built with exported configs. This is not always the case.
Yes, you're right. I'm open to better checks.
If kernel configs are not exported I don't see any other way to check if CONFIG_PAGE_TABLE_ISOLATION is on. All other methods given in this article don't work.
But I have a better idea. If a user has a "standard" kernel running (the one from Debian/Ubuntu repo) we can check it for vulns related to meltdown/spectre, their list is here. Otherwise, i.e. custom kernel is running, if the kernel is older than 4.14.12, 4.9.75, or 4.4.110 (needs some versioning logic here) it's vulnerable. If it's newer - we try "heuristics" described in the article.
By the way this script checks for all meltdown/spectre vulnerabilities using just grep, perl and binutils. Looks cool.
Just found this SO thread where they give one simple command to check for PTI: cat /sys/devices/system/cpu/vulnerabilities/* | grep PTI
. It works on my Ubuntu, although I'm afraid if this list of vulnerabilities in sysfs may be a switchable option.
Also grep -q "cpu_insecure\|cpu_meltdown\|kaiser" /proc/cpuinfo && echo "patched :)" \ || echo "unpatched :("
works too.
Checking dmesg or systemd journal is not an option because they both get rotated after some uptime, and the message about PTI is among the very first.
And there's another mitigation agains Spectre v2, called Retpoline. Need to check for CONFIG_RETPOLINE, or
$ cat /sys/devices/system/cpu/vulnerabilities/spectre_v2
Mitigation: Full generic retpoline, IBPB: conditional, IBRS_FW, STIBP: conditional, RSB filling
also
$ grep "cpu_insecure\|cpu_meltdown\|kaiser" /proc/cpuinfo
bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs
@a-martynovich Let's assume everyone will be using upstream kernels (which is the case for most today), in which case, checking the kernel against the CVE list is perhaps the path of least resistance.
@vpetersson By upstream you mean kernel upstream or Ubuntu/Debian upstream?
Upstream from Ubuntu/Debian.
Another addition. This article states that most AMD and ARM CPUs are not subject to these vulnerabilities. We should only check x86 (i386 and x86_64) and make sure it's an Intel CPU. Agent needs to send CPU model in ping.
Yep, this is a sensible filter. The bug was Intel only.
We want to see which deb package contains the currently running kernel. Here's how I think we can do it with some level of certainty.
Get the currently running kernel version:
# uname -a
Linux artem-linux-gf 5.0.0-32-generic #34~18.04.2-Ubuntu SMP Thu Oct 10 10:36:02 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
Find which vmlinuz
has the same version:
# file /boot/vmlinuz-5.0.0-32-generic
/boot/vmlinuz-5.0.0-32-generic: Linux kernel x86 boot executable bzImage, version 5.0.0-32-generic (buildd@lgw01-amd64-015) #34~18.04.2-Ubuntu SMP Thu Oct 10 10:36:02 UTC 2019, RO-rootFS, swap_dev 0x8, Normal VGA
We can't tell with 100% certainty if the currently running kernel was loaded from this vmlinuz
unless we compare the checksum of the running kernel and the uncompressed file, but having identical versions (5.0.0-32-generic ... #34~18.04.2-Ubuntu SMP Thu Oct 10 10:36:02 UTC 2019
) is already enough IMO.
Find which installed deb package has this vmlinuz
:
# dpkg -L linux-image-5.0.0-32-generic
/.
/boot
/boot/vmlinuz-5.0.0-32-generic
...
This means the currently running kernel is installed with linux-image-5.0.0-32-generic
. Should work on Debian too.
Doesn't work on Raspbian because its kernel gets installed as part of raspberrypi-kernel
package which contains kernel packed into "ARM boot executable zImage". To see which kernel is inside we need to extract the kernel from the image. That's not very easy and IMO not worth it.
Here's what I learned from studying kernel source code and Debian repos.
All kernels used by all Debian suites since Jessie are patched against all known CPU vulnerabilities. That includes versions 3.16, 4.4, 4.9 and 5.0+. The patches export vulnerability status at /sys/devices/system/cpu/vulnerabilities/*
, and the possible status values are described in the docs. Also it's possible to disable every one of them by passing options to the kernel, but this should be reflected in status files as well (needs additional checking).
There're six mitigations (below are corresponding files in /sys/devices/system/cpu/vulnerabilities):
Not affected
or Mitigation: PTE Inversion[; ...]
Not affected
, Vulnerable[: ...]
, Mitigation: Clear CPU buffers[; ...]
Not affected
, Vulnerable[: ...]
, Mitigation: ...
If any of these are absent or have status different from Not affected
or Mitigation: ...
this means the system is probably vulnerable. Otherwise the system is protected.
It is possible to bind-mount anything over /sys/devices/system/cpu/vulnerabilities in which case these files won't be available. Also they won't be available if the kernel does not have the protection compiled in. In this case we should check the kernel against the list of corresponding CVEs. If the kernel is not vulnerable to any of CVEs (meaning it has all the patches) but it has any mitigations disabled in its cmdline then it's vulnerable.
Here's what the agent should send to the server:
{ cpu: {vendor: "Intel", vulnerable: true/false/null, mitigations_disabled: true/false}}
In case if vulnerable == null
the server should check the kernel against the list of corresponding CVEs and report it as vulnerable if either a CVE is found or mitigations_disabled==true
.
Kernel cmdline parameters which disable miitigations:
mds=off
pti=off
nopti
mitigations=off
nospectre_v1
nospectre_v2
spectre_v2=off
spectre_v2_user=off
spec_store_bypass_disable=off
CVEs:
Most of these CVEs affect not only the kernel (linux*
packages) but also xen, qemu and nvidia drivers. Therefore not only the currently installed and running kernel package should be queried for CVEs, but also all the listed CVEs should be queried for any installed package.
In case of Jessie, if any Nvidia drivers (nvidia-graphics-drivers
or nvidia-graphics-drivers-legacy*
) is installed from non-free
repo the system will be vulnerable to some of these CVEs and there's no fix (and there won't be any). I think it should be told to the user. The user has an option to uninstall the drivers.
To find out which kernel is currently running we need to get the BOOT_IMAGE
kernel cmdline parameter which points to a file in /boot
. Then find which deb binary package contains this file and send the corresponding source package to the server.
@vpetersson do we need a security tab section for this check or having only recommended action is enough?
yes, let's add a security tab section for this too.
@a-martynovich ^
@vpetersson Please provide text for the recommended action.
@a-martynovich / @rptrchv found it here.
Header: $HOST is vulnerable to Meltdown/Spectre
We detected that $HOST is vulnerable to Meltdown/Spectre. You can learn more about these issues <a href="https://meltdownattack.com/">here</a>. To fix the issue, please run `apt-get update && apt-get install $PACKAGES`
@vpetersson I've changed the text, but I had to write apt-get update && apt-get upgrade
instead because the current code doesn't report which packages are affected (other than the kernel). Is this ok or should i list which packages are affected?
Yeah that's fine for now.
Meltdown/Spectre was a big thing. Let's add a security check for it.
We should be able to check it as follows:
(The patched/unpateched is obviously just for readability)