Skip to content

Commit

Permalink
Do not attempt access beyond the declared end of the dn_blkptr array
Browse files Browse the repository at this point in the history
This loop in dmu_objset_write_ready():

	for (i = 0; i < dnp->dn_nblkptr; i++)
		bp->blk_fill += dnp->dn_blkptr[i].blk_fill;

invokes _undefined behavior_ for the (common) case of dn_nblkptr=3,
therefore, the compiler is free to do whatever it wants (such as
optimizing it away, or otherwise messing up your expections).

The fix is to be honest about the array size.

Signed-off-by: Tim Chase <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes openzfs#2511
Closes openzfs#2010
  • Loading branch information
jengelh authored and behlendorf committed Jul 22, 2014
1 parent 7a8f0e8 commit aca19e0
Showing 1 changed file with 25 additions and 3 deletions.
28 changes: 25 additions & 3 deletions include/sys/dnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,31 @@ typedef struct dnode_phys {

uint64_t dn_pad3[4];

blkptr_t dn_blkptr[1];
uint8_t dn_bonus[DN_MAX_BONUSLEN - sizeof (blkptr_t)];
blkptr_t dn_spill;
/*
* The tail region is 448 bytes, and there are three ways to
* look at it.
*
* 0 64 128 192 256 320 384 448 (offset)
* +---------------+---------------+---------------+-------+
* | dn_blkptr[0] | dn_blkptr[1] | dn_blkptr[2] | / |
* +---------------+---------------+---------------+-------+
* | dn_blkptr[0] | dn_bonus[0..319] |
* +---------------+-----------------------+---------------+
* | dn_blkptr[0] | / | dn_spill |
* +---------------+-----------------------+---------------+
*/
union {
blkptr_t dn_blkptr[1+DN_MAX_BONUSLEN/sizeof (blkptr_t)];
struct {
blkptr_t __dn_ignore1;
uint8_t dn_bonus[DN_MAX_BONUSLEN];
};
struct {
blkptr_t __dn_ignore2;
uint8_t __dn_ignore3[DN_MAX_BONUSLEN-sizeof (blkptr_t)];
blkptr_t dn_spill;
};
};
} dnode_phys_t;

typedef struct dnode {
Expand Down

0 comments on commit aca19e0

Please sign in to comment.