blob: a4e507c8d72bbf18e049726a5c6a856df058fce5 [file] [log] [blame]
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (c) 2024-2025 - Greg Kroah-Hartman <gregkh@linuxfoundation.org>
#
# dyad - create a listing of "pairs" of vulnerable:fixed kernels based on a
# specific git SHA that purports to fix an issue. Used in combination
# with 'bippy' to create CVE entries for the Linux kernel. Is VERY
# specific to how the Linux kernel has its stable branches and how it
# labels things.
#
# Usage:
# dyad [options] GIT_SHA
# For full options, see the help text below.
#
# Requires:
# A kernel git tree with the SHA to be used in it
# id_found_in - tool to find what kernel a specific SHA is in
# set to 1 to get some debugging logging messages (or use -v/--verbose option)
DEBUG=0
# Initialize our color variables if we are a normal terminal
if [[ -t 1 ]]; then
txtred=$(tput setaf 1) # Red
txtgrn=$(tput setaf 2) # Green
txtblu=$(tput setaf 4) # Blue
txtcyn=$(tput setaf 6) # Cyan
txtrst=$(tput sgr0) # Text reset
else
txtred=""
txtgrn=""
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##*/}
SCRIPT_VERSION=$(cd "${DIR}" && git ls-tree --abbrev=12 HEAD | grep -w "${SCRIPT}" | awk '{print $3}')
# Initialize some global variable arrays
fixed_set=()
vulnerable_set=()
fixed_pairs=()
#############################
#############################
# Functions for us to use, main flow starts below
#############################
#############################
#############################
# help()
# Print out help options and exit
#############################
help()
{
echo "Usage: $0 [OPTIONS] GIT_SHA"
echo "Create a list of pairs of VULNERABLE:FIXED kernel versions and git ids based on a specific git sha value."
echo ""
echo "Arguments:"
echo " --vulnerable=GIT_SHA The kernel git sha1 that this issue became vulnerable at (optional)"
echo " -h, --help This information"
echo " -v, --verbose Show debugging information to stdout"
echo ""
exit 1
}
#############################
# dbg()
# if DEBUG is enabled, print out a message.
# Can also be set with -v or --verbose command line option
# Does so with an initial "#" so it can be easily filtered out
# arguments:
# "message to print"
# assumes:
# DEBUG is defined to something
#############################
dbg()
{
if [[ ${DEBUG} -ge 1 ]] ; then
echo "${txtcyn}# ${1}${txtrst}"
fi
}
#############################
# info()
# Print out a string as "information"
# Does so with an initial "#" so it can be easily filtered out
# arguments:
# "message to print"
#############################
info()
{
echo "${txtgrn}# ${1}${txtrst}"
}
#############################
# get_kernel_version_type()
# Determine the type of a kernel version (mainline, rc, queue, or stable)
# arguments:
# "kernel version"
# returns:
# Prints one of: "mainline", "rc", "queue", or "stable"
#############################
get_kernel_version_type() {
local VERSION=$1
# First check if it's a queue version since that's a simple string match
if [[ "${VERSION}" =~ .*"queue" ]]; then
echo "queue"
return
fi
# Parse version number into components
# shellcheck disable=SC2206
local VERSION_PARTS=(${VERSION//./ })
local MAJOR=${VERSION_PARTS[0]}
# Check for -rc versions
if [[ "${VERSION}" =~ .*"rc" ]]; then
echo "rc"
return
fi
# 2.6.X is just one more level "deep"
if [[ "${MAJOR}" == "2" ]]; then
if [[ "${#VERSION_PARTS[@]}" == "3" ]]; then
echo "mainline"
return
fi
fi
# If version only has X.Y format (no .Z), it's mainline
if [[ "${#VERSION_PARTS[@]}" == "2" ]]; then
echo "mainline"
return
fi
# Otherwise it's a stable release
echo "stable"
}
#############################
# kernel_version_is_mainline()
# Check if a kernel version is mainline
# Note: Both pure mainline and rc versions are considered mainline
#
# Arguments:
# $1: Kernel version string to check
#
# Returns:
# 1 if version is mainline or rc, 0 otherwise
#
# Example:
# kernel_version_is_mainline "6.7" # Returns: 1
# kernel_version_is_mainline "6.7-rc1" # Returns: 1
# kernel_version_is_mainline "6.7.1" # Returns: 0
#############################
kernel_version_is_mainline() {
local TYPE
TYPE=$(get_kernel_version_type "$1")
[[ "${TYPE}" == "mainline" || "${TYPE}" == "rc" ]] && return 1 || return 0
}
#############################
# kernel_version_match()
# Compare two kernel version strings to see if they share the same major.minor
# version numbers (X.Y), ignoring any patch version (Z). For example,
# "4.9.1" and "4.9.2" match, while "4.9.1" and "4.10.1" don't.
#
# Arguments:
# $1: First kernel version string (format: X.Y or X.Y.Z)
# $2: Second kernel version string (format: X.Y or X.Y.Z)
#
# Returns:
# 1 if major.minor versions match
# 0 if they don't match
#
# Example:
# kernel_version_match "4.9.1" "4.9.2" # returns 1 (match)
# kernel_version_match "4.9" "4.9.1" # returns 1 (match)
# kernel_version_match "4.9.1" "4.10.1" # returns 0 (no match)
#############################
kernel_version_match()
{
local v1=(${1//./ })
local v2=(${2//./ })
[[ "${v1[0]}" == "${v2[0]}" && "${v1[1]}" == "${v2[1]}" ]] && return 1 || return 0
}
#############################
# create_fix_set()
# Adds a new "fixed set" of kernel_version:git_id that fixes the problem
# we are tracking to the global list of fixed sets
# arguments:
# "kernel version"
# "git id"
#############################
create_fix_set()
{
local f=$1
local f_git=$2
fixed_set+=("${f}:${f_git}")
#dbg "fixed pair='${f}:${f_git}'"
}
#############################
# create_vulnerable_set()
# Adds a new "vulnerable set" of kernel_version:git_id to the global list of
# vulnerable sets we want to track
# arguments:
# "kernel version"
# "git id"
#############################
create_vulnerable_set()
{
local v=$1
local v_git=$2
vulnerable_set+=("${v}:${v_git}")
#dbg "vulnerable pair='${v}:${v_git}'"
}
#############################
# create_fixed_set()
# Adds a new "fixed pair" of vulnerable:fixed kernel information to the
# global list of fixes that we want to output.
# arguments:
# "vulnerable_kernel:vulnerable_git"
# "fixed_kernel:fixed_git"
#############################
create_fixed_pair()
{
local v=$1
local f=$2
fixed_pairs+=("${v}:${f}")
#dbg "v='${v}' f='${f}'"
#dbg "fixed pair = ${v}:${f}"
}
#############################
# git_full_id()
# returns the "FULL" sha1 of the short git id passed in
# arguments
# git-id ("subject")
# returns
# "full git id" if found, "" if not found
# assumes:
# KERNEL_TREE points to a valid Linux stable git tree
#############################
git_full_id()
{
local arg="$@"
local short_id=${arg%% *}
local subject=${arg#* }
local long_id
local id=""
long_id=($($git_cmd rev-parse --disambiguate="${short_id}" 2> /dev/null))
if [ ${#long_id[@]} -eq 1 ]; then
echo "${long_id[0]}"
return
fi
if [ ${#long_id[@]} -eq 0 ]; then
echo ""
return
fi
# Otherwise, disambiguate the short id.
# Strip the ("...") around the Subject.
subject=$(echo "${subject}" | sed -e 's/("\(.*\)")[ \t]*$/\1/')
for id in "${long_id[@]}"; do
local id_subject=$($git_cmd log -1 --format="%s" "${id}")
if [ "${id_subject}" == "${subject}" ]; then
# Found the matching subject; stop here.
echo "${id}"
return
fi
done
}
#############################
# git_short_id()
# returns the "SHORT" sha1 of the short git id passed in
# arguments
# "git id"
# returns
# "short git id" if found, "" if not found
# assumes:
# KERNEL_TREE points to a valid Linux stable git tree
#############################
git_short_id()
{
local id=${1}
local short_id
short_id=$($git_cmd log -1 --abbrev=12 --format="%h" "${id}" 2> /dev/null)
echo "${short_id}"
}
#############################
# kernel_greater_than()
# if kernel 1 is greater than kernel 2, then 1 is returned, otherwise 0
# arguments
# "kernel 1"
# "kernel 2"
#############################
kernel_greater_than()
{
local k1=$1
local k2=$2
local temp
local small
temp=$(echo -e "${k1} \n")
temp+=$(echo -e "${k2} \n")
# ${temp} is not escaped on purpose, otherwise we end up with a
# trailing space
# shellcheck disable=SC2086
small=$(printf "%s\n" ${temp} | sort -V | head -n 1)
if [[ "${small}" == "${k1}" ]]; then
return 0
else
return 1
fi
}
#############################
#############################
# "main" logic starts here
#############################
#############################
# Verify that some basic environment variables are set up
KERNEL_TREE=${CVEKERNELTREE}
# Try to find the most useful version of FOUND_IN:
# If we have one in our tools/ directory, then use that, otherwise fall back to
# the "old" version in the stand-alone repo.
if [[ -x "${DIR}/../tools/verhaal/id_find_active" ]]; then
FOUND_IN="${DIR}/../tools/verhaal/id_find_active"
elif [[ -x "${DIR}/tools/verhaal/id_find_active" ]]; then
FOUND_IN="${DIR}/tools/verhaal/id_find_active"
else
echo "${txtred}ERROR: no version of ${txtcyn}id_find_active${txtrst} found"
echo " Usually this is in the verhaal directory, please be sure you have it somewhere for us to use"
exit 1
fi
# Find our verhaal database
if [[ -f "${DIR}/../tools/verhaal/verhaal.db" ]]; then
DB="${DIR}/../tools/verhaal/verhaal.db"
elif [[ -f "${DIR}/tools/verhaal/verhaal.db" ]]; then
DB="${DIR}/tools/verhaal/verhaal.db"
else
echo "${txtred}ERROR: no verhaal database file called ${txtcyn}id_is_revert${txtrst} found"
echo " Usually this is in the verhaal directory, please be sure you have it somewhere for us to use"
exit 1
fi
SQL="sqlite3 ${DB}"
git_cmd="git --git-dir=${KERNEL_TREE}/.git"
if [[ ! -d "${KERNEL_TREE}" ]]; then
echo "${txtred}ERROR:${txtrst}"
echo " ${txtblu}CVEKERNELTREE${txtrst} needs setting to the stable repo directory"
echo -e "\nEither manually export them or add them to your .bashrc/.zshrc et al."
echo -e "\nSee HOWTO in the root of this repo"
exit 1
fi
# Parse the command line
short_opts="hv"
long_opts="vulnerable:,help,verbose"
GIT_SHA=""
GIT_VULNERABLE=""
TMP=$(getopt -o "${short_opts}" --long "${long_opts}" --name="${SCRIPT}" -- "$@")
eval set -- "${TMP}"
while :; do
dbg "arg=${1}"
case "${1}" in
-h | --help ) help;;
-v | --verbose ) DEBUG=1; shift ;;
--vulnerable ) GIT_VULNERABLE="${2}"; shift 2 ;;
-- ) shift; break ;;
esac
done
# Rest of the command line argument is the git sha we are looking at
GIT_SHA=$1
# Now we can test for unset variables, before we would have failed if someone
# forgot the git sha on the command line.
set -o nounset
# Verify we have a git sha on the command line
if [[ "${GIT_SHA}" == "" ]]; then
help
fi
# Header boiler plate info to show what is happening
info "${SCRIPT} version: ${SCRIPT_VERSION}"
#
# See if the SHA given to us is a valid SHA in the git repo.
# This tests if we have a valid kernel tree, AND we need a full/long SHA1 for
# many of the searches we do later on. If we stuck with a short one, some of
# the searches would give us false-positives as people use short shas in commit
# messages.
GIT_SHA_FULL=$(git_full_id "${GIT_SHA}")
if [[ "${GIT_SHA_FULL}" == "" ]] ; then
echo "${txtred}ERROR:${txtrst} git id ${txtcyn}${GIT_SHA}${txtrst} is not found!"
exit 1
fi
info " getting vulnerable:fixed pairs for git id ${txtcyn}${GIT_SHA_FULL}${txtrst}"
# Grab a "real" 12 character short sha to use as well, we "know" this will not
# fail as the original id was valid.
GIT_SHA_SHORT=$(git_short_id "${GIT_SHA_FULL}")
dbg "GIT_SHA=${GIT_SHA} GIT_SHA_FULL=${GIT_SHA_FULL} GIT_SHA_SHORT=${GIT_SHA_SHORT}"
#
# Find all of the places (git id and release number) where this commit has been
# applied to.
#
# To do so we call ${FOUND_IN} to get the versions, and then we iterate over
# the branches to get the git ids.
#
# ${FOUND_IN} will give us version:commit_id pairs, so we don't have to do much afterward
fixed_kernels=$("${FOUND_IN}" "${GIT_SHA_FULL}")
dbg "fixed_kernels=${fixed_kernels}"
for kernel in ${fixed_kernels}; do
kernel_split=(${kernel//:/ })
kernel_split_version=${kernel_split[0]}
kernel_split_id=${kernel_split[1]}
# dbg "version=${kernel_split_version} id=${kernel_split_id}"
create_fix_set "${kernel_split_version}" "${kernel_split_id}"
done
dbg "We have found ${#fixed_set[@]} sets of fixed kernels"
if [[ "${#fixed_set[@]}" == "0" ]] ; then
echo "${txtred}ERROR:${txtrst} No vulnerable and then fixed pairs of kernels were found for commit ${txtcyn}${GIT_SHA_SHORT}${txtrst}"
exit 1
fi
for fixed_entry in "${fixed_set[@]}"; do
dbg " ${fixed_entry}"
done
#
# We have a set of where everything was fixed up, based on the original git id,
# so now let's try to determine where the problem first showed up (i.e. became
# vulnerable)
#
# If this is passed to us on the command line, it's easy, use that as the
# commit that will be deemed the "vulnerable" version (and might have been
# backported).
#
# Otherwise, try to dig in the changelog text and find any "Fixes:" lines and
# parse them to try to figure out where the issue first showed up at (i.e. what
# kernel version and git id caused the problem.)
#
# Kernel ids in a "Fixes:" line are almost always the the id in Linus's tree,
# so we need to dig through the stable branches to get the real git id for
# where the commit happened. But note that sometimes they are the stable id.
# Rely on the regression tests to get this all correct.
v=()
if [[ "${GIT_VULNERABLE}" != "" ]]; then
# We are asked to set the original vulnerable kernel to be a specific
# one, so no need to look it up.
full_id=$(git_full_id "${GIT_VULNERABLE}")
if [[ "${full_id}" == "" ]]; then
echo "${txtred}ERROR:${txtrst} Vulnerable git id ${txtcyn}${GIT_VULNERABLE}${txtrst} is not found!"
exit 2
fi
kernel=$(${SQL} "SELECT release FROM commits WHERE id='${full_id}';")
if [[ "${kernel}" == "" ]]; then
echo "ERROR: Vulnerable git id ${txtcyn}${full_id}${txtrst} is not found in any version!"
exit 2
fi
info " Setting original vulnerable kernel to be kernel ${txtcyn}${kernel}${txtrst} and git id ${txtcyn}${full_id}${txtrst}"
v+=("${full_id}")
else
# rely on verhaal to have already parsed and fixed up the "Fixes:" lines for us
vuln_lines=$(${SQL} "SELECT fixes FROM commits where id='${GIT_SHA_FULL}'")
dbg "vuln_lines=${vuln_lines}"
if [[ "${vuln_lines}" != "" ]] ; then
# Break up our list of vulnerable kernels into an array, we
# will sort them later
for id in ${vuln_lines}; do
full_id=$(git_full_id "${id}")
if [[ "${full_id}" == "" ]]; then
dbg "invalid fix entry of '${id}', skipping"
continue
fi
v+=("${full_id}")
done
else
# We do NOT have a fixes line, so let's try one last thing,
# let's ask the database if this is a revert, and if so, what
# commit it is reverting as we can imply that a revert is
# actually "fixing" the original commit.
#
reverts=$(${SQL} "SELECT reverts FROM commits WHERE id='${GIT_SHA_FULL}';")
if [[ "${reverts}" != "" ]]; then
# Found a revert!
dbg "sha is a revert of ${reverts}"
v+=("${reverts}")
fi
fi
fi
# We now have a list of "vulnerable" kernels in v(), so walk them and create a
# bunch of matching "vulnerable : fixed" kernel pairs
dbg " number in v: ${#v[@]}"
if [[ "${#v[@]}" == "0" ]]; then
dbg " nothing in v, skipping vuln lines check"
else
# We have some vulnerable kernels, let's figure out where they are
v_file=$(mktemp -t "${SCRIPT}".XXXX || exit 1)
for id in "${v[@]}"; do
dbg " ${id}"
echo "${id}" >> "${v_file}"
done
# use 'tac' as it's faster than having git do --reverse for 'git rev-list'
sort_order=$($git_cmd rev-list --topo-order $(cat "${v_file}") | grep --file "${v_file}" --max-count ${#v[@]} | tac)
rm "${v_file}"
# git rev-list --topo-order $(cat SET_OF_SHA1S) | grep --file SET_OF_SHA1S --max-count $(wc -l SET_OF_SHA1S)
dbg "sort_order=${sort_order}"
# figure out what kernels this commit fixes, (i.e. which are
# vulnerable) and add them to a list of vulnerable sets.
for id in ${sort_order}; do
full_id=$(git_full_id "${id}")
if [[ "${full_id}" == "" ]]; then
dbg "invalid fix: ${id}"
continue
fi
x=$("${FOUND_IN}" "${full_id}")
for kernel in ${x}; do
kernel_split=(${kernel//:/ })
kernel_split_version=${kernel_split[0]}
kernel_split_id=${kernel_split[1]}
kernel_version_is_mainline "${kernel_split_version}"
kernel_is_mainline=$?
if [[ "${kernel_is_mainline}" == "0" ]]; then
create_vulnerable_set "${kernel_split_version}" "${kernel_split_id}"
else
create_vulnerable_set "${kernel_split_version}" "${full_id}"
fi
done
done
fi
dbg "Before winnowing we have found ${#vulnerable_set[@]} sets of vulnerable kernels"
for vuln_entry in "${vulnerable_set[@]}"; do
dbg " ${vuln_entry}"
done
#
# Now that we have a list of vulnerable kernels, we need to find the "root"
# mainline version that had the oldest issue in it. We might have many
# mainline kernels listed in here, but we only care about the "oldest" one, so
# throw away all the rest.
#
# To do this, we create 2 lists, one for mainline kernels, and one for stable
# kernels. The stable kernel list we will keep "as is", but for the mainline
# kernel list, we will sort it and then throw away everything EXCEPT the oldest
# kernel. After that, we will re-create the vulnerable set with the new
# information.
vulnerable_stable_set=()
vulnerable_mainline_set=()
for vuln_entry in "${vulnerable_set[@]}"; do
# shellcheck disable=SC2206
y=(${vuln_entry//:/ })
vuln_version=${y[0]}
vuln_git=${y[1]}
kernel_version_is_mainline "${vuln_version}"
kernel_is_mainline=$?
if [[ "${kernel_is_mainline}" == "1" ]]; then
vulnerable_mainline_set+=("${vuln_entry}")
else
vulnerable_stable_set+=("${vuln_entry}")
fi
done
# Reset the list
vulnerable_set=()
dbg " vuln_stable_set: ${#vulnerable_stable_set[@]}"
for vuln_entry in "${vulnerable_stable_set[@]}"; do
dbg " ${vuln_entry}"
done
temp=""
#
# The "default" vulnerable point in mainline where this issue first showed up.
# We need this for any fix that happened in a stable branch that happened AFTER
# this point in time (i.e. fixed in 6.6.3 for an issue that showed up in 5.4).
vuln_mainline_pair=""
dbg " vuln_mainline_set: ${#vulnerable_mainline_set[@]}"
if [[ "${#vulnerable_mainline_set[@]}" != "0" ]]; then
for vuln_entry in "${vulnerable_mainline_set[@]}"; do
# trailing space is important
temp+=$(echo -e "${vuln_entry} \n")
dbg " ${vuln_entry}"
done
# ${temp} is not escaped on purpose, otherwise we end up with a
# trailing space
# shellcheck disable=SC2086
vuln_mainline_pair=$(printf "%s\n" ${temp} | sort -V | head -n 1)
dbg " vuln_mainline_pair=${vuln_mainline_pair}"
vulnerable_set+=("${vuln_mainline_pair}")
vm=("${vuln_mainline_pair}")
vuln_mainline_version=${vm[0]}
# iterate over all of the stable entries, and only add the ones that
# are "older" than the mainline release.
if [[ "${#vulnerable_stable_set[@]}" != "0" ]]; then
for vuln_stable_entry in "${vulnerable_stable_set[@]}"; do
# shellcheck disable=SC2206
vs=(${vuln_stable_entry//:/ })
vuln_stable_version=${vs[0]}
kernel_greater_than "${vuln_mainline_version}" "${vuln_stable_version}"
fixed_version_greater=$?
if [[ "${fixed_version_greater}" == "1" ]] ; then
vulnerable_set+=("${vuln_stable_entry}")
fi
done
fi
else
# No mainline vulnerable kernels, so just take all of the stable ones
if [[ "${#vulnerable_stable_set[@]}" != "0" ]]; then
for vuln_entry in "${vulnerable_stable_set[@]}"; do
vulnerable_set+=("${vuln_entry}")
done
fi
fi
dbg "We have found ${#vulnerable_set[@]} sets of vulnerable kernels"
for vuln_entry in "${vulnerable_set[@]}"; do
dbg " ${vuln_entry}"
done
#
# Now we have two lists, one where the kernel became vulnerable (could not be
# known, so we assume 0), and where it was fixed (the id originally passed to
# us and where it has been backported to.) Take those two lists and start
# matching them up based on kernel versions in order to get a set of
# vulnerable:fixed pairs
#
# Iterate over all of the "fixed" kernel versions/ids and try to match them up
# with any vulnerable kernel entries (if any)
for fixed_entry in "${fixed_set[@]}" ; do
create=0
# shellcheck disable=SC2206
x=(${fixed_entry//:/ })
fixed_version=${x[0]}
fixed_git=${x[1]}
dbg "fixed_entry: '${fixed_version}' '${fixed_git}'"
kernel_version_is_mainline "${fixed_version}"
fixed_version_mainline=$?
# See if we have ANY kernels where the vulnerability showed up. If not, assume
# that it "has always been there", so create our final set of vulnerable/fixed
# pairs straight from the fixed list
if [[ "${#vulnerable_set[@]}" == "0" ]] ; then
create_fixed_pair "0:0" "${fixed_entry}"
create=1
continue
fi
# We have some vulnerable kernels set, so let's try to match them up
for vuln_entry in "${vulnerable_set[@]}" ; do
# shellcheck disable=SC2206
y=(${vuln_entry//:/ })
vuln_version=${y[0]}
vuln_git=${y[1]}
dbg " vuln_entry: '${vuln_version}' '${vuln_git}'"
# vulnerable and fixed in the same version. Save this off as
# it is needed for the git vulnerable information (small window
# of where things went wrong).
if [[ "${fixed_version}" == "${vuln_version}" ]]; then
dbg " ${fixed_version} == ${vuln_version} save it"
create_fixed_pair "${vuln_entry}" "${fixed_entry}"
create=1
break
fi
kernel_version_is_mainline "${vuln_version}"
vuln_version_mainline=$?
# If these are both mainline commits then create a matching pair
if [[ "${vuln_version_mainline}" == "1" ]] ; then
if [[ "${fixed_version_mainline}" == "1" ]]; then
dbg " ${vuln_version} and ${fixed_version} are both mainline, save it"
create_fixed_pair "${vuln_entry}" "${fixed_entry}"
create=1
break
fi
fi
# if this is the same X.Y version, make a pair
kernel_version_match "${vuln_version}" "${fixed_version}"
match=$?
if [[ "${match}" == "1" ]] ; then
dbg " ${vuln_version} and ${fixed_version} are same major release, save it"
create_fixed_pair "${vuln_entry}" "${fixed_entry}"
create=1
break
fi
done
# We did not create any entry at all above, so we need to set the
# "default" vulnerable point to the original vulnerable mainline pair
# found way above as that's where the issue showed up (i.e before this
# stable kernel branch was forked from mainline.)
if [[ "${create}" == "0" ]]; then
if [[ "${vuln_mainline_pair}" == "" ]]; then
dbg " no mainline pair vulnerable at this point in time (fix in the future?), so skipping ${fixed_version} for now"
else
dbg " nothing found for ${fixed_version}, using default of ${vuln_mainline_pair}"
create_fixed_pair "${vuln_mainline_pair}" "${fixed_entry}"
fi
fi
done
#
# Now the fun starts, which justified all of the hard work we did above. We
# need to track the places where we are vulnerable, but NOT fixed. So walk the
# vulnerable list, see if anything in the fixed_pair matches up, and if NOT,
# then add it to the list as an "unfixed" pair
for vuln_entry in "${vulnerable_set[@]}"; do
found=0
# shellcheck disable=SC2206
y=(${vuln_entry//:/ })
vuln_version=${y[0]}
vuln_git=${y[1]}
for fixed_entry in "${fixed_pairs[@]}"; do
# shellcheck disable=SC2206
x=(${fixed_entry//:/ })
a=${x[0]}
b=${x[1]}
c=${x[2]}
#d=${x[3]}
# if the vulnerable version and git matches what is in the
# list, mark this as found
if [[ "${a}" == "${vuln_version}" ]]; then
if [[ "${b}" == "${vuln_git}" ]]; then
found=1
break
fi
fi
# If the fixed version matches the vuln version, mark this as
# found
if [[ "${c}" == "${vuln_version}" ]]; then
found=1
break
fi
done
if [[ "${found}" == "0" ]]; then
dbg "not found: ${vuln_entry}"
create_fixed_pair "${vuln_entry}" "0:0"
fi
done
#
# We are done!
# Print out the pairs we found so that bippy can do something with them.
dbg "Number of vulnerable / fixed kernel pairs: ${#fixed_pairs[@]}"
for entry in "${fixed_pairs[@]}" ; do
echo "${txtgrn}${entry}${txtrst}"
done
exit 0