summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Engelhardt <[email protected]>2014-07-18 20:00:27 +0200
committerBrian Behlendorf <[email protected]>2014-07-22 09:55:37 -0700
commitaca19e063b5126aab797f5739faaf3ddc82bd587 (patch)
tree3baaf2f237d1978a106bb29cc17759c37fc58787
parent7a8f0e80eae9053ebe6a3c5ce5f3360e8df8de2f (diff)
Do not attempt access beyond the declared end of the dn_blkptr array
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 #2511 Closes #2010
-rw-r--r--include/sys/dnode.h28
1 files changed, 25 insertions, 3 deletions
diff --git a/include/sys/dnode.h b/include/sys/dnode.h
index 55b87bc39..fa0aa4bb7 100644
--- a/include/sys/dnode.h
+++ b/include/sys/dnode.h
@@ -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 {