| #!/bin/bash |
| # SPDX-License-Identifier: GPL-2.0 |
| # |
| # Copyright (c) 2024 - Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| # |
| # cve_update - Update all existing CVE entries based on the latest information |
| # pulled from the git tree(s). |
| # |
| # Will look through the list of all published cve ids and run 'bippy' on them |
| # to update the mbox and json files. It is recommended that after this |
| # happens, submit the json files to CVE again, if version numbers have changed. |
| # |
| # This is good to do after older stable kernels have been released as often |
| # CVEs are included in older stable kernels AFTER they show up in newer ones, |
| # and this keeps the database at CVE more up to date and friendly for others to |
| # rely on. The mbox files generally shouldn't be resent, as that's just noise |
| # that no one wants to see. |
| # |
| # Usage: |
| # cve_update |
| # |
| # Requires: |
| # bippy |
| |
| # Colors are good! |
| if [[ -t 1 ]]; then |
| txtred=$(tput setaf 1) # Red |
| txtgrn=$(tput setaf 2) # Green |
| txtylw=$(tput setaf 3) # Yellow |
| txtblu=$(tput setaf 4) # Blue |
| txtcyn=$(tput setaf 6) # Cyan |
| txtrst=$(tput sgr0) # Text reset |
| else |
| txtred="" |
| txtgrn="" |
| txtylw="" |
| txtblu="" |
| txtcyn="" |
| txtrst="" |
| fi |
| |
| # set where the tool was run from, |
| # the name of our script, |
| # and the git version of it |
| DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" |
| SCRIPT=${0##*/} |
| |
| help() { |
| echo "${SCRIPT}" |
| echo " Note, CVE_USER must be set to your CVE_USER email address" |
| exit 1 |
| } |
| |
| CVE=$1 |
| |
| # don't use unset variables |
| set -o nounset |
| |
| cd "${DIR}"/../ || exit 1 |
| |
| update_cve() |
| { |
| local id=$1 |
| local string=$2 |
| local message="" |
| local tmp_json |
| local tmp_mbox |
| local sha |
| local cve |
| local root |
| local vuln_file |
| local vulnerable_sha |
| local vulnerable_option |
| local diff_file |
| local reference_file |
| local reference_option |
| local result |
| local updated_file |
| local diff |
| local diff_option |
| |
| tmp_json=$(mktemp -t "${SCRIPT}XXXX.json" || exit 1) |
| tmp_mbox=$(mktemp -t "${SCRIPT}XXXX.mbox" || exit 1) |
| sha=$(cat "${id}") |
| cve=$(echo "${id}" | cut -f 1 -d '.' | cut -f 4 -d '/') |
| root=$(echo "${id}" | cut -f 1 -d '.') |
| #echo "id=${id} sha=${sha} cve=${cve}" |
| message+="Updating ${txtcyn}${cve}${txtrst} ${txtylw}${string}${txtrst}..." |
| |
| # Look to see if we have a "og_vuln" that is provided to us in a |
| # published CVE. This is used for when we can't determine it on our |
| # own, but we have manually looked it up later on and added it to a |
| # CVE-*.vulnerable file |
| vuln_file="${root}.vulnerable" |
| #echo "vuln_file=${vuln_file}" |
| vulnerable_option="" |
| vulnerable_sha="" |
| if [[ -f "${vuln_file}" ]]; then |
| vulnerable_sha=$(cat "${vuln_file}") |
| vulnerable_option="--vulnerable=${vulnerable_sha}" |
| fi |
| |
| diff_option="" |
| diff_file="${root}.diff" |
| if [[ -f "${diff_file}" ]]; then |
| diff_option="--diff=${diff_file}" |
| fi |
| |
| reference_option="" |
| reference_file="${root}.reference" |
| if [[ -f "${reference_file}" ]]; then |
| reference_option="--reference=${reference_file}" |
| fi |
| |
| # Create the new json and mbox files |
| sha_args=() |
| while IFS= read -r line; do |
| [ -n "$line" ] && sha_args+=(--sha="$line") |
| done < "${id}" |
| "${DIR}"/bippy --cve="${cve}" "${sha_args[@]}" --json="${tmp_json}" --mbox="${tmp_mbox}" --vulnerable="${vulnerable_sha}" "${diff_option}" "${reference_option}" |
| result=$? |
| if [[ "${result}" != 0 ]]; then |
| # bippy failed, so report it and continue on |
| echo "${txtred}Error:${txtrst} bippy failed to create ${txtcyn}${cve}${txtrst} for commit ${txtgrn}${sha}${txtrst}" |
| return |
| fi |
| |
| # see if the json and/or mbox files actually changed, EXCEPT for the bippy-VERSIONINFO string |
| updated_file="" |
| diff=$(diff -u "${root}.json" "${tmp_json}" | grep -v "${tmp_json}" | grep -v "${root}.json" | grep -v "bippy" | grep -v "^@@ " | grep "^[+|-]" | grep -v "@kernel.org" | grep -v "@linuxfoundation.org") |
| #echo "diff json=${diff}" |
| if [[ "${diff}" != "" ]] ; then |
| mv -f "${tmp_json}" "${root}.json" |
| updated_file+="${root}.json" |
| else |
| rm "${tmp_json}" |
| #echo "diff for json was empty" |
| fi |
| |
| diff=$(diff -u "${root}.mbox" "${tmp_mbox}" | grep -v "${tmp_mbox}" | grep -v "${root}.mbox" | grep -v "bippy-" | grep -v "^@@ " | grep "^[+|-]" | grep -v "@kernel.org" | grep -v "@linuxfoundation.org") |
| #echo "diff mbox=${diff}" |
| if [[ "${diff}" != "" ]] ; then |
| mv -f "${tmp_mbox}" "${root}.mbox" |
| updated_file+=" ${root}.mbox" |
| else |
| rm "${tmp_mbox}" |
| #echo "diff for mbox was empty" |
| fi |
| if [[ "${updated_file}" == "" ]] ; then |
| message+=" ${txtgrn}Nothing changed${txtrst}" |
| else |
| message+=" Updated ${txtblu}${updated_file}${txtrst}" |
| fi |
| echo "${message}" |
| } |
| |
| update_year() { |
| local year=$1 |
| local threads=$(nproc) |
| |
| # get a count of ids for this year |
| total_count=$(ls cve/published/${year}/*.sha1 | wc -l) |
| count=0 |
| |
| echo "Updating ${txtcyn}${total_count}${txtrst} CVE ids for ${txtgrn}${year}${txtrst} with ${txtcyn}${threads}${txtrst} processes..." |
| for id in cve/published/${year}/*.sha1 ; do |
| count=$((count + 1)) |
| count_string=$(printf "[%04d/%04d]" ${count} ${total_count}) |
| while : |
| do |
| if [[ $(jobs -p | wc -l) -lt ${threads} ]]; then |
| #echo "id=${id}" |
| update_cve "${id}" "${count_string}" & |
| break |
| else |
| sleep 1 |
| fi |
| done |
| done |
| wait |
| } |
| |
| if [[ "${CVE}" == "" ]]; then |
| # Nothing specified on the command line, so just update everything by |
| # looping through all years |
| for y in cve/published/* ; do |
| year=$(echo "${y}" | cut -f 3 -d '/') |
| update_year ${year} |
| done |
| else |
| # Either the year, or a specific CVE id is specified here. |
| # |
| # Test for a specific cve id first |
| found=$(${DIR}/cve_search ${CVE}) |
| found_result=$? |
| if [[ "${found_result}" == "0" ]]; then |
| CVE_ROOT="${DIR}/../cve/" |
| found=$(find "${CVE_ROOT}" -type f | grep -v testing | grep "${CVE}" | grep "sha1") |
| #echo "found='${found}" |
| if [[ "${found}" != "" ]]; then |
| # strip off the CVE root, as that's what update_cve is expecting: |
| update_cve "cve/${found/#$CVE_ROOT}" "1" |
| exit 0 |
| fi |
| fi |
| |
| # Not a specific id, let's try to do this for a year |
| # |
| if [[ -d cve/published/${CVE} ]]; then |
| update_year ${CVE} |
| exit 0 |
| fi |
| |
| echo "${txtred}ERROR:${txtrst} ${txtcyn}${CVE}${txtrst} is not found or is not a year." |
| exit 1 |
| fi |
| |