Hello,

In ffs_inode_alloc(), inode generation numbers are incremented after
being assigned an initial random value. Since the di_gen field is a
signed integer, it may overflow, causing undefined behavior (this is
unlikely to ever happen, though).

This patch always assigns a random non-zero positive integer in [1,
INT_MAX] range, not equal to the previous generation number.

--
Dmitry Chestnykh
https://www.codingrobots.com


Index: src/sys/ufs/ffs/ffs_alloc.c
===================================================================
RCS file: /cvs/src/sys/ufs/ffs/ffs_alloc.c,v
retrieving revision 1.108
diff -u -p -u -r1.108 ffs_alloc.c
--- src/sys/ufs/ffs/ffs_alloc.c 23 May 2016 20:47:49 -0000      1.108
+++ src/sys/ufs/ffs/ffs_alloc.c 24 Jun 2017 19:25:04 -0000
@@ -361,6 +361,7 @@ ffs_inode_alloc(struct inode *pip, mode_
        struct inode *ip;
        ufsino_t ino, ipref;
        int cg, error;
+       int32_t ngen;

        *vpp = NULL;
        fs = pip->i_fs;
@@ -413,16 +414,12 @@ ffs_inode_alloc(struct inode *pip, mode_

        /*
         * Set up a new generation number for this inode.
-        * XXX - just increment for now, this is wrong! (millert)
-        *       Need a way to preserve randomization.
         */
-       if (DIP(ip, gen) != 0)
-               DIP_ADD(ip, gen, 1);
-       if (DIP(ip, gen) == 0)
-               DIP_ASSIGN(ip, gen, arc4random() & INT_MAX);
-
-       if (DIP(ip, gen) == 0 || DIP(ip, gen) == -1)
-               DIP_ASSIGN(ip, gen, 1); /* Shouldn't happen */
+       do {
+               ngen = arc4random_uniform(INT_MAX) + 1;
+       } while (DIP(ip, gen) == ngen);
+
+       DIP_ASSIGN(ip, gen, ngen);

        return (0);

Reply via email to