As it stands the current "fixes" for Meltdown and Spectre mainly involve updating and upgrading hosts to include their patched kernel upgrades. When it comes to applying the updates to multiple Linux servers, one approach is to use the playbook/plays in this "lockdown" repo from Ansible.
https://github.com/ansible/ansible-lockdown/blob/master/meltdown-spectre-linux.yml
This is how the YAML works to patch the aforementioned exploits.
First off for the hosts directive, either the default all
hosts is used or any hosts provided -i
when running ansible-playbook
take precedence. The tasks are to be carried out with become:
and thereby super user privileges.
# https://meltdownattack.com
- name: Patch Linux systems against Meltdown and Spectre
hosts: "{{ target_hosts | default('all') }}"
become: yes
Variables are defined ready for use later on in the tasks section.
reboot_after_update:
is set to no
but should be set to "yes" where possible by yourself. The reason for this is covered properly towards the end of these explanations.
packages:
contains the required kernel package versions for each respective Linux distro. Most of the Debian/Ubuntu entries are empty with the exception of Debian 9 (the latest stable version) which contains the specific kernel package.
The empty values may be updated by the maintainers at some point, but you can add in the kernel packages yourself for the empty ones. I've done this in the next code snippet, from the information given at these two links:
https://www.debian.org/security/2018/dsa-4078
https://wiki.ubuntu.com/SecurityTeam/KnowledgeBase/SpectreAndMeltdown
These kernel packages are in essence the only Meltdown and or Spectre "fixes" currently available.
vars:
reboot_after_update: no
packages:
# https://access.redhat.com/security/vulnerabilities/speculativeexecution
RedHat7:
- kernel-3.10.0-693.11.6.el7
- microcode_ctl-2.1-22.2.el7
- perf-3.10.0-693.11.6.el7
- python-perf-3.10.0-693.11.6.el7
RedHat6:
- kernel-2.6.32-696.18.7.el6
- kernel-firmware-2.6.32-696.18.7.el6
- perf-2.6.32-696.18.7.el6
- python-perf-2.6.32-696.18.7.el6
# https://www.debian.org/security/2018/dsa-4078
Debian7:
- linux-image-3.2.0-5-amd64
Debian8:
- linux-image-3.16.0-5-amd64
Debian9:
- linux-image-4.9.0-5-amd64
# https://wiki.ubuntu.com/SecurityTeam/KnowledgeBase/SpectreAndMeltdown
Ubuntu14:
- linux-image-3.13.0-141-generic
Ubuntu16:
- linux-image-4.4.0-112-generic
Ubuntu17:
- linux-image-4.13.0-31-generic
Note: Please remember that this is as things stand right now with the kernel patching in late January, so these version numbers are always subject to change as new fixes are released.
There are two tasks in total. One for each type of package manager in use on the various distros.
When Yum is detected on the host by Ansible, the first task is executed and the distro packages defined previously are referenced for installation. This is done using the ansible_os_family
and ansible_distribution_major_version
system fact variables - the distro name and version number respectively.
A handler is then called to reboot the host (explained later on).
tasks:
- name: RHEL | Install kernel updates
yum:
name: "{{ packages[ansible_os_family ~ ansible_distribution_major_version] }}"
state: present
when: ansible_pkg_mgr == 'yum'
notify: reboot system
If Aptitude (apt
) is detected on the host in place of Yum, the second task is run instead. Which uses a similar process. The distro type and version number are sourced from the start in order to install the correct packages (like in the other task), whilst the package index is updated via update_cache:
.
As before the host is then rebooted via the handler (more on that now, as promised).
- name: DEBIAN | Install kernel updates
apt:
name: "{{ item }}"
state: present
update_cache: yes
cache_valid_time: 3600
with_items: "{{ packages[ansible_distribution ~ ansible_distribution_major_version] }}"
when: ansible_pkg_mgr == 'apt'
notify: reboot system
If the variable reboot_after_update
from the start is set to yes
or true. The host(s) will reboot at the end of each task run, as the handler is called.
This is here as it's necessary to reboot the system to begin using the new kernel changes brought in for the Spectre/Meltdown exploits. So you should set reboot_after_update
to "yes" at the start of the file, as long as it's safe to do so in terms of node availability and uptime.
Lastly async:
allows the shutdown command to run for a maximum of 15
seconds, but also poll:
tells Ansible to check constantly for its completion. This is all so Ansible moves on and doesn't idle from the node's system shutdown.
handlers:
- name: reboot system
shell: sleep 3; reboot
async: 15
poll: 0
when: reboot_after_update
It might be better to download the repository itself but if you want the meltdown-spectre-linux.yml
file I showed here (with all the kernel package versions added in) use this Gist instead:
https://gist.github.com/5car1z/ddbb17cb763d5aedf129732213febac4
Warning: Be aware that the "reboot" variable is set to yes in this Gist.
Run the file against your desired host groups or host patterns as normal, adding a -K
sudo password or -u
user switch if relevant e.g.
$ ansible-playbook -l webservers meltdown-spectre-linux.yml -K
Then watch Ansible check and update the kernel packages on each host. Oh and uname -r
reveals the kernel package in use by your current node.
Thanks to Sam Doran for the plays and the Ansible repository this is taken from.