Author: fsu
Date: Wed Sep 27 16:12:13 2017
New Revision: 324064
URL: https://svnweb.freebsd.org/changeset/base/324064

Log:
  Add check to avoid raw inode iblocks fields overflow in case of huge_file 
feature.
  Use the Linux logic for now.
  
  Reviewed by:    pfg (mentor)
  Approved by:    pfg (mentor)
  MFC after:      2 weeks
  Differential Revision: https://reviews.freebsd.org/D12131

Modified:
  head/sys/fs/ext2fs/ext2_alloc.c
  head/sys/fs/ext2fs/ext2_extern.h
  head/sys/fs/ext2fs/ext2_inode.c
  head/sys/fs/ext2fs/ext2_inode_cnv.c

Modified: head/sys/fs/ext2fs/ext2_alloc.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_alloc.c     Wed Sep 27 15:29:17 2017        
(r324063)
+++ head/sys/fs/ext2fs/ext2_alloc.c     Wed Sep 27 16:12:13 2017        
(r324064)
@@ -56,7 +56,6 @@
 static daddr_t ext2_alloccg(struct inode *, int, daddr_t, int);
 static daddr_t ext2_clusteralloc(struct inode *, int, daddr_t, int);
 static u_long  ext2_dirpref(struct inode *);
-static void    ext2_fserr(struct m_ext2fs *, uid_t, char *);
 static u_long  ext2_hashalloc(struct inode *, int, long, int,
                                daddr_t (*)(struct inode *, int, daddr_t, 
                                                int));
@@ -1303,7 +1302,7 @@ ext2_mapsearch(struct m_ext2fs *fs, char *bbp, daddr_t
  * The form of the error message is:
  *     fs: error message
  */
-static void
+void
 ext2_fserr(struct m_ext2fs *fs, uid_t uid, char *cp)
 {
 

Modified: head/sys/fs/ext2fs/ext2_extern.h
==============================================================================
--- head/sys/fs/ext2fs/ext2_extern.h    Wed Sep 27 15:29:17 2017        
(r324063)
+++ head/sys/fs/ext2fs/ext2_extern.h    Wed Sep 27 16:12:13 2017        
(r324064)
@@ -62,9 +62,10 @@ int  ext2_bmap(struct vop_bmap_args *);
 int    ext2_bmaparray(struct vnode *, daddr_t, daddr_t *, int *, int *);
 void   ext2_clusteracct(struct m_ext2fs *, char *, int, daddr_t, int);
 void   ext2_dirbad(struct inode *ip, doff_t offset, char *how);
+void   ext2_fserr(struct m_ext2fs *, uid_t, char *);
 void   ext2_ei2i(struct ext2fs_dinode *, struct inode *);
 int    ext2_getlbns(struct vnode *, daddr_t, struct indir *, int *);
-void   ext2_i2ei(struct inode *, struct ext2fs_dinode *);
+int    ext2_i2ei(struct inode *, struct ext2fs_dinode *);
 void   ext2_itimes(struct vnode *vp);
 int    ext2_reallocblks(struct vop_reallocblks_args *);
 int    ext2_reclaim(struct vop_reclaim_args *);

Modified: head/sys/fs/ext2fs/ext2_inode.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_inode.c     Wed Sep 27 15:29:17 2017        
(r324063)
+++ head/sys/fs/ext2fs/ext2_inode.c     Wed Sep 27 16:12:13 2017        
(r324064)
@@ -90,8 +90,12 @@ ext2_update(struct vnode *vp, int waitfor)
                brelse(bp);
                return (error);
        }
-       ext2_i2ei(ip, (struct ext2fs_dinode *)((char *)bp->b_data +
+       error = ext2_i2ei(ip, (struct ext2fs_dinode *)((char *)bp->b_data +
            EXT2_INODE_SIZE(fs) * ino_to_fsbo(fs, ip->i_number)));
+       if (error) {
+               brelse(bp);
+               return (error);
+       }
        if (waitfor && !DOINGASYNC(vp))
                return (bwrite(bp));
        else {

Modified: head/sys/fs/ext2fs/ext2_inode_cnv.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_inode_cnv.c Wed Sep 27 15:29:17 2017        
(r324063)
+++ head/sys/fs/ext2fs/ext2_inode_cnv.c Wed Sep 27 16:12:13 2017        
(r324064)
@@ -136,11 +136,13 @@ ext2_ei2i(struct ext2fs_dinode *ei, struct inode *ip)
 /*
  *     inode to raw ext2 inode
  */
-void
+int
 ext2_i2ei(struct inode *ip, struct ext2fs_dinode *ei)
 {
+       struct m_ext2fs *fs;
        int i;
 
+       fs = ip->i_e2fs;
        ei->e2di_mode = ip->i_mode;
        ei->e2di_nlink = ip->i_nlink;
        /*
@@ -167,8 +169,19 @@ ext2_i2ei(struct inode *ip, struct ext2fs_dinode *ei)
        ei->e2di_flags |= (ip->i_flags & UF_NODUMP) ? EXT2_NODUMP : 0;
        ei->e2di_flags |= (ip->i_flag & IN_E3INDEX) ? EXT3_INDEX : 0;
        ei->e2di_flags |= (ip->i_flag & IN_E4EXTENTS) ? EXT4_EXTENTS : 0;
-       ei->e2di_nblock = ip->i_blocks & 0xffffffff;
-       ei->e2di_nblock_high = ip->i_blocks >> 32 & 0xffff;
+       if (ip->i_blocks > ~0U &&
+           !EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_HUGE_FILE)) {
+               ext2_fserr(fs, ip->i_uid, "i_blocks value is out of range");
+               return (EIO);
+       }
+       if (ip->i_blocks <= 0xffffffffffffULL) {
+               ei->e2di_nblock = ip->i_blocks & 0xffffffff;
+               ei->e2di_nblock_high = ip->i_blocks >> 32 & 0xffff;
+       } else {
+               ei->e2di_flags |= EXT4_HUGE_FILE;
+               ei->e2di_nblock = dbtofsb(fs, ip->i_blocks);
+               ei->e2di_nblock_high = dbtofsb(fs, ip->i_blocks) >> 32 & 0xffff;
+       }
        ei->e2di_facl = ip->i_facl & 0xffffffff;
        ei->e2di_facl_high = ip->i_facl >> 32 & 0xffff;
        ei->e2di_gen = ip->i_gen;
@@ -181,4 +194,6 @@ ext2_i2ei(struct inode *ip, struct ext2fs_dinode *ei)
                ei->e2di_blocks[i] = ip->i_db[i];
        for (i = 0; i < EXT2_NIADDR; i++)
                ei->e2di_blocks[EXT2_NDIR_BLOCKS + i] = ip->i_ib[i];
+
+       return (0);
 }
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to