Bug#695285: /etc/cron.daily/apt backup RNG is very wasteful
Package: apt
Version: 0.9.7.6
Severity: minor
/etc/cron.daily/apt does:
random_sleep()
{
RandomSleep=1800
eval $(apt-config shell RandomSleep APT::Periodic::RandomSleep)
if [ $RandomSleep -eq 0 ]; then
return
fi
if [ -z "$RANDOM" ] ; then
# A fix for shells that do not have this bash feature.
RANDOM=$(dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -c"1-5")
fi
TIME=$(($RANDOM % $RandomSleep))
debug_echo "sleeping for $TIME seconds"
sleep $TIME
}
This backup for a missing $RANDOM reads 512 bytes out of /dev/urandom, only
to reduce it (incorrectly) to a 5-digit number (16.6 bits max, although
the distribution is skewed), then to 10.8 bits (modulo 1800).
It's incorrect because cksum produces a 32-bit checksum, formatted as
"%u", so some small fraction of the time (1 in 4.3 million times), it'll
be less than 1000 and the cut will produce a result of the form "123 4", causing the evaluation
of TIME to fail.
Two other options, which both use a lot less entropy and don't have the
bug, are:
RANDOM=$(dd if=/dev/urandom bs=2 count=1 2>/dev/null | cksum | cut -d' ' -f1)
RANDOM=$(od -N2 -d /dev/urandom | cut -s -d' ' -f2)
or, using more shell builtins:
read x RANDOM <<EOF
$(od -N2 -d /dev/urandom)
EOF
(The fact that you can't just pipe into read is a well-known sh problem.)
Also, you don't need to prefix variables with $ inside $(()); you can
use TIME=$((RANDOM % RandomSleep))
Reply to: