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
This commit is contained in:
Fedor Uporov 2017-09-27 16:12:13 +00:00
parent 0e492f2faa
commit 72530f91cf
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=324064
4 changed files with 26 additions and 7 deletions

View File

@ -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 bpref)
* The form of the error message is:
* fs: error message
*/
static void
void
ext2_fserr(struct m_ext2fs *fs, uid_t uid, char *cp)
{

View File

@ -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 *);

View File

@ -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 {

View File

@ -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);
}