]> granicus.if.org Git - zfs/commitdiff
Preserve itx alloc size for zio_data_buf_free()
authorBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 4 Dec 2017 19:44:39 +0000 (11:44 -0800)
committerGitHub <noreply@github.com>
Mon, 4 Dec 2017 19:44:39 +0000 (11:44 -0800)
Using zio_data_buf_alloc() to allocate the itx's may be unsafe
because the itx->itx_lr.lrc_reclen field is not constant from
allocation to free.  Using a different itx->itx_lr.lrc_reclen
size in zio_data_buf_free() can result in the allocation being
returned to the wrong kmem cache.

This issue can be avoided entirely by storing the allocation size
in itx->itx_size and using that for zio_data_buf_free().

Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #6912

include/sys/zil.h
module/zfs/zil.c

index 11c7fb4a28e74dd5373eeefefefc02c4d178756e..442fee4a1f8fb5c01e38c79d635a386c84030884 100644 (file)
@@ -395,6 +395,7 @@ typedef struct itx {
        uint8_t         itx_sync;       /* synchronous transaction */
        zil_callback_t  itx_callback;   /* Called when the itx is persistent */
        void            *itx_callback_data; /* User data for the callback */
+       size_t          itx_size;       /* allocated itx structure size */
        uint64_t        itx_oid;        /* object id */
        lr_t            itx_lr;         /* common part of log record */
        /* followed by type-specific part of lr_xx_t and its immediate data */
index d43b2693789dc4586f57e3c93712925c23c03794..9f4312a5a28dafa8982b26ba9ab0ee49f173ade3 100644 (file)
@@ -1254,17 +1254,20 @@ cont:
 itx_t *
 zil_itx_create(uint64_t txtype, size_t lrsize)
 {
+       size_t itxsize;
        itx_t *itx;
 
        lrsize = P2ROUNDUP_TYPED(lrsize, sizeof (uint64_t), size_t);
+       itxsize = offsetof(itx_t, itx_lr) + lrsize;
 
-       itx = zio_data_buf_alloc(offsetof(itx_t, itx_lr) + lrsize);
+       itx = zio_data_buf_alloc(itxsize);
        itx->itx_lr.lrc_txtype = txtype;
        itx->itx_lr.lrc_reclen = lrsize;
        itx->itx_lr.lrc_seq = 0;        /* defensive */
        itx->itx_sync = B_TRUE;         /* default is synchronous */
        itx->itx_callback = NULL;
        itx->itx_callback_data = NULL;
+       itx->itx_size = itxsize;
 
        return (itx);
 }
@@ -1272,7 +1275,7 @@ zil_itx_create(uint64_t txtype, size_t lrsize)
 void
 zil_itx_destroy(itx_t *itx)
 {
-       zio_data_buf_free(itx, offsetof(itx_t, itx_lr)+itx->itx_lr.lrc_reclen);
+       zio_data_buf_free(itx, itx->itx_size);
 }
 
 /*