Any OKs or objections to this diff?  This looks solid to me, FWIW.

On Wed, Jan 27, 2016 at 09:52 +0100, Martin Natano wrote:
> In ufs, the calculation of i_modrev can produce signed overflow on 32
> bit architectures (found on i386). The tv.tv_usec * 4294 calculation is
> designed to move the microseconds part of a struct timeval to the upper
> bits of an unsigned(!) 32 bit value to make room for simple i_modrev
> increments, but the calculation is performed signed, causing overflow.
> The diff below gets rid of the overflow by casting to unsigned first.
> 
> While there I replaced the union _qcvt/SETHIGH/SETLOW dance with simple
> bitshift operations.
> 
> Index: ufs/ext2fs/ext2fs_subr.c
> ===================================================================
> RCS file: /cvs/src/sys/ufs/ext2fs/ext2fs_subr.c,v
> retrieving revision 1.33
> diff -u -p -u -r1.33 ext2fs_subr.c
> --- ufs/ext2fs/ext2fs_subr.c  14 Mar 2015 03:38:52 -0000      1.33
> +++ ufs/ext2fs/ext2fs_subr.c  27 Jan 2016 08:26:05 -0000
> @@ -49,25 +49,6 @@
>  #include <ufs/ext2fs/ext2fs_extern.h>
>  #include <ufs/ext2fs/ext2fs_extents.h>
>  
> -union _qcvt {
> -     int64_t qcvt;
> -     int32_t val[2];
> -};
> -
> -#define SETHIGH(q, h) {                      \
> -     union _qcvt tmp;                \
> -     tmp.qcvt = (q);                 \
> -     tmp.val[_QUAD_HIGHWORD] = (h);  \
> -     (q) = tmp.qcvt;                 \
> -}
> -
> -#define SETLOW(q, l) {                       \
> -     union _qcvt tmp;                \
> -     tmp.qcvt = (q);                 \
> -     tmp.val[_QUAD_LOWWORD] = (l);   \
> -     (q) = tmp.qcvt;                 \
> -}
> -
>  #ifdef _KERNEL
>  
>  /*
> @@ -220,8 +201,8 @@ ext2fs_vinit(struct mount *mp, struct vo
>  
>       /* Initialize modrev times */
>       getmicrouptime(&tv);
> -     SETHIGH(ip->i_modrev, tv.tv_sec);
> -     SETLOW(ip->i_modrev, tv.tv_usec * 4294);
> +     ip->i_modrev = (u_quad_t)tv.tv_sec << 32;
> +     ip->i_modrev |= (u_quad_t)tv.tv_usec * 4294;
>  
>       *vpp = vp;
>  
> Index: ufs/ufs/ufs_vnops.c
> ===================================================================
> RCS file: /cvs/src/sys/ufs/ufs/ufs_vnops.c,v
> retrieving revision 1.123
> diff -u -p -u -r1.123 ufs_vnops.c
> --- ufs/ufs/ufs_vnops.c       8 Dec 2015 15:31:01 -0000       1.123
> +++ ufs/ufs/ufs_vnops.c       27 Jan 2016 08:26:10 -0000
> @@ -78,24 +78,6 @@ int filt_ufswrite(struct knote *, long);
>  int filt_ufsvnode(struct knote *, long);
>  void filt_ufsdetach(struct knote *);
>  
> -union _qcvt {
> -     int64_t qcvt;
> -     int32_t val[2];
> -};
> -
> -#define SETHIGH(q, h) { \
> -     union _qcvt tmp; \
> -     tmp.qcvt = (q); \
> -     tmp.val[_QUAD_HIGHWORD] = (h); \
> -     (q) = tmp.qcvt; \
> -}
> -#define SETLOW(q, l) { \
> -     union _qcvt tmp; \
> -     tmp.qcvt = (q); \
> -     tmp.val[_QUAD_LOWWORD] = (l); \
> -     (q) = tmp.qcvt; \
> -}
> -
>  /*
>   * A virgin directory (no blushing please).
>   */
> @@ -1879,8 +1861,8 @@ ufs_vinit(struct mount *mntp, struct vop
>        * Initialize modrev times
>        */
>       getmicrouptime(&mtv);
> -     SETHIGH(ip->i_modrev, mtv.tv_sec);
> -     SETLOW(ip->i_modrev, mtv.tv_usec * 4294);
> +     ip->i_modrev = (u_quad_t)mtv.tv_sec << 32;
> +     ip->i_modrev |= (u_quad_t)mtv.tv_usec * 4294;
>       *vpp = vp;
>       return (0);
>  }
> 
> cheers,
> natano
> 

Reply via email to