submit_report.sh, kdump.etc: Add log submission mechanism

Finally we have a functional mechanism to upload the crash logs
to Valve servers (special thanks to TonyP for the API help).
Documentation is present in the README.MD as usual.

NOTE: worth to reinforce here what was alread mentioned in the
README: kdump-steamos doesn't perform any significant validation
against malicious usage of the log submission mechanism, like DDoS,
submitting a malicious ZIP binary, a very huge file, etc.
All of this is expected to be handled by the server side.

Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
This commit is contained in:
Guilherme G. Piccoli
2022-02-02 16:43:41 -03:00
parent b1e183e1dc
commit fae5982a50
4 changed files with 231 additions and 33 deletions

View File

@ -33,6 +33,7 @@ KDUMP_LOGS_FOLDER="${KDUMP_MAIN_FOLDER}/logs"
# Use UTC timezone to match kdump collection
CURRENT_TSTAMP=$(date -u +"%Y%m%d%H%M")
CURRENT_EPOCH=$(date +"%s")
# We assume pstore is mounted by default, in this location;
# if not, we get a 0 and don't loop.
@ -115,6 +116,7 @@ if [ ${LOGS_FOUND} -ne 0 ]; then
fi
STEAM_ACCOUNT=0
STEAM_ID=0
if [ -s "${LOGINVDF}" ]; then
# The following awk command was borrowed from:
# https://unix.stackexchange.com/a/663959
@ -128,24 +130,147 @@ if [ ${LOGS_FOUND} -ne 0 ]; then
fi
STEAM_ACCOUNT=$(awk -v n=${IDX} -v RS='}' 'NR==n{gsub(/.*\{\n|\n$/,""); print}' "${LOGINVDF}" | grep "AccountName" | cut -f4 -d\")
# Get also the Steam ID, used in the POST request to Valve servers; this
# is a bit fragile, but there's no proper VDF parse tooling it seems...
LN=$(grep -n "AccountName.*${STEAM_ACCOUNT}\"" "${LOGINVDF}" | cut -f1 -d:)
LN=$((LN - 2))
STEAM_ID=$(sed -n "${LN}p" "${LOGINVDF}" | cut -f2 -d\")
break
done
fi
# Here we collect some more info, like DMI data, os-release, etc;
# ToDo: Add Steam application / Proton / Games logs collection...
# TODO: Add Steam application / Proton / Games logs collection...
dmidecode > "${KDUMP_LOGS_FOLDER}/dmidecode.${CURRENT_TSTAMP}"
grep "BUILD_ID" "/etc/os-release" | cut -f2 -d\= > "${KDUMP_LOGS_FOLDER}/build.${CURRENT_TSTAMP}"
uname -r > "${KDUMP_LOGS_FOLDER}/version.${CURRENT_TSTAMP}"
BUILD_FNAME="${KDUMP_LOGS_FOLDER}/build.${CURRENT_TSTAMP}"
cp "/etc/os-release" "${BUILD_FNAME}"
VERSION_FNAME="${KDUMP_LOGS_FOLDER}/version.${CURRENT_TSTAMP}"
uname -r > "${VERSION_FNAME}"
# Before compressing the logs, save a crash summary
CRASH_SUMMARY="${KDUMP_LOGS_FOLDER}/crash_summary.${CURRENT_TSTAMP}"
SED_EXPR="/Kernel panic \-/,/Kernel Offset\:/p"
sed -n "${SED_EXPR}" "${KDUMP_LOGS_FOLDER}"/dmesg* > "${CRASH_SUMMARY}"
sync "${BUILD_FNAME}" "${VERSION_FNAME}" "${CRASH_SUMMARY}"
# Create the dump compressed pack.
LOG_FNAME="steamos-${SN}-${STEAM_ACCOUNT}.${CURRENT_TSTAMP}.zip"
LOG_FNAME="${KDUMP_MAIN_FOLDER}/${LOG_FNAME}"
zip -9 -jq "${LOG_FNAME}" "${KDUMP_LOGS_FOLDER}"/* 1>/dev/null 2>&1
zip -9 -jq "${LOG_FNAME}" ${KDUMP_LOGS_FOLDER}/* 1>/dev/null 2>&1
sync "${LOG_FNAME}"
sync "${LOG_FNAME}" 2>/dev/null
if [ ! -s "${LOG_FNAME}" ]; then
logger "kdump-steamos: couldn't create the log archive, aborting..."
exit 0
fi
##############################
# Log submission mechanism #
##############################
# The POST request requires a valid Steam ID.
if [ "${STEAM_ID}" -eq 0 ]; then
logger "kdump-steamos: invalid Steam ID, cannot submit logs"
exit 0
fi
# Construct the POST request fields...
REQ_DUMP_SZ="$(stat --printf="%s" "${LOG_FNAME}")"
REQ_PRODUCT="holo"
REQ_BUILD="$(grep "BUILD_ID" "${BUILD_FNAME}" | cut -f2 -d=)"
REQ_VER="$(cat "${VERSION_FNAME}")"
REQ_PLATFORM="linux"
REQ_TIME="${CURRENT_EPOCH}"
STACK_SED_EXPR="/ Call Trace\:/,/ RIP\:/p"
REQ_STACK="$(sed -n "${STACK_SED_EXPR}" "${CRASH_SUMMARY}" | sed "1d")"
REQ_NOTE="$(cat "${CRASH_SUMMARY}")"
POST_REQ="steamid=${STEAM_ID}&have_dump_file=1&dump_file_size=${REQ_DUMP_SZ}&product=${REQ_PRODUCT}&build=${REQ_BUILD}"
POST_REQ="${POST_REQ}&version=${REQ_VER}&platform=${REQ_PLATFORM}&crash_time=${REQ_TIME}&stack=${REQ_STACK}&note=${REQ_NOTE}&format=json"
# Now we can safely delete this folder.
rm -rf "${KDUMP_LOGS_FOLDER}"
# TODO: implement a log submission mechanism, in order to send the zip file
# to Valve servers through an API.
# Network validation before log submission
LOOP_CNT=0
MAX_LOOP=99
TEST_URL="steampowered.com"
while [ ${LOOP_CNT} -lt ${MAX_LOOP} ]; do
if ping -i 0.5 -w 2 -c 2 "${TEST_URL}" 1>/dev/null 2>&1; then
break
fi
LOOP_CNT=$((LOOP_CNT + 1))
sleep 1
done
# Bail out in case we have network issues
if [ ${LOOP_CNT} -ge ${MAX_LOOP} ]; then
logger "kdump-steamos: network issue - cannot send logs"
exit 0
fi
CURL_ERR="${KDUMP_MAIN_FOLDER}/.curl_err"
START_URL="$(echo "${POST_URL}" | sed 's/ACTION/Start/g')"
FINISH_URL="$(echo "${POST_URL}" | sed 's/ACTION/Finish/g')"
RESPONSE_FILE="${KDUMP_MAIN_FOLDER}/.curl_response"
if ! curl -X POST -d "${POST_REQ}" "${START_URL}" 1>"${RESPONSE_FILE}" 2>"${CURL_ERR}"; then
logger "kdump-steamos: curl issues - failed in the log submission POST (err=$?)"
#rm -f "${RESPONSE_FILE}" # keep this for now, as debug information
exit 0
fi
RESPONSE_PUT_URL="$(jq -r '.response.url' "${RESPONSE_FILE}")"
RESPONSE_GID="$(jq -r '.response.gid' "${RESPONSE_FILE}")"
# Construct the PUT request based on the POST response
CURL_PUT_HEADERS="${KDUMP_MAIN_FOLDER}/.curl_put_headers"
PUT_HEADERS_LEN=$(jq '.response.headers.pairs | length' "${RESPONSE_FILE}")
# Validate the response headers; allow a maximum of 20 arguments for now...
if [ "${PUT_HEADERS_LEN}" -le 0 ] || [ "${PUT_HEADERS_LEN}" -gt 20 ]; then
logger "kdump-steamos: unsupported number of response headers (${PUT_HEADERS_LEN}), aborting..."
#rm -f "${RESPONSE_FILE}" # keep this for now, as debug information
exit 0
fi
LOOP_CNT=0
while [ ${LOOP_CNT} -lt "${PUT_HEADERS_LEN}" ]; do
NAME="$(jq -r ".response.headers.pairs[${LOOP_CNT}].name" "${RESPONSE_FILE}")"
VAL="$(jq -r ".response.headers.pairs[${LOOP_CNT}].value" "${RESPONSE_FILE}")"
echo "${NAME}: ${VAL}" >> "${CURL_PUT_HEADERS}"
LOOP_CNT=$((LOOP_CNT + 1))
done
rm -f "${RESPONSE_FILE}"
if ! curl -X PUT --data-binary "@${LOG_FNAME}" -H "@${CURL_PUT_HEADERS}" "${RESPONSE_PUT_URL}" 1>/dev/null 2>"${CURL_ERR}"; then
logger "kdump-steamos: curl issues - failed in the log submission PUT (err=$?)"
#rm -f "${CURL_PUT_HEADERS}" # keep this for now, as debug information
exit 0
fi
rm -f "${CURL_PUT_HEADERS}"
if ! curl -X POST -d "gid=${RESPONSE_GID}" "${FINISH_URL}" 1>/dev/null 2>"${CURL_ERR}"; then
logger "kdump-steamos: curl issues - failed in the log finish POST (err=$?)"
exit 0
fi
# If we reached this point, the zipped log should have been submitted
# succesfully; save a local copy as well.
# TODO: implement a clean-up routine to just keep up to N logs...
rm -f "${CURL_ERR}"
SENT_FLD="${KDUMP_MAIN_FOLDER}/sent_logs/"
mkdir -p "${SENT_FLD}"
mv "${LOG_FNAME}" "${SENT_FLD}"
logger "kdump-steamos: successfully submitted crash log to Valve"
fi