Skip to content

Commit

Permalink
Move meltdown check to base system
Browse files Browse the repository at this point in the history
  • Loading branch information
alexAubin committed May 8, 2020
1 parent 355ed7f commit a799740
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 101 deletions.
74 changes: 73 additions & 1 deletion data/hooks/diagnosis/00-basesystem.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#!/usr/bin/env python

import os
import json
import subprocess

from moulinette.utils.process import check_output
from moulinette.utils.filesystem import read_file
from moulinette.utils.filesystem import read_file, read_json, write_to_json
from yunohost.diagnosis import Diagnoser
from yunohost.utils.packages import ynh_packages_version

Expand Down Expand Up @@ -74,5 +76,75 @@ def run(self):
details=ynh_version_details)


if self.is_vulnerable_to_meltdown():
yield dict(meta={"test": "meltdown"},
status="ERROR",
summary="diagnosis_security_vulnerable_to_meltdown",
details=["diagnosis_security_vulnerable_to_meltdown_details"]
)

def is_vulnerable_to_meltdown(self):
# meltdown CVE: https://security-tracker.debian.org/tracker/CVE-2017-5754

# We use a cache file to avoid re-running the script so many times,
# which can be expensive (up to around 5 seconds on ARM)
# and make the admin appear to be slow (c.f. the calls to diagnosis
# from the webadmin)
#
# The cache is in /tmp and shall disappear upon reboot
# *or* we compare it to dpkg.log modification time
# such that it's re-ran if there was package upgrades
# (e.g. from yunohost)
cache_file = "/tmp/yunohost-meltdown-diagnosis"
dpkg_log = "/var/log/dpkg.log"
if os.path.exists(cache_file):
if not os.path.exists(dpkg_log) or os.path.getmtime(cache_file) > os.path.getmtime(dpkg_log):
self.logger_debug("Using cached results for meltdown checker, from %s" % cache_file)
return read_json(cache_file)[0]["VULNERABLE"]

# script taken from https://github.com/speed47/spectre-meltdown-checker
# script commit id is store directly in the script
SCRIPT_PATH = "/usr/lib/moulinette/yunohost/vendor/spectre-meltdown-checker/spectre-meltdown-checker.sh"

# '--variant 3' corresponds to Meltdown
# example output from the script:
# [{"NAME":"MELTDOWN","CVE":"CVE-2017-5754","VULNERABLE":false,"INFOS":"PTI mitigates the vulnerability"}]
try:
self.logger_debug("Running meltdown vulnerability checker")
call = subprocess.Popen("bash %s --batch json --variant 3" %
SCRIPT_PATH, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)

# TODO / FIXME : here we are ignoring error messages ...
# in particular on RPi2 and other hardware, the script complains about
# "missing some kernel info (see -v), accuracy might be reduced"
# Dunno what to do about that but we probably don't want to harass
# users with this warning ...
output, err = call.communicate()
assert call.returncode in (0, 2, 3), "Return code: %s" % call.returncode

# If there are multiple lines, sounds like there was some messages
# in stdout that are not json >.> ... Try to get the actual json
# stuff which should be the last line
output = output.strip()
if "\n" in output:
self.logger_debug("Original meltdown checker output : %s" % output)
output = output.split("\n")[-1]

CVEs = json.loads(output)
assert len(CVEs) == 1
assert CVEs[0]["NAME"] == "MELTDOWN"
except Exception as e:
import traceback
traceback.print_exc()
self.logger_warning("Something wrong happened when trying to diagnose Meltdown vunerability, exception: %s" % e)
raise Exception("Command output for failed meltdown check: '%s'" % output)

self.logger_debug("Writing results from meltdown checker to cache file, %s" % cache_file)
write_to_json(cache_file, CVEs)
return CVEs[0]["VULNERABLE"]


def main(args, env, loggers):
return BaseSystemDiagnoser(args, env, loggers).diagnose()
98 changes: 0 additions & 98 deletions data/hooks/diagnosis/90-security.py

This file was deleted.

2 changes: 0 additions & 2 deletions locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,6 @@
"diagnosis_regenconf_allgood": "All configurations files are in line with the recommended configuration!",
"diagnosis_regenconf_manually_modified": "Configuration file <code>{file}</code> appears to have been manually modified.",
"diagnosis_regenconf_manually_modified_details": "This is probably OK if you know what you're doing! YunoHost will stop updating this file automatically... But beware that YunoHost upgrades could contain important recommended changes. If you want to, you can inspect the differences with <cmd>yunohost tools regen-conf {category} --dry-run --with-diff</cmd> and force the reset to the recommended configuration with <cmd>yunohost tools regen-conf {category} --force</cmd>",
"diagnosis_security_all_good": "No critical security vulnerability was found.",
"diagnosis_security_vulnerable_to_meltdown": "You appear vulnerable to the Meltdown criticial security vulnerability",
"diagnosis_security_vulnerable_to_meltdown_details": "To fix this, you should upgrade your system and reboot to load the new linux kernel (or contact your server provider if this doesn't work). See https://meltdownattack.com/ for more infos.",
"diagnosis_description_basesystem": "Base system",
Expand All @@ -236,7 +235,6 @@
"diagnosis_description_web": "Web",
"diagnosis_description_mail": "Email",
"diagnosis_description_regenconf": "System configurations",
"diagnosis_description_security": "Security checks",
"diagnosis_ports_could_not_diagnose": "Could not diagnose if ports are reachable from outside in IPv{ipversion}.",
"diagnosis_ports_could_not_diagnose_details": "Error: {error}",
"diagnosis_ports_unreachable": "Port {port} is not reachable from outside.",
Expand Down

0 comments on commit a799740

Please sign in to comment.