Skip to content

Commit 952ab07

Browse files
committed
dom0-update: In download mode, only send specifically requested packages to dom0
Save output of the package manager command. Then, if called with an action that downloads packages, parse out the requested packages and only send those to dom0. This fixes an issue where packages could be installed that were not intended or where packages could not be installed due to missing dependencies from packages not explicitly requested by the user. Fixes QubesOS/qubes-issues#10716
1 parent 2e5866f commit 952ab07

1 file changed

Lines changed: 59 additions & 6 deletions

File tree

package-managers/qubes-download-dom0-updates.sh

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,24 +168,74 @@ if [ "$UPDATE_ACTION" = "download" ]; then
168168
fi
169169

170170
set -e
171+
set -o pipefail
171172

172-
"${UPDATE_COMMAND[@]}" "${OPTS[@]}" "${PKGLIST[@]}"
173+
"${UPDATE_COMMAND[@]}" "${OPTS[@]}" "${PKGLIST[@]}" | \
174+
tee "$DOM0_UPDATES_DIR/download.out"
173175

176+
# Collect rpms from various download locations into one directory
174177
find "$DOM0_UPDATES_DIR/var/cache" -name '*.rpm' -print0 2>/dev/null |\
175178
xargs -0 -r ln -f -t "$DOM0_UPDATES_DIR/packages/"
176179

177-
if ls "$DOM0_UPDATES_DIR"/packages/*.rpm > /dev/null 2>&1; then
180+
case "$UPDATE_ACTION" in
181+
# Never send package to dom0 for the following commands. This by no
182+
# means is an exhaustive list, just some common ones.
183+
changelog|list|search) ;;
184+
# TODO: Look for any other commands that download packages to add and
185+
distro-sync|downgrade|download|install|upgrade)
186+
RPMS=$(
187+
grep '^ ' "$DOM0_UPDATES_DIR/download.out" |
188+
tail -n +2 |
189+
while read -r PKG ARCH VER _REPO _SIZE; do
190+
# Assumption: Package names do not contain spaces
191+
F="$PKG-${VER##*:}.$ARCH.rpm"
192+
if [ -f "$DOM0_UPDATES_DIR"/packages/"$F" ]; then
193+
echo "$F"
194+
else
195+
# Did not find package that was supposed to be downloaded... bail
196+
echo "Package $F requested but not downloaded" >&2
197+
exit 1
198+
fi
199+
done
200+
) || RET=$?
201+
if [ -z "$RPMS" ]; then
202+
cat >&2 <<EOF
203+
No packages found in output for action $UPDATE_ACTION. This is likely
204+
due to a change in the output format. Falling back to old method that
205+
sends all verified packages in the package cache.
206+
Output:
207+
EOF
208+
cat "$DOM0_UPDATES_DIR/download.out" >&2
209+
fi
210+
if [ "${RET:-0}" -ne 0 ]; then
211+
# An error occured in determining or finding requested packages,
212+
# unset RPM to fallback to old method.
213+
RPMS=
214+
fi
215+
216+
;&
217+
# Fallback to previous implementation of uploading all verified rpms
218+
# for all other actions and above failure condition.
219+
*)
220+
if [ -z "$RPMS" ]; then
221+
RPMS=$(for P in "$DOM0_UPDATES_DIR"/packages/*.rpm; do echo ${P##*/}; done)
222+
fi
223+
;;
224+
esac
225+
226+
if [ -n "$RPMS" ]; then
178227
if [ -n "$SIGNATURE_REGEX" ]; then
179228
rpmkeys_error=0
180-
for pkg in "$DOM0_UPDATES_DIR"/packages/*.rpm; do
229+
for rpmfile in $RPMS; do
230+
pkg="$DOM0_UPDATES_DIR"/packages/"$rpmfile"
181231
rpmkeys_exit_code=0
182232
output="$(rpmkeys --root "$DOM0_UPDATES_DIR" --checksig "$pkg")" \
183233
|| rpmkeys_exit_code="$?"
184234
if [ ! "$rpmkeys_exit_code" = "0" ]; then
185235
echo "ERROR: could not verify $pkg" >&2
186236
rpmkeys_error=1
187237
rm "$pkg"
188-
elif ! echo "$output" |grep -Pq "$SIGNATURE_REGEX"; then
238+
elif ! echo "$output" | grep -Pq "$SIGNATURE_REGEX"; then
189239
echo "ERROR: missing or invalid signature for $pkg" >&2
190240
rpmkeys_error=1
191241
rm "$pkg"
@@ -201,11 +251,14 @@ if ls "$DOM0_UPDATES_DIR"/packages/*.rpm > /dev/null 2>&1; then
201251

202252
cmd="/usr/lib/qubes/qrexec-client-vm dom0 qubes.ReceiveUpdates /usr/lib/qubes/qfile-agent"
203253
qrexec_exit_code=0
204-
$cmd "$DOM0_UPDATES_DIR"/packages/*.rpm || { qrexec_exit_code=$? ; true; };
254+
rpmfiles=$(for rpmfile in $RPMS; do echo "$DOM0_UPDATES_DIR"/packages/"$rpmfile"; done)
255+
# shellcheck disable=SC2086
256+
$cmd $rpmfiles || { qrexec_exit_code=$? ; true; };
205257
if [ ! "$qrexec_exit_code" = "0" ]; then
206-
echo "'$cmd $DOM0_UPDATES_DIR/packages/*.rpm' failed with exit code ${qrexec_exit_code}!" >&2
258+
echo "'$cmd $rpmfiles' failed with exit code ${qrexec_exit_code}!" >&2
207259
exit "$qrexec_exit_code"
208260
fi
209261
else
210262
echo "No packages downloaded" >&2
211263
fi
264+
rm -f "$DOM0_UPDATES_DIR/download.out"

0 commit comments

Comments
 (0)