[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: