Theo's diff inspired me to look for other cases of modulo bias. The
following diff converts most modulus operations on a random number to
use arc4random_uniform or & as appropriate. I excluded

lib/libsqlite3/src/resolve.c
regress/lib/libevent/test-time.c
usr.sbin/nsd/rrl.c
usr.sbin/nsd/util.c
usr.sbin/nsd/xfrd.c

as they seem to have upstreams. The only other case is games/wump/wump.c
which has

if (arc4random() % 2 == 1)

This is safe and seems obvious enough to me.

- Matthew Martin


Index: games/atc/update.c
===================================================================
RCS file: /cvs/src/games/atc/update.c,v
retrieving revision 1.16
diff -u -p -r1.16 update.c
--- games/atc/update.c  9 Dec 2014 05:01:14 -0000       1.16
+++ games/atc/update.c  7 Dec 2015 06:42:17 -0000
@@ -59,6 +59,15 @@ atcrandom()
                return arc4random();
 }
 
+uint32_t
+atcrandom_uniform(uint32_t upper_bound)
+{
+       if (seeded)
+               return random() % upper_bound;
+       else
+               return arc4random_uniform(upper_bound);
+}
+
 void
 update(int dummy)
 {
@@ -212,7 +221,7 @@ update(int dummy)
         * Otherwise, prop jobs show up *on* entrance.  Remember that
         * we don't update props on odd updates.
         */
-       if ((atcrandom() % sp->newplane_time) == 0)
+       if (atcrandom_uniform(sp->newplane_time) == 0)
                addplane();
 }
 
@@ -308,10 +317,10 @@ addplane(void)
        memset(&p, 0, sizeof (p));
 
        p.status = S_MARKED;
-       p.plane_type = atcrandom() % 2;
+       p.plane_type = atcrandom_uniform(2);
 
        num_starts = sp->num_exits + sp->num_airports;
-       rnd = atcrandom() % num_starts;
+       rnd = atcrandom_uniform(num_starts);
 
        if (rnd < sp->num_exits) {
                p.dest_type = T_EXIT;
@@ -324,7 +333,7 @@ addplane(void)
        /* loop until we get a plane not near another */
        for (i = 0; i < num_starts; i++) {
                /* loop till we get a different start point */
-               while ((rnd2 = atcrandom() % num_starts) == rnd)
+               while ((rnd2 = atcrandom_uniform(num_starts)) == rnd)
                        ;
                if (rnd2 < sp->num_exits) {
                        p.orig_type = T_EXIT;
Index: games/hack/hack.mklev.c
===================================================================
RCS file: /cvs/src/games/hack/hack.mklev.c,v
retrieving revision 1.7
diff -u -p -r1.7 hack.mklev.c
--- games/hack/hack.mklev.c     27 Oct 2009 23:59:25 -0000      1.7
+++ games/hack/hack.mklev.c     7 Dec 2015 06:42:17 -0000
@@ -66,8 +66,8 @@
 #include <unistd.h>
 #include "hack.h"
 
-#define somex() ((random()%(croom->hx-croom->lx+1))+croom->lx)
-#define somey() ((random()%(croom->hy-croom->ly+1))+croom->ly)
+#define somex() (arc4random_uniform(croom->hx-croom->lx+1)+croom->lx)
+#define somey() (arc4random_uniform(croom->hy-croom->ly+1)+croom->ly)
 
 #define        XLIM    4       /* define minimum required space around a room 
*/
 #define        YLIM    3
Index: games/hack/rnd.c
===================================================================
RCS file: /cvs/src/games/hack/rnd.c,v
retrieving revision 1.5
diff -u -p -r1.5 rnd.c
--- games/hack/rnd.c    27 Oct 2009 23:59:25 -0000      1.5
+++ games/hack/rnd.c    7 Dec 2015 06:42:17 -0000
@@ -61,7 +61,7 @@
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#define RND(x) ((random()>>3) % x)
+#define RND(x) (arc4random_uniform(x))
 
 #include <stdlib.h>
 
Index: lib/libc/stdlib/rand.c
===================================================================
RCS file: /cvs/src/lib/libc/stdlib/rand.c,v
retrieving revision 1.15
diff -u -p -r1.15 rand.c
--- lib/libc/stdlib/rand.c      13 Sep 2015 08:31:47 -0000      1.15
+++ lib/libc/stdlib/rand.c      7 Dec 2015 06:42:17 -0000
@@ -50,7 +50,7 @@ int
 rand(void)
 {
        if (rand_deterministic == 0)
-               return (arc4random() % ((u_int)RAND_MAX + 1));
+               return (arc4random_uniform((u_int)RAND_MAX + 1));
        return (rand_r(&next));
 }
 
Index: sbin/dhclient/dhclient.c
===================================================================
RCS file: /cvs/src/sbin/dhclient/dhclient.c,v
retrieving revision 1.367
diff -u -p -r1.367 dhclient.c
--- sbin/dhclient/dhclient.c    5 Dec 2015 13:09:11 -0000       1.367
+++ sbin/dhclient/dhclient.c    7 Dec 2015 06:42:18 -0000
@@ -1285,15 +1285,13 @@ send_discover(void)
         */
        if (!client->interval)
                client->interval = config->initial_interval;
-       else {
-               client->interval += (arc4random() >> 2) %
-                   (2 * client->interval);
-       }
+       else
+               client->interval += arc4random_uniform(2 * client->interval);
 
        /* Don't backoff past cutoff. */
        if (client->interval > config->backoff_cutoff)
-               client->interval = ((config->backoff_cutoff / 2) +
-                   ((arc4random() >> 2) % config->backoff_cutoff));
+               client->interval = (config->backoff_cutoff / 2) +
+                   arc4random_uniform(config->backoff_cutoff);
 
        /* If the backoff would take us to the panic timeout, just use that
           as the interval. */
@@ -1410,13 +1408,12 @@ send_request(void)
        if (!client->interval)
                client->interval = config->initial_interval;
        else
-               client->interval += ((arc4random() >> 2) %
-                   (2 * client->interval));
+               client->interval += arc4random_uniform(2 * client->interval);
 
        /* Don't backoff past cutoff. */
        if (client->interval > config->backoff_cutoff)
-               client->interval = ((config->backoff_cutoff / 2) +
-                   ((arc4random() >> 2) % client->interval));
+               client->interval = (config->backoff_cutoff / 2) +
+                   arc4random_uniform(client->interval);
 
        /*
         * If the backoff would take us to the expiry time, just set the
Index: sys/dev/ic/sili.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/sili.c,v
retrieving revision 1.57
diff -u -p -r1.57 sili.c
--- sys/dev/ic/sili.c   9 Sep 2015 18:24:26 -0000       1.57
+++ sys/dev/ic/sili.c   7 Dec 2015 06:42:18 -0000
@@ -377,7 +377,7 @@ sili_simulate_error(struct sili_ccb *ccb
                case ATA_C_READDMA_EXT:
                case ATA_C_WRITEDMA:
                case ATA_C_READDMA:
-                       if ((arc4random() % sili_error_test_inv_p) == 0) {
+                       if (arc4random_uniform(sili_error_test_inv_p) == 0) {
                                printf("%s: faking error on slot %d\n",
                                    PORTNAME(sp), ccb->ccb_xa.tag);
                                ccb->ccb_xa.state = ATA_S_ERROR;
Index: sys/netinet6/nd6_rtr.c
===================================================================
RCS file: /cvs/src/sys/netinet6/nd6_rtr.c,v
retrieving revision 1.136
diff -u -p -r1.136 nd6_rtr.c
--- sys/netinet6/nd6_rtr.c      3 Dec 2015 21:57:59 -0000       1.136
+++ sys/netinet6/nd6_rtr.c      7 Dec 2015 06:42:18 -0000
@@ -1951,7 +1951,7 @@ in6_ifadd(struct nd_prefix *pr, int priv
                ifra.ifra_lifetime.ia6t_vltime = ND6_PRIV_VALID_LIFETIME;
            if (ifra.ifra_lifetime.ia6t_pltime > ND6_PRIV_PREFERRED_LIFETIME)
                ifra.ifra_lifetime.ia6t_pltime = ND6_PRIV_PREFERRED_LIFETIME
-                       - (arc4random() % ND6_PRIV_MAX_DESYNC_FACTOR);
+                       - arc4random_uniform(ND6_PRIV_MAX_DESYNC_FACTOR);
        }
 
        /* XXX: scope zone ID? */
Index: sys/ufs/ffs/ffs_alloc.c
===================================================================
RCS file: /cvs/src/sys/ufs/ffs/ffs_alloc.c,v
retrieving revision 1.106
diff -u -p -r1.106 ffs_alloc.c
--- sys/ufs/ffs/ffs_alloc.c     28 Nov 2015 21:52:02 -0000      1.106
+++ sys/ufs/ffs/ffs_alloc.c     7 Dec 2015 06:42:19 -0000
@@ -937,7 +937,7 @@ ffs_dirpref(struct inode *pip)
         * Force allocation in another cg if creating a first level dir.
         */
        if (ITOV(pip)->v_flag & VROOT) {
-               prefcg = (arc4random() & INT_MAX) % fs->fs_ncg;
+               prefcg = arc4random_uniform(fs->fs_ncg);
                mincg = prefcg;
                minndir = fs->fs_ipg;
                for (cg = prefcg; cg < fs->fs_ncg; cg++)
Index: usr.bin/awk/run.c
===================================================================
RCS file: /cvs/src/usr.bin/awk/run.c,v
retrieving revision 1.39
diff -u -p -r1.39 run.c
--- usr.bin/awk/run.c   5 Sep 2015 22:07:10 -0000       1.39
+++ usr.bin/awk/run.c   7 Dec 2015 06:42:19 -0000
@@ -1581,7 +1581,7 @@ Cell *bltin(Node **a, int n)      /* builtin 
                u = (Awkfloat) system(getsval(x)) / 256;   /* 256 is unix-dep */
                break;
        case FRAND:
-               u = (Awkfloat) (random() % RAND_MAX) / RAND_MAX;
+               u = (Awkfloat) arc4random_uniform(RAND_MAX) / RAND_MAX;
                break;
        case FSRAND:
                if (isrec(x)) {         /* no argument provided */
Index: usr.sbin/npppd/common/slist.c
===================================================================
RCS file: /cvs/src/usr.sbin/npppd/common/slist.c,v
retrieving revision 1.6
diff -u -p -r1.6 slist.c
--- usr.sbin/npppd/common/slist.c       5 Dec 2015 18:43:36 -0000       1.6
+++ usr.sbin/npppd/common/slist.c       7 Dec 2015 06:42:20 -0000
@@ -434,7 +434,7 @@ slist_shuffle(slist *list)
 
        len = slist_length(list);
        for (i = len; i > 1; i--)
-               slist_swap0(list, i - 1, (int)(arc4random() % i));
+               slist_swap0(list, i - 1, (int)arc4random_uniform(i));
 }
 
 /** Init an iterator. Only one iterator exists.  */
Index: usr.sbin/npppd/l2tp/l2tpd.c
===================================================================
RCS file: /cvs/src/usr.sbin/npppd/l2tp/l2tpd.c,v
retrieving revision 1.17
diff -u -p -r1.17 l2tpd.c
--- usr.sbin/npppd/l2tp/l2tpd.c 5 Dec 2015 18:43:36 -0000       1.17
+++ usr.sbin/npppd/l2tp/l2tpd.c 7 Dec 2015 06:42:20 -0000
@@ -113,11 +113,11 @@ l2tpd_init(l2tpd *_this)
                    __func__);
                return 1;
        }
-       off = arc4random() % L2TP_SESSION_ID_MASK;
+       off = arc4random() & L2TP_SESSION_ID_MASK;
        for (i = 0; i < L2TP_NCALL; i++) {
-               id = (i + off) % L2TP_SESSION_ID_MASK;
+               id = (i + off) & L2TP_SESSION_ID_MASK;
                if (id == 0)
-                       id = (off - 1) % L2TP_SESSION_ID_MASK;
+                       id = (off - 1) & L2TP_SESSION_ID_MASK;
                if (slist_add(&_this->free_session_id_list,
                    (void *)(uintptr_t)id) == NULL) {
                        l2tpd_log(_this, LOG_ERR,
Index: usr.sbin/npppd/pppoe/pppoed.c
===================================================================
RCS file: /cvs/src/usr.sbin/npppd/pppoe/pppoed.c,v
retrieving revision 1.18
diff -u -p -r1.18 pppoed.c
--- usr.sbin/npppd/pppoe/pppoed.c       11 Oct 2015 07:32:06 -0000      1.18
+++ usr.sbin/npppd/pppoe/pppoed.c       7 Dec 2015 06:42:20 -0000
@@ -147,11 +147,11 @@ pppoed_init(pppoed *_this)
 #if PPPOE_NSESSION > 0xffff
 #error PPPOE_NSESSION must be less than 65536
 #endif
-       off = arc4random() % 0xffff;
+       off = arc4random() & 0xffff;
        for (i = 0; i < PPPOE_NSESSION; i++) {
-               id = (i + off) % 0xffff;
+               id = (i + off) & 0xffff;
                if (id == 0)
-                       id = (off - 1) % 0xffff;
+                       id = (off - 1) & 0xffff;
                if (slist_add(&_this->session_free_list, (void *)(intptr_t)id)
                    == NULL) {
                        pppoed_log(_this, LOG_ERR,
Index: usr.sbin/npppd/pptp/pptpd.c
===================================================================
RCS file: /cvs/src/usr.sbin/npppd/pptp/pptpd.c,v
retrieving revision 1.28
diff -u -p -r1.28 pptpd.c
--- usr.sbin/npppd/pptp/pptpd.c 5 Dec 2015 18:43:36 -0000       1.28
+++ usr.sbin/npppd/pptp/pptpd.c 7 Dec 2015 06:42:20 -0000
@@ -122,7 +122,7 @@ pptpd_init(pptpd *_this)
        for (i = 0; i < countof(call) ; i++)
                call[i] = i + 1;
        for (i = countof(call); i > 1; i--) {
-               m = arc4random() % i;
+               m = arc4random_uniform(i);
                call0 = call[m];
                call[m] = call[i - 1];
                call[i - 1] = call0;

Reply via email to