commit: fc3cb03273c38d997e22d294a76647c82303797f
Author: Kerin Millar <kfm <AT> plushkava <DOT> net>
AuthorDate: Thu Jun 19 23:48:22 2025 +0000
Commit: Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Fri Jun 20 05:45:35 2025 +0000
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=fc3cb032
emerge-webrsync: validate repo and snapshot timestamps
As concerns the get_repository_timestamp() function, check not only that
the "timestamp.x" file can be opened but that it also contains at least
one complete line whose first field is a valid timestamp (in unix time).
Otherwise, have both of its calling functions raise an error and exit.
As concerns the get_snapshot_timestamp() function, check that the output
of tar(1) constitutes at least one complete line whose first field is a
valid timestamp (in unix time). Otherwise, have its calling function
raise an error and exit.
To validate inputs is a matter of common sense. However, one must also
be mindful that the arithmetic context permits arbitrary code execution.
$ f() { echo 'a[$(echo hi >&2)0]'; }
$ (( 0 < $(f) ))
hi
$ [[ 0 -lt $(f) ]]
hi
Signed-off-by: Kerin Millar <kfm <AT> plushkava.net>
Signed-off-by: Sam James <sam <AT> gentoo.org>
bin/emerge-webrsync | 39 +++++++++++++++++++++++++++++----------
1 file changed, 29 insertions(+), 10 deletions(-)
diff --git a/bin/emerge-webrsync b/bin/emerge-webrsync
index ffe8096906..6358ec7f51 100755
--- a/bin/emerge-webrsync
+++ b/bin/emerge-webrsync
@@ -194,13 +194,20 @@ get_unixtime_by_date() {
}
get_repository_timestamp() {
- local portage_current_timestamp=0
+ local unixtime path
- if [[ -f "${repo_location}/metadata/timestamp.x" ]]; then
- portage_current_timestamp=$(cut -f 1 -d " "
"${repo_location}/metadata/timestamp.x" )
+ path=${repo_location}/metadata/timestamp.x
+ if [[ ! -f ${path} ]]; then
+ unixtime=0
+ elif ! read -r unixtime _ < "${path}" || ! is_uint "${unixtime}"; then
+ return 1
fi
- echo "${portage_current_timestamp}"
+ printf '%s\n' "${unixtime}"
+}
+
+is_uint() {
+ [[ $1 == @(0|[1-9]*([0-9])) ]]
}
fetch_file() {
@@ -373,8 +380,14 @@ check_file_signature() {
get_snapshot_timestamp() {
local file=$1
+ local unixtime
- do_tar "${file}" --to-stdout -f - --wildcards -x
'*/metadata/timestamp.x' | cut -f 1 -d " "
+ do_tar "${file}" --to-stdout -f - --wildcards -x
'*/metadata/timestamp.x' |
+ {
+ read -r unixtime _ \
+ && is_uint "${unixtime}" \
+ && printf '%s\n' "${unixtime}"
+ }
}
sync_local() {
@@ -448,7 +461,7 @@ sync_local() {
do_snapshot() {
local ignore_timestamp=$1 date=$2
- local snapshot_timestamp have_files signature unixtime digest mirror
file
+ local {repo,snapshot}_timestamp have_files signature unixtime digest
mirror file
local -A suffix_by
local -a tarballs
@@ -494,10 +507,14 @@ do_snapshot() {
if (( have_files )); then
einfo "Getting snapshot timestamp ..."
- snapshot_timestamp=$(get_snapshot_timestamp
"${DISTDIR}/${file}")
-
+ if !
snapshot_timestamp=$(get_snapshot_timestamp "${DISTDIR}/${file}"); then
+ die "couldn't determine the timestamp
of snapshot ${file@Q}"
+ fi
if [[ ${ignore_timestamp} == 0 ]]; then
- if (( snapshot_timestamp <
$(get_repository_timestamp) )); then
+ if !
repo_timestamp=$(get_repository_timestamp); then
+ die "couldn't determine the
timestamp of repo ${repo_location@Q}"
+ fi
+ if (( snapshot_timestamp <
repo_timestamp )); then
ewarn "Repository (age) is
newer than fetched snapshot"
have_files=0
fi
@@ -547,7 +564,9 @@ do_latest_snapshot() {
# are considered to be approximately equal.
min_time_diff=$(( 2 * 60 * 60 ))
- existing_timestamp=$(get_repository_timestamp)
+ if ! existing_timestamp=$(get_repository_timestamp); then
+ die "couldn't determine the timestamp of repo
${repo_location@Q}"
+ fi
printf -v start_time '%(%s)T'
printf -v start_hour '%(%H)T' "${start_time}"